本节摘要:LangChain 的演进有五个已经发生的方向——链结构走向图结构、代理协议走向原生函数调用、可观测性成为标配、检索增强走向精细化、框架能力走向平台化。本节逐个讲清动因与代码形态的变化,最后给一个"学不变量、不追新接口"的判断框架。
谈趋势容易变成算命,所以本节只讲代码里已经留下痕迹的分流:你今天写的链,哪些部分两年后大概率还在,哪些部分明年就可能换写法。判断依据不是官方路线图(那会变),而是结构性压力——什么任务在现有结构里真的卡住了。
链式结构的隐含假设是单向流动:工艺单进、答案出,一站接一站。但有两类任务天然不是单向的——需要循环的任务(写完自检、不过重写),需要人工介入的任务(关键操作前请人确认)。在纯链结构里硬做循环,代码会扭曲成"递归调用自己"的怪样。
于是生态里长出了图结构的组件:把"节点"和"边"显式化,循环与分支成为一等公民。看一个最小例子,体会"图"和"链"的差别:
# 生态中的图组件(独立分包 需单独安装) from langgraph.graph import StateGraph, END from typing_extensions import TypedDict # 状态:在节点之间流转的共享工作台 class State(TypedDict): draft: str ok: bool def write(state: State): # 起草节点:产出初稿 return {"draft": "初稿:本季棉袜采用新疆长绒棉……"} def review(state: State): # 审查节点:判定是否合格(示意) return {"ok": "长绒棉" in state["draft"]} graph = StateGraph(State) graph.add_node("write", write) graph.add_node("review", review) graph.set_entry_point("write") graph.add_edge("write", "review") # 条件边:不合格回到起草 循环在这里发生 graph.add_conditional_edges( "review", lambda s: "write" if not s["ok"] else END) app = graph.compile() print(app.invoke({"draft": "", "ok": False})["draft"]) # 输出:初稿:本季棉袜采用新疆长绒棉……
对照第2章的链:链用管道符连接、数据单向流;图要显式声明节点、边与条件跳转,换来的是循环与人工介入不再别扭。如果你的业务是固定流程(分类、抽取、固定话术),留在链结构里更简单;一旦出现"做不好就重来"的需求,就是该考虑图的时候。
旧式代理靠文本协议工作:让模型输出一段"想法加工具名加参数"的文本,框架再解析这段文本。协议靠提示词约定,模型偶尔写出格式跑偏的句子,解析就崩。
新的分流是直接用模型原生的函数调用能力:工具列表随请求发给模型,模型返回结构化的调用请求,解析这一步整个消失:
from langchain_openai import ChatOpenAI from langchain_core.tools import tool @tool def get_weather(city: str) -> str: """查询指定城市的当前天气。""" return f"{city}:晴,26 摄氏度" llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0) # 绑定工具:不再是文本约定 而是原生调用请求 llm_with_tools = llm.bind_tools([get_weather]) msg = llm_with_tools.invoke("北京今天天气怎么样") print(msg.tool_calls[0]["name"], msg.tool_calls[0]["args"]) # 输出示例:get_weather {'city': '北京'}
对学习者的含义:第2章讲的代理执行循环(模型决策与工具执行交替)依然成立,变的只是"决策如何表达"。你掌握了循环骨架,协议换代只是换皮。
前几年的应用多半"跑通即黑箱",排错靠 print。现在风向明确:每次调用自动上报轨迹,成为框架的默认能力。接入只要两个环境变量:
import os # 打开轨迹上报:此后每次链调用都会记录完整链路 os.environ["LANGCHAIN_TRACING_V2"] = "true" os.environ["LANGCHAIN_API_KEY"] = "你在观测平台申请的密钥" # 无需改任何链代码 下一行调用就会出现在平台的时间线上 # qa_chain.invoke("定制款能退吗") print("追踪已开启") # 输出:追踪已开启
这股风潮的根源是成本:模型调用按次计费,看不见链路就看不见钱花在哪。3.4 节的回调日志是"自己搭仪表",观测平台是"整车自带黑匣子"——两者不冲突,前者定制、后者省事。
还有两股分流值得记下。检索增强走向精细化:朴素检索(切块、嵌入、取前三)已是及格线,竞争转向重排序、混合检索(语义加关键词)、评估驱动的调参——本质是把 3.3 节的质检思维搬到检索环节。框架能力走向平台化:托管运行、模板市场、可视化编排陆续出现,框架在从"给程序员的库"变成"给团队的平台"。对这两股,跟踪即可,不必抢先——它们改变的是使用成本,不是装配线的本质。
| 类别 | 内容 | 两年后的命运 |
|---|---|---|
| 不变量 | 组装思维:零件职责、接口约定、输入输出类型 | 大概率还在 |
| 不变量 | 评估、调试、安全的工程纪律 | 越来越重要 |
| 半变量 | 具体导入路径、类名、构造参数 | 随版本漂移 |
| 快变量 | 新组件名、新平台功能 | 随时可能换代 |
本教程把大量篇幅花在"为什么这个零件存在"而不是"这个方法怎么拼写"上,原因就在这张表:接口会过期,结构不会。你背下的每个类名都可能被替换,但你建立的产线图纸——谁负责什么、数据怎么流、坏了从哪查——会跟着你迁移到任何后续框架。
💡 判断要不要学一个新组件的三个问题:它替换了图纸上哪个工位?没有它时这个工位怎么干?它的接口约定和其他零件一致吗?三个都答得上来再投入,答不上来就先观望——新东西永远学不完,工位只有那几个。
把 2.4 节的旧式代理代码与本章的原生函数调用写法各跑一遍同一个小任务,观察输出格式的差别(文本协议对结构化调用)。再打开轨迹上报,在观测平台回放一次完整调用。两件事做完,你对"分流"二字就有体感了。下一节换话题:面对快速演进的生态,你的补给线该怎么搭——学习资源这么多,先读哪个、怎么判断新旧。