Part 4. LangChain 1.0 Agent 开发流程(Markdown 笔记)

主题:LangChain 1.0 全新 Agent 框架、create_agent 的模型接入、工具接入(内置/自定义)、ReAct 循环、记忆管理

关键词:Agent Runtime / LangGraph / Tools / Tool Calling / ReAct Loop / Checkpointer / thread_id


0. 总览:LangChain 1.0 的 Agent 发生了什么变化?

LangChain 1.0 最大的变化之一:Agent 体系被"重做"并"统一"

  • 从"碎片化 Agent" → "统一 create_agent API"

    • 0.x 时代:各种 Agent 创建函数分散(不同范式不同入口),学习与维护成本高。

    • 1.0 时代:官方主推统一入口 create_agent(...),把 Agent 的创建方式"收敛"为一个更统一、可插拔的框架。

  • 从"链式脚本" → "Agent Runtime(运行时)"

    • Agent 不只是模型调用脚本,而更像一个可持续运行、能维护状态、能调度工具、能循环推理的"运行体"。
  • 底层以 LangGraph 为核心

    • 1.0 开始 LangGraph 更像"底座":用图结构组织 Agent 的节点与边(推理、工具调用、状态更新等),使 Agent 更可控、更工程化。

1. LangChain 1.0 最大更新:全新 Agent 框架介绍

1.1 Agent API "大一统":统一为 create_agent

LangChain 1.0 把 Agent 的核心创建方式统一到:

  • create_agent(model=..., tools=[...], system_prompt=..., checkpointer=...)

相比过去"要记住不同 Agent 工厂函数/不同范式",1.0 的目标是:

  • 接口统一:减少分支、降低心智负担

  • 可插拔:模型/工具/记忆都可以灵活替换

  • 可扩展:更适合工程化与生产落地

1.2 create_agent 极简调用流程(核心代码骨架)

Notebook 给出的最小创建流程:模型 + 工具 + system_prompt → agent

python 复制代码
from langchain.agents import create_agent
from langchain_deepseek import ChatDeepSeek
from langchain_community.tools.tavily_search import TavilySearchResults

web_search = TavilySearchResults(max_results=2)
model = ChatDeepSeek(model="deepseek-chat")

agent = create_agent(
    model=model,
    tools=[web_search],
    system_prompt="你是一名多才多艺的智能助手,可以调用工具帮助用户解决问题。"
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "请帮我查询2024年诺贝尔物理学奖得主是谁?"}]}
)

要点:

  • 输入输出遵循 messages 结构(类似 Chat Completions 的对话消息)

  • Agent 内部会根据需要决定是否调用工具,并把工具结果纳入后续推理

1.3 底层架构:LangGraph 作为 Agent Runtime 的支撑

从 1.0 开始:

  • Agent 不再是"线性链式执行"

  • 而是"图结构运行"(节点/边/状态)

带来典型优势:

  1. 接口统一,降低心智负担:开发者更少关心内部差异

  2. 跨生态兼容增强:更容易与不同模型/工具体系对接

  3. 工程化增强:状态管理、循环控制、可观察性更自然

1.4 与 Agents SDK / ADK 的关系(笔记观点)

Notebook 提到:LangChain 1.0 的 create_agent() 在形式上与某些 Agent SDK 风格接近:
"传入模型 + 工具 + 说明 → 返回可交互 Agent 实例"


2. create_agent API:模型接入方法(静态 / 动态)

2.1 Agent Loop(智能体循环)的核心理解

Agent 并非"一次模型调用结束",而是一个循环结构(Agent Loop):

  • 模型读入当前上下文(messages + 状态)

  • 推理是否要调用工具

  • 调用工具、获得 observation(工具返回)

  • 结合 observation 再推理

  • 不断迭代,直到满足停止条件(给出最终回答)

2.2 两种模型接入模式

A) 静态模型(Static Model)

特点:模型固定,适合快速 demo 与多数稳定生产场景。

方式 1:直接传字符串(框架自动映射/补全标识的思路)

  • 你只需要传一个模型名,LangChain 会推断完整标识(Notebook 举了 deepseek 的例子)。

方式 2:先实例化模型对象,再传入

python 复制代码
model = ChatDeepSeek(model="deepseek-chat")
agent = create_agent(model=model, tools=[...])
B) 动态模型(Dynamic Model)

特点:可根据上下文/阶段切换模型(成本与效果平衡)

  • 例如:

    • 对话初期用小模型省钱

    • 推理变复杂再切到强模型

Notebook 更强调概念与价值:动态模型更适合"复杂任务与成本优化"。


3. create_agent 接入内置工具与 Agent 创建流程

3.1 为什么工具接入是 Agent 的关键?

Notebook 直接点明:

  • 如果只是模型调用,用 model.invoke 就够了

  • 要做 Agent(能行动、能执行任务)就必须接入工具 Tools

3.2 LangChain 常见内置工具类型(Notebook 表格总结)

领域 工具示例 功能说明
搜索与检索 DuckDuckGo / Brave / Bing 联网问答、检索网页摘要与链接
网页浏览提取 Playwright / Selenium 自动化访问、抓取文本、截图等
生产力集成 Slack / Jira / Google Drive 读写消息、工单、文档、文件检索
数据库与向量检索 SQLDatabase / Faiss/Chroma/Milvus SQL 查询、向量相似检索(RAG)
代码与终端执行 Python REPL / Shell / Requests 运行代码、执行命令、发 HTTP 请求
多模态 DALL·E / Image Search / Whisper 文生图、图片搜索、语音转文本
知识检索增强 VectorStoreRetriever / MultiQuery 文档片段检索、多查询扩展
云与 AI 服务 OpenAI/Azure Functions / Anthropic 调用函数、工具调用能力集成
文件与数据处理 CSV Toolkit / Pandas DF Tool 表格分析、过滤、统计等

示例中重点演示:TavilySearchResults(联网搜索工具)

3.3 内置工具示例:Tavily 搜索工具

初始化工具并直接调用工具:

python 复制代码
from langchain_community.tools.tavily_search import TavilySearchResults
web_search = TavilySearchResults(max_results=2)

web_search.invoke("请问截至目前,2025年诺贝尔奖颁发了几个?")

3.4 把内置工具接入 Agent(完整流程)

python 复制代码
from langchain.agents import create_agent
from langchain_deepseek import ChatDeepSeek
from langchain_community.tools.tavily_search import TavilySearchResults

web_search = TavilySearchResults(max_results=2)
model = ChatDeepSeek(model="deepseek-chat")

agent = create_agent(
    model=model,
    tools=[web_search],
    system_prompt="你是一名多才多艺的智能助手,可以调用工具帮助用户解决问题。"
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "请帮我查询2024年诺贝尔物理学奖得主是谁?"}]}
)

3.5 result["messages"]:理解 Agent 的"过程输出"

Notebook 后面逐个查看了:

  • result['messages']

  • len(result['messages'])

  • result['messages'][0/1/2/3]

这暗示一个重要点:

  • Agent 输出不仅有最终回答,还可能包含:

    • 用户输入消息

    • 模型的中间响应

    • 工具调用请求(tool call)

    • 工具返回(observation)

    • 最终总结回答

调试 Agent 时,messages 是最关键的可观察对象


4. create_agent 接入自定义工具 & ReAct 循环介绍

4.1 自定义工具的本质

工具 = 一个可被 Agent 调用的函数(带清晰输入输出约束)

Notebook 给了两个工具案例:

  1. get_weather(loc):调用 OpenWeather API 查天气

  2. write_file(content):写入本地文件

4.2 自定义工具示例 1:天气查询(requests 调 API)

(原始函数版本)

python 复制代码
def get_weather(loc):
    url = "https://api.openweathermap.org/data/2.5/weather"
    params = {
        "q": loc,
        "appid": os.getenv("OPENWEATHER_API_KEY"),
        "units": "metric",
        "lang": "zh_cn"
    }
    response = requests.get(url, params=params)
    data = response.json()
    return json.dumps(data)

关键点:

  • 通过环境变量读取 OPENWEATHER_API_KEY

  • 返回 JSON(字符串化)作为工具输出,便于模型消费

4.3 用 @tool 把函数"工具化"

LangChain 需要知道:

  • 这个函数可以被工具调用

  • 其参数与返回值是什么

Notebook 的做法:

python 复制代码
from langchain.tools import tool

@tool
def get_weather(loc):
    ...

4.4 自定义工具示例 2:写文件工具(强调健壮性)

python 复制代码
@tool
def write_file(content: str) -> str:
    try:
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"output_{timestamp}.txt"

        with open(filename, "w", encoding="utf-8") as f:
            f.write(content)

        abs_path = os.path.abspath(filename)
        return f"✅ 已成功写入本地文件:{abs_path}"
    except Exception as e:
        return f"❌ 文件写入失败:{str(e)}"

这里有个工程细节非常重要(Notebook 特意标注 ✅):

  • 先定义 filename/timestamp,避免异常路径下变量未绑定

4.5 把多个自定义工具接入 Agent,并触发"多步任务"

python 复制代码
agent = create_agent(
    model=model,
    tools=[get_weather, write_file],
    system_prompt="你是一名多才多艺的智能助手,可以调用工具帮助用户解决问题。"
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "请帮我查询天津、石家庄、上海等地天气,并写入本地文件。"}]}
)

这类任务通常会触发典型的 ReAct / Agent Loop:

  • 先规划:要查多个城市

  • 多次调用 get_weather

  • 汇总成一段内容

  • 调用 write_file 写入落盘

  • 最后把结果路径/摘要回复用户

4.6 ReAct 循环(你需要把它当成"运行机制"而不是"提示词技巧")

虽然 Notebook 没把 ReAct 展开成公式,但从"工具调用 + observation + 再推理"的 messages 过程可以直接理解:

  • Reason(推理):决定下一步做什么

  • Act(行动):调用哪个工具、传什么参数

  • Observe(观察):读取工具返回

  • 循环直到完成目标


5. create_agent 记忆管理(Memory / Checkpointer)

5.1 为什么需要记忆?

真实 Agent 场景里必须解决:

  • 多轮对话上下文

  • 状态持久化(同一会话 thread)

  • 多用户/多线程隔离

Notebook 用 LangGraph 的 checkpointer 做记忆保存。

5.2 InMemorySaver:最小可用的"内存型 checkpoint"

python 复制代码
from langgraph.checkpoint.memory import InMemorySaver
checkpointer = InMemorySaver()

tools = [get_weather]
agent = create_agent(model=model, tools=tools, checkpointer=checkpointer)

要点:

  • checkpointer 负责保存/恢复状态

  • InMemorySaver 适合 demo(进程重启就没了),生产一般换持久化实现

5.3 用 thread_id 区分会话(同一 thread 才能"记得你")

同一 thread:记忆生效
python 复制代码
config = {"configurable": {"thread_id": "1"}}

response = agent.invoke(
    {"messages": [{"role": "user", "content": "你好,我叫陈明,好久不见!"}]},
    config
)

response = agent.invoke(
    {"messages": [{"role": "user", "content": "你好,请问你还记得我叫什么名字么?"}]},
    config
)

并可读取当前线程状态:

python 复制代码
latest = agent.get_state(config)
不同 thread:重新开一段新对话(记忆隔离)
python 复制代码
config2 = {"configurable": {"thread_id": "2"}}

response2 = agent.invoke(
    {"messages": [{"role": "user", "content": "你好,你还记得我叫什么名字么?"}]},
    config2
)

核心结论:

  • thread_id 是"记忆作用域"的关键开关

  • 同 thread = 共享记忆;不同 thread = 互相隔离


6. 开发清单(按 Notebook 流程提炼)

  1. 准备环境变量

    • 模型 key / 工具 key(如 OpenWeather、Tavily 等)
  2. 选择模型接入方式

    • 静态模型(简单稳定)

    • 动态模型(成本/能力自适应)

  3. 准备工具

    • 先用内置工具验证流程(如 Tavily)

    • 再写自定义工具(用 @tool 包装)

  4. 创建 Agent

    • create_agent(model, tools, system_prompt, checkpointer)
  5. 调试与可观察性

    • 重点看 result["messages"] 的全过程
  6. 上线前补齐记忆/状态

    • checkpointer + thread_id 做多轮会话隔离与记忆
相关推荐
Aliex_git2 小时前
性能优化 - 渲染优化
前端·javascript·笔记·学习·性能优化·html
Jenlybein2 小时前
Git 仓库过滤敏感信息,通过配置 clean/smudge 过滤器的方式
前端·后端·github
TonyLee0172 小时前
测试数据集
python
nvd112 小时前
基于 LangChain + Gemini + CloudSQL (pgvector) 的 RAG 实现指南
数据库·langchain
wdfk_prog2 小时前
[Linux]学习笔记系列 -- [fs]pidfs
linux·笔记·学习
woodykissme2 小时前
数控车刀片选型学习笔记
笔记·学习
啃火龙果的兔子2 小时前
Pyglet开发游戏流程详解
python·游戏·pygame
航Hang*2 小时前
第十三章:网络系统建设与运维(高级)—— 路由控制和策略路由
运维·服务器·网络·笔记·ensp
千寻girling2 小时前
面试官 : “ 说一下 Vue 的 8 个生命周期钩子都做了什么 ? ”
前端·vue.js·面试