LangChain Agent 从零入门:让大模型学会“自己动手“
2026/7/24 0:54:04 网站建设 项目流程

LangChain Agent 从零入门:让大模型学会"自己动手"

从 Chain 到 Agent,大模型终于有了"手脚"和"判断力"

一、Chain 不够用了,我需要一个能"自己做决定"的东西

学 LangChain 的过程中,我先搞定了 Model I/O(怎么调模型),又学会了 Prompt 模板和输出解析,接着掌握了 Chain(把几个步骤串起来)。用 Chain 搭一个固定的流程,比如"翻译一段文字"或者"总结一篇文章",确实够用了。

但有一天我想做一个稍微复杂点的功能:用户说"帮我查查北京明天会不会下雨,如果下雨就帮我把明天的户外活动取消掉"

用 Chain 怎么实现?我得提前把流程写死:先调天气 API → 判断返回结果 → 如果下雨就调取消日程 API → 如果不下雨就直接回复。看起来还行,但问题在于——如果用户换成"查查上海后天的天气,不下雨就帮我订一张迪士尼门票"呢?流程完全不一样了。每来一种新的问法,我就得写一条新的 Chain。

这时候我才意识到,我需要的不是一个固定的流水线,而是一个能“自己做决定”的东西——给它一个目标,它能自己判断该干什么、怎么干、干完了没有。

这就是 Agent(智能代理)。

二、Agent 是啥?一句话说清楚

Agent = LLM(大脑)+ 工具(手脚)+ 自主决策

在 Chain 里,流程是开发者定的——“你先干 A,再干 B,最后干 C”。在 Agent 里,流程是 LLM 自己定的——“用户想要 X,我看看……我需要先做 A,拿到结果后再做 B,好了任务完成,回复用户”。

用大白话总结:

  • Chain:你告诉 LLM “怎么做”,它照做
  • Agent:你告诉 LLM “要做什么”,它自己想办法

Agent 不是一次调用就结束的。它内部是一个"感知 → 推理 → 行动"的循环,可能转好几轮才完成任务:

  1. 感知:收到用户消息
  2. 推理:LLM 想"我该干点啥?"
  3. 行动:调用一个工具(或者直接回复)
  4. 观察:拿到工具返回的结果
  5. 回到第 2 步:继续推理"结果拿到了,下一步呢?"
  6. 直到 LLM 觉得"搞定了",输出最终答案

整个过程里,没有任何一行代码规定"先调用哪个工具、再调用哪个工具"。全是 LLM 自己判断的。如果天气是晴天,它压根不会去调用"取消预约"那个工具。

三、核心组件:大脑、手脚、记忆、规划

Agent 有四个核心组件,但并不是所有 Agent 都需要全部具备。最简的 Agent 只需要大脑 + 手脚。

① LLM(大脑):负责理解用户意图,决定每一步干什么。这是 Agent 的核心驱动力。

② Tools(手脚):负责执行具体操作。LLM说"我要查天气",工具就去调用天气 API;LLM说"我要搜索",工具就去执行搜索。LLM 只负责"想",工具负责"做"。

③ Memory(记忆):负责记住对话历史。没有记忆的话,你上一句说"我叫张三",下一句问"我叫什么名字",它就答不上来了。

④ Planning(规划):负责把复杂任务拆成步骤。在 LangChain 的基础 Agent 里,规划不是单独一个模块,而是融合在 LLM 的推理过程中——它每走一步都想一下"下一步该干啥"。这种方式叫ReAct 模式(边走边看,步步为营)。

四、定义工具:用 @tool 装饰器

工具是 Agent 能"动手做事"的关键。LangChain 里定义工具超级简单,用@tool装饰器包一下普通 Python 函数就行。

fromlangchain.toolsimporttool@tooldefget_weather(city:str,date:str)->str:"""获取指定城市在指定日期的天气。 Args: city: 城市名称,如"北京"、"上海" date: 日期,格式为 YYYY-MM-DD """# 实际项目中调用真实天气 APIreturnf"{city}{date}天气多云,有下雨的可能性。"

就这么几行,LangChain 会自动帮你:

  • 根据函数名生成工具名称
  • 根据 docstring 生成工具描述(LLM 靠这个理解工具是干啥的)
  • 根据参数类型注解生成 JSON Schema(LLM 靠这个知道该传什么参数)

三个影响准确率的关键点:

要素建议
函数名用清晰的动词+名词,如get_weathersearch_documents
docstring写清楚"这个工具做什么",越具体越好
参数注解每个参数都要有类型和说明,LLM 靠这个决定传什么值

经验之谈:docstring 别写太简略。你写"查天气",LLM 可能不知道什么时候该用、该传什么格式的日期。你写"获取指定城市在指定日期的实时天气,返回温度和天气状况",LLM 就清楚多了。

五、构建 Agent:create_agent 一行搞定

工具定义好了,LLM 选好了,组装成 Agent 只需要一行:

fromlangchain.agentsimportcreate_agentfromlangchain.chat_modelsimportinit_chat_model llm=init_chat_model(model="gpt-4o-mini",model_provider="openai")tools=[get_weather,search_tool]# 所有工具放列表里agent=create_agent(model=llm,tools=tools,system_prompt="你是一个智能助手,请根据用户需求调用合适的工具。")

create_agent帮你封装了所有底层细节:

  • 工具描述的自动生成和注入
  • LLM 返回的"工具调用指令"的解析
  • 工具执行结果的回传
  • 循环控制(什么时候继续调工具、什么时候结束)

六、调用 Agent:invoke 和 stream

invoke:一次性拿结果

result=agent.invoke({"messages":[{"role":"user","content":"今天北京的天气怎么样?"}]})print(result["messages"][-1].content)

stream:观察每一步(适合调试)

forstepinagent.stream({"messages":[{"role":"user","content":"今天北京的天气怎么样?"}]}):print(step,end="\n\n")

stream会依次展示:LLM 第一次推理(决定调天气工具)→ 工具返回结果 → LLM 第二次推理(生成最终回复)。开发阶段用它排查问题特别好使。

七、MCP:像插 U 盘一样接入外部工具

前面定义的@tool工具都是写在自己项目里的本地工具。但很多时候你想用的工具是别人已经封装好的——比如查火车票、操作数据库、读取 GitHub 仓库。每个服务的接入方式不一样,如果每接入一个都要写一套适配代码,太累了。

MCP(模型上下文协议)就是来解决这个问题的。它统一了 LLM 和外部工具之间的通信方式,可以理解成 AI 领域的"USB-C 标准"。

MCP 的工作流程

  1. Agent 启动时连接 MCP Server,问"你有哪些工具?"
  2. Server 返回工具列表(工具名 + 描述 + 参数)
  3. Agent 把这些工具描述和用户问题一起发给 LLM(LLM 根本不知道这工具是本地的还是远程的)
  4. LLM 决定调用某个工具,传什么参数
  5. Agent 通过 MCP 协议把调用请求发给 Server
  6. Server 执行并返回结果
  7. Agent 把结果给 LLM,继续推理

LangChain 接入 MCP

fromlangchain_mcp_adapters.clientimportMultiServerMCPClient client=MultiServerMCPClient({"my-local-tools":{"transport":"stdio","command":"python","args":["mcp_server.py"]},"remote-tools":{"transport":"streamable_http","url":"https://xxx.com/mcp"}})tools=awaitclient.get_tools()# 自动获取所有工具agent=create_agent(llm,tools)# 和本地工具一样用

核心价值:一个 Agent 可以同时挂载多个 MCP Server,本地工具和远程工具混合使用。对 Agent 来说没有任何区别。

八、记忆管理:让 Agent 别"失忆"

默认情况下,Agent 每次调用都是独立的——它不记得上一轮说了什么。你上一句说"我叫张三",下一句问"我叫什么名字",它就懵了。

LangChain 通过Checkpointer机制解决这个问题:

fromlanggraph.checkpoint.memoryimportInMemorySaver checkpointer=InMemorySaver()agent=create_agent(model=llm,tools=tools,checkpointer=checkpointer)

每次调用结束后,Checkpointer 自动保存本次对话的所有消息;下次调用时,自动加载历史消息拼接到新的输入前面。LLM 看到的就是"历史消息 + 新消息",自然就"记住"了。

Thread ID 实现多会话隔离

# 用户张三的会话agent.invoke({"messages":[{"role":"user","content":"我叫张三"}]},config={"configurable":{"thread_id":"user_zhangsan"}})# 用户李四的会话(完全独立)agent.invoke({"messages":[{"role":"user","content":"我叫李四"}]},config={"configurable":{"thread_id":"user_lisi"}})

不同thread_id的对话历史互不干扰。

九、中间件:拦截器模式

记忆功能解决了"失忆"问题,但带来了新问题——对话轮次多了,历史消息列表会无限增长。100 轮对话就是 200+ 条消息,每次都发给 LLM,Token 消耗扛不住。

SummarizationMiddleware自动压缩历史消息:

fromlangchain.agents.middlewareimportSummarizationMiddleware middleware=SummarizationMiddleware(model=ChatOpenAI(model="gpt-4o-mini"),trigger=("messages",100)# 消息达到100条时触发压缩)agent=create_agent(model=llm,tools=tools,middleware=[middleware])

压缩效果:100 条消息 → 压缩成一段摘要(系统消息)+ 最近几条消息。Token 消耗大幅降低。

HumanInTheLoopMiddleware人工审核高风险操作:

fromlangchain.agents.middlewareimportHumanInTheLoopMiddleware middleware=HumanInTheLoopMiddleware(interrupt_on={"transfer_money":True,# 转账要审核"delete_record":True,# 删除要审核"get_weather":False# 查天气不需要})

配置后,Agent 调用这些工具时会暂停,等人类确认后才真正执行。

十、一些实用经验

工具设计五原则

  1. 单一职责:一个工具只做一件事。get_weatherget_forecast分开,别搞一个handle_weather_and_forecast_and_alert
  2. 描述清晰:LLM 完全靠描述决定什么时候用工具。"获取指定城市今天的实时天气,返回温度和天气状况"比"查天气"强一百倍
  3. 参数具体date: str = Field(description="日期,格式 YYYY-MM-DD")date: str
  4. 错误友好:返回"城市名’北精’无法识别,你是否指’北京’?"比抛一个KeyError
  5. 幂等安全get_user(id=123)调用多次结果一样,create_order()调用多次会创建多个订单——后者要小心

系统提示词怎么写

好的系统提示词 = 角色定位 + 工作流程 + 约束条件 + 输出格式

你是一个专业的数据分析助手。 工作流程: 1. 理解用户的分析需求 2. 使用 search 工具获取相关数据 3. 使用 calculate 工具进行计算 4. 用简洁的语言呈现结果 注意事项: - 计算结果保留 2 位小数 - 如果数据不足,主动告知用户 - 不要编造数据

调试三板斧

  1. 开启日志logging.basicConfig(level=logging.DEBUG),看每次 LLM 调用的输入输出
  2. LangSmith:可视化追踪每一步,工具选错、参数传错一目了然
  3. stream 代替 invoke:实时观察 Agent 的每一步在想啥、在干啥

大多数 Agent 问题的根源就三类:工具描述不够清晰(LLM 选错工具)、系统提示词不够明确(LLM 执行顺序乱)、工具返回值格式不规范(LLM 看不懂结果)。优先从这三个方向排查。

十一、总结

Agent 的核心就三句话:

  1. 为什么需要 Agent:Chain 只能处理固定流程,动态任务需要 Agent 的自主决策
  2. Agent 是什么:LLM(大脑)+ 工具(手脚)+ 自主决策,通过"感知→推理→行动"循环完成任务
  3. 什么时候用:流程确定用 Chain(简单可靠),需要动态判断用 Agent(灵活但更复杂)

从 Model I/O 到 Chain 到 RAG 到 Agent,我算是把 LangChain 的核心模块都摸了一遍。下一步打算学LangGraph——当 Agent 的流程越来越复杂、需要多个 Agent 协作的时候,LangGraph 能提供更精细的控制。到时候再来分享。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询