尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

大模型Agent智能体开发实战:架构设计与工具调用全解析

大模型Agent智能体开发实战:架构设计与工具调用全解析 1. 从“服范-九添菜菜”到可落地的Agent项目这个标题到底在讲什么先别被名字劝退——我最初看到“服范-九添菜菜大模型Agent智能体开发实战”这个标题时第一反应是这八成又是某个内部项目代号或者团队用昵称命名的实验项目。等你真正把标题拆开看会发现它其实是一个很典型的“大模型Agent智能体”从零到一的实战案例用一套可复用的框架把大模型从“只会聊天”变成“能干活、会调用工具、记忆上下文、自动完成任务”的智能体。我接触过不少类似的项目名字五花八门但内核高度一致都是围绕Agent的规划Planning、工具调用Tool Use、记忆管理Memory、多轮对话状态维护State这几个核心模块展开的。如果你正在学Agent开发或者准备把大模型接入自己的业务系统这个项目标题背后藏着的技术栈和踩坑经验几乎可以原样复用到你的场景里。这篇文章我不会给你讲空泛的概念而是把整个项目的拆解思路、实操过程、常见问题全部摊开来讲。内容包括Agent整体架构怎么设计、记忆该怎么管理、工具调用怎么落地、推理链路怎么调试、部署上线有哪些坑。无论你是刚接触大模型的小白还是已经写过一些Prompt但没真正做过Agent的开发者都能照着往下走。先说明一点由于原始标题只给出了项目代号和方向下文涉及的具体技术选型、参数配置、架构设计是基于一名从业者在这个场景下最常用的主流方案做的合理补充不代表唯一答案。但它能帮你少走至少一半的弯路这一点我很有把握。2. Agent智能体开发的核心拆解别把“大模型”和“Agent”混为一谈2.1 大模型是大脑Agent是完整的人很多人刚接触这个概念时会误以为“接入了大模型API就等于做了一个Agent”。这是个非常常见的误区。打个比方大模型本身像一个知识渊博但坐在办公室里不出门的专家你问他问题他能回答但他不会主动去查资料、不会翻文件柜、不会打电话确认信息而Agent则是给这位专家配了秘书、配了电脑、配了行动权限让他能真正“把事情办了”。具体到技术层面一个完整的Agent至少要具备以下能力任务拆解把用户的一句话目标自动分解成多个可执行的子任务。工具选择与调用知道在什么场景下调用什么外部工具比如搜索、数据库查询、API请求。记忆管理能记住用户说过的话、之前的结果、长期偏好而不是每次对话都“失忆”。结果校验对工具返回的结果做判断如果不符合预期能重新规划或换一种方式再试。多轮上下文维护在复杂对话中保持话题连贯不被中间插入的新信息带偏。从这个角度来看“服范-九添菜菜”这类项目本质上是在做这样一个“人形化”的封装。大模型只负责其中的“思考”部分其他能力需要靠开发者在工程层面补齐。2.2 为什么说Agent是当前大模型落地的最佳形态之一现在市面上的大模型很多——GPT系列、Claude、文心一言、通义千问、Qwen系列、DeepSeek、Kimi等等各有各的优势。但不管选哪一个如果你只是把API接进来做一个问答机器人那跟搜索引擎的差别并不大商业价值也很有限。Agent的价值就在于它把大模型的“语言理解能力”和外部系统的“执行能力”打通了。拿一个真实的例子来说。假设用户说“帮我查一下最近三天广州到北京的机票如果是周五下午的航班我就订一张预算在800以内。”如果你只调用大模型它只能给你一段“建议你上携程查看”的敷衍回答。但如果你做了一个Agent它可以调用航班查询工具获取近三天广州到北京的航班列表筛选出周五下午出发的航班比较价格筛出800以内的选项调用预订接口完成下单最后把订单信息用自然语言反馈给用户。整个过程涉及多个工具调用、条件判断、数据筛选这就是Agent相对普通问答的质的区别。这类能力恰好是企业数字化、自动化、客服智能化等场景最需要的也是为什么Agent开发的热度在持续上升。3. Agent智能体的整体架构设计3.1 一套通用的Agent拓扑分层的思路我在实际项目中常用的Agent架构可以采用经典的四层结构。这套结构不依赖某个特定框架你用LangChain、MetaGPT、AutoGen、LlamaIndex或者完全自研都能套用。第一层用户交互层Interface Layer这一层负责接收用户输入可以是命令行、网页对话框、IM机器人接入或者企业微信/钉钉的Webhook。它的核心任务是把用户的原始文本和必要的元数据如用户ID、会话ID、当前页面上下文传给下一层。对于“九添菜菜”这类偏实战的项目前期用Streamlit或FastAPI搭一个简单的Web聊天界面就够了没必要一上来就做多端适配。第二层Agent核心引擎Agent Core这是整个系统的大脑。它负责维护对话状态、调用大模型进行推理、决定下一步动作。在这一层里最关键的组件是一个“决策循环”——先看当前任务完成没有如果没完成就判断下一步该调用工具还是该换一种回答策略。这个循环可以自己用While循环实现也可以用现成框架的AgentExecutor。第三层工具层Tool Layer这一层是Agent的“手脚”。每一个工具本质上就是一个函数有明确的输入输出定义。比如“查询天气”、“计算运费”、“检索知识库”、“发送邮件”等等。在设计上我会给每个工具加上清晰的描述和参数Schema因为这直接决定了大模型能不能正确理解这个工具是做啥的、该传什么参数。第四层记忆与数据层Memory Data Layer这一层负责持久化存储对话历史、用户偏好、任务执行记录等。对于简单的项目直接用SQLite或JSON文件就能搞定对于生产级项目需要引入向量数据库如Milvus、FAISS、pgvector、Chroma来做长期记忆的相似度检索。3.2 单Agent和多Agent怎么选“服范-九添菜菜”这个项目名里虽然只有一个Agent的指向但实际开发中你很快就会面临一个问题到底做一个全能Agent还是拆成多个专业Agent协作我的建议是新手期和大部分中小型项目优先做单Agent方案。原因很实在单Agent的调试链路短出问题好定位你只需要盯一个决策循环。多Agent协作需要处理Agent之间的通信协议、任务分派、结果合并、异常传导复杂度呈指数级上升。大模型的推理成本随上下文长度增长多Agent之间反复传递完整对话历史浪费token。什么时候才需要考虑多Agent比如你的业务流程明显分为几个专业领域每个领域需要不同的Prompt、不同的工具集而且这些步骤是天然串行的。这时候可以按“主管Agent 专家Agent”的模式拆主管负责拆任务专家负责干具体活。但即便如此我也建议先用单Agent跑通整个流程再考虑拆。3.3 框架选型LangChain、MetaGPT、自研如何取舍框架选型是所有Agent项目的第一个决策点这个决策会直接影响后面所有代码的写法。我整理了一个对比表供你参考框架优势劣势适合场景LangChain生态丰富、教程多、社区活跃内置大量工具集成抽象层级多Debug不直观版本更新快API变动大快速验证想法、做标准化AgentMetaGPT多Agent协作设计成熟SOP化流程做得精细偏重软件公司模拟场景定制化成本高偏重自动化软件开发、流程型多AgentAutoGen微软出品多Agent对话调度灵活概念较重上手曲线较陡研究性质的项目、需要复杂Agent协作自研基于OpenAI Function Calling/ReAct完全可控逻辑透明依赖少需要自己处理Prompt模板、执行循环、异常处理生产环境、需要深度定制、团队有能力维护就我个人的经验如果你做的是偏业务落地的项目自研一个轻量级Agent引擎往往是长期最优解。原理无非是把ReActReasoning Acting模式的循环自己实现一遍核心代码量并不大但可控性和可调试性比套框架好得多。框架更多是用来学习、参考、做Prototype的。4. 核心细节解析与实操要点4.1 提示词工程Agent的“岗位说明书”很多Agent项目跑起来效果差80%的原因出在Prompt写得不到位。注意这里说的Prompt不是简单的一句话而是整套“系统提示词System Prompt”。在“九添菜菜”这个项目里我建议按照以下结构来组织System Prompt角色定义明确Agent的身份以及它的能力和边界。写得越具体越好不要让模型自由发挥。任务目标说明这个Agent总体要达成什么目标以及面对用户请求时的优先处理顺序。工具使用规范告诉模型你有哪几个工具、分别在什么情况下使用、参数怎么填。最好给出正反示例。输出格式要求明确回答的语言风格、是否要附带思考过程、格式是纯文本还是JSON。兜底策略告诉模型当它不确定或者工具调用失败时该怎么回应不要胡编乱造。举一个具体示例你是一个擅长电商订单处理的智能助理。 你的任务是帮助用户查询订单状态、发起退款申请、修改收货地址。 你可以使用以下工具 1. query_order(order_id) - 查询订单基本信息 2. apply_refund(order_id, reason) - 发起退款 3. update_address(order_id, new_address) - 修改收货地址 使用规则 - 查询订单前必须先向用户确认订单号。 - 退款必须给出理由不能帮用户编造理由。 - 如果工具调用失败如实告知用户错误原因不要假装成功。 - 回答保持简洁使用中文。这段Prompt看起来简单但效果远远好过只写一句话“你是电商客服助手”。因为模型需要非常明确的约束才能稳定输出。4.2 工具调用的落地实现让大模型学会“用手”工具调用是Agent区别于普通聊天机器人的关键能力。目前主流有三种实现方式方式一Function Calling推荐OpenAI、Qwen等模型原生支持function calling模型会根据工具定义自动输出一个结构化的调用请求开发者只需解析并执行。这是目前最稳定的方案因为模型经过了专门训练输出规范不容易乱。代码逻辑大致长这样tools [ { type: function, function: { name: query_order, description: 查询电商订单基本信息, parameters: { type: object, properties: { order_id: {type: string, description: 订单号} }, required: [order_id] } } } ] # 调用大模型时传入 tools模型返回 tool_calls response client.chat.completions.create( modelqwen-plus, messagesmessages, toolstools, tool_choiceauto, )方式二ReAct模式适合自研让模型在文本输出中“思考”Thought、“行动”Action、“观察”Observation循环每轮输出一个JSON或固定格式的动作指令开发者在代码里解析这些指令并执行。这种方式灵活但要求Prompt写得非常严谨否则模型会输出一堆废话。方式三JSON Mode 自定义协议要求模型输出一个包含“next_action”和“params”字段的JSON开发者判断这个JSON并对Dashboard不同字段做处理。适合对输出格式有强控制需求的场景。我踩过一次坑在最早期做Agent时我让模型直接输出“调用查询订单工具”然后靠正则匹配从中抓出订单号结果模型换了多种句式表达正则写得跟“开盲盒”似的崩溃率奇高。后来改成Function Calling整个调用链路才稳定下来。4.3 记忆管理为什么你的Agent总是“聊着聊着就忘记”记忆管理是Agent开发中一个很容易被忽视、但直接决定用户体感好坏的模块。Agent的记忆可以分为三种短期记忆指当前会话内的对话上下文。一般直接通过messages数组传入大模型注意长度为模型上下文窗口限制超出后需要做裁剪或摘要。长期记忆跨会话的、关于用户偏好和历史事实的信息。例如用户上次说过“我不吃辣”下次对话时Agent应该还记得。实现方式是把这些信息以文本或结构化数据形式存入数据库在对话开始时检索并注入Prompt。向量记忆用于存“难以用结构化字段表达的语义信息”。比如用户对某个问题态度的变化、项目里不同文档之间的关联。做法是切块后用Embedding模型向量化存进向量数据库每次对话前根据用户问题做相似度检索。在实际开发中我用过一个很实用的策略双轨记忆。一边存结构化字段用户ID、偏好标签、订阅信息一边存向量化记录对话摘要、重要事实。每次新会话开始时先把结构化字段直接放入System Prompt再用向量检索把相关的历史对话摘要作为参考信息注入。4.4 多轮对话状态维护别让上下文“越聊越乱”做过客服类Agent的朋友一定遇到过这种情况用户说“帮我查一下上个订单”——如果Agent不记得“上个订单”指的是哪一个对话就会卡死。这背后就是对话状态管理的问题。我习惯的做法是建立一个“会话状态机”维护以下状态字段current_task当前正在执行的任务目标confirmed_entities用户已确认的关键信息订单号、时间、地点pending_question当前需要用户补充的信息tool_results最近一次工具调用的结果在每一轮Agent处理逻辑中先读取状态机更新状态再生成回复。具体代码可以用一个简单的Python类来维护class SessionState: def __init__(self, session_id): self.session_id session_id self.current_task self.confirmed_entities {} self.pending_question self.tool_results [] def update(self, **kwargs): self.__dict__.update(kwargs)这样写有一个好处你随时可以把状态机序列化成JSON记录到日志里出问题后重放一遍就能看到整个对话的“心路历程”排查效率提升很多。5. 实操过程与核心环节实现5.1 环境准备与模型选择做Agent开发之前先把环境搭好。我推荐以下组合既能跑通流程成本也可控编程语言Python 3.10以上Python的类型提示对工具Schema校验很有帮助。开发框架FastAPI Uvicorn做后端接口Streamlit做前端演示页面。大模型API前期用国内可稳定调用的API如通义千问的qwen-plus或DashScope、DeepSeek的API、智谱GLM成本低、速度快。有条件的再用开源模型本地部署比如Qwen2.5-7B-Instruct用Ollama或vLLM跑。工具库requestsHTTP调用、pydantic参数校验、openai SDK兼容几乎所有OpenAI协议的接口。数据库SQLite起步后期换PostgreSQL或向量数据库。模型选择上我的经验是Agent推理能力比单轮回答质量更重要。一个7B或14B的模型单轮回答可能听上去也可以但到了复杂Agent任务中就容易“糊涂”忘记调用工具、传错参数、输出格式不稳定。如果你的Agent要做复杂推理预算允许的情况下尽量选能力更强的模型。5.2 一步一步搭出一个最小可用Agent下面这个例子以“九添菜菜”风格项目为背景我们做一个“帮用户查天气并推荐穿搭”的Agent。它会调用一个天气API和一个简单的穿搭推荐工具。第一步定义工具函数def get_weather(city: str, date: str) - dict: # 这里是模拟数据实际项目对接真实天气API data { city: city, date: date, temperature: random.randint(5, 30), condition: random.choice([晴, 多云, 小雨, 雪]), } return data def recommend_outfit(temperature: int, condition: str) - str: if temperature 0: return 建议穿羽绒服、厚毛衣、围巾和手套。 elif temperature 10: return 建议穿大衣、针织衫。 elif temperature 20: return 建议穿外套、长袖T恤。 else: return 建议穿短袖或薄衬衫。第二步定义工具Schematools [ { type: function, function: { name: get_weather, description: 获取指定城市在指定日期的天气情况, parameters: { type: object, properties: { city: {type: string, description: 城市名如北京、上海}, date: {type: string, description: 日期格式YYYY-MM-DD} }, required: [city, date] } } }, { type: function, function: { name: recommend_outfit, description: 根据温度和天气状况推荐穿搭, parameters: { type: object, properties: { temperature: {type: integer, description: 温度摄氏度}, condition: {type: string, description: 天气状况} }, required: [temperature, condition] } } } ]第三步实现Agent核心循环def run_agent(user_input: str, messages: list): # 1. 把用户输入追加到消息列表 messages.append({role: user, content: user_input}) # 2. 调用大模型 response client.chat.completions.create( modelMODEL_NAME, messagesmessages, toolstools, tool_choiceauto, ) # 3. 解析返回结果 assistant_message response.choices[0].message messages.append(assistant_message) # 4. 处理工具调用 if assistant_message.tool_calls: for tool_call in assistant_message.tool_calls: func_name tool_call.function.name args json.loads(tool_call.function.arguments) if func_name get_weather: result get_weather(**args) elif func_name recommend_outfit: result recommend_outfit(**args) # 把工具结果放回消息列表 messages.append({ role: tool, tool_call_id: tool_call.id, content: json.dumps(result, ensure_asciiFalse), }) # 5. 再调用一次模型让它根据工具结果组织最终回答 final_response client.chat.completions.create( modelMODEL_NAME, messagesmessages, toolstools, tool_choiceauto, ) return final_response.choices[0].message.content else: # 模型直接回答了没有调用工具 return assistant_message.content这段代码虽然粗糙却是绝大多数Agent框架内部逻辑的“最小共核”。你只要理解了这个循环——模型先思考要不要调工具、调完工具再把结果喂回去、最终组织回答——那么无论用什么框架底层逻辑都是相通的。5.3 参数配置温度、TopP、最大Token怎么调Agent开发里有几个关键参数直接影响执行稳定性。我总结了一套经验值参数建议值说明temperature0.2以下Agent场景追求确定性不要让模型太“发散”否则工具调用格式容易乱top_p0.9~0.95与temperature配合使用一般不用调太低max_tokens1024~2048太短会导致推理或输出被截断太长会增加延迟和费用presence_penalty0Agent场景默认0避免模型为了避免重复而更换措辞frequency_penalty0同上尤其是temperature——很多新手习惯保留默认值0.7或1.0结果模型在调用工具时经常“自由发挥”生成一些不存在的参数名。把temperature调到0.1~0.2之后稳定性能上一个台阶。这是我实测下来最立竿见影的一个配置。5.4 Agent执行链路加日志把“黑盒”变成“白盒”Debug Agent最痛苦的一件事模型到底为什么这么回复为了排查这个问题我会给整个执行链路加上结构化的日志记录记录每一步的输入输出。import logging logger logging.getLogger(agent) logger.setLevel(logging.INFO) def log_step(step_name, data): logger.info(json.dumps({ step: step_name, data: data }, ensure_asciiFalse))在每个关键节点调用log_step比如用户输入了什么模型第一次返回了什么是直接回答还是工具调用工具调用的参数是什么工具返回什么结果模型最终回答是什么。有了这些日志你就能像“回看监控录像”一样分析Agent的每次行为。尤其是当用户反馈“它怎么突然乱说”的时候直接拉日志基本能定位到是哪一步出了问题。6. 常见问题与排查技巧实录6.1 模型一直不调用工具怎么办这是新手最常遇到的现象你明明把工具定义传给了模型但它就是不用只给文字回答。排查顺序如下检查工具描述是否足够清晰。大模型靠描述判断何时调用工具。如果描述写得太泛比如“获取天气信息”模型会犹豫改成“获取指定城市指定日期的天气情况。当用户询问天气时必须使用该工具”效果会好很多。检查模型是否支持Function Calling。不是所有模型都支持有些开源模型需要你在Prompt里手把手教它输出JSON格式的工具调用。检查参数Schema是否合法。有些模型对类型定义很敏感属性名拼错、类型写错都会导致模型困惑。降低temperature。温度高了模型容易“想太多”宁可少输出也不调工具。我最常用的一招在System Prompt里直接写一句“当用户的问题可以被工具解决时你必须调用工具不要自行回答”。对大多数模型都有奇效。6.2 工具返回结果后模型还是给出错误答案这种情况比“不调用工具”更隐蔽。模型确实调了工具但把工具结果解读错了。常见原因工具返回的数据结构太复杂模型没理解字段含义。解决方法在工具返回结果里增加一个人类可读的summary字段比如“天气晴朗温度25度”模型直接基于这段话来组织回答。模型在多轮对话中遗忘了先前信息。导致这个的根源往往是上下文被截断。解决方法对关键信息做摘要而不是原样全量保留。模型编造了工具没有返回的数据。这属于幻觉问题。解决方法是给系统提示词加上严令“只能基于工具返回的真实数据回答如果数据不足明确告知用户无法回答。”6.3 上下文越来越长token消耗失控Agent项目跑一段时间后你会发现对话历史越来越多每个请求都把所有历史传给模型token费用蹭蹭上涨。这里有三个降本思路滑动窗口只保留最近N轮对话更早的对话压缩成摘要。摘要化每过几轮用模型对前面的对话做一次压缩摘要替换原始内容。仅保留关键信息状态机里的confirmed_entities其实已经涵盖了很多必要信息对话历史里的重复询问可以删掉。我有一次做客服Agent原本每轮对话要带上3万token的历史记录优化成“结构化状态 滑动窗口”之后直接降到2000成本和响应速度都改善了一大截。6.4 工具调用报错或者超时怎么办Agent的稳定性很大程度取决于工具调用的健壮性。你能想到的异常基本上都要做兜底异常类型兜底策略外部API超时设置超时时间比如5秒超时后返回“暂时无法获取数据请稍后再试”参数校验失败工具函数内部用try/except捕获异常返回错误信息而不是崩溃模型幻觉参数在调用工具前做一次参数校验不合法就重新要求模型修正重复调用同一工具设置调用次数上限比如最多3次超过则终止并通知用户我曾经遇到过一个情况模型连续5次调用同一个查询工具参数完全一样导致接口被打爆。后来我在工具层加了一个“相同参数静默3秒内不重复请求”的缓存机制问题直接消失。6.5 如何评估一个Agent好不好没有评估标准Agent开发就是“盲人摸象”。我的做法是建立一组测试用例集Golden Set包含至少20个典型问题场景每次修改Prompt或逻辑后全量跑一遍回归测试看通过率变化。测试用例可以按维度分类基础问答型用户随便问一句应该正常回复工具调用型用户明确要求查数据、下单、检索信息缺失型用户没说清楚参数Agent应该主动追问边界情况型用户请求超出能力范围Agent应该礼貌拒绝多轮状态保持型用户在中途切换话题Agent应该不丢前文我用一个简单的脚本跑这些用例记录每个用例是否通过、失败原因是什么。有了这套回归机制你再调Prompt就有底气了不会出现“调好了一个问题带崩了其他问题”的尴尬。7. 一些使用大模型和Agent的生产级经验7.1 优先选稳定API开源模型做备胎很多人一提到“大模型”就想着本地部署开源模型尤其是看到有RX6750GRE这类显卡跑训练的文章手痒就想试。本地部署和学习训练很酷但做Agent产品的话我建议先把云端API的方案跑通再考虑私有化部署。原因有两个Agent是非常看重稳定性的场景API的SLA、并发能力和冷却机制都比本地部署成熟得多。本地部署一个7B模型容易但跑Agent任务时开源小模型的工具调用格式不稳定推理能力也有限实际效果会让你怀疑人生。如果你确实需要离线环境我推荐先试Ollama加Qwen2.5-7B-Instruct先把推理链路跑通再谈其他。7.2 关于Prompt上下文工程的进阶玩法除了工具调用和状态管理上下文工程Context Engineering是目前大模型应用领域另一个高价值技能。简单来说就是“你怎么组织喂给模型的信息”。我在Agent里常用以下几种技巧动态信息注入根据用户ID从数据库提取相关信息拼进System Prompt让Agent“看起来”记得用户。检索增强针对知识型任务先用向量检索找相关资料再拼进上下文。分块摘要超长文档切成多个块每块生成摘要再组合使用。这些技巧不是为了炫技而是解决一个实际问题模型上下文窗口终归有限你没有更多空间就只能更聪明地利用它。7.3 “服范-九添菜菜”这类项目的扩展方向如果你已经跑通了一个基础Agent后续可以扩展的方向非常多把Agent接入企业微信群或钉钉机器人做成真正的业务助手。给Agent增加语音入口集成ASR/TTS做成语音助手。对接数据库或业务系统让Agent能查订单、查库存、发工单。做成多模态Agent让它可以看图、识别图片中的信息。每往前走一步前一阶段踩过的坑就能复用一次。这也是为什么我说把一个最小Agent跑通的经验价值远高于空谈一堆架构概念。8. 最后的几点实战心得先说一个我反复强调的观点不要一上来就套框架先手写一遍核心循环。很多学员问我学Agent该不该直接学LangChain我的回答是“可以学但先自己写一遍”。手写一遍之后你对什么该做成抽象模块、什么该直接编码会有完全不同的理解。等回头再用框架就不会被框架的抽象层绕晕。再说一个项目管理的经验Agent项目的进度估算要放大到传统开发的1.5倍。因为Agent的不确定性主要来自模型行为的不确定性同样的Prompt换个模型版本、换个温度值结果都可能不同。你排期的时候要留足调参和回归测试的时间。最后说一点关于成本控制的体会。Agent每执行一个任务往往要调用大模型两三次甚至更多一次决策、一次工具结果整理、可能还来一次纠错。算账的时候不能只算单次tokens成本要算“每个任务完成需要多少个tokens”。很多项目就是上线后才发现成本失控再回头优化上下文策略非常被动。我的建议是从第一天起就在日志里记录每个任务消耗的token数做成监控指标随时掌握成本走势。跑Agent这条路说容易也容易核心代码量不大说难也难稳定性和效果调优是长期功夫。遇到问题不要慌把日志开起来把状态拆清楚把Prompt写规范你会发现大部分问题都源于这几件事没做踏实。
返回列表