Agent范式与LangGraph-②零基础保姆级教程

第 5 章:为什么需要框架 ------ 手搓的六道坎

手搓了 ReAct、工具循环、Agentic RAG------够用了吗? 把系统推向生产时会撞上六道坎:

  1. 状态管理乱:messages、scratchpad、检索结果、计划清单......全是散装变量,流程一复杂就成面条代码;
  1. 流程不可视:口头说"先规划再执行遇错反思",代码里却是嵌套 if/while,新同事看三天;
  1. 挂了不能续:跑到第 8 步崩了/用户关了页面,只能从头再来------长任务不可接受;
  1. 没法暂停等人 :"人工确认"是靠工具返回话术软实现的,无法真正暂停进程等审批
  1. 多会话隔离:一百个用户同时用,各自的状态怎么存、怎么取?
  1. 可观测性:哪一步慢了、贵了、错了?打印大法撑不住生产。

LangGraph 的答案 :把 Agent 建模成状态图(State Graph) ------状态集中定义、流程显式画成节点和边、每步自动存档(Checkpoint)、原生支持暂停/恢复/人工介入、按 thread_id 天然隔离会话、每步可追踪。接下来五章,你手搓过的每样东西都会在图上找到自己的工位。


第 6 章:LangChain 核心件速通 ------ Model / Prompt / Tool / LCEL

定位校准:2026 年的正确姿势是"LangChain 当零件库用,LangGraph 当装配线用"。所以本章只速通四个真正高频的零件------每个都会立刻映射到你手搓过的东西。

6.1 Model:统一的模型接口

python 复制代码
import os
from langchain_openai import ChatOpenAI     # pip install langchain-openai

llm = ChatOpenAI(
    model="deepseek-chat",
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com",     # 老规矩:换平台改两个字符串
    temperature=0.3,
)
resp = llm.invoke("用一句话解释LangGraph")     # 简单场景直接传字符串
print(resp.content)                           # 返回的是 AIMessage 对象

消息对象化 :LangChain 把 {"role": "user", ...} 字典升级成了类------SystemMessage / HumanMessage / AIMessage / ToolMessage,与你熟悉的四种 role 一一对应;AIMessage.tool_calls 是解析好的申请单列表({"name", "args", "id"}args 已经是 dict,不用再 json.loads------框架替你做了)。字典写法在 1.x 里也仍然兼容,两种都要认识。

6.2 Tool:@tool 装饰器

python 复制代码
from langchain_core.tools import tool

@tool
def get_weather(city: str) -> str:
    """查询指定城市当前实时天气。用户询问天气/气温/穿衣建议时使用。"""
    import requests
    r = requests.get(f"https://wttr.in/{city}?format=3", timeout=10)
    return r.text.strip()

print(get_weather.name)          # get_weather
print(get_weather.args_schema.model_json_schema())   # schema 自动生成了!

@tool函数签名(类型注解)+ docstring,自动生成你那坨 JSON Schema------ "docstring 会被喂给大模型",至此完全兑现。绑定到模型:

python 复制代码
llm_with_tools = llm.bind_tools([get_weather])
ai_msg = llm_with_tools.invoke("上海热不热")
print(ai_msg.tool_calls)     # [{'name': 'get_weather', 'args': {'city': '上海'}, 'id': ...}]

6.3 Prompt 模板与 LCEL 管道(看懂即可,重度使用在图里)

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是{role},回答不超过50字"),
    ("user", "{question}"),
])
chain = prompt | llm | StrOutputParser()       # LCEL:用 | 把组件接成流水线
print(chain.invoke({"role": "宋朝诗人", "question": "什么是AI"}))

| 管道(LCEL)= "上一个的输出当下一个的输入",并白送 .invoke/.stream/.batch/.ainvoke 四件套。认知边界:LCEL 适合线性流程;有分支、循环、状态的一律上 LangGraph------官方 1.x 也是这么划的地界。

6.4 结构化输出的框架姿势

python 复制代码
from pydantic import BaseModel, Field

class Plan(BaseModel):
    steps: list[str] = Field(description="按顺序执行的步骤清单,每步一句话")

planner = llm.with_structured_output(Plan)          # 底层自动走FC或JSON Mode
plan = planner.invoke("帮我调研'2026国产大模型价格战'并写份简报,先列执行计划")
print(plan.steps)                                    # 直接就是校验好的 Plan 对象!

with_structured_output(PydanticModel) = 你手写的"schema 提示 + JSON Mode + 校验 + 重试"一条龙。


第 7 章:LangGraph 起步 ------ State / Node / Edge 三件套

7.1 心智模型:Agent = 一张会流转状态的图

复制代码
LangGraph 三件套
├── State(状态):一个 TypedDict ------ 全流程共享的"公共白板"
├── Node(节点):普通Python函数 ------ 读白板、干活、返回"要更新白板的哪几格"
└── Edge(边):节点间的连线 ------ 固定边(必经) / 条件边(看白板内容选路)
运行 = 状态沿着边在节点间流动,每个节点改一点白板,直到走到 END

7.2 第一张图:三节点流水线(先不带 AI,纯理解机制)

python 复制代码
"""first_graph.py"""
from typing import TypedDict
from langgraph.graph import StateGraph, START, END

class State(TypedDict):          # ① 定义白板的格子
    topic: str
    outline: str
    article: str

def make_outline(state: State) -> dict:          # ② 节点=函数:入参是整个白板
    print("  [节点] 生成大纲")
    return {"outline": f"《{state['topic']}》三段式大纲"}   # 只返回要更新的格子!

def write_article(state: State) -> dict:
    print("  [节点] 依据大纲写正文")
    return {"article": f"根据[{state['outline']}]写出的正文..."}

builder = StateGraph(State)                       # ③ 搭图
builder.add_node("outline", make_outline)
builder.add_node("write", write_article)
builder.add_edge(START, "outline")                # START→outline→write→END
builder.add_edge("outline", "write")
builder.add_edge("write", END)
graph = builder.compile()                         # ④ 编译成可执行对象

result = graph.invoke({"topic": "AI Agent 的一天"})   # ⑤ 给初始状态,开跑
print(result)                                     # 终态白板:三个格子都填上了

四条核心规则(背下):

  • 节点函数返回"增量字典",不是整个 State------LangGraph 负责合并进白板;
  • 默认合并方式 = 覆盖(后写的盖前写的);
  • compile() 之前是图纸,之后才是机器;
  • graph.get_graph().draw_mermaid() 能吐出流程图代码------粘进任何 Mermaid 预览器就是架构图,写文档/答辩神器。

7.3 Reducer:改写"合并规则"------add_messages 的真身

对话场景下,白板里的 messages 每次都被覆盖 就完了------我们要的是追加 。LangGraph 用 Annotated 给格子指定专属合并函数(reducer):

python 复制代码
from typing import Annotated
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages

class ChatState(TypedDict):
    messages: Annotated[list, add_messages]    # 合并规则=追加(且按消息id去重/更新)

def chatbot(state: ChatState) -> dict:
    reply = llm.invoke(state["messages"])       # llm 直接吃消息列表
    return {"messages": [reply]}                # 只返回新消息,reducer 负责append

builder = StateGraph(ChatState)
builder.add_node("chatbot", chatbot)
builder.add_edge(START, "chatbot")
builder.add_edge("chatbot", END)
graph = builder.compile()

out = graph.invoke({"messages": [{"role": "user", "content": "你好,我叫王小明"}]})
print(out["messages"][-1].content)

看懂 Annotated[list, add_messages]这一行,你就看懂了 LangGraph 一半的示例代码 ------它宣告:这格是消息列表,更新方式是智能追加。(官方还提供了内置的 MessagesState 类,就是上面两行的预制版,class MyState(MessagesState): 其它字段... 继承着用即可

相关推荐
白色机械键盘24 分钟前
LangGPT结构化提示词工程:从手写提示词到模块化编程的范式升级
人工智能
熙丫 1338148238626 分钟前
AI前沿部署工程师(FDE)适合谁考?工信部教考中心高级证书,打通大模型落地最后一公里
人工智能
ShallWeL33 分钟前
RAG 文档变更后的检索回归清单
人工智能·agent·知识库·rag·检索
Hrain-AI34 分钟前
企业 AI 治理运营怎么做:分级授权、Token 用量可观测与模型统一纳管
大数据·人工智能·算法
2401_8652616338 分钟前
亦唐科技:创新驱动下的国产贴片机领航者
人工智能
Mr数据杨39 分钟前
【CanMV K210】硬件基础 面包板连通规则与无焊接电路搭建
人工智能·硬件开发·canmv k210
长江后浪博客1 小时前
陶瓷浮雕盘印刷视觉定位方案:8K线扫相机 + 暗场光源 + 旋转平台
人工智能·数码相机·机器视觉·视觉定位·线扫相机·暗场光源·陶瓷印刷
江苏赛融科技1 小时前
数据驱动:能耗管理系统如何将能源数据转化为管理决策资产
大数据·人工智能·能源·智慧园区·企业资产管理·园区智能化
LFly_ice1 小时前
Langchain-05 消息
langchain