简介:本资源是面向Delphi 11–13 Florence版本开发者的AI功能集成工具包——TMS AI Studio v1.3.0.0完整源码版,专为缺乏AI底层经验但熟悉Delphi快速开发的中高级开发者设计,解决在传统桌面/跨平台应用中便捷嵌入图像识别、自然语言处理与机器学习能力的痛点。压缩包共216个文件,含68个Pascal源文件(核心控件逻辑)、32个DPROJ工程配置(适配多版本Delphi)、23个DPR主程序入口、9个DFM/FMX界面定义及8个RES资源文件,辅以说明文档(PDF/MD)、示例数据库(sample.db)与启动脚本(movefiles.bat),整体大小61.44MB。已有111人下载学习,可直接编译运行全部示例(如Uaisimple.dfm、Uaiweather.dfm等),深入理解AI控件封装机制;完整源码支持二次定制、调试追踪与算法模块替换,显著降低Delphi场景下AI工程落地门槛。
1. 项目概述:一份来自社区的“硬核”资源
最近在Delphi开发者圈子里,一个名为“TMS AI Studio v1.3.0.0 for Delphi 11-13 Florence Full Source.rar”的压缩包文件引起了不小的讨论。从文件名就能看出它的分量:这是一个由知名第三方组件厂商TMS Software出品的AI集成开发套件,版本号v1.3.0.0,支持从Delphi 11 Alexandria到最新的Delphi 12 Athens(项目标题中的“13 Florence”可能指代社区对Delphi 12的早期内部代号或误称),并且最关键的是——它附带“Full Source”,即完整源代码。
对于任何一位深耕Delphi生态的开发者来说,这都像是一份从天而降的“宝藏”。TMS的组件向来以高质量和稳定性著称,但通常以编译后的二进制包形式授权分发。能拿到其核心产品TMS AI Studio的完整源代码,意味着你不仅可以无限制地使用这套强大的AI工具集,更能深入其内部,理解每一行代码的实现逻辑,进行定制化修改,甚至学习顶尖组件厂商的架构设计。这不仅仅是获得了一个工具,更是拿到了一本“武功秘籍”。无论是想快速为自家应用注入AI能力(如智能文本分析、图像识别),还是希望研究大型VCL/FireMonkey组件库该如何组织,这个资源都具有极高的参考价值。当然,随之而来的也是关于版权、版本兼容性以及如何正确“消化”这份资源的现实挑战。
2. TMS AI Studio 核心价值与功能模块解析
2.1 为什么是TMS AI Studio?
在Delphi的第三方组件生态中,TMS Software是毫无争议的巨头之一。他们的产品线覆盖了UI控件、报表、图表、ORM、云连接等几乎所有领域。TMS AI Studio则是他们面向人工智能浪潮推出的战略级产品。与网络上零散的、基于某个特定AI接口(如只封装了OpenAI ChatGPT)的组件不同,TMS AI Studio是一个统一的、可扩展的AI能力集成框架。
它的核心价值在于抽象与整合。它将不同AI服务提供商(如OpenAI、Google AI、Hugging Face、本地运行的Ollama等)的API,以及不同的AI任务类型(聊天补全、文本嵌入、图像生成、语音识别等),封装成一套统一的、基于Delphi接口的组件。开发者无需关心底层是调用HTTP REST API还是本地DLL,只需在设计时拖放TMSAI、TMSAIChat、TMSAIImage等控件,设置好Provider(供应商)和模型参数,就能以一致的编程模式调用AI功能。这极大地降低了在Delphi应用中集成AI的门槛和复杂度。
2.2 主要功能模块拆解
拥有完整源代码,我们可以清晰地看到其架构。通常,TMS AI Studio会包含以下几个核心模块:
核心接口与抽象层 (
TMS.AI.Core):这是整个库的基石。它定义了IAIProvider、IAIChat、IAIImage等核心接口,以及TAIRequest、TAIResponse等通用数据模型。所有具体的AI服务实现都是这些接口的派生。这种设计遵循了“依赖倒置”原则,使得上层应用代码依赖于抽象接口,而非具体实现,从而轻松切换AI服务商。提供商实现层 (
TMS.AI.Providers):这个目录下包含了针对各个AI服务的具体实现。例如:TMS.AI.Provider.OpenAI.pas: 封装OpenAI的GPT系列、DALL-E等模型的API调用。TMS.AI.Provider.GoogleAI.pas: 封装Google Gemini API的调用。TMS.AI.Provider.Ollama.pas: 封装与本地Ollama服务(用于运行Llama2、Mistral等开源模型)的通信。- 可能还有
TMS.AI.Provider.Azure、TMS.AI.Provider.Claude等。每个Provider单元都负责处理身份验证、网络请求、错误处理以及将服务商特有的响应格式转换为库定义的通用格式。
可视化控件层 (
TMS.AI.Components):这是提供给开发者在IDE表单上直接拖放使用的控件。例如:TMSAI: 主控件,用于配置全局的API密钥、默认提供商等。TMSAIChat: 专门用于聊天对话场景,管理对话历史、发送消息、流式接收回复。TMSAIImage: 用于图像生成或图像理解任务。TMSAITranscription: 用于语音转文字。- 这些控件在内部会创建并管理对应的Provider实例,将属性设置和事件调用桥接到核心API上。
工具与辅助单元:包括用于处理JSON序列化/反序列化(因为大部分AI API使用JSON)、异步任务管理、日志记录、本地缓存(用于存储嵌入向量或对话历史)等功能的辅助单元。
注意:分析源代码时,要特别注意其网络请求库的选择(是使用Indy、NetHTTPClient还是其他)、异步处理模型(是基于线程、匿名线程还是使用
System.Threading),以及错误处理机制。这些是评估其稳定性和性能的关键。
3. 从源代码到可用组件库的完整构建指南
拿到一个.rar格式的完整源代码包,直接使用是不行的。我们需要将其编译、安装到Delphi的IDE中,或者至少将其编译为可供项目引用的DCU/BPL文件。以下是基于常见实践的标准化步骤。
3.1 环境准备与源代码审视
首先,确保你的开发环境符合要求。根据文件名,它支持Delphi 11-13。建议使用Delphi 12 Athens进行尝试,因为其兼容性最好。你需要准备好对应版本的IDE。
解压“TMS AI Studio v1.3.0.0 for Delphi 11-13 Florence Full Source.rar”后,不要急于打开所有文件。先花时间浏览目录结构。一个规范的TMS源码包通常包含以下关键文件/目录:
Source\: 核心源代码目录,里面按模块分文件夹。Demos\: 示例程序,这是学习如何使用该库的最佳资料。Packages\: 包含各种版本的DPK(Delphi Package)项目文件,用于编译和安装。Readme.txt或Install.txt: 安装说明(如果有的话,但社区资源往往缺失)。License.txt: 许可协议(**必须仔细阅读!**社区分享的完整源码可能涉及版权风险,仅限个人学习研究)。
第一步:寻找入口点。进入Packages文件夹,你会看到类似TMSAIStudio_D12.dproj(Delphi项目文件)和TMSAIStudio_D12.dpk(包文件)的文件。D12代表Delphi 12。找到与你IDE版本匹配的文件。
3.2 编译与安装的详细步骤
这里以在Delphi 12中安装运行时包(Runtime Package)和设计时包(Design-Time Package)为例。运行时包包含核心功能代码,设计时包负责在IDE工具栏注册控件。
设置库路径(Library Path):在安装前,最好先将源码路径添加到IDE的库路径中。打开Delphi,点击
Tools -> Options -> Language -> Delphi Options -> Library。在Library path中,添加你的源码根目录(例如D:\Components\TMSAIStudio\Source)。这能确保编译器在编译时能找到所有依赖的单元。编译运行时包:在IDE中打开
Packages目录下的TMSAIStudio_D12.dpk文件。在项目管理器(Project Manager)中,右键点击该包,选择“Compile”。如果编译成功,会在输出目录(通常是.\Bin)生成TMSAIStudio_D12.bpl(运行时包)和.dcu文件。如果编译失败,需要根据错误信息排查。- 常见错误1:缺少依赖单元。错误信息可能提示找不到
Vcl.Controls或System.JSON等。这通常是因为项目搜索路径未包含Delphi标准库路径,但标准包一般不会出现此问题。更可能的是缺少TMS自家的其他依赖包,比如TMS的核心库TMS.Comm.Base等。你需要确认这个AI Studio包是否依赖其他TMS组件,并确保那些组件的源码或DCU路径也在库路径中。 - 常见错误2:版本不兼容语法。例如,源代码中使用了Delphi 12的新特性,而你的环境是Delphi 11。这时需要根据错误行进行语法降级调整,或者寻找对应Delphi 11版本的包文件。
- 常见错误1:缺少依赖单元。错误信息可能提示找不到
安装设计时包:编译通过后,在项目管理器中,右键点击
TMSAIStudio_D12.dpk,这次选择“Install”。这个操作会将设计时包注册到IDE。如果安装成功,IDE会提示“Package xxxx has been installed”,并且在工具栏的“TMS”或“AI”分类下,你应该能看到TMSAI、TMSAIChat等控件图标。备用方案:仅使用DCU文件:如果安装过程复杂或总失败,可以采用更轻量的方式。不执行“Install”,只“Compile”。编译成功后,将生成的
.dcu文件(分散在Source各子目录下)全部复制到一个统一的目录(如.\DCU)。然后,在你的应用程序项目中,通过Project -> Options -> Delphi Compiler -> Unit scope names或直接在该项目的搜索路径中添加这个.\DCU目录。这样,你就可以在代码中uses相关的AI单元来编程调用,只是无法在表单设计器上拖放控件。
3.3 验证安装与跑通第一个Demo
安装成功后,创建一个新的VCL Application项目。在工具栏找到TMS AI控件,拖一个TMSAI和TMSAIChat到表单上。查看TMSAI控件的属性,找到Provider属性,将其设置为OpenAI(或其他你配置好的提供商)。然后在TMSAI控件的属性中填入你的API密钥(注意:为了安全,永远不要将硬编码的API密钥提交到版本控制系统,应使用环境变量或配置文件)。
接下来,打开Demos文件夹,找一个最简单的聊天Demo(例如ChatDemo)打开并运行。这是验证整个库是否正常工作的最快方式。运行Demo,输入消息,看是否能收到AI的回复。如果Demo运行成功,说明从源码到编译安装的整个链条是通的。
4. 核心功能实战:构建一个智能文本分析工具
为了深入理解TMS AI Studio的使用,我们抛开Demo,从头构建一个实用的工具:一个本地文档智能摘要与问答工具。它将支持加载文本文件,利用AI生成摘要,并允许用户就文档内容进行提问。
4.1 界面设计与控件布局
我们使用VCL框架。在表单上放置以下控件:
TMemo(命名为MemoSource): 用于显示和编辑原始文档文本。TButton(命名为BtnLoadFile): 点击后打开文件对话框加载.txt文件到MemoSource。TMSAI(命名为AI): 全局AI控制器。设置其Provider为Ollama(假设我们在本地运行了Ollama和Llama2模型),在OnCreate事件中设置其BaseURL为http://localhost:11434(Ollama默认地址)。TMSAIChat(命名为AIChat): 将其AI属性指向AI控件。这是我们与模型交互的核心。TButton(命名为BtnSummarize): 点击后触发摘要生成。TMemo(命名为MemoSummary): 显示生成的摘要。TEdit(命名为EditQuestion): 用于输入关于文档的问题。TButton(命名为BtnAsk): 点击后提交问题。TMemo(命名为MemoAnswer): 显示AI对问题的回答。
4.2 关键代码实现与逻辑
1. 摘要生成功能:
procedure TFormMain.BtnSummarizeClick(Sender: TObject); var Prompt: string; begin if MemoSource.Text.Trim.IsEmpty then begin ShowMessage('请先加载文档内容。'); Exit; end; // 构建一个指令清晰的Prompt Prompt := '请为以下文本生成一个简洁、准确的摘要,突出核心内容。文本内容如下:' + sLineBreak + sLineBreak + MemoSource.Text; // 设置聊天角色和消息。我们使用“系统”消息来设定AI行为,“用户”消息传递文本。 AIChat.ClearMessages; AIChat.Messages.AddRole(TMessageRole.System).Content := '你是一个专业的文本分析助手,擅长生成简洁的摘要。'; AIChat.Messages.AddRole(TMessageRole.User).Content := Prompt; MemoSummary.Lines.Text := '正在生成摘要,请稍候...'; BtnSummarize.Enabled := False; // 异步调用,避免界面卡死 AIChat.ExecuteAsync( procedure begin // 此回调在AI响应完成后,在主线程中执行 TThread.Synchronize(nil, procedure begin MemoSummary.Lines.Text := AIChat.Messages.Last.Content; BtnSummarize.Enabled := True; end); end, procedure (const Error: string) begin // 错误处理回调 TThread.Synchronize(nil, procedure begin MemoSummary.Lines.Text := '摘要生成失败:' + Error; BtnSummarize.Enabled := True; end); end ); end;2. 文档问答功能:这个功能的关键在于将文档内容作为“上下文”提供给AI。对于长文档,我们需要使用“嵌入”或“上下文窗口”技术。这里演示一个简单版,将整个文档(假设不长)作为上下文附加到每个问题中。
procedure TFormMain.BtnAskClick(Sender: TObject); var Question: string; ContextPrompt: string; begin Question := EditQuestion.Text.Trim; if Question.IsEmpty then Exit; // 将文档内容作为上下文与问题一起发送 ContextPrompt := '请根据以下文档内容回答问题。如果文档中没有明确答案,请说明“根据提供文档,无法找到相关信息”。' + sLineBreak + sLineBreak + '【文档内容开始】' + sLineBreak + MemoSource.Text + sLineBreak + '【文档内容结束】' + sLineBreak + sLineBreak + '问题:' + Question; AIChat.ClearMessages; // 可以保留一个系统角色设定 AIChat.Messages.AddRole(TMessageRole.System).Content := '你是一个严谨的文档分析员,只根据提供的文档内容回答问题。'; AIChat.Messages.AddRole(TMessageRole.User).Content := ContextPrompt; MemoAnswer.Lines.Text := '正在思考...'; BtnAsk.Enabled := False; AIChat.ExecuteAsync( procedure begin TThread.Synchronize(nil, procedure begin MemoAnswer.Lines.Text := AIChat.Messages.Last.Content; BtnAsk.Enabled := True; end); end, procedure (const Error: string) begin TThread.Synchronize(nil, procedure begin MemoAnswer.Lines.Text := '回答失败:' + Error; BtnAsk.Enabled := True; end); end ); end;实操心得:在实际使用中,直接将长文档作为上下文会很快耗尽模型的Token限制(通常4K-128K)。对于生产环境,更优的做法是:
- 文档分块:将长文档按段落或固定大小分割成多个片段。
- 向量化与检索:使用TMS AI Studio的文本嵌入功能(如果该版本支持),将每个片段转换为向量,并存入向量数据库(如Chroma、Qdrant)。
- 语义检索:当用户提问时,将问题也向量化,在向量数据库中检索出最相关的几个文档片段。
- 构建Prompt:只将这些相关片段作为上下文发送给大模型生成答案。这就是经典的RAG(检索增强生成)架构。TMS AI Studio的完整源码为我们实现这套流程提供了底层API支持。
5. 深度定制与源码学习:修改Provider以适配国产大模型
拥有完整源代码的最大优势在于定制。假设公司要求接入一个国产大模型,如智谱AI、文心一言或通义千问,而TMS AI Studio官方并未提供该Provider。这时,我们就可以自己动手,丰衣足食。
5.1 创建自定义Provider的步骤
研究现有Provider:打开
TMS.AI.Provider.OpenAI.pas或TMS.AI.Provider.Ollama.pas,这是最好的模板。你会发现它们都继承自一个基类(例如TCustomAIProvider),并实现了IAIProvider、IAIChat等核心接口。创建新单元:在
Source目录下(或你自己的组件目录),新建一个单元文件,例如TMS.AI.Provider.ZhiPu.pas。定义Provider类:
unit TMS.AI.Provider.ZhiPu; interface uses System.Classes, System.SysUtils, TMS.AI.Core; // 引用核心单元 type TZhiPuAIProvider = class(TCustomAIProvider, IAIProvider, IAIChat) private FApiKey: string; FBaseURL: string; // 其他私有字段,如HTTP客户端 protected // 实现IAIChat接口的方法 function GetChatCompletion(const ARequest: TAIChatCompletionRequest): TAIChatCompletionResponse; override; procedure GetChatCompletionAsync(const ARequest: TAIChatCompletionRequest; const OnResponse: TProc<TAIChatCompletionResponse>; const OnError: TProc<string>); override; // 可能还需要实现IAIImage, IAIEmbedding等接口的方法 public constructor Create(AOwner: TComponent); override; // 发布必要的属性,如ApiKey, BaseURL property ApiKey: string read FApiKey write FApiKey; property BaseURL: string read FBaseURL write FBaseURL default 'https://open.bigmodel.cn/api/paas/v4/'; end; implementation uses System.Net.HttpClient, System.Net.URLClient, System.JSON; // 可能需要HTTP和JSON单元 constructor TZhiPuAIProvider.Create(AOwner: TComponent); begin inherited; FBaseURL := 'https://open.bigmodel.cn/api/paas/v4/'; end; function TZhiPuAIProvider.GetChatCompletion(const ARequest: TAIChatCompletionRequest): TAIChatCompletionResponse; var LHttpClient: THTTPClient; LRequestStream: TStringStream; LResponseStream: TStringStream; LUrl: string; LJsonReq, LJsonResp: TJSONObject; LMsgArray: TJSONArray; LMsg: TMessage; begin Result := TAIChatCompletionResponse.Create; LHttpClient := THTTPClient.Create; LRequestStream := TStringStream.Create('', TEncoding.UTF8); LResponseStream := TStringStream.Create('', TEncoding.UTF8); try // 1. 构建符合智谱API要求的JSON请求体 LJsonReq := TJSONObject.Create; try LJsonReq.AddPair('model', 'glm-4'); // 指定模型 LMsgArray := TJSONArray.Create; for LMsg in ARequest.Messages do begin LMsgArray.AddElement(TJSONObject.Create .AddPair('role', LMsg.Role.ToString.ToLower) // 注意角色名称可能需转换 .AddPair('content', LMsg.Content)); end; LJsonReq.AddPair('messages', LMsgArray); LJsonReq.AddPair('stream', TJSONBool.Create(False)); LRequestStream.WriteString(LJsonReq.ToJSON); finally LJsonReq.Free; end; // 2. 配置HTTP请求 LUrl := FBaseURL + 'chat/completions'; LHttpClient.CustomHeaders['Authorization'] := 'Bearer ' + FApiKey; LHttpClient.ContentType := 'application/json'; // 3. 发送同步请求 LHttpClient.Post(LUrl, LRequestStream, LResponseStream); // 4. 解析智谱API的响应,并填充到通用的TAIChatCompletionResponse中 LJsonResp := TJSONObject.ParseJSONValue(LResponseStream.DataString) as TJSONObject; try if Assigned(LJsonResp) and LJsonResp.TryGetValue('choices', LMsgArray) and (LMsgArray.Count > 0) then begin Result.Choices.Add(TMessage.Create); Result.Choices.Last.Role := TMessageRole.Assistant; Result.Choices.Last.Content := LMsgArray.Items[0].GetValue<string>('message.content'); end else begin raise Exception.Create('Invalid response from ZhiPu AI: ' + LResponseStream.DataString); end; finally LJsonResp.Free; end; finally LRequestStream.Free; LResponseStream.Free; LHttpClient.Free; end; end; // GetChatCompletionAsync的实现类似,但需使用异步HTTP调用,这里省略... end.注册Provider:为了让
TMSAI控件能在设计时选择你的ZhiPu提供商,你需要在Provider单元的最后,调用RegisterProvider过程(如果库提供了这样的机制),或者在控件初始化时手动将你的Provider类添加到工厂中。具体方法需要参考源码中其他Provider是如何被注册的,通常在一个TMS.AI.Providers.pas或TMS.AI.Register.pas的单元里。
5.2 源码学习的要点
通过这个自定义过程,你能深入学习到:
- 网络层封装:库是如何抽象HTTP客户端,处理超时、重试和错误的。
- 数据模型转换:如何将通用的
TAIRequest转换为特定厂商的API格式,又如何将厂商的响应转换回来。这是适配器的经典应用。 - 异步编程模型:库是使用回调、事件还是
Future/Promise来处理异步操作,这对于编写响应式UI至关重要。 - 配置与状态管理:API密钥、端点URL等配置是如何在控件间传递和管理的。
6. 常见问题、排查技巧与版本兼容性处理
在实际使用和编译这类第三方源码时,会遇到各种问题。以下是一些典型问题及其解决思路。
6.1 编译与安装阶段问题
| 问题现象 | 可能原因 | 排查与解决思路 |
|---|---|---|
| 编译时提示“Unit xxx not found” | 1. 库路径未正确设置。 2. 依赖的其他包(如TMS Core库)未安装或路径不对。 3. 源代码包本身不完整。 | 1. 检查并添加所有必要的源码路径到IDE库路径。 2. 查看包文件(.dpk)的“Requires”列表,确保其中列出的所有包都已安装或能找到。 3. 对比网络上的其他资源,确认文件是否齐全。 |
| 安装时提示“Cannot load package xxx. It contains unit xxx, which is also contained in package yyy” | 单元冲突。同一个单元(如TMS.AI.Core)被编译进了多个不同的包中。 | 1. 卸载所有已安装的TMS AI Studio旧版本包。 2. 清理旧的DCU/BPL文件,确保编译环境干净。 3. 尝试只编译运行时包,然后在项目中引用DCU,放弃安装设计时包。 |
| 控件安装成功,但拖到表单上提示“Class TMSAI not found” | 设计时包(包含控件注册信息)与运行时包(包含实际代码)版本不匹配或未正确加载。 | 1. 关闭所有Delphi IDE实例,重新打开。 2. 检查 Component -> Install Packages,确保对应的设计时包已勾选且路径正确。3. 在系统搜索路径中,确保运行时BPL文件的目录在PATH环境变量中,或者将BPL复制到系统目录。 |
6.2 运行时与API调用问题
| 问题现象 | 可能原因 | 排查与解决思路 |
|---|---|---|
| 调用AI功能时,程序无响应或报网络错误。 | 1. API密钥、BaseURL配置错误。 2. 网络代理问题。 3. 异步调用未正确处理,导致主线程阻塞。 | 1. 使用TMSAI控件的OnError事件捕获详细错误信息。2. 对于本地模型(如Ollama),用浏览器访问 http://localhost:11434/api/tags测试服务是否正常。3. 检查防火墙和代理设置。在代码中为HTTP客户端显式配置代理。 4. 确保异步调用的回调函数被正确执行,避免在回调中做耗时操作。 |
| 流式输出(Streaming)不工作,必须等全部生成完才显示。 | 1. 使用的Provider或模型不支持流式响应。 2. 代码中未正确处理流式回调事件。 | 1. 查阅对应AI服务的API文档,确认是否支持流式(如OpenAI的stream: true参数)。2. 检查 TMSAIChat控件是否有OnStreamingChunkReceived之类的事件,并在该事件中实时更新UI。 |
| 处理长文本时,返回“context length exceeded”错误。 | 输入的文本(Prompt+对话历史)超过了模型的最大上下文长度(Token限制)。 | 1. 对输入文本进行智能截断或分块总结。 2. 使用“摘要-问答”链式调用,先对长文档生成摘要,再基于摘要提问。 3. 考虑使用支持更长上下文的模型(如GPT-4 Turbo 128K)。 |
6.3 关于“Delphi 13.1”与版本兼容性的特别说明
项目标题中提到了“Delphi 13.1”,但Embarcadero官方发布的版本序列中,Delphi 11之后是Delphi 12 Athens。所谓的“13.1”或“Florence”很可能是发布前的内部开发代号,或者是社区/资源分享者的一种误称或未来版本占位。在处理此类资源时,版本兼容性是首要问题。
- 向前兼容:为Delphi 12编译的包,通常无法直接在Delphi 11上安装,因为DCU/BPL格式可能不兼容,且可能使用了Delphi 12的新特性。
- 向后兼容:为Delphi 11编译的包,在Delphi 12上可能可以安装,但可能需要重新编译。
- 最佳实践:永远尝试用源代码重新编译。打开与你当前Delphi版本最接近的
.dpk文件进行编译。如果版本号不匹配(如只有D11的包,但你在用D12),直接打开D11的包,Delphi IDE通常会提示进行转换,转换后尝试编译。根据编译错误逐一调整(例如,替换过时的单元引用,修改不兼容的语法)。
一个关键的技巧是:如果包文件转换后编译困难,可以放弃安装整个包。转而创建一个新的“Package”项目,将Source目录下所有相关的.pas文件添加到这个新包中,然后编译。这样可以排除原有包项目配置的干扰。
本文还有配套的精品资源,点击获取