资讯动态

Delphi/FPC AI应用开发实战:基于MakerAI Suite构建RAG与智能体系统

发布时间:2026/10/16 2:21:25 来源:尧图企业网站定制
1. 项目概述MakerAI Suite一个为Delphi/FPC打造的完整AI应用生态如果你是一名Delphi或Free Pascal开发者正琢磨着怎么把当下火热的AI能力比如大语言模型、智能体、知识库问答这些集成到你的桌面应用、企业系统或者工业控制软件里那你很可能已经发现了一个尴尬的现实社区里能找到的库大多只是某个AI服务API的简单封装。你调用OpenAI的Chat Completion接口可能没问题但一旦想搞点复杂的比如让AI能读取你本地的PDF文件、接入私有知识库做精准问答、或者构建一个能自动执行多步骤任务的智能工作流就得自己吭哧吭哧写一大堆胶水代码处理各种协议、状态管理和错误恢复。这感觉就像给你一堆乐高基础砖块却让你去造一座功能齐全的城堡中间的楼梯、门窗、电路都得自己从零打磨。MakerAI Suite的出现就是为了彻底改变这个局面。它不是一个简单的API包装器而是一个为Delphi和Free Pascal量身定制的、完整的AI应用开发生态系统。我第一次深入使用它的时候感觉就像从手工作坊突然搬进了一个现代化的全自动工厂。它的核心设计哲学是让开发者能用熟悉的Pascal语言和Delphi的组件化思维去构建生产级的、复杂的AI增强型应用。无论是简单的聊天机器人还是涉及多模型调度、知识检索、工具调用和持久化工作流的智能体系统MakerAI都提供了一套原生、连贯的解决方案。这个项目由Gustavo Enríquez主导目前已经迭代到v3.3版本支持从Delphi 10.4 Sydney到最新的13 Florence以及Free Pascal 3.2和Lazarus。这意味着无论你是维护着历史悠久的VCL项目还是用FMX开发跨平台应用甚至是纯粹的FPC/Lazarus用户都能无缝接入。它覆盖了从OpenAI、Claude、Gemini、Grok、Mistral等主流云服务到本地部署的Ollama、LM Studio模型真正做到了“一套框架连接所有”。2. 核心架构解析从通用连接到专业工具链MakerAI的架构设计清晰地分为了几个层次这种分层设计保证了灵活性和强大功能的并存。理解这个架构是你能否高效利用它的关键。2.1 统一连接层TAiChatConnection的价值最底层是原生驱动。对于每一个支持的AI服务商ProviderMakerAI都提供了一个专属组件例如TAiOpenChat、TAiClaudeChat等。这些组件提供了对该服务商API的全功能、高保真访问。每一个模型参数、每一个响应字段、每一个流式事件都按照服务商的原始定义暴露给你。当你需要精细控制某个特定服务的独有功能时比如调整Claude特有的“思维链”参数或者使用OpenAI的JSON强制输出模式直接使用这些组件是最佳选择。然而真正体现MakerAI“生态”价值的是其上的TAiChatConnection通用连接器。这是一个抽象层它定义了一套统一的接口。在你的应用代码中你只需要与TAiChatConnection交互。切换AI服务商或模型在运行时只需要修改DriverName和Model属性即可业务逻辑完全不用动。// 初始化连接器 AiConn: TAiChatConnection; AiConn : TAiChatConnection.Create(nil); try // 使用OpenAI的GPT-5.2模型 AiConn.DriverName : OpenAI; AiConn.Model : gpt-5.2; AiConn.ApiKey : OPENAI_API_KEY; // 从环境变量读取 // 发送消息并获取流式响应 AiConn.AddMessage(user, 用Pascal写一个快速排序函数。); AiConn.OnChunk : procedure (const Chunk: string) begin Memo1.Lines.Text : Memo1.Lines.Text Chunk; end; AiConn.ExecuteAsync; // 运行时无缝切换到Gemini 3.0 // AiConn.DriverName : Gemini; // AiConn.Model : gemini-3.0-flash; // AiConn.ApiKey : GEMINI_API_KEY; // ... 再次调用ExecuteAsync代码无需任何其他改动 finally AiConn.Free; end;这种设计带来了巨大的灵活性。你可以在开发阶段使用本地的Ollama模型进行快速迭代和测试零成本、速度快部署时再切换到云端的GPT或Claude以获得更强的能力。或者你可以根据用户订阅级别、任务类型或当前网络状况动态选择最合适的模型提供商。2.2 能力系统与工具桥接TAiCapabilities的智能补位v3.3版本引入的TAiCapabilities系统是另一个精妙的设计。它解决了不同模型能力参差不齐带来的兼容性问题。每个模型都有其原生能力集ModelCaps比如cap_Image识图、cap_Reasoning深度思考。而你的应用会话可能会有特定的能力需求SessionCaps。当SessionCaps超出了ModelCaps时MakerAI不会直接报错而是自动激活相应的工具桥接。例如你向一个不支持直接读取PDF的模型如早期的DeepSeek模型发送一个PDF文件进行分析。SessionCaps包含了cap_Pdf但模型的ModelCaps没有。此时MakerAI会自动调用配置好的IAiPdfTool比如基于Mistral OCR或Ollama OCR的工具先将PDF转换为文本再将文本和你的问题一起发送给模型。这一切对开发者是透明的你无需在代码中写一堆if...else来判断模型是否支持某功能。ThinkingLeveltlLow,tlMedium,tlHigh是对“扩展思考”能力的统一抽象。对于支持“深度思考”或“链式推理”的模型如Claude 3.7 Sonnet、DeepSeek-R1你可以通过这个属性来请求不同深度的推理过程而不用去记每个服务商特有的参数名。2.3 核心功能模块RAG、智能体与MCP在统一连接层之上是MakerAI的三大核心功能支柱它们将AI从简单的对话提升到了复杂系统集成的层面。1. RAG让AI拥有“长期记忆”和“专业知识”RAG是当前构建企业级AI应用几乎必不可少的技术。MakerAI提供了两套互补的检索引擎向量RAG基于嵌入Embeddings和向量数据库。它擅长语义搜索。你上传文档TXT、PDF、Word等系统会将其切块、向量化并存入PostgreSQL配合pgvector扩展或SQLite数据库。当用户提问时系统会先检索出最相关的文本片段再连同问题和片段一起发给LLM让回答基于你的私有知识。其亮点是VQL一种类似SQL的查询语言让你能进行复杂的混合检索结合语义和关键词、过滤和重排序。图RAG基于知识图谱。它将文档中的实体人、地点、概念和关系提取出来构建成图结构。这特别适合回答涉及多跳推理的问题比如“公司A的CEO在哪个城市读过书”。其查询语言GQL类似Cypher能进行路径查询、中心性分析等图数据库操作。2. 智能体自动化工作流引擎TAIAgentManager和TAIAgentsNode构成了一个基于有向图的智能体工作流系统。你可以将复杂的任务分解成多个节点Node每个节点可以是一个LLM调用、一个工具执行如调用MCP工具、读写文件或者一段自定义Pascal代码。节点之间通过链接Link定义执行顺序和条件分支。 这个系统是线程安全的支持并行执行lmFanout、条件路由lmConditional。更强大的是通过TAiFileCheckpointer整个工作流的状态可以持久化到磁盘。这意味着一个运行了半小时的自动化流程如果因为程序崩溃或断电中断重启后可以从断点继续执行这对于生产环境至关重要。TAiWaitApprovalTool则实现了“人在回路”可以在关键节点暂停等待人工审核确认后再继续。3. MCP打破应用壁垒的协议MCP是一个新兴但非常重要的协议它允许不同的AI应用和工具以一种标准化的方式相互通信。MakerAI完整实现了MCP的客户端和服务器端。MCP服务器允许你将任何Delphi函数或功能暴露为一个MCP工具。例如你可以写一个GetCustomerOrders的函数然后通过MakerAI将其发布为一个MCP服务器。接下来Claude Desktop、Cursor IDE或者其他任何支持MCP的AI助手就能直接发现并调用你这个工具来查询数据库AI助手本身并不需要知道你的数据库结构。MCP客户端允许你的Delphi应用去消费外部的MCP工具。比如你可以连接到一个管理文件系统的MCP服务器让你的AI应用获得操作文件的能力或者连接到一个数据库查询工具让AI能实时获取数据。3. 实战入门从零构建一个带私有知识库的智能问答应用理论说得再多不如动手试一下。我们假设要构建一个内部技术文档查询助手它能读取我们项目目录下的所有PDF和Word文档建立知识库然后以自然语言回答关于这些文档的问题。3.1 环境准备与项目配置首先从GitHub克隆仓库并安装必要的包。这一步的编译顺序很重要因为存在依赖关系。获取源码git clone https://github.com/gustavoeenriquez/MakerAi.git配置Delphi库路径打开Delphi进入Tools - Options - Language - Delphi - Library。在Library path中添加MakerAI源码的所有核心目录。我建议直接添加整个Source目录的上一级并确保包含以下子路径YourPath\MakerAi\Source\Agents YourPath\MakerAi\Source\Chat YourPath\MakerAi\Source\Core YourPath\MakerAi\Source\RAG YourPath\MakerAi\Source\MCPClient YourPath\MakerAi\Source\MCPServer YourPath\MakerAi\Source\Tools YourPath\MakerAi\Source\Utils ... (其他所有Source下的子目录)注意确保路径正确无误这是后续编译和代码提示能正常工作的基础。如果遇到“单元未找到”的错误首先检查库路径。编译并安装包打开Source/Packages/MakerAiGrp.groupproj组项目文件。按照以下顺序编译并安装右键项目选择Compile然后InstallMakerAI.dpk这是核心运行时包必须第一个安装。MakerAi.RAG.Drivers.dpk如果你计划使用PostgreSQL作为向量数据库需要这个包。如果只用SQLite可以跳过。MakerAi.UI.dpk如果你需要使用FMX视觉组件如TChatList安装这个。MakerAiDsg.dpk这是设计时包会在IDE的组件面板上添加MakerAI的页签并提供属性编辑器如DriverName的下拉列表。安装它需要关闭所有项目并以管理员身份运行Delphi仅Windows。设置API密钥环境变量为了安全不建议将API密钥硬编码在代码中。MakerAI支持从环境变量读取格式为变量名。在Windows中你可以这样设置或在系统属性中设置setx OPENAI_API_KEY sk-your-actual-key-here setx CLAUDE_API_KEY your-claude-key-here设置后需要重启Delphi IDE或命令行终端才能生效。3.2 构建SQLite向量知识库我们选择SQLite作为向量存储因为它轻量、无需额外服务适合桌面应用或小型部署。创建数据库和表MakerAI的RAG模块会帮你处理大部分事情但我们需要先初始化一个SQLite数据库文件并安装必要的扩展。你可以参考Demos\022-1-RAG_SQLite这个示例项目。核心代码如下uses uMakerAi.RAG.Vector.Drivers.SQLite, uMakerAi.RAG.Vector.Core; procedure TForm1.BuildDatabase; var VRAG: TAiVectorRAG; VConn: TAiVectorSQLiteConnection; begin // 1. 创建SQLite连接 VConn : TAiVectorSQLiteConnection.Create(nil); try VConn.Database : .\MyKnowledgeBase.db; // 指定数据库文件路径 VConn.EnableExtensions : True; // 启用向量搜索扩展 // 2. 创建RAG引擎实例并指定连接 VRAG : TAiVectorRAG.Create(nil); try VRAG.VectorConnection : VConn; // 3. 创建集合Collection类似于数据库的表 // 参数集合名嵌入模型维度例如text-embedding-3-small是1536距离度量方式 VRAG.CreateCollection(TechnicalDocs, 1536, dmCosineSimilarity); // 4. 添加文档到集合 // 这里可以遍历文件夹处理PDF、Word、TXT等 VRAG.AddDocumentToCollection(TechnicalDocs, .\docs\project_spec.pdf, // 文件路径 Project Specification v2.1, // 可选的文档标题 {“category”: “spec”, “author”: “dev_team”} // 可选的元数据JSON ); VRAG.AddDocumentToCollection(TechnicalDocs, .\docs\api_guide.docx, API Guide, ); // ... 添加更多文档 ShowMessage(知识库构建完成); finally VRAG.Free; end; finally VConn.Free; end; end;AddDocumentToCollection方法内部会自动完成一系列复杂操作文本提取调用已配置的IAiPdfTool等、分块Chunking、为每个文本块生成嵌入向量Embedding、最后将向量和元数据存入SQLite。这个过程可能会比较耗时取决于文档数量和大小建议在后台线程中进行。配置文本提取工具为了让RAG能处理PDF我们需要在应用启动时配置一个PDF工具。例如使用Mistral的OCR服务需要API密钥uses uMakerAi.Tools.Pdf.MistralOcr; procedure TForm1.FormCreate(Sender: TObject); var PdfTool: TAiPdfMistralOcrTool; begin PdfTool : TAiPdfMistralOcrTool.Create(nil); PdfTool.ApiKey : MISTRAL_API_KEY; // 将该工具注册到全局工具管理器RAG引擎会自动发现并使用它 RegisterAiPdfTool(PdfTool); end;3.3 实现问答聊天界面知识库建好后我们来创建一个简单的问答界面。这里我们使用通用的TAiChatConnection以便未来灵活切换模型。设计界面在FMX窗体上放置一个TMemo命名为MemoLog用于显示对话一个TEdit命名为EditQuestion用于输入问题一个TButton命名为BtnAsk用于发送。从MakerAi.UI组件面板拖一个TChatConnection组件到窗体上命名为AiConn。配置连接和RAG在窗体创建时或通过对象观察器进行配置。procedure TForm1.FormCreate(Sender: TObject); begin // 配置AI连接 AiConn.DriverName : OpenAI; // 或 Gemini, Ollama 等 AiConn.Model : gpt-4o-mini; // 选择一个合适的模型 AiConn.ApiKey : OPENAI_API_KEY; // 配置RAG连接复用之前创建的SQLite连接 AiConn.RAGVectorConnection : VConn; // VConn是之前创建的TAiVectorSQLiteConnection实例 AiConn.RAGCollectionName : TechnicalDocs; // 指定要查询的集合 AiConn.RAGTopK : 5; // 每次检索返回最相关的5个文本块 end;实现问答逻辑在按钮的点击事件中我们需要将用户问题、检索到的相关知识片段组合成一个“增强的提示词”发送给AI。procedure TForm1.BtnAskClick(Sender: TObject); var Question, AugmentedPrompt: string; RelevantChunks: TArrayTAiVectorSearchResult; i: Integer; begin Question : EditQuestion.Text.Trim; if Question.IsEmpty then Exit; MemoLog.Lines.Add(You: Question); EditQuestion.Text : ; BtnAsk.Enabled : False; try // 1. 检索相关知识 RelevantChunks : AiConn.SearchVector(Question, AiConn.RAGTopK); // 2. 构建增强提示词 AugmentedPrompt : 请基于以下提供的上下文信息来回答问题。 sLineBreak 如果上下文信息不足以回答问题请直接说明你不知道不要编造信息。 sLineBreak sLineBreak 【上下文】: sLineBreak; for i : 0 to High(RelevantChunks) do begin AugmentedPrompt : AugmentedPrompt Format(片段 %d: %s sLineBreak sLineBreak, [i1, RelevantChunks[i].Text]); end; AugmentedPrompt : AugmentedPrompt 【问题】: Question sLineBreak 【回答】:; // 3. 使用连接器发送请求流式 AiConn.Messages.Clear; AiConn.AddMessage(user, AugmentedPrompt); AiConn.OnChunk : procedure (const Chunk: string) begin // 在UI线程中更新显示 TThread.Synchronize(nil, procedure begin MemoLog.Lines[MemoLog.Lines.Count - 1] : MemoLog.Lines[MemoLog.Lines.Count - 1] Chunk; end); end; AiConn.OnFinished : procedure begin TThread.Synchronize(nil, procedure begin MemoLog.Lines.Add(); // 空行分隔 BtnAsk.Enabled : True; EditQuestion.SetFocus; end); end; MemoLog.Lines.Add(Assistant: ); AiConn.ExecuteAsync; // 异步执行不阻塞UI except on E: Exception do begin MemoLog.Lines.Add(Error: E.Message); BtnAsk.Enabled : True; end; end; end;这段代码实现了最基本的RAG流程提问 - 检索 - 增强提示 - AI生成。AiConn.SearchVector方法封装了向量相似度搜索的细节。在实际产品中你可能需要对检索结果进行重排序Reranking或过滤这些都可以通过更高级的VQL查询或配置AiConn的属性来实现。4. 进阶应用构建一个自动化文档处理智能体现在我们来点更刺激的利用MakerAI的智能体框架构建一个能自动处理邮箱附件、解析内容并归档的智能体工作流。这个例子将串联起多个组件。4.1 定义智能体工作流图我们设想的工作流如下监控节点定期检查某个邮箱文件夹如“待处理PDF”。PDF解析节点发现新PDF附件后调用工具提取文本和元数据如发票号、日期、金额。分类节点根据解析出的内容使用LLM判断文档类型如“发票”、“合同”、“报告”。归档节点根据分类结果将文件移动到对应的网络文件夹并更新数据库记录。通知节点处理完成后发送一封摘要邮件或Teams消息。在MakerAI中我们用TAIAgentManager来编排这个图。我们可以用代码动态构建也可以利用其设计时支持如果安装了设计时包进行可视化设计。这里演示代码方式uses uMakerAi.Agents.Core, uMakerAi.Agents.Nodes, uMakerAi.Agents.Blackboard; procedure TForm1.CreateDocumentProcessingAgent; var AgentMgr: TAIAgentManager; NodeMonitor, NodeParse, NodeClassify, NodeArchive, NodeNotify: TAIAgentNode; Link1, Link2, Link3, Link4: TAIAgentLink; begin AgentMgr : TAIAgentManager.Create(Self); AgentMgr.Name : DocProcessorAgent; AgentMgr.ThreadPoolSize : 4; // 使用4个线程并行处理任务 // 1. 监控节点自定义逻辑节点 NodeMonitor : AgentMgr.CreateNode; NodeMonitor.Name : MonitorEmail; NodeMonitor.NodeType : ntCustom; NodeMonitor.OnExecute : MonitorEmailExecute; // 需要自己实现这个事件 // 2. PDF解析节点工具调用节点 NodeParse : AgentMgr.CreateNode; NodeParse.Name : ParsePDF; NodeParse.NodeType : ntFunctionCall; // 这里需要关联一个具体的TAiFunctions组件该组件定义了ParsePDF这个函数 // 假设我们有一个TAiFunctions组件里面注册了调用Mistral OCR的工具函数 NodeParse.Functions : AiFunctions1; // 3. 分类节点LLM调用节点 NodeClassify : AgentMgr.CreateNode; NodeClassify.Name : ClassifyDoc; NodeClassify.NodeType : ntLLM; NodeClassify.ChatConnection : AiConn; // 使用之前配置的AI连接 NodeClassify.SystemPrompt : 你是一个文档分类助手。根据提供的文本内容判断它是“发票”、“合同”、“技术报告”还是“其他”。只输出这个类别单词。; // 4. 归档节点自定义逻辑节点 NodeArchive : AgentMgr.CreateNode; NodeArchive.Name : ArchiveFile; NodeArchive.NodeType : ntCustom; NodeArchive.OnExecute : ArchiveFileExecute; // 5. 通知节点自定义逻辑节点 NodeNotify : AgentMgr.CreateNode; NodeNotify.Name : SendNotification; NodeNotify.NodeType : ntCustom; NodeNotify.OnExecute : SendNotificationExecute; // 建立节点间的链接 Link1 : AgentMgr.CreateLink(NodeMonitor, NodeParse); Link1.LinkMode : lmFanout; // 监控到多个文件可以并行解析 Link2 : AgentMgr.CreateLink(NodeParse, NodeClassify); Link2.LinkMode : lmExpression; // 可以设置条件例如只对解析成功的文档进行分类 Link2.ConditionExpression : ParsePDF.Result.Success True; Link3 : AgentMgr.CreateLink(NodeClassify, NodeArchive); Link3.LinkMode : lmExpression; // 将分类结果作为参数传递给归档节点 Link3.DataBinding : ArchiveFile.DocType ClassifyDoc.Result; Link4 : AgentMgr.CreateLink(NodeArchive, NodeNotify); Link4.LinkMode : lmAll; // 等待所有分支的归档操作完成后再通知 // 启动智能体 AgentMgr.Start; end;4.2 实现节点逻辑与黑板通信智能体节点之间通过TAIBlackboard黑板共享数据。这是一个线程安全的键值存储。在每个节点的OnExecute事件中我们可以从黑板读取上游节点的输出并将自己的结果写回黑板。procedure TForm1.MonitorEmailExecute(Sender: TAIAgentNode; const Blackboard: TAIBlackboard); var NewFiles: TStringList; FilePath: string; begin // 模拟检查邮箱附件获取新文件列表 NewFiles : CheckEmailAttachments(待处理PDF); try Blackboard.WriteStringList(DiscoveredFiles, NewFiles); // 可以设置一个标志表示本节点执行成功 Blackboard.WriteBool(MonitorEmail.Success, True); finally NewFiles.Free; end; end; procedure TForm1.ParsePDFExecute(Sender: TAIAgentNode; const Blackboard: TAIBlackboard); var FileList: TStringList; FilePath, ExtractedText: string; ParseResult: TJsonObject; begin if not Blackboard.ReadStringList(DiscoveredFiles, FileList) then Exit; for FilePath in FileList do begin // 调用PDF解析工具这里简化了实际应调用注册的IAiPdfTool ExtractedText : CallPdfTool(FilePath); ParseResult : TJsonObject.Create; try ParseResult.AddPair(file_path, FilePath); ParseResult.AddPair(extracted_text, ExtractedText); ParseResult.AddPair(success, TJsonBool.Create(not ExtractedText.IsEmpty)); // 将单个文件的解析结果存入黑板键名可以包含文件标识符以防冲突 Blackboard.WriteJsonObject(Format(ParseResult.%s, [ExtractFileName(FilePath)]), ParseResult); finally ParseResult.Free; end; end; end;ClassifyDoc节点LLM类型会自动从黑板获取输入。默认情况下它会尝试查找名为Input或与节点同名的键。我们可以在链接的DataBinding属性中配置将ParsePDF的结果作为ClassifyDoc的输入。4.3 加入持久化与人工审核对于生产环境我们还需要两个关键特性持久化检查点使用TAiFileCheckpointer让工作流状态在崩溃后能恢复。Checkpointer : TAiFileCheckpointer.Create(AgentMgr); Checkpointer.StoragePath : .\AgentCheckpoints\; AgentMgr.Checkpointer : Checkpointer; AgentMgr.OnLoadState : LoadStateFromCheckpoint; // 启动时加载状态人工审核节点在关键节点如涉及大额发票或陌生合同插入一个TAiWaitApprovalTool。// 在ClassifyDoc和ArchiveFile之间插入一个审核节点 NodeApprove : AgentMgr.CreateNode; NodeApprove.Name : HumanApprove; NodeApprove.NodeType : ntFunctionCall; NodeApprove.FunctionName : WaitForApproval; // 关联到TAiWaitApprovalTool // 修改链接ClassifyDoc - HumanApprove - ArchiveFile // 当HumanApprove节点挂起时会触发AgentMgr的OnSuspend事件 AgentMgr.OnSuspend : procedure (const ThreadID: TGUID; const Node: TAIAgentNode) begin // 在这里更新UI弹出一个对话框让用户审核 // 用户点击“批准”后调用 AgentMgr.ResumeThread(ThreadID, Node.Name, {approved:true}) end;这样一个健壮的、支持断点续传和人工干预的自动化文档处理流程就搭建完成了。你可以通过AgentMgr.VisualizeToFile(workflow.dot)导出图形用GraphViz查看整个工作流图。5. 深度集成将内部系统暴露为AI工具最后我们看看如何利用MCP协议将你现有的Delphi业务系统如ERP、CRM的能力安全地暴露给AI使用。假设我们有一个TOrderManager类可以查询客户订单。5.1 创建MCP服务器首先定义一个工具函数。MakerAI利用RTTI运行时类型信息来自动生成JSON Schema所以我们需要用[AiFunction]等属性来装饰。uses uMakerAi.MCPServer.Core, uMakerAi.MCP.Types, uMakerAi.Attributes; type TMyBusinessTools class public // 定义一个查询客户订单的函数 [AiFunction(get_customer_orders, 获取指定客户在某个时间范围内的订单列表)] [AiParameter(customer_id, string, 客户编号)] [AiParameter(start_date, string, 开始日期格式YYYY-MM-DD)] [AiParameter(end_date, string, 结束日期格式YYYY-MM-DD, True)] // True表示可选 function GetCustomerOrders( [AiParam(customer_id)] const CustomerId: string; [AiParam(start_date)] const StartDate: string; [AiParam(end_date)] const EndDate: string ): TJsonArray; end; function TMyBusinessTools.GetCustomerOrders(const CustomerId, StartDate, EndDate: string): TJsonArray; var Orders: TOrderList; Order: TOrder; begin Result : TJsonArray.Create; // 这里是你的业务逻辑从数据库或服务中查询订单 Orders : FOrderManager.QueryOrders(CustomerId, StartDate, EndDate); try for Order in Orders do begin Result.AddElement(TJsonObject.Create .AddPair(order_id, Order.ID) .AddPair(amount, TJsonNumber.Create(Order.Amount)) .AddPair(status, Order.Status) .AddPair(date, FormatDateTime(yyyy-mm-dd, Order.Date)) ); end; finally Orders.Free; end; end;然后创建并启动MCP服务器procedure TForm1.StartMCPServer; var MCPServer: TAiMCPServer; Tools: TMyBusinessTools; begin Tools : TMyBusinessTools.Create; MCPServer : TAiMCPServer.Create(Self); MCPServer.Port : 8080; // HTTP端口 MCPServer.Transport : mtHttp; // 使用HTTP传输 // 将我们的工具类实例注册到服务器 MCPServer.RegisterToolInstance(Tools); // 如果需要认证 MCPServer.AuthRequired : True; MCPServer.ApiKeys.Add(my-secret-token-123); MCPServer.Start; ShowMessage(MCP服务器已启动在 http://localhost:8080); end;现在任何支持MCP的客户端如Claude Desktop、Cursor只要配置了正确的服务器地址和API密钥就能发现并调用get_customer_orders这个工具。AI助手可以直接在对话中说“帮我看看客户C001上周的订单情况”背后就会调用你的Delphi系统。5.2 在智能体中使用MCP工具不仅外部AI能调用你的工具你自己的MakerAI智能体也能调用外部MCP工具。比如连接一个公开的天气MCP服务。// 配置MCP客户端 MCPClient : TAiMCPClient.Create(Self); MCPClient.ServerName : WeatherService; MCPClient.TransportType : mctHttp; MCPClient.HttpServerURL : http://api.weather-mcp.example.com; MCPClient.ApiKey : weather-api-key; // 将MCP客户端注册为一个函数工具这样智能体或聊天连接就能像调用普通函数一样调用它 AiFunctions1.RegisterMCPClientAsFunctions(MCPClient);之后在你的智能体节点或聊天会话中就可以直接让模型去调用get_weather假设天气服务提供了这个工具了。这种架构极大地扩展了AI应用的能力边界使其能够与几乎任何系统交互。6. 性能调优、问题排查与社区资源在实际使用中你可能会遇到一些挑战。以下是我积累的一些经验和常见问题的解决方法。6.1 性能调优要点嵌入模型选择RAG的性能和成本很大程度上取决于嵌入模型。对于英文文本text-embedding-3-small在精度和速度、成本间取得了很好的平衡。对于中文可以考虑OpenAI的同类模型或专门优化的本地模型通过Ollama部署。在TAiEmbeddingsConnection中配置。分块策略文档分块大小和重叠度对检索质量影响巨大。默认设置可能不适用于所有场景。对于技术文档较小的块256-512字符和较大的重叠50-100字符可能效果更好。你可以在调用AddDocumentToCollection前通过VRAG.ChunkSize和VRAG.ChunkOverlap属性进行调整。智能体并发控制TAIAgentManager的ThreadPoolSize不要设置得过大通常与CPU核心数相当即可。过多的并发线程会导致资源争抢反而降低性能。对于IO密集型节点如网络请求、文件读写可以考虑使用异步操作而非阻塞线程。流式响应与UI更新在FMX或VCL中处理流式响应时务必使用TThread.Synchronize或TThread.Queue来更新UI组件否则会导致界面卡死或崩溃。对于高频更新的场景如逐字输出可以考虑使用定时器批量更新而不是每个字符都同步一次。6.2 常见问题排查“Driver not found” 错误确保已正确编译并安装了MakerAI.dpk运行时包并且库路径包含了Source\Chat目录该目录下有各个驱动的实现单元如uMakerAi.Chat.OpenAI.pas。API调用返回401或403错误首先检查API密钥是否正确环境变量是否已设置且被正确读取。可以使用SysUtils.GetEnvironmentVariable(OPENAI_API_KEY)在代码中调试。其次检查你的网络是否能访问对应的API服务某些地区或网络环境可能需要配置。RAG检索结果不相关检查嵌入模型是否匹配如果你用OpenAI的嵌入模型构建了向量库后来切换到了本地Ollama的嵌入模型两者向量空间不同必然检索失败。确保构建和查询使用相同的嵌入模型配置。调整检索参数尝试增加TopK值或使用VQL进行混合搜索结合BM25关键词匹配。检查文本预处理PDF解析出的文本可能包含大量无意义的换行符、页眉页脚。考虑在入库前进行简单的文本清洗。智能体工作流卡住首先检查TAIBlackboard中的数据是否正确传递。可以通过Blackboard.SaveToFile(debug.json)将黑板状态保存下来查看。其次检查链接Link上的条件表达式ConditionExpression是否评估为False导致流程中断。使用AgentMgr.GetGraphState可以获取当前所有节点的状态进行调试。内存泄漏MakerAI组件大多设计为需要手动管理生命周期。确保在窗体销毁或适当的时候释放TAiChatConnection,TAiVectorRAG,TAIAgentManager等对象。使用FastMM等内存管理工具进行检测。6.3 如何获取帮助与进一步学习官方示例Demos目录是宝藏包含了从最小聊天程序到复杂智能体的所有功能示例。从010-MinimalChat开始逐步深入。GitHub仓库遇到问题首先查看 GitHub Issues 很可能已经有人提出并解决了。提交新Issue时请详细描述问题、复现步骤、你的环境Delphi版本、操作系统和相关的代码片段。Telegram社区有西班牙语和英语两个活跃的Telegram群组开发者Gustavo本人经常在其中回答问题。这是获取实时帮助和了解最新动态的最佳渠道。阅读源码MakerAI的代码结构清晰注释详细。当你不确定某个功能如何工作时直接阅读源码往往是最高效的学习方式尤其是uMakerAi.Core.pas和各个功能模块的接口定义文件。从我个人的使用体验来看MakerAI Suite代表了Delphi生态在AI集成领域的最高水准。它不仅仅是一个库更是一套完整的方法论和工具链将现代AI应用开发的复杂模式如Agent、RAG、MCP以非常“Delphi”的方式呈现出来——组件化、可视化、强调稳定性和生产力。它显著降低了在Delphi应用中构建复杂AI功能的门槛让开发者能够专注于业务逻辑而不是底层通信和协议细节。无论是快速原型验证还是构建需要长期运行、稳定可靠的企业级智能系统MakerAI都提供了坚实的基石。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑