资讯动态

langchain 构建智能体 Agent

发布时间:2026/10/22 23:00:32 来源:尧图企业网站定制
1.理解 Agent1.1 什么是 Agent在大模型应用开发中智能体通常指一种以大语言模型为推理与决策核心结合记忆、工具调用与环境交互能力能够进行规划决策并执行复杂任务以达成目标的软件系统Agent 的关键能力理解用户问题拆解任务判断是否需要工具判断需要调用哪些工具利用工具结果生成回答推进任务1.2 Agent 的核心组件实际开发中几个要素并不需要同时出现一句话总结必须的行动Action几乎总是存在的工具Tool有条件存在的规划决策Planning最容易被省略的记忆Memory1.3 Agent 的创建和调用当下所有 Agent 的创建方式统一为一个入口create_agent( )同时在底层通过“中间件机制Middleware”和“标准模型接口invoke / stream”实现全局统一。这让框架更轻、更稳也更易于被集成到其他 Agent 平台中用法如下2. Agent 基本用法1模型的传入方式在 LangChain 1.2 中 create_agent 是构建智能体的核心方式底层基于 LangGraph 实现更多参考create_agent | langchain | LangChain Reference模型是 Agent 的“大脑”负责决策和推理。根据模型传入 agent 方式的不同分为两种方式传入模型字符串传入模型对象2.1 传入模型字符串Agent根据传入的模型字符串自主创建模型对象语法如下agent 本质LangGraph 的CompiledStateGraph 实例底层实现是一个图结构通过上述代码最后一行代码可以显示 agent 的图结构2.2 传入模型对象用法如下from langchain.chat_models import init_chat_model from dotenv import load_dotenv import os from rich import print as rprint from langchain_core.messages import SystemMessage, HumanMessage, AIMessage from langchain_core.tools import tool from langchain.agents import create_agent # 1.加载配置信息 load_dotenv(overrideTrue) api_key os.getenv(BAILIAN_API_KEY) base_url os.getenv(BAILIAN_API_BASE) # 2.初始化模型 llm init_chat_model( model_provideropenai, # 模型提供商 modeldeepseek-v4.1-flash, # 模型名称 api_keyapi_key, # API Key base_urlbase_url, # API Base URL ) # 3.创建智能体 agent create_agent(llm) # 4.查看智能体 print(type(agent)) from IPython.display import Image, display display(Image(agent.get_graph().draw_mermaid_png()))输出与上文一致3. Agent的基本用法2如何调用Agentagent.invoke( )是 Agent 的同步调用方法它会阻塞程序执行直到返回最终结果输入传入的参数为字典类型字典内通过 messages 字段传递消息列表。即“ {messages: [{role: ..., content: ...}]} ”输出通过 invoke 调用Agent底层可能会经历多轮交互返回的是完整的消息列表被封装在字典中是 messages 字段的值案例from langchain.chat_models import init_chat_model from dotenv import load_dotenv import os from rich import print as rprint from langchain_core.messages import SystemMessage, HumanMessage, AIMessage from langchain_core.tools import tool from langchain.agents import create_agent tool(parse_docstringTrue) def get_weather(city: str) - str: 获取当地天气信息 Args: city (str): 城市名称 Returns: str: 天气信息 return 晴天, 20度℃ tool(parse_docstringTrue) def get_history(city: str) - str: 获取当地历史信息 Args: city (str): 城市名称 Returns: str: 历史信息 return 历史悠久 # 1.加载配置信息 load_dotenv(overrideTrue) api_key os.getenv(BAILIAN_API_KEY) base_url os.getenv(BAILIAN_API_BASE) # 2.初始化模型 llm init_chat_model( model_provideropenai, # 模型提供商 modeldeepseek-v4.1-flash, # 模型名称 api_keyapi_key, # API Key base_urlbase_url, # API Base URL ) # 3.创建智能体 agent create_agent( modelllm, tools[get_weather, get_history], system_promptAgent 的行为指令 ) # 4.调用智能体 response agent.invoke({ messages:[{role: user, content: 今天北京的天气如何北京这座城市历史如何?}], }) rprint(response)输出如下{ messages: [ HumanMessage( content今天北京的天气如何北京这座城市历史如何?, additional_kwargs{}, response_metadata{}, id6c52411e-4deb-490f-a8f3-2848ecd9ff2b ), AIMessage( content我来帮您查询北京的天气和历史信息。, additional_kwargs{refusal: None}, response_metadata{ token_usage: { completion_tokens: 96, prompt_tokens: 361, total_tokens: 457, completion_tokens_details: { accepted_prediction_tokens: None, audio_tokens: None, reasoning_tokens: 21, rejected_prediction_tokens: None, text_tokens: 75 }, prompt_tokens_details: {audio_tokens: None, cached_tokens: 0, text_tokens: 361} }, model_provider: openai, model_name: deepseek-v4.1-flash, system_fingerprint: None, id: chatcmpl-dede3d58-c465-9a17-a8ec-1d3ee26c24d5, finish_reason: tool_calls, logprobs: None }, idlc_run--01a15860-34f0-7993-b616-8c9dd5e944e8-0, tool_calls[ { name: get_weather, args: {city: 北京}, id: call_7da856d6f90446d7aab382d2, type: tool_call }, { name: get_history, args: {city: 北京}, id: call_ad44233baf4644bd9ae887ae, type: tool_call } ], invalid_tool_calls[], usage_metadata{ input_tokens: 361, output_tokens: 96, total_tokens: 457, input_token_details: {cache_read: 0}, output_token_details: {reasoning: 21} } ), ToolMessage( content晴天, 20度℃, nameget_weather, ide60e1afd-f2e2-4e01-8d4f-292cd78c1d3f, tool_call_idcall_7da856d6f90446d7aab382d2 ), ToolMessage( content历史悠久, nameget_history, idf24543e7-8933-4b86-bd29-93f7e05b054e, tool_call_idcall_ad44233baf4644bd9ae887ae ), AIMessage( content我为您查询到了以下信息\n\n## ️ 今日北京天气\n- **天气状况**晴天 ☀️\n- **气温**20℃\n\n今天北京天气晴朗气温 20 度比较舒适宜人适合外出活动建议根据早晚温差适当增减衣物。\n\n## 北京城市历史\n- **历史概况**历史悠久\n\n关于北京的历史工具返回的信息较为简略。不过补充一些背景供您参考北京是中国著名的古都 拥有三千多年的建城史和八百多年的建都史曾是元、明、清等多个朝代的都城拥有故宫、天坛、长城等众多世界级历史文化遗 产。\n\n如果您希望了解更详细的历史内容如具体朝代、名胜古迹等欢迎告诉我我可以再帮您进一步查询。, additional_kwargs{refusal: None}, response_metadata{ token_usage: { completion_tokens: 187, prompt_tokens: 463, total_tokens: 650, completion_tokens_details: { accepted_prediction_tokens: None, audio_tokens: None, reasoning_tokens: 18, rejected_prediction_tokens: None, text_tokens: 168 }, prompt_tokens_details: {audio_tokens: None, cached_tokens: 0, text_tokens: 463} }, model_provider: openai, model_name: deepseek-v4.1-flash, system_fingerprint: None, id: chatcmpl-9d8f113a-5e42-904b-a4a3-e744bc5b8b5f, finish_reason: stop, logprobs: None }, idlc_run--01a15860-3de2-7282-9adf-1cde6f7de6e4-0, tool_calls[], invalid_tool_calls[], usage_metadata{ input_tokens: 463, output_tokens: 187, total_tokens: 650, input_token_details: {cache_read: 0}, output_token_details: {reasoning: 18} } ) ] }4. Agent的基本用法3绑定工具Agent支持静态和动态绑定工具动态绑定需要用到中间件工具可以是 LangChain 内置的也可以是自定义的官方工具文档 guanfgTool integrations - Docs by LangChain4.1 基本用法Agent 支持绑定一个或多个工具语法如下agent create_agent( model **** tool [工具1, 工具2, 工具3, ...] ... )案例使用内置工具from langchain.chat_models import init_chat_model from dotenv import load_dotenv import os from rich import print as rprint from langchain_core.messages import SystemMessage, HumanMessage, AIMessage from langchain_core.tools import tool from langchain.agents import create_agent from langchain_tavily import TavilySearch # 1.加载配置信息 load_dotenv(overrideTrue) api_key os.getenv(BAILIAN_API_KEY) base_url os.getenv(BAILIAN_API_BASE) # 定义内置工具 web_search TavilySearch( max_results2, tavily_api_keyos.getenv(TAVILY_API_KEY), ) # 2.初始化模型 llm init_chat_model( model_provideropenai, # 模型提供商 modeldeepseek-v4.1-flash, # 模型名称 api_keyapi_key, # API Key base_urlbase_url, # API Base URL ) # 3.创建智能体 agent create_agent( modelllm, tools[web_search], name搜索引擎工具, ) # 4.调用智能体 response agent.invoke({ messages:[{role: user, content: 帮我查一下2026年无畏契约上海冠军赛的冠军是谁}] }) rprint(response[messages][-1].content)输出结果如下一次完整的 Function calling 执行流程如下注意只给 Agent 需要的工具工具太多会混淆。一般 2-5 个工具最佳4.2 工具调用流程LangChain 的 Agent 会将 模型 与 工具 结合起来在实现上由一个基于 LangGraph 的图结构来编排执 行流程如下所示本质上就是经典的ReAct 结构一个具备“思考-行动-观察” 不断循环的自主工作者用户输入 —— 模型思考 —— 调用工具 —— 模型观察工具调用结果 —— 模型思考 —— ... —— 结果输出Agent 会在一个循环中反复调用模型和工具直到某次模型输出中不再包含工具调用则结束最后综合所有信息给出最终答案执行流程图如下4.3 重试机制Agent可以在工具调用结果不满足要求时自主重试案例from langchain.chat_models import init_chat_model from dotenv import load_dotenv import os from rich import print as rprint from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage from langchain_core.tools import tool from langchain.agents import create_agent number 0 # 0.定义工具 tool(parse_docstringTrue) def get_current_weather(city: str) - str: 获取指定城市的天气信息 Args: city (str): 城市名称 Returns: str: 天气信息 global number number 1 if number 3: return 工具调用失败,请重试! else: return city 晴天, 温度15度, 风力3级 # 1.加载配置信息 load_dotenv(overrideTrue) api_key os.getenv(BAILIAN_API_KEY) base_url os.getenv(BAILIAN_API_BASE) # 2.初始化模型 llm init_chat_model( model_provideropenai, # 模型提供商 modeldeepseek-v4.1-flash, # 模型名称 api_keyapi_key, # API Key base_urlbase_url, # API Base URL ) # 3.创建智能体 agent create_agent( modelllm, tools[get_current_weather], name天气助手1, ) # 4.调用智能体 response agent.invoke({ messages:[ {role: system, content: 你是一个天气查询助手, 当天气工具的调用结果为工具调用失败,请重试!时请不要放弃至少重复调用3此}, {role: user, content: 杭州天气如何} ] }) for message in response[messages]: if isinstance(message, ToolMessage): rprint(message.content)输出结果4.4 常见问题问题1Agent 如何选择工具依据 工具的 docstringAI 会根据问题内容每个工具的描述自动选择最匹配的工具问题2Agent 为什么没有调用工具原因工具的 docstring 不清晰问题表述不明确模型认为不需要工具问题3Agent 选错工具原因多个工具的功能描述相似工具太多导致混淆解决方案只给必要的工具工具描述要有明确区分在 system_prompt 中说明工具使用场景问题4如何知道 Agent 何时完成当 AIMessage 不包含 tool_calls 时问题5Agent 可以调用多少次工具默认没有限制直到得到最终答案。但可能会超时达到 token 限制模型决定停止问题6如何限制工具调用次数LangChain 1.0 的 create_agent 默认使用 LangGraph可以通过配置限制5. Agent的高级用法1设置Agent名称创建Agent时LangChain允许用户指定其名称这时输出的 AI Message带有 Name 信息6. Agent的高级用法2系统提示词使用 create_agent 创建 Agent 时需传入模型和工具、可选地传入系统提示词系统提示词为 Agent 提供了任务背景、行为准则和操作指南系统指令即 SystemMessage通过 system_prompt 设置定义 Agent 行为。这个参数可以是str 或者 SystemMessage 类型使用建议明确说明 Agent 的角色定义输出格式说明何时使用工具用法如下提示词设置有两种方式静态设置和动态设置静态设置Agent 实例创建时通过 system_prompt 参数一次性写死之后所有 invoke / stream 调用自动带上这段系统指令每次调用都相同运行时不可变动态设置每一轮模型调用前实时生成根据本次请求的上下文、用户身份、会话状态、数据库记忆动态拼接不同的 system 指令方法是dynamic_prompt 中间件 runtime.context7. Agent的高级用法3结构化输出agent 结构化输出允许 Agent 以特定、可预测的格式返回数据而不是传统的自然语言响应通过结构化输出开发者可以直接获得Pydantic模型、JSON对象或数据类等结构化数据这些数据能够被应用程序直接使用无需复杂的解析过程7.1 模型 vs Agent 的结构化输出对比7.2 结构化输出的4种策略LangChain 的 create_agent( ) 函数自动处理结构化输出的全过程用户只需通过“response_format” 参数设置期望的输出模式Schema当模型生成结构化数据时系统会自动捕获、验证并将结果存储在 Agent 状态的structured_response键中用法如下create_agent函数中的 response_format 参数支持四种不同的策略设置方式① ProviderStrategy使用模型提供商的原生结构化输出功能实现结构化输出原生结构化输出指的是大语言模型LLM提供商通过其 API 直接提供的、在模型响应阶段就强制保证输出格式符合预定规范的能力这种能力能够在模型生成内容的源头确保结构化准确性适用于支持原生结构化输出的模型比如 OpenAI、Anthropic Claude 或 xAI Gro k等案例如下② ToolStrategy对于不支持原生结构化输出的模型LangChain采用 “ToolStrategy” 工具调用的方式实现结构化输出原理动态创建一个 虚拟工具 该工具的输入参数对应着期望的数据结构当模型需要生成最终答案时系统会引导模型 调用 这个虚拟工具 从而间接产生符合要求的结构化数据案例③ type / AutoStrategy官方没有在参数列表或官方文档列出这种策略但阅读源码可以看到当我们直接传入一个定义类型时LangChain 会自动包装为 AutoStrategy触发自动选择策略如果模型支持原生结构化输出如OpenAI、Anthropic Claude或xAI Grok则优先使用 ProviderStrategy否则使用 ToolStrategy④ None默认配置表示不以结构化输出以自然语言响应用户问题总结在实际大模型 Agent 开发场景中如果使用到了结构化输出推荐使用 “ToolStrategy” 策略7.3 ToolStrategy使用详解ToolStrategy 通过工具调用 Tool Calling/Function Calling实现结构化输出所以 LangChain会在消息列表末尾追加一条 ToolMessage但实际上没有实际的工具执行这是一条伪消息ToolStrategy 适用于任何支持工具调用的现代模型ToolStrategy 的配置包含三个主要参数schema必需参数与提供商策略的 schema 参数功能一致支持Pydantic 模型 、 TypedDict 、 JSON Schema 、 数据类(dataclass)同时还支持联合类型 Union [类型1, 类型 2] 允许模型根据输入内容选择最匹配的数据结构tool_message_content可选参数用于自定义生成结构化输出时会话历史中记录的提示信息。默认使用展示输出数据的标准响应语句handle_errors可选参数用于指定数据校验失败时的重试策略 默认值为True7.3.1 结构化输出schema 参数输出模式1Pydantic类型Pydantic类型的 Schema 支持数据验证是优先推荐使用的方式输出如下观察日志可知这种方式将结构化信息作为伪工具传递显然使用了Function Calling方法输出模式2TypedDict 类型TypedDict 允许为字典对象定义固定的键名和对应的值类型 是带有类型提示的字典结构TypedDict 字段定义采用Annotated [类型, 默认值, 描述]格式可选字段使用 Optional 包装默认值在 Annotated 中指定TypedDict不支持运行时验证案例如下输出模式3JsonSchema 类型JSON Schema 是提供一个标准的 JSON Schema 字典来定义结构适合需要与多种编程语言交互或进行复杂数据约束定义的场景案例如下以上代码中定义 json_schema 的时候指定的 title, description, type, properties, required 是遵循 JSON Schema 规范的标准关键字是固定写法输出模式4dataclass类型dataclass是Python 3.7引入的一个装饰器用于简化数据存储类的定义多 schema 联合模式ToolStrategy 允许指定多个类型 “Union[类型1, 类型2]” 这种写法LLM能够根据输入文本的内容智能地选择最合适的一个 数据模型Schema来生成结构化输出最终会只有一种类型输出输出结果如下继续输出结果如下7.3.2 自定义工具消息tool_message_content 参数我们已经知道采用 ToolStrategy 策略处理结构化输出时LangChain 会在消息列表末尾追加一条 Tool_message让整个链路完整tool_message_content定制 Tool_message 消息内容将指定的内容写入对话历史的提示信息这样做的好处如下:在最终用户可见的对话流中使用 更自然的消息替代原始数据用简短的确认信息替代可能很长的数据块 减少token消耗注意当不设置 tool_message_content 时模型收到的 ToolMessage 里就包含了像 {name: 张三, email: zhangsanemail.com... ...} 这样的具体数据当设置了 tool_message_content 时模型收到的 ToolMessage 只是一个预定义的确认信息如“ 格式化输出成功 ”这种方式节省了上下文窗口的令牌消耗并且让对话流对最终用户更友好说明无论 tool_message_content 如何设置成功提取的结构化数据最终都会正确存入 result[structured_response]返回自定义消息仅影响对话历史中的一条记录7.3.3 错误处理handle_errors 参数ToolStrategy 通过其 handle_errors 参数提供了结构化过程错误处理策略以下是主要的几种方式及其用途handle_errorsTrue默认方式 捕获所有异常 并使用 LangChain 内置的错误消息模板提示模型重试确保最终能得到符合预定格式的有效数据handle_errorsFalse关闭自动重试机制任何异常都会直接抛出 会中断程序运行handle_errors自定义字符串捕获所有异常但使用开发者预设的固定字符串作为错误消 息handle_errorsExceptionType仅捕获指定类型(如ValueError) 或元组中的异常类型并进行重 试 其他异常直接抛出handle_errorscallable灵活性最高的方式使用开发者自定义的函数来处理异常 可根据不 同的异常类型返回差异化的提示信息情况1设置为True/False/固定字符串设计思路模型对于单条信息的格式化输出请求输出了多个工具调用请求。也称为多结构化输出错误1handle_errors设置为True运行后结果如下模型接收到错误反馈后再次生成新的调用请求直至成功或达到内部的最大重试次数注意ToolStrategy 中自定义的 tool_message_content控制的是成功后的消息内容不影响错误消息内容2handle_errors 设置为 False运行后会直接报错3handle_errors设置为“请检查输入数据”以上代码中注意如下几点1. ToolStrategy 允许指定多个类型“Union[ContactInfo, EventDetails]” 这种写法但是最终只会转换成一种结构化类型输出2. 当 ToolStrategy 通过“Union[ContactInfo, EventDetails]”指定多个类型时在内部调用生成结构化类型工具会报错此时handle_errorsTrue默认值开始发挥作用系统会生成一个ToolMessage明确告诉 LLM“Error: Model incorrectly returned multiple structured responses (ContactInfo, EventDetails) when only one is expected.”大模型收到这个精准的反馈后会重新进行推理最终选择并输出一个最符合要求的Schema如果handle_errors 设置为False执行代码过程直接报错3. 当格式化输出有错误时Agent内部会进行工具调用重试直到符合要求格式化输出前 可能会进行多次重试情况2设置为指定异常类型默认情况下LangChain 会处理结构化输出处理时抛出的两类异常1. MultipleStructuredOutputsError多结构化输出错误当返回的工具调用请求数量大于1时抛出该异常默认情况下 LangChain 会拦截异常并提醒模型重试2. StructuredOutputValidationError输出结构化验证错误当输出格式不符合结构化要求时抛出上述异常。 默认情况下 LangChain 会拦截该异常并自动重试案例如下输出结果如下情况3设置为自定义错误处理函数指定异常处理函数并返回字符串时LangChain 会在遇到异常时自动重试并将异常处理函数的返回值作为ToolMessage的内容我们也可以选择在异常处理函数中抛出异常案例如下运行后结果如下8. Agent的高级用法4流式输出及模式设置方式通过 “agent.stream(stream_mode指定模式)” 来指定具体模式有values、updates默认、 messages、custom、checkpoints、tasks、debug8.1 具体的输出模式8.1.1 values 输出模式stream_mode values每个步骤执行后都会输出完整的状态信息适用于每一步都要获取完整状态、状态持久化场景案例from pydantic import BaseModel, Field from langchain.agents import create_agent from langchain.agents.structured_output import ProviderStrategy from langchain.messages import HumanMessage, SystemMessage from langchain_core.tools import tool from rich import print as rprint from langchain.chat_models import init_chat_model from dotenv import load_dotenv import os # 0.定义工具 tool(parse_docstringTrue) def get_weather(city: str) - str: 获取指定城市的天气信息 Args: city (str): 城市名称 Returns: str: 天气信息 return f{city}的天气是晴天温度是25度 tool(parse_docstringTrue) def get_location(city: str) - str: 获取指定城市的地理位置信息 Args: city (str): 城市名称 Returns: str: 地理位置信息 return f{city}的经纬度是30.123, 120.123 # 1.加载环境变量 load_dotenv(overrideTrue) api_key os.getenv(BAILIAN_API_KEY) base_url os.getenv(BAILIAN_API_BASE) # 2.初始化模型 llm init_chat_model( model_provideropenai, model deepseek-v4.1-flash, api_key api_key, base_url base_url, ) # 3.agent 初始化 agent create_agent( model llm, tools [get_weather, get_location], ) # 4.构建消息列表 messages { messages:[ SystemMessage(content你是一个AI助手你需要根据用户的输入进行智能处理并返回结果。), HumanMessage(content杭州天气如何杭州在哪里), ] } # 5.调用agent response agent.stream( messages, stream_modevalues ) for chunk in response: rprint(chunk) print( - * 50)运行后结果示意如下8.2.2 updates 输出模式stream_mode updates默认模式每个步骤执行后只增量更新状态中发生变化的内容用于监控 Agent 执行进度用法如下输出结果示例如下8.2.3 messages 输出模式stream_mode messages输出流式返回的 Token 以及相关的元数据可以用在实现类似 ChatGPT 的打字机效果场景为聊天机器人等交互式应用提供最佳的实时体验用法如下输出结果如下8.2.4 tasks 输出模式stream_mode tasks输出当前task任务开始和结束的时间包含任务的结果和错误信息该模式用于监控任务的生命周期8.2.5 debug 输出模式stream_mode debug与tasks模式类似比 task 模式多输出任务步骤、时间戳、task 类型task/task_result该模式用于调试、监控 task 任务的生命周期8.2.6 checkpoints 输出模式stream_mode checkpoints每当检查点checkpoint被创建时会触发输出输出包含检查点中的状态用于需要状态持久化、工作流恢复或分布式执行跟踪的高级场景用法from langgraph.checkpoint.memory import InMemorySaver #--其他代码同上-- # 1. 创建内存检查点存储 checkpointer InMemorySaver() # 2. 创建Agent agent create_agent( modelllm, tools[get_weather, get_location], checkpointercheckpointer # 启用检查点 ) # 3. 创建唯一的会话ID config {configurable: {thread_id: session01}} # 4.构建消息列表 messages { messages:[ SystemMessage(content你是一个AI助手你需要根据用户的输入进行智能处理并返回结果。), HumanMessage(content杭州天气如何杭州在哪里), ] } # 5.调用agent response agent.stream( messages, configconfig, stream_modecheckpoints ) checkpoint_count 0 for chunk in response: checkpoint_count 1 print(f检查点 #{checkpoint_count}) print(chunk) print(- * 50)输出结果如下每次输出都会将相关 MESSAGE 追加到 values.messages 中8.2.7 custom 输出模式stream_mode custom开发者通过get_stream_writer在工具或节点内部自定义发送的数据 用于输出业务逻辑相关的进度信息如“已处理10/100条记录”、自定义日志或指标案例输出结果如下8.2 流式输出总结我们可以根据不同的目标来选择不同的输出模式实现实时对话交互优先选择 messages 模式观察Agent的思考与执行步骤 优先选择 updates 模式需要查看每一步状态优先选择 values/tasks/debug 模式在工具执行时输出自定义业务日志优先选择 custom 模式此外以上这些模式还可以组合使用例如可以同时指定 stream_mode[“tasks”“updates”] 这 样在同一个循环里既能查看Agent task任务执行内容 又能显示Agent每步的更新

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

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

免费获取报价 →
↑