从Demo到生产:LLM Agent工程化实战与架构设计

📅 2026/8/8 13:29:27
从Demo到生产:LLM Agent工程化实战与架构设计
1. 从“玩具”到“生产力”Agent开发的现实困境与破局思路最近和几个做AI应用的朋友聊天大家不约而同地提到了一个词“玩具感”。我们基于各种开源框架吭哧吭哧地搭出了一个能对话、能联网、能调工具的AgentDemo跑起来效果惊艳但一旦想把它嵌入到真实的业务流里或者交给非技术同事去用问题就全暴露出来了。要么是回答的内容飘忽不定这次能准确调用API查天气下次就给你编一段天气预报要么是处理多轮复杂对话时前言不搭后语完全忘了用户上一分钟说了什么再或者面对一个稍微复杂点的用户请求Agent就像陷入了死循环在几个工具之间来回横跳就是给不出最终答案。这其实就是当前很多Agent项目从“技术演示”迈向“生产级应用”时遇到的核心瓶颈。我们手里握着一堆闪闪发光的组件大语言模型LLM是大脑记忆Memory是海马体工具Tool是手脚检索增强生成RAG是外部知识库模型上下文协议MCP是神经接口技能Skills是肌肉记忆。但如何把这些部件有机地组装起来形成一个稳定、可靠、可用的智能体而不是一个时不时就“死机”或“胡言乱语”的拼接怪这才是真正的挑战。今天这篇笔记我不想再重复那些框架的基础用法而是想结合我最近在几个真实项目中趟过的坑聊聊在LLM Memory Tool RAG MCP Skills这个经典架构下如何做一些“接地气”的思考和设计让Agent真正能扛事儿。你会发现很多问题的答案不在最新的论文里而在最朴素的工程实践和架构权衡中。2. LLM作为“推理引擎”选型、提示工程与稳定性驯服LLM是Agent的绝对核心它负责理解、规划、决策和生成。但把它当作一个“黑盒魔法”来用是项目失控的开始。2.1 模型选型在成本、能力与延迟之间做残酷的权衡很多人一上来就问“用GPT-4还是Claude 3” 这其实是个错误的问题。正确的问题是“我的Agent需要处理的任务类型是什么它的失败成本有多高”复杂规划与逻辑推理场景如果你的Agent需要像项目经理一样拆解复杂任务例如“帮我规划一个三天的北京旅游行程要兼顾历史、美食和购物预算有限”那么GPT-4、Claude 3 Opus这类顶级闭源模型或DeepSeek-V2、Qwen2.5-72B这类顶尖开源模型几乎是唯一选择。它们的思维链CoT能力更强规划更可靠。这里的失败成本是用户得到一个混乱或无用的计划体验直接归零。标准化工具调用与信息提取场景如果Agent的主要工作是遵循固定流程调用工具例如根据用户问题查询数据库、生成报告、发送邮件那么GPT-3.5-Turbo、Claude 3 Haiku甚至一些优秀的7B-14B开源模型如Qwen2.5-14B, Llama 3.1-8B可能就足够了。通过精细的提示工程它们能非常稳定地输出结构化的JSON来调用工具。此时失败成本是偶尔的工具调用错误可以通过重试或降级处理来弥补而成本效益却大幅提升。高并发、低延迟的轻量级交互场景对于需要实时响应的客服助手或游戏NPC延迟是关键。更小参数量的模型如Phi-3-mini, Gemma-2B或经过蒸馏的专用模型是更好的选择。你需要测试在95%的常见问题上小模型能否达到可接受的准确率。我的实操心得不要追求“一步到位”的顶级模型。采用分层模型策略。让一个轻量、快速的“路由模型”先对用户意图进行分类简单查询走小模型复杂规划走大模型工具调用走中等模型。这能极大优化综合成本与体验。我们一个内部服务Agent用Qwen2.5-7B做路由和简单响应只有约15%的复杂任务才路由到GPT-4月度成本降低了70%而终端用户几乎无感。2.2 提示工程超越“零样本”构建可预测的思维框架“请扮演一个助手…”这种提示在Demo里还行在生产环境里太脆弱了。生产级的提示是一个精密的“控制程序”。强制结构化输出这是稳定性的基石。永远要求LLM以指定格式如JSON、XML输出。这不仅是为了方便程序解析更是为了约束LLM的“胡思乱想”。// 一个工具调用指令的强制格式 { thought: 用户想查北京明天的天气我需要调用天气查询工具。, tool: get_weather, tool_input: { city: 北京, date: tomorrow } }使用Pydantic或JSON Schema在调用前就定义好输出结构许多框架如LangChain, LlamaIndex都支持能有效减少输出格式错误。提供“少样本”范例而非泛泛而谈与其说“请仔细思考”不如直接给它一个同类问题的完整思考过程示例。这比任何描述都有效。用户我想去上海出差帮我看看这周末的航班和酒店。 助理思考过程 1. 目标分解这是一个多步骤任务需要先查航班再根据航班时间查酒店。 2. 信息确认需要用户出发城市、具体日期本周末指周六出发周日回、预算偏好。 3. 工具规划先调用 flight_search再调用 hotel_search。 4. 行动先询问用户确认信息。设计“安全护栏”提示在系统提示词中明确写入负面指令比如“你绝对不能代替用户执行支付操作”、“如果用户询问的知识不在提供的资料中你必须明确告知不知道并拒绝编造”。这能预防很多越界行为。2.3 应对“幻觉”与不稳定性工程兜底方案LLM天生会“胡扯”我们必须接受这一点并设计兜底机制。重试与回退如果LLM的输出无法解析或调用的工具返回了意外错误不要直接向用户报错。设计一个重试循环例如最多3次每次重试时将错误信息作为上下文重新提示LLM。如果重试失败则回退到一个预设的安全回复如“当前服务繁忙请稍后再试”或引导用户简化问题。置信度过滤对于一些关键事实尤其是从RAG中检索到的可以让LLM对自己生成答案的置信度进行评分。如果低于阈值如70%则触发人工审核流程或直接回复“我对此不太确定建议您查阅官方文档”。输出验证与清洗在最终回复呈现给用户前用一套简单的规则如关键词过滤、敏感词检测或另一个轻量级模型对内容进行最后的安全和合规性检查。3. Memory设计短期、长期与会话如何不让Agent“失忆”Memory决定了Agent的连续感和个性化能力。一个没有记忆的Agent每一轮对话都是“初见”。3.1 短期记忆会话记忆不仅仅是保存聊天记录短期记忆通常指当前会话的上下文。最朴素的做法就是把所有历史对话都塞进上下文窗口。但这很快会遇到瓶颈上下文长度限制、成本增加、无关信息干扰。关键技巧摘要式记忆不要原封不动地存储每一轮对话。当对话轮数达到一定阈值如10轮或上下文长度接近限制时触发一个摘要动作。让LLM用一两句话总结本轮对话的核心事实、用户偏好和待办事项然后用这个摘要替换掉早期的详细历史。这样我们始终用有限的令牌数保存了对话的“精髓”。摘要时机可以在每轮对话后异步进行也可以在设计对话流程时在自然段落结束时比如用户说“好的那我们接下来定酒店吧”主动触发摘要。摘要内容应包括1) 已确认的事实如“用户张三计划5月20日-22日前往北京”2) 用户的明确偏好如“偏好高铁 over 飞机预算中等”3) 未完成的任务项如“需要查询故宫门票 availability”。3.2 长期记忆向量数据库让Agent真正“认识”用户长期记忆用于存储跨会话的、需要持久化的信息比如用户的个人资料、历史交互习惯、曾经处理过的项目详情等。存储什么不是存原始对话。而是存结构化或半结构化的“用户事实”。结构化信息直接存入传统数据库MySQL, PostgreSQL。例如{user_id: 123, preferred_city: 上海, dietary_restriction: 素食, project_history: [项目A-2023, 项目B-2024]}。非结构化信息将值得记忆的对话片段如“用户曾提到他对古典音乐特别感兴趣”通过嵌入模型Embedding转换成向量存入向量数据库如Chroma, Pinecone, Weaviate。检索时用当前对话的向量去查找相关的长期记忆。如何检索与激活在每次对话开始时或当LLM认为需要更多用户背景时例如用户说“像上次那样安排就行”自动从长期记忆中检索最相关的几条信息作为上下文插入到当前对话中。这相当于给了Agent一个关于当前用户的“个人档案速览”。3.3 记忆的更新与维护避免信息过时与冲突记忆不是只写不读的日志它需要维护。更新策略当用户明确更正信息时如“我不喜欢上海了现在更喜欢杭州”需要直接更新或覆盖长期记忆中的对应条目。对于偏好类信息可以采用“加权衰减”或“最新优先”的策略。冲突解决如果从不同来源如本次对话 vs 长期记忆检测到信息冲突例如用户之前说爱喝咖啡现在说要戒咖啡优先采用本次对话中明确陈述的信息并可以询问用户进行确认“注意到您之前提到常喝咖啡现在是想减少咖啡因摄入吗”根据确认结果更新记忆。记忆的“遗忘”为记忆设置TTL生存时间或重要性评分。一些临时性的、低重要性的记忆如“用户今天问了天气”可以在一段时间后自动清理防止记忆库膨胀和检索噪音。4. Tool与Skills的编排从“能调用”到“会调用”Tools是Agent的手臂但让Agent知道在何时、用何种顺序、传递什么参数去挥舞这些手臂是更大的挑战。4.1 工具描述的“玄学”清晰、具体、带示例工具的描述Description是LLM决定是否调用以及如何调用的唯一依据。模糊的描述必然导致错误的调用。反面教材search_web(query: str): 搜索网络。正面教材search_web(query: str): 使用搜索引擎获取最新的、公开的网络信息。适用于查询实时新闻、体育比分、名人简介、未知概念等。参数query应是一个简洁明确的关键词或短语例如“2024年巴黎奥运会开幕式时间”避免使用长句或问题形式。此工具无法访问私人或付费墙后的内容。好的描述要说明1)工具用途干什么用2)适用场景什么时候用3)输入要求参数格式和示例4)能力边界什么不能做。4.2 动态工具选择与规划解决“工具迷宫”问题当工具数量众多时LLM可能陷入选择困难或做出错误规划。工具分组与路由不要一股脑地把所有工具描述都塞给LLM。根据场景对工具进行分组。例如一个“旅行规划Agent”可以分成【交通查询组】、【住宿查询组】、【景点信息组】。在对话开始时根据用户意图先确定激活哪个工具组只将该组的工具描述提供给LLM大大降低了选择的复杂度。分步执行与人工确认对于涉及多个步骤、有潜在风险或高成本的操作如“预订机票-预订酒店-租车”不要让它一气呵成。设计工作流让Agent在完成每一步后将结果汇总给用户确认再执行下一步。这既是安全措施也让用户有掌控感。工具调用结果的后处理工具返回的往往是原始数据JSON、HTML等。LLM并不擅长直接理解这些数据。最佳实践是为重要的工具编写一个专用的“结果解析器”。这个解析器将原始数据转换成一段自然语言摘要或更结构化的信息再交给LLM进行后续处理和生成回复。这比让LLM去“阅读理解”一堆杂乱JSON要可靠得多。4.3 Skills可复用的复杂操作单元Skill可以理解为一系列Tool和逻辑判断的预编排组合。比如“预订航班”这个Skill内部可能包含了search_flights、filter_by_price、get_seat_map、create_booking等多个工具的协调调用以及一些业务逻辑如“国际航班需提前至少2小时”。Skill的设计哲学一个Skill应该对应一个完整的、用户可理解的业务目标而不是一个技术动作。它的存在让LLM可以从更高、更稳定的层面进行规划“用户要订机票我执行‘预订航班’Skill”而无需关心底层十几个工具的具体调用顺序和异常处理。Skill的封装将Skill的实现封装成一个独立的函数或类内部处理好工具调用序列、异常处理、结果合并。对LLM暴露的只是一个清晰的Skill描述和简单的输入输出接口。5. RAG的深度融合知识库不是外挂而是大脑延伸RAG解决了LLM知识陈旧和幻觉的问题但简单的“检索-拼接-生成”模式在复杂Agent场景下常常失灵。5.1 检索的时机与策略主动还是被动被动检索Reactive RAG这是最常见的方式。当用户提问时Agent将问题转换为查询向量去知识库检索相关片段然后生成答案。这适用于明确的问答。主动检索Proactive RAG / Agentic RAG在Agent执行多步骤任务的过程中自主判断何时需要检索知识。例如在规划旅游行程时当LLM打算推荐“颐和园”时它可以主动触发一次检索获取颐和园的最新开放时间、门票价格和游客评价再基于这些信息进行推荐。这需要LLM具备一定的“元认知”能力知道自己知识不足。5.2 解决“检索质量”核心痛点从嵌入到重排序检索不到或检索不准RAG就失败了。查询改写Query Rewriting用户的原始问题可能模糊、口语化。在检索前先用LLM对查询进行改写或扩展。例如用户问“苹果那个新出的东西怎么样”可以改写成“Apple 最新发布的 iPhone 15 产品评测与用户体验”。混合检索Hybrid Search不要只依赖向量检索语义相似度。结合关键词检索BM25。向量检索擅长处理“意思相似”关键词检索擅长处理“字面匹配”。两者结合如通过加权分数能显著提升召回率。许多向量数据库如Weaviate, Elasticsearch已原生支持。重排序Re-ranking初步检索可能返回几十个片段其中只有前几个是真正相关的。使用一个更小、更快的重排序模型如BGE-Reranker, Cohere Rerank对Top N的结果进行精排根据与问题的相关性重新排序将最相关的3-5个片段喂给LLM。这一步成本增加很小但效果提升巨大。元数据过滤为知识库文档添加丰富的元数据如文档类型、创建日期、部门、产品线。检索时除了语义匹配还可以用元数据进行过滤。例如“只检索2024年发布的、属于‘财务政策’类别的文档”。这能极大提升精度。5.3 让LLM“知道”它知道什么引用与置信度当Agent基于RAG生成答案时必须告诉用户信息的来源。引用溯源在最终答案中以脚注或括号的形式标明引用的文档名称或编号。例如“根据《2024年公司差旅政策V2.1》第3条规定…”。这增加了可信度也方便用户追溯。处理“无答案”情况如果检索到的知识片段都无法回答用户问题要设计LLM的回复话术如“根据我现有的知识库未能找到关于XX的确切信息。这可能是因为信息尚未更新建议您通过其他渠道核实。”绝对禁止在这种情况下让LLM自由发挥、编造答案。6. MCP的角色连接异构世界的“标准插座”模型上下文协议Model Context Protocol, MCP是近期一个非常值得关注的方向。你可以把它理解为智能体世界的“USB-C接口”标准。6.1 MCP解决了什么痛点在没有MCP之前每个工具、每个数据源都需要为不同的Agent框架LangChain, LlamaIndex, AutoGen…编写特定的适配器。一个公司内部的CRM系统如果想被多个AI应用调用集成成本很高。MCP定义了一套标准协议让任何资源数据库、API、文件系统、甚至另一个服务都可以以一个标准化的方式向AI应用或Agent暴露其可查询和可操作的能力。资源提供方只需要实现一个MCP服务器Server任何兼容MCP的客户端如Claude Desktop, Cursor IDE以及未来更多的AI应用就能立即发现并使用这些资源和工具。6.2 在Agent开发中如何利用MCP对于Agent开发者而言MCP带来了两个层面的便利快速集成外部能力如果你需要让Agent能搜索网络、查询公司数据库、读取Notion文档你不再需要去找特定的SDK或自己写API封装。你可以直接寻找或部署对应的MCP服务器如tavily-mcp用于搜索postgres-mcp用于数据库filesystem-mcp用于读文件。你的Agent框架如果支持MCP就能像插拔U盘一样动态加载这些能力。封装和暴露自身能力如果你开发了一个强大的内部Agent你也可以将它的一些功能如“生成周报”、“分析销售数据”通过MCP服务器暴露出去。这样其他AI应用比如公司的智能助手就能直接调用你这个“专家Agent”的服务实现AI能力的模块化和复用。6.3 当前实践与展望目前MCP主要由Anthropic推动在Claude Desktop和Cursor中集成得较好。在更广泛的Agent开发框架如LangChain中对MCP的完全支持还在演进中。但它的理念非常先进——解耦能力提供方和能力消费方。作为开发者我们可以开始关注两方面作为消费者在架构设计时考虑未来通过MCP来集成工具而不仅仅是硬编码API调用。作为提供者思考如何将你的Agent核心能力模块化未来或许可以打包成一个MCP服务器提供更广泛的服务。7. 构建Skill工作流从单点智能到流程自动化单一的问答或工具调用是“点”而Skill工作流是将这些“点”连成“线”解决复杂任务。7.1 工作流设计模式顺序流最直接的模式A做完做BB做完做C。适用于步骤明确、依赖清晰的任务如“数据获取 - 数据清洗 - 数据分析 - 生成报告”。条件分支流根据上一步的结果决定下一步的走向。这需要LLM或一个规则引擎来判断。例如“查询天气”后如果是“晴天”则推荐“户外活动”如果是“雨天”则推荐“室内展览”。并行与聚合流多个可以独立执行的任务同时进行最后汇总结果。例如规划旅行时同时查询“航班”、“酒店”、“景点门票”等所有结果返回后再统一生成方案。这能显著降低整体耗时。循环与迭代流用于需要反复调整或优化的任务。例如生成一个图表如果不满意可以循环执行“分析问题 - 调整参数 - 重新生成”的步骤直到满足条件或达到最大迭代次数。7.2 工作流中的状态管理与错误处理这是工作流稳定性的关键。状态持久化复杂工作流可能耗时很长几分钟甚至几小时。必须将每个步骤的输入、输出、执行状态成功、失败、进行中持久化到数据库。这样即使进程中断重启后也能从断点恢复。统一的错误处理框架为工作流定义一个标准的错误类型和恢复策略。例如工具调用超时重试3次。LLM输出格式错误尝试修复或回退到默认流程。业务逻辑错误如“库存不足”触发一个“人工审核”节点或向用户发送通知。用户介入点在关键决策点如确认订单、选择最终方案或工作流卡住时设计优雅的“中断”机制允许用户提供额外输入或做出选择然后工作流继续。7.3 编排工具的选择LangGraph vs 其他目前LangGraph因其对LangChain生态的良好集成和清晰的状态图StateGraph模型成为构建复杂Agent工作流的热门选择。它用“节点”和“边”来直观地定义工作流非常适合实现上述各种模式。当然你也可以用更通用的工作流引擎如Airflow、Prefect或甚至自己用状态机来实现。核心在于将Agent的“思考”和“行动”逻辑从杂乱的if-else代码中抽离出来变成一个可视、可管理、可监控的流程。8. 测试、评估与监控让Agent在线上稳定奔跑开发完成只是第一步让Agent在真实环境中可靠运行需要一套完整的运维体系。8.1 测试模拟用户暴露问题单元测试测试单个工具、单个Skill的功能是否正确。Mock掉LLM和外部API保证逻辑无误。集成测试测试多个组件串联起来的工作流。可以使用一个轻量级的、确定性的LLM Mock比如总是返回固定JSON来验证流程编排。端到端E2E测试这是最重要的。准备一个涵盖核心场景的测试用例库例如100个典型用户问题用真实或接近真实的LLM如GPT-3.5-Turbo在全链路环境中跑。评估指标包括任务完成率Agent是否最终给出了有效答案或完成了操作工具调用准确率调用的工具和参数是否正确人工评分随机抽取结果让人工从“有用性”、“准确性”、“流畅性”维度评分。8.2 评估量化Agent的表现除了测试时的指标线上运行也需要持续评估。业务指标如果Agent用于客服关注“问题解决率”、“转人工率”、“平均会话轮数”。如果用于销售关注“线索转化率”。成本指标密切监控Token消耗、API调用次数和费用。分析哪些场景或用户消耗了主要成本是否存在优化空间。用户体验指标通过用户反馈点赞/点踩、会话时长、退出率等间接评估体验。8.3 监控与可观测性快速发现并定位问题Agent系统是动态的随时可能因为外部API变化、模型波动或意料之外的用户输入而出错。链路追踪为每个用户会话分配唯一ID记录下完整的执行链路用户输入 - LLM思考 - 工具调用及参数/结果- 最终输出。这就像飞机的“黑匣子”当出现问题比如用户投诉回答不对时可以快速回溯定位是哪个环节出了问题。关键日志与告警记录所有LLM的输入输出可脱敏、工具调用错误、耗时过长的操作。设置告警规则例如连续出现5次工具调用失败、或LLM返回格式错误的频率超过1%。“熔断”与降级当检测到某个外部服务如某个关键API持续失败时触发“熔断”机制暂时停止调用该服务并降级到备用方案或给用户一个友好的提示防止故障扩散。Agent开发从技术炫技到工程落地是一条从“知道所有零件”到“造出一辆能跑且安全的车”的道路。它要求我们不仅理解LLM、Memory、Tool这些组件的原理更要以系统性的思维去设计它们之间的交互以产品化的思维去关注稳定性、成本和用户体验。这个过程充满挑战但每当看到一个自己打造的Agent能稳定、流畅地帮用户解决一个真实问题时那种成就感远非跑通一个Demo可比。这条路还很长但方向已经越来越清晰。