Delphi/FPC AI开发实战:MakerAI Suite构建企业级智能应用
1. 项目概述MakerAI Suite一个为Delphi/FPC打造的完整AI应用生态如果你是一名Delphi或Free Pascal开发者最近想在自己的桌面或企业应用中集成AI能力比如让软件能理解文档、自动处理流程或者构建一个智能助手那你很可能面临一个尴尬的局面社区里能找到的库大多只是对某个AI服务商API的简单HTTP封装。你需要自己处理复杂的对话上下文、工具调用、文件上传更别提构建RAG知识库或多智能体工作流了——这些高级功能几乎都要从零开始。MakerAI Suite的出现彻底改变了这个局面。它不是一个简单的API包装器而是一个为Delphi和Free Pascal量身定制的、完整的AI应用开发生态系统。我从v2.x版本开始关注并使用它到如今的v3.3亲眼看着它从一个优秀的聊天组件成长为一个涵盖RAG、智能体、工具桥接、可视化UI的庞然大物。它的核心思想是让Pascal开发者能用自己最熟悉的语言和范式组件、事件、RTTI去构建生产级的AI应用而无需在Python生态和Delphi之间反复横跳。简单来说MakerAI让你能用拖放组件和编写Pascal代码的方式实现其他语言需要复杂框架才能完成的任务。无论是连接最新的GPT-5.2、Claude 4.6还是构建一个能检索内部知识库并自动审批的智能工作流它都提供了一站式的原生解决方案。接下来我将带你深入拆解这个套件的架构、核心功能并分享从环境搭建到实战开发的全流程经验。2. 核心架构与设计哲学为何它不止是API调用2.1 双轨制设计直接控制与统一抽象的平衡MakerAI最精妙的设计之一是它的“双轨制”访问模式。这解决了开发者面临的一个经典矛盾既要追求对特定API的完全控制力又希望业务逻辑代码能保持通用、可切换。轨道一原生提供者组件这是为需要“满血”API功能的场景准备的。例如TAiOpenChat、TAiClaudeChat等组件提供了对应服务商API的全功能、原生映射。这意味着如果OpenAI的Chat Completion接口有一个名为seed的参数那么TAiOpenChat组件就一定会有一个对应的Seed属性。你可以精细控制每一次调用的温度、top_p、最大token数等所有参数并直接获取API返回的原始数据结构。当你需要利用某个提供者的独有特性比如OpenAI的JSON模式强制输出或Claude的XML工具调用时就应该使用这些原生组件。轨道二统一连接器这是大多数应用场景的推荐入口TAiChatConnection。它是一个通用的、提供者无关的接口。你的业务代码只与TAiChatConnection交互而具体背后是OpenAI、Gemini还是Ollama仅仅通过设置DriverName和Model属性来决定。这种抽象带来了巨大的灵活性环境隔离API密钥可以通过ENV_VAR语法从环境变量读取避免将敏感信息硬编码在源码或配置文件中。动态切换你可以根据用户订阅、成本或模型特性在运行时动态切换AI服务商而无需重写任何对话逻辑。降级容灾当主要服务商出现故障时可以快速回退到备用服务商。在实际项目中我通常采用混合策略核心业务流使用TAiChatConnection以保证可移植性而在某些对特定模型行为有强依赖的模块例如依赖Claude的长时间推理能力则直接使用对应的原生组件。2.2 能力系统声明式需求与自动桥接v3.3引入的TAiCapabilities系统是框架智能化程度的一个飞跃。传统上你需要手动检查模型是否支持某功能比如视觉识别如果不支持就得自己写代码调用外部工具如OCR服务来“补全”。这个过程繁琐且容易出错。TAiCapabilities将这个过程自动化、声明化了。它包含两个核心集合ModelCaps描述一个模型原生支持的能力例如[cap_Text, cap_Image, cap_Reasoning]。SessionCaps描述当前会话需要的能力比如用户上传了一张图片并要求描述那么会话就需要cap_Image能力。框架会自动进行“缺口分析”。当SessionCaps超出了ModelCaps的范围MakerAI不会报错而是自动激活相应的“桥接工具”。例如你向一个不支持图片理解的文本模型如某些Ollama模型发送图片框架会检测到cap_Image缺口自动调用配置好的IAiVisionTool比如连接到一个支持视觉的模型来处理图片将结果转换为文本描述后再发送给主模型。这一切对开发者是透明的你只需要声明“我需要什么”而不用关心“它怎么实现”。此外ThinkingLevel属性tlLow,tlMedium,tlHigh提供了一个跨提供者的统一推理深度控制接口。对于支持“扩展思考”的模型如DeepSeek-Reasoner、Claude 3.7 Sonnet设置更高的ThinkingLevel会触发模型更长时间的链式推理对于不支持的模型该属性则被忽略。这简化了为不同模型优化提示词的复杂度。3. 核心模块深度解析与实战要点3.1 RAG引擎从向量检索到知识图谱检索增强生成是让AI应用“拥有”私有知识的关键。MakerAI提供了两套互补的RAG引擎远超简单的向量搜索。向量RAG语义搜索的工业级实现其核心是基于TAiVectorRAGConnection组件的向量数据库。它支持多种后端PostgreSQL/pgvector适用于生产环境支持大规模的向量索引和复杂的联表查询。SQLite轻量级选择适合桌面应用或原型开发无需单独部署数据库服务。内存模式用于单元测试或极小数据量的瞬时检索。它的强大之处在于混合搜索策略。单纯的向量相似度搜索语义搜索有时会错过关键关键词而单纯的关键词匹配BM25又无法理解语义。MakerAI的向量RAG引擎可以同时执行两种搜索并通过RRF倒数排名融合或加权分数融合算法将两者的结果智能合并。这大大提高了检索的召回率和准确率。VQL像查询数据库一样检索知识这是MakerAI的一大亮点。你不再需要拼接复杂的函数调用而是使用一种类似SQL的声明式语言——VQLVector Query Language。var VQL: string; Results: TArrayTAiVectorSearchResult; begin VQL : MATCH documents SEARCH “项目进度延迟” USING HYBRID WEIGHTS(semantic: 0.7, lexical: 0.3) FUSION RRF WHERE department “研发部” AND date “2024-01-01” RERANK “根本原因分析” WITH REGENERATE LIMIT 5; Results : VectorRAGConn.Query(VQL); end;这段VQL语句的意思是在documents集合中搜索“项目进度延迟”使用混合搜索语义权重0.7关键词权重0.3结果用RRF算法融合。同时筛选department为“研发部”且日期在2024年之后的文档。然后用“根本原因分析”这个查询对初步结果进行神经重排序以提升Top结果的相关性。最后返回5条最相关的结果。WITH REGENERATE选项允许重排序模型改写或扩充结果片段使其更贴合查询意图。这种表达方式极其高效和直观。图RAG挖掘知识背后的关联如果说向量RAG找到了相关的“点”那么图RAG则揭示了这些“点”之间的“线”。它将知识存储为节点实体和边关系组成的图结构每个节点和边都可以有嵌入向量和属性。例如将公司文档提取后可以形成(人员)-[属于]-(部门)、(项目)-[依赖]-(技术)等关系。图RAG的强大查询语言GQLGraph Query Language允许你进行图遍历查询MATCH (p:Person)-[r:WORKS_ON]-(proj:Project) WHERE proj.status “高风险” DEPTH 2 RETURN p.name, proj.name, r.role这条查询会找出所有参与“高风险”项目的人员并向外探索两层关系比如这些人还参与了哪些其他项目。这对于根因分析、影响面评估、知识发现等场景非常有用。新的uMakerAi.RAG.Graph.Documents.pas单元提供了完整的文档到知识图谱的流水线管理摄取、分块、嵌入、链接使得构建图RAG应用变得更加系统化。实操心得RAG的“分块”艺术RAG的效果很大程度上取决于文档分块Chunking策略。MakerAI提供了基础的分块器但对于复杂文档如混合了文本、表格、代码的PDF默认策略可能不够。我的经验是按语义分块优先使用基于句子或段落边界的语义分块而不是固定大小的滑动窗口这能保证上下文的完整性。重叠区域设置一定的重叠token数如100-200避免答案恰好被切分在两个块之间。元数据丰富化在分块时尽可能为每个块添加丰富的元数据如所属章节、页码、文档类型、重要性标签等。这些元数据可以在VQL的WHERE子句中用于强力过滤极大提升检索精度。对于图RAG分块策略更侧重于“实体提取”和“关系定义”。你需要设计好从文本到节点/边的映射规则这可能需要对领域有更深的理解。3.2 智能体框架构建可持久化的自动化工作流MakerAI的智能体系统是基于有向图的这比线性的链式调用强大得多。核心组件是TAIAgentManager它负责执行一个由TAIAgentsNode节点和连接线构成的图。节点与黑板每个TAIAgentsNode代表一个执行单元它可以是一个LLM调用、一个工具调用如计算器、数据库查询或者一段自定义的Pascal代码。节点之间通过链接传递数据。TAIBlackboard是一个线程安全的键值存储作为所有节点的共享内存。节点可以从黑板读取输入并将输出写回黑板。这种设计使得节点之间松耦合易于复用和组合。链接模式与执行控制链接决定了工作流的走向lmFanout广播。一个节点的输出会同时触发所有下游节点并行执行。lmConditional条件路由。根据上游节点的输出值或某个条件决定下一步执行哪个分支。lmExpression表达式绑定。允许使用简单的表达式语言将上游节点的输出值动态赋值给下游节点的输入参数。lmManual手动触发。用于需要人工干预的步骤。持久化执行与人工介入这是v3.3的两个重磅特性对于生产环境至关重要。TAiFileCheckpointer智能体工作流可能很长如果在执行中途程序崩溃或服务器重启传统方式只能从头开始。检查点机制会将整个图的状态每个节点的完成状态、黑板上的数据序列化到磁盘。恢复时TAIAgentManager可以从检查点文件加载并自动从中断的节点继续执行确保了长时间工作流的可靠性。TAiWaitApprovalTool与OnSuspend事件并非所有决策都应该交给AI。你可以插入一个“等待审批”节点。当工作流执行到此节点时它会触发OnSuspend事件并将自身线程ID、节点名和当前上下文通常从黑板获取暴露给你的UI层。你的应用程序可以弹出一个对话框让用户审核。用户做出“批准”或“拒绝”的决定后调用ResumeThread方法并传入决策结果工作流便会继续执行。这实现了真正的“人在回路”控制。3.3 MCP集成与外部AI工具生态无缝对接模型上下文协议是一个新兴但非常重要的标准它允许AI应用如Claude Desktop、Cursor安全地调用外部工具如文件系统、数据库。MakerAI完整实现了MCP的客户端和服务器端。作为MCP服务器将你的Delphi应用能力暴露给AI通过TAiMCPServer组件你可以轻松地将任何Delphi函数注册为MCP工具。例如你可以暴露一个“查询本月销售数据”的工具。当用户在Claude Desktop中与你配置的MCP服务器连接后他就可以直接对Claude说“帮我查一下本月的销售数据”Claude会自动调用你这个工具并返回结果。MakerAI支持HTTP、SSE和StdIO多种传输协议并且提供了TAiFunctions到MCP工具的自动桥接这意味着你现有的基于TAiFunctions的工具链几乎可以零成本转换为MCP服务。作为MCP客户端在你的应用中使用外部AI工具反过来你也可以在你的Delphi应用中集成外部MCP服务器。例如连接一个公开的天气数据MCP服务器你的智能体就可以获得实时天气信息。TAiMCPClient组件处理了所有JSON-RPC通信的细节你只需要提供服务器地址和工具列表就可以像调用本地函数一样调用远程工具。注意事项MCP并发调用的坑在v3.3之前MCP客户端在处理单个回合内多个工具调用时存在一个隐蔽的并发Bug。如果模型一次返回两个需要调用同一个MCP服务器的工具框架会尝试并行执行它们。但由于一个MCP服务器实例通常共享一个进程/管道并行调用会导致JSON-RPC消息交错引发通信混乱和随机失败。v3.3通过在TMCPClientCustom中引入FCallLock: TCriticalSection修复了这个问题确保对同一服务器的调用是串行的而对不同服务器的调用仍可并行。这提醒我们在集成异步工具调用时必须仔细考虑资源竞争和线程安全。3.4 ChatTools弥补模型能力短板的瑞士军刀ChatTools是一组标准化接口将各种确定性能力OCR、语音、图像生成、文件操作等封装成AI可以调用的“工具”。其核心价值在于自动桥接。例如你的会话需要cap_Pdf能力来读取一份PDF合同但你当前使用的模型比如GPT-3.5并不原生支持PDF解析。在传统方式下你需要手动编写代码先调用一个OCR服务解析PDF再将文本传给GPT。而使用MakerAI你只需要配置一个IAiPdfTool的实现例如使用Mistral的OCR API。在会话中声明需要cap_Pdf能力。当用户上传PDF时框架会自动检测到模型能力缺口并调用你配置的IAiPdfTool进行转换整个过程对开发者透明。这种模式极大地降低了集成复杂度。目前支持的Tool包括PDF解析、视觉识别、语音合成与识别、网页搜索、图像/视频生成、Shell命令执行、文件编辑甚至鼠标键盘控制Computer Use。你可以混合使用多个工具让一个“能力平平”的模型通过工具链的辅助完成复杂的多模态任务。4. 从零开始安装、配置与第一个AI对话应用4.1 环境准备与源码获取首先你需要一个支持Delphi 10.4 Sydney或更高版本推荐11 Alexandria以上的IDE或者使用Free Pascal 3.2.0配合Lazarus。MakerAI对Free Pascal的支持非常完善所有核心功能在fpc分支上均可使用。通过Git克隆项目是第一步git clone https://github.com/gustavoeenriquez/MakerAi.git我建议创建一个独立的目录来存放这个库例如D:\Dev\Libs\MakerAI以便管理。4.2 包编译顺序与库路径设置这是新手最容易出错的地方。MakerAI由多个运行时包和一个设计时包组成必须按顺序编译。打开Delphi选择File - Open Project导航到MakerAi\Source\Packages\目录。按顺序打开并编译安装MakerAI.dpk这是核心运行时包包含绝大多数单元。编译并安装它。MakerAi.RAG.Drivers.dpkRAG引擎的数据库驱动包主要是PostgreSQL支持。如果你只用SQLite或内存模式可以不安装此包但建议编译以备不时之需。MakerAi.UI.dpkFMX可视化聊天组件包。如果你计划使用TChatList,TChatBubble等UI控件需要安装它。MakerAiDsg.dpk设计时包。这个包提供了Object Inspector中的属性编辑器如DriverName下拉列表、组件图标等。注意此包依赖VCL和DesignIDE通常只在Windows的Delphi IDE中安装。在Linux下或纯FPC/Lazarus环境中无需此包。更简单的方法是直接打开MakerAi\Source\Packages\MakerAiGrp.groupproj组项目文件IDE会加载所有包你可以一次性编译整个组。库路径设置至关重要否则IDE找不到单元文件。在Delphi中进入Tools - Options - Language - Delphi Options - Library在Library path中添加以下路径请根据你的实际克隆目录调整D:\Dev\Libs\MakerAi\Source\Agents D:\Dev\Libs\MakerAi\Source\Chat D:\Dev\Libs\MakerAi\Source\ChatUI D:\Dev\Libs\MakerAi\Source\Core D:\Dev\Libs\MakerAi\Source\Design D:\Dev\Libs\MakerAi\Source\MCPClient D:\Dev\Libs\MakerAi\Source\MCPServer D:\Dev\Libs\MakerAi\Source\Packages D:\Dev\Libs\MakerAi\Source\RAG D:\Dev\Libs\MakerAi\Source\Resources D:\Dev\Libs\MakerAi\Source\Tools D:\Dev\Libs\MakerAi\Source\Utils添加后点击“OK”并重启IDE以确保生效。4.3 配置API密钥与环境变量硬编码API密钥是安全实践的大忌。MakerAI推荐使用环境变量。在Windows中你可以这样设置以OpenAI为例打开系统属性 - 高级 - 环境变量。在“用户变量”或“系统变量”中新建一个变量名称为OPENAI_API_KEY值为你的OpenAI API密钥。重启你的Delphi IDE以便它获取新的环境变量。在代码中这样引用AiConn : TAiChatConnection.Create(Self); AiConn.DriverName : OpenAI; AiConn.Model : gpt-4o; AiConn.ApiKey : OPENAI_API_KEY; // 框架会自动解析符号并读取环境变量对于其他提供商同理设置GEMINI_API_KEY、ANTHROPIC_API_KEY等环境变量。你也可以直接在属性中填写真实的密钥字符串但仅限于开发和测试。4.4 创建第一个聊天应用两种方式方式一使用可视化组件快速原型新建一个FireMonkey多设备应用程序。在工具栏的“MakerAI”页签下找到TChatList、TChatInput和TAiChatConnection组件拖放到窗体上。设置TAiChatConnection的DriverName、Model和ApiKey。在TChatInput的OnSendMessage事件中编写如下代码procedure TForm1.ChatInput1SendMessage(Sender: TObject; const AMessage: string; AAttachments: TStrings); var Response: string; begin // 将用户消息添加到聊天列表可选TChatInput可能已自动处理 ChatList1.AddMessage(AMessage, ctUser); // 使用连接器发送消息并获取流式响应 AiChatConnection1.SendChatMessageAsync( AMessage, procedure (const AContent: string; AIsFinal: Boolean) begin // 流式回调AContent是陆续到达的文本块 if AIsFinal then ChatList1.AddMessage(AContent, ctAssistant) else ChatList1.UpdateLastMessage(AContent, ctAssistant); // 更新最后一条消息通常是助理的回复 end, procedure (AError: Exception) begin ShowMessage(Error: AError.Message); end ); end;运行程序你就能得到一个具有流式响应效果的聊天界面。方式二使用代码驱动更灵活控制如果你不需要UI或者需要更精细的控制可以直接使用TAiChatConnection。procedure TForm1.Button1Click(Sender: TObject); var Chat: IAiChat; Msg: TAiChatMessage; Response: TAiChatResponse; begin Chat : AiChatConnection1.CreateChat; // 添加系统指令可选 Chat.AddMessage(ctSystem, 你是一个有帮助的助手。); // 添加用户消息 Msg : Chat.AddMessage(ctUser, 你好请介绍一下你自己。); // 可以附加文件 Msg.AddFile(path/to/image.png); // 同步调用简单但会阻塞UI Response : Chat.Execute; Memo1.Lines.Add(Response.Content); // 或者异步调用推荐不阻塞UI Chat.ExecuteAsync( procedure (AResponse: TAiChatResponse) begin TThread.Queue(nil, procedure begin Memo1.Lines.Add(AResponse.Content); end); end, procedure (AError: Exception) begin TThread.Queue(nil, procedure begin ShowMessage(Error: AError.Message); end); end ); end;5. 进阶实战与避坑指南5.1 构建一个带RAG的智能问答系统假设我们要构建一个内部技术文档问答机器人。知识库构建使用TAiVectorRAGConnection连接一个SQLite数据库。编写一个后台服务遍历所有技术文档.pdf, .docx, .md使用TAiRAGDocumentProcessor进行分块、提取文本、生成嵌入向量并存储到向量数据库中。这个过程可以定期运行以更新知识库。查询集成在聊天逻辑中当用户提出问题时先不直接发送给LLM。而是使用VQL从向量数据库中检索最相关的5个文档片段。VQL : MATCH chunks SEARCH “ UserQuestion ” LIMIT 5; RelevantChunks : VectorRAGConn.Query(VQL);构造增强提示将检索到的片段作为上下文与用户问题一起构造最终提示。ContextText : ; for Chunk in RelevantChunks do ContextText : ContextText --- 参考文档 --- sLineBreak Chunk.Text sLineBreak; FinalPrompt : 请根据以下提供的上下文信息回答用户的问题。 sLineBreak 如果上下文信息不足以回答问题请如实告知。 sLineBreak sLineBreak 【上下文】 sLineBreak ContextText sLineBreak 【用户问题】 sLineBreak UserQuestion;调用LLM并返回将FinalPrompt发送给TAiChatConnection获取答案并返回给用户。5.2 实现一个带人工审批的自动化流程利用智能体框架我们可以设计一个采购申请审批流程。定义节点Node1 (LLM)分析采购申请邮件内容提取物品、数量、预算、申请理由。Node2 (Tool)调用内部系统API查询申请人的预算余额。Node3 (Conditional)判断逻辑。如果物品为常规物品 AND 金额 阈值 AND 预算充足则链接到Node4自动批准否则链接到Node5人工审批。Node4 (Custom Code)执行自动批准调用系统接口创建采购单。Node5 (WaitApproval)挂起流程等待人工审批。触发OnSuspend事件在UI上显示待审批项。配置检查点为TAIAgentManager设置TAiFileCheckpointer。这样即使流程在Node5等待审批时服务器重启重启后也能从Node5恢复状态而不会丢失已提取的数据。人工干预当UI收到OnSuspend事件时弹出对话框展示申请详情。用户点击“批准”后调用AgentManager1.ResumeThread(SuspendedThreadID, Node5, {decision:approve})工作流将继续执行Node5之后的节点可能是发送通知的节点。5.3 常见问题与排查技巧问题1编译时提示“单元找不到”或“未声明的标识符”。排查99%的原因是库路径没有正确设置。请严格按照上文“库路径设置”部分检查所有路径是否都已添加并注意路径分隔符和大小写在Linux上很重要。确认后尝试对项目进行“Clean”然后“Build”。问题2运行时错误“Driver [OpenAI] not registered”。排查确保MakerAI运行时包已正确安装。在项目文件中检查是否包含了MakerAI在requires部分。对于控制台或简单项目可能需要手动在.dpr文件的uses部分早期添加MakerAI以初始化驱动注册。问题3流式响应不工作或者UI卡顿。排查确保异步调用和UI更新是在正确的线程中进行的。在FireMonkey中所有对可视化组件的更新都必须在主线程UI线程中进行。如上文示例所示在异步回调中使用TThread.Queue或TThread.Synchronize将更新操作派发到主线程。问题4RAG检索结果不相关。排查嵌入模型检查使用的嵌入模型是否适合你的文本领域。对于中文text-embedding-3-small或专门的多语言模型可能比纯英文模型更好。MakerAI允许你通过TAiEmbeddingsConnection配置独立的嵌入模型。分块大小分块太大超过模型上下文窗口或太小失去语义都会影响效果。尝试调整分块大小和重叠区域。混合搜索权重调整VQL中WEIGHTS(semantic: X, lexical: Y)的X和Y值。对于专业术语多的文档可以增加关键词权重lexical。重排序务必启用RERANK子句。初步检索召回追求全面重排序精排追求精准两者结合效果最佳。问题5工具调用时出现EAggregateException。排查这是v3.3修复的一个Bug但如果你遇到类似的多任务异常请检查你的工具执行代码特别是在OnExecute事件或自定义工具中是否有未处理的异常。确保所有工具调用都有完善的try...except并将错误信息通过OnError事件或返回值妥善传递而不是让异常抛到任务调度层。问题6在Free Pascal/Lazarus下某些功能不可用。排查首先确认你使用的是fpc分支的代码。其次FPC版本需3.2.0。某些高级特性如特定平台的语音识别、计算机控制可能依赖外部库或操作系统特定API在非Windows平台或FPC上可能受限。请参考fpc分支的README和Demo它们专门展示了在Lazarus下的可用功能。我个人在几个企业级项目中深度应用了MakerAI最大的体会是它极大地提升了开发效率将AI集成的复杂度从“基础设施搭建”降级为“业务逻辑组装”。它的架构设计非常“Delphi”符合Pascal开发者的思维习惯。开始使用时建议从010-MinimalChat和012-ChatAllFunctions这两个Demo入手先跑通基本流程再逐步深入研究RAG、智能体等高级模块。遇到问题时除了查阅GitHub Issues其活跃的Telegram社区有英文和西班牙文频道是获取帮助的绝佳途径。记住用好TAiCapabilities系统和统一连接器是写出整洁、可维护AI应用代码的关键。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2581605.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!