ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LangChain 应用开发(十一):Agent 高级配置与结构化输出

LangChain 应用开发(十一):Agent 高级配置与结构化输出 目录一、Agent 高级配置概述1. 从基础 Agent 到精细化控制二、设置 Agent 名称1. Agent 名称与模型名称2. Agent 名称使用场景三、使用系统提示词控制 Agent1. 系统提示词如何影响 Agent 决策2. 在 create_agent 中配置 system_prompt四、Agent 结构化输出1. 结构化输出的执行流程2. 配置 response_format 与提取 structured_response五、Model 与 Agent 的结构化输出对比六、Agent 结构化输出策略ToolStrategy 使用详解1. 工作原理与流程2. schema 参数3. tool_message_content 参数4. handle_errors 自动纠错七、Agent 流式输出与 Stream Mode1. 基本语法与核心问题2. values获取完整状态3. updates只获取状态变化4. messages模型 Token 流与打字机效果5. 同时使用多个 Stream Mode6. 辅助模式与扩展应用7. Stream Mode 选型决策总结一、Agent 高级配置概述在生产落地时仅靠默认配置的 Agent 往往像是一个不受约束的野马——它可能不遵守特定业务规则、对自己的身份认知不足或者在完成长链条推导后依然返回一段难以解析的口语化文本从 能运行迈向 可控制我们需要掌握 Agent 的高级配置机制1. 从基础 Agent 到精细化控制基础模式下Agent 的能力完全依赖模型的自发推理而在高级配置下我们可以从身份、行为准则、最终输出等维度对其进行拦截与重塑二、设置 Agent 名称在创建 Agent 时许多开发者会看到 name 这个可选参数。首先需要明确一个常见误区设置 Agent 名称并不等于在 Prompt 里告诉模型 你是谁Agent 的名称本质上是系统架构层面的身份标识符真正的行为引导与角色塑造依然由 system_prompt 决定1. Agent 名称与模型名称区分 Agent 名称与模型名称非常关键它们作用于完全不同的层面Agent 名称模型名称本质定位当前智能体实例在业务系统中的逻辑标识底层大语言模型的模型型号常见示例researcher、coding_assistantgpt‑4o、claude‑3‑5‑sonnet主要作用多 Agent 路由、日志 Trace 监控、状态机标识决定基础推理能力、上下文窗口大小与 Token 计费行为影响不直接改变模型的回答逻辑决定模型的代码能力、逻辑推导能力上限2. Agent 名称使用场景在单体 Agent 项目中设置 name 的主要价值在于运维监控——在 LangSmith 等 Trace 追踪平台中你可以通过名称迅速过滤并定位具体是哪个 Agent 触发了调用而在多智能体系统中name 则是不可或缺的核心路由依据Supervisor Agent (主控路由) │ ┌───────────────────┼───────────────────┐ ▼ ▼ ▼ research_agent coding_agent database_agent (负责资料检索) (负责代码编写) (负责 SQL 查询)在 Supervisor主管调度模式或 LangGraph 状态图协同中主控模型需要依赖明确的 name 列表来决定把当前任务派发给哪一个子 Agent 处理# 多 Agent 系统中显式指定标识名称 research_agent create_agent( modelmodel, tools[search_tool], nameresearch_agent # 主控智能体识别并调用该 Agent 的逻辑 ID )如果只是写一个单体工具 Agentname 可以留空或随手配置但若要构建多 Agent 分工协同的项目name 就是智能体之间相互识别与交接任务的工号三、使用系统提示词控制 Agentsystem_prompt系统提示词决定了 Agent 的思维方式、身份认同、合规边界以及在面对模糊需求时的决策倾向1. 系统提示词如何影响 Agent 决策模型在决定 下一步是调用 Tool 还是直接回答 时是在综合评估一个多维度的决策用户提问 System Prompt 当前对话历史 Tool Description (工具说明) Tool Args Schema (参数定义) 模型原生推理能力 │ ▼ Model │ ▼ 下一步行动 (调用 Tool 或 直接回答)当 Tool Description 写得不够强硬或者模型自以为知道答案时它很容易直接输出结果。此时通过 system_prompt 注入强制性的规则指令能够最直接地修正模型的决策偏差一个写得足够健壮的 Agent 系统提示词通常包含以下四个核心维度1. 明确角色身份明确 Agent 的专业领域与能力设定避免其回答超越自身权责范围的问题2. 限制行为边界划定红线与安全栅栏。例如“严禁向用户承诺具体投资收益”、“非公司内部数据拒绝回答”。3. 制定 Tool 使用原则针对某些模型 懒得调用工具 的毛病直接在提示词中下达死命令只要涉及实时气温、股票价格或数据库记录必须且只能通过调用工具获取数据严禁使用预训练知识进行推测或虚构4. 规定回答要求约束自然语言输出的语气、语言如 必须统一使用中文回答或格式2. 在 create_agent 中配置 system_prompt在 LangChain 现代 API 中配置 system_prompt 非常简单直观system_prompt 你是一名严谨的金融分析助手。 【工具使用原则】 1. 当用户询问特定股票的最新价格或实时汇率时必须优先调用对应的查询工具。 2. 绝不允许依赖自身训练记忆猜测或虚构任何金融数据。 3. 如果工具返回数据为空请据实告知用户。 【回答要求】 - 保持专业、中立的分析口吻。 - 严禁向用户提供具体的买入/卖出投资建议。 # 在创建 Agent 时直接传入 system_prompt agent create_agent( modelmodel, tools[get_stock_price, get_exchange_rate], system_promptsystem_prompt )四、Agent 结构化输出Agent 在经历漫长且复杂的多轮工具调用后如果最终只返回一段任意发挥的口语下游的后端业务代码将极难提取关键字段LangChain 提供了response_format参数用来为 Agent 的最终输出挂载强类型契约1. 结构化输出的执行流程配置了 response_format 后Agent 的内部收敛流程如下用户任务 │ ▼ Agent 循环启动 │ ├─► 调用 Tool A ── 获得中间数据 ├─► 调用 Tool B ── 获得中间数据 └─► 信息搜集完毕判定任务完成 │ ▼ 按照 response_format 约束生成结构化数据 │ ▼ 包装并返回包含 structured_response 的字典2. 配置 response_format 与提取 structured_response创建 Pydantic 模型将其作为 response_format 传给 create_agent()# 1. 定义最终期望的结构化结果 Schema class WeatherReport(BaseModel): city: str Field(description城市名称) temperature: float Field(description摄氏度气温) weather: str Field(description天气状况如晴、多云) recommendation: str Field(description基于当前天气的出行或穿衣建议) # 2. 创建 Agent 并指定 response_format agent create_agent( modelmodel, tools[get_weather], response_formatWeatherReport # 绑定最终输出规范 ) # 3. 执行 Agent result agent.invoke({messages: [{role: user, content: 帮我查下东京今天的天气并给点出行建议}]}) # 4. 获取强类型结构化响应 structured_data: WeatherReport result[structured_response] print(type(structured_data)) print(structured_data.city) print(structured_data.temperature) print(structured_data.recommendation)输出结果通过这一配置无论 Agent 在中间阶段调用了多少次工具或经历了怎样的复杂思考最终输出永远是一个经过校验、可以直接用点号调用的强类型 Python 对象五、Model 与 Agent 的结构化输出对比在 LangChain 中模型层面的 with_structured_output() 与智能体层面的 response_format 都能实现结构化输出但两者的底层运行机制与能力边界存在本质区别Model 结构化输出with_structured_output() 属于单次推理模式。模型只能依赖输入文本和预训练知识一步到位生成 Schema 结构用户输入 ── Model (单次调用) ── 匹配 Schema ── 结构化结果Agent 结构化输出循环后收敛response_format 属于多轮循环模式。Agent 可以先发起多轮工具调用把所有实时数据和中间推导收集齐备后再将最终结果收敛为 Schema 结构用户输入 ── Agent ── [ Model ◄──► Tool ] (自主循环 N 轮) ── 汇总上下文 ── 匹配 Schema ── 最终结构化结果返回结果位置差异理解两者的返回值结构差异能有效避免在解析数据时引发 KeyError# 1. Model 结构化输出返回值本身就是 Pydantic 实例 result model.with_structured_output(WeatherReport).invoke(东京天气晴 25度) print(result.temperature) # 直接读取属性 # 2. Agent 结构化输出返回值是包含全局 Context 的字典 result agent.invoke({messages: [{role: user, content: 查下东京天气}]}) structured_data result[structured_response] # 在特定 Key 中提取 print(structured_data.temperature)如何正确选型with_structured_output()任务所需的信息已经完整包含在用户输入或已知的 Context 中例如阅读理解提取、新闻分类、将一段已有文本转换为 JSON 格式response_format任务所需的信息无法通过纯 Prompt 提供必须让 Agent 深入外部系统搜索网页、查数据库、算公式完成数据收集后再吐出符合标准的最终报告或决策数据六、Agent 结构化输出策略response_format 接收的不仅仅是一个简单的 Pydantic 类其底层涵盖了一套完整的策略选择机制。根据 LangChain 现代 API 设计我们可以根据需求划分输出策略体系LangChain 的 Agent 结构化输出 API 在 0.2 / 0.3 体系及 LangGraph 引擎驱动下已趋于稳定。在工程实践中推荐优先使用兼容性最好、掌控力最强的ToolStrategyToolStrategy 使用详解ToolStrategy 是目前开发中最通用、最稳定的 Agent 结构化收敛策略1. 工作原理与流程ToolStrategy 的核心思想是把 生成最终结构化结果 伪装成 Agent 的最后一个 虚拟工具当 Agent 在内部完成了搜集信息的所有业务工具调用后引擎会强制引导模型调用这个工具进而完成数据的校验与提取2. schema 参数schema 明确了 Agent 必须返回的数据规范直接复用已有的 Pydantic 模型、TypedDict 或 JSON Schema 即可from langchain.agents import ToolStrategy 使用 ToolStrategy 包装 WeatherReport Schema strategy ToolStrategy( schemaWeatherReport )3. tool_message_content 参数很多开发者容易混淆这个参数的作用当 Agent 在内部触发虚拟工具时LangChain 引擎会在内部对话链条中插入一条 ToolMessage。tool_message_content 允许你自定义这条内部工具消息的文本回显例如设置为 成功提取结构化响应任务结束class ContactInfo(BaseModel): 用户的联系方式 name: str Field(description用户姓名) email: str Field(description用户邮箱地址) phone: str Field(description用户的手机号) agent create_agent( modelmodel, response_formatToolStrategy(ContactInfo, tool_message_content已成功抽取信息) ) response agent.invoke( { messages: [ HumanMessage(从这段话中抽取结构化信息小明的邮箱地址为songhk atguigu.com手机号12345678912) ] } ) rprint(response[messages][-1])输出结果注意tool_message_content 影响的只是 Agent 内部 Context 消息流的表达绝不会影响最终在 result[structured_response] 中拿到的强类型 Python 对象。4. handle_errors 自动纠错结构化输出并非百分之百成功模型可能在最后一步输出不符合 Schema 约束的数据例如把 temperature: float 生成了 暖和导致 Pydantic 抛出 ValidationError通过配置 handle_errorsAgent 会自动开启校验失败重试handle_errorsTrueLangChain 默认方式捕获所有异常使用 LangChain 内置的错误消息模板提示模型重试确保最终得到符合预定 Schema 格式的有效数据。适合大多数希望自动处理错误的通用场景handle_errorsFalse关闭自动重试机制。任何校验异常都会直接抛出并中断程序运行适合在开发阶段快速暴露并定位 Prompt 或模型本身的问题handle_errors自定义提示字符串捕获所有异常但使用预设的字符串作为错误消息送回模型。适合需要统一提示语或进行特定业务引导的场景handle_errorsExceptionType仅捕获指定类型如 ValidationError 或 (ValueError, TypeError) 元组的异常并重试其他未匹配的异常直接抛出handle_errorscallable自定义函数灵活性最高的方式。传入一个开发者自定义的函数入参为捕获到的 Exception返回值为字符串根据不同的异常类型返回差异化的提示信息。适合需要精细化错误处理的场景# 1. 定义目标输出 Schema class UserProfile(BaseModel): name: str Field(description用户姓名) age: int Field(description用户年龄必须是大于 0 的整型数字) 2. 定义自定义错误处理函数 def custom_error_handler(error: Exception) - str: 当模型生成的输出不满足 Schema 时该函数会被自动触发。 if isinstance(error, ValidationError): return f【格式校验失败】违反字段约束 ({str(error)})请重新生成 return 【数据提取失败】请确保严格按照 Pydantic 定义的格式返回。 3. 构建配置了 handle_errors 的 ToolStrategy strategy ToolStrategy( schemaUserProfile, tool_message_content结构化数据解析完成, handle_errorscustom_error_handler )七、Agent 流式输出与 Stream Mode在真实应用中如果等 Agent 完成多轮工具调用与思考后才一次性把结果吐给用户极长的等待时间会带来极差的体验。为了实现 边思考、边执行、边打字 的流畅交互我们需要使用agent.stream()1. 基本语法与核心问题调用流式接口的基本语法非常简单for chunk in agent.stream( {messages: [{role: user, content: 查询东京天气}]} ): print(chunk)然而在实际运行中一个根本性问题随之浮出水面我们到底希望 Agent 在流式传输中输出什么数据是模型的每一个 Token 字符是 Agent 当前执行到了哪一步还是工具执行的进度为了满足不同的交互需求LangChain 提供了stream_mode参数模式主要返回内容values每次状态更新后的完整全局状态updates每次状态更新产生的状态增量messages模型生成的 LLM Token / Message 实时文本流custom开发者在代码中自主发射的自定义流式数据checkpoints状态持久化产生的 Checkpoint 信息tasks底层 Task 执行与调度的生命周期事件debug包含极其详尽的框架内部调试日志重点掌握 values、updates 和 messages 这三大核心模式即可。其他模式服务于特定场景了解其定位即可2. values获取完整状态values 模式的核心逻辑是 Agent 内部每完成一步如模型推理结束或工具执行结束就把当前的 完整 State 输出内部状态演进初始状态: messages ── [ HumanMessage ] Step 1 (Model 推理完成): messages ── [ HumanMessage, AIMessage(tool_calls) ] Step 2 (Tool 执行完成): messages ── [ HumanMessage, AIMessage(tool_calls), ToolMessage ] Step 3 (Model 最终生成): messages ── [ HumanMessage, AIMessage(tool_calls), ToolMessage, AIMessage(最终答案) ]代码示例# 每次循环返回截至当前为止的完整消息列表 for chunk in agent.stream( {messages: [{role: user, content: 东京天气}]}, stream_modevalues ): latest_msg chunk[messages][-1] print(f【当前节点】: {latest_msg.__class__.__name__} - {latest_msg.content})输出结果3. updates只获取状态变化与 values 不同updates 模式采用增量模式只告诉我们刚才这一步新增了什么数据代码示例for chunk in agent.stream( {messages: [{role: user, content: 东京天气}]}, stream_modeupdates ): print(chunk) print(- * 50)输出结果4. messages模型 Token 流与打字机效果values 和 updates 都是以 Agent 步Step为粒度返回状态变化的。如果模型正在生成一段 500 字的回答用户依然需要等待这 500 字全部生成完才能在 updates 里看到为了实现真正的逐字打字机效果我们需要使用 stream_modemessages代码示例# 逐 Token 实时输出文本流 for chunk, metadata in agent.stream( {messages: [{role: user, content: 写一篇关于东京天气的短文}]}, stream_modemessages ): if chunk.content: print(chunk.content, end, flushTrue)输出结果与 model.stream() 的区别model.stream()只能观察单一模型的直出 Token。agent.stream()在Agent 整个复杂循环内部包括中间工具调用的思考过程、最终答复生成等实时捕获模型的 Token 流5. 同时使用多个 Stream Mode在构建现代 Web Agent 界面时我们通常需要一边向用户展示 Agent 当前的步骤状态如 正在查询天气...一边以打字机效果渲染模型的最终答复你可以向 stream_mode 传入一个列表同时开启多种模式# 同时开启状态增量与 Token 流 for mode, payload in agent.stream( {messages: [{role: user, content: 查询东京天气并生成总结}]}, stream_mode[updates, messages] ): if mode updates: # 展示 Agent 执行到了哪个步骤 print(f\n[系统状态更新]: {list(payload.keys())}) elif mode messages: # 逐 Token 打印回答 token, meta payload if token.content: print(token.content, end, flushTrue)输出结果6. 辅助模式与扩展应用custom自定义业务流式数据当需要在自定义 Tool 内部向前端实时推送业务进度如批量处理进度条时可以使用 custom 模式如“已处理10/100条记录”、自定义日志或指标checkpoints用于观察 Agent 运行过程中产生的 Checkpoint 状态检查点。它主要与状态持久化、断点续传、人工干预Human-in-the-loop强绑定将在后续学习 LangGraph 及 Agent Memory 时详细展开tasks聚焦于底层 Task 的生命周期事件Task 开始、Task 成功、Task 失败常用于构建复杂的任务调度监控仪表盘debug输出详尽的内部执行日志包含 Prompt 组装过程、原始 API 响应等仅建议在开发调试阶段使用生产环境切勿开启7. Stream Mode 选型决策根据你的实际开发需求快速选择最恰当的流式模式在真实项目开发场景下updates、values、messages 是使用最为广泛、值得优先研习的核心模式。对三者进行灵活组合便可实现优雅的 AI 应用交互体验构建总结本章在基础 Agent 的创建与工具调用之上进一步学习了 Agent 的高级配置方式。通过 name、system_prompt 和 response_format我们可以分别对 Agent 的身份、行为规则以及最终输出结构进行更加精细的控制并进一步了解了模型结构化输出与 Agent 结构化输出之间的区别以及 ToolStrategy 中 schema、tool_message_content、handle_errors 等重要配置此外本章还学习了 Agent 的流式输出机制重点掌握了 values、updates 和 messages 三种常用 Stream Mode并了解了 custom、checkpoints、tasks 和 debug 等模式的基本用途。通过流式输出我们不仅可以实时获取模型生成内容还能够观察 Agent 在多轮推理与工具调用过程中的状态变化至此我们已经能够从身份、行为、输出格式以及运行过程多个维度控制 Agent。下一篇将继续深入 Agent 的扩展机制——Middleware 中间件学习如何在 Agent 执行流程的不同阶段插入自定义逻辑对模型调用、工具执行和运行状态进行更加灵活的干预与控制
返回列表