第一性原理分析:LangChain
第一步:问题是什么?
假设你已经掌握了提示词工程,能够通过精心设计的提示词让大模型完成各种任务。但你很快会发现几个新的问题:
问题 1:单次对话有长度限制 你有一本 500 页的 PDF,想让它总结核心内容。但大模型的上下文窗口有限(比如 128K tokens),放不下一整本书。你需要一种方法处理超出上下文窗口的内容。
问题 2:模型没有长期记忆 你和 AI 聊了半小时,它记得刚才说过什么。但明天你再回来,它忘得一干二净。你需要一种方法让 AI 记住跨会话的信息。
问题 3:模型不能主动采取行动 你想让 AI 帮你查今天的天气、订餐厅、发邮件。它说"好的,我帮你查",但实际上它只是生成文字,不会真的调用天气 API、不会真的操作你的邮箱。你需要一种方法让 AI 能调用外部工具。
问题 4:复杂任务需要多步协作 你想让 AI 写一份市场分析报告:先搜资料、再分析数据、然后写报告、最后检查格式。单个提示词搞不定,你需要把多个步骤串联起来。
问题 5:同样的事要反复做 你每天都要处理类似的文档:读 PDF、提取要点、翻译成英文、保存到数据库。每次写提示词太累,你需要把流程固定下来,重复使用。
所以问题来了:如何把大模型的能力从"单次对话"扩展成"可组合、可记忆、可行动、可重复的应用程序"? 这就是 LangChain 要解决的问题。
第二步:从零设计,我们需要什么?
假设我们要从零设计一个框架,把大模型变成真正的应用开发平台,从最基本的需求推导:
需求 1:模型抽象(Model Abstraction)
不同的大模型(OpenAI、Claude、LLaMA)有不同的 API、不同的参数、不同的定价。我们不能让应用代码直接依赖某个具体模型,需要统一接口,想换模型时只需改一行配置。
需求 2:提示词管理(Prompt Management)
提示词会变得越来越长、越来越复杂:
- 系统提示词(角色设定)
- 用户输入(动态内容)
- 示例(少样本学习)
- 格式指令(输出格式)
我们需要一种结构化组织提示词的方式,而不是用字符串拼接。
需求 3:记忆机制(Memory)
应用需要记住对话历史:
- 短期记忆:当前对话的上下文
- 长期记忆:跨会话的用户偏好、历史记录
- 向量记忆:把历史信息存成向量,需要时检索相关部分
需求 4:链式组合(Chaining)
复杂任务需要多个步骤:
- 步骤1:检索相关信息
- 步骤2:基于信息生成答案
- 步骤3:检查答案质量
- 步骤4:格式化输出
我们需要一种把多个组件串成流水线的方式。
需求 5:工具调用(Tools)
AI 需要能与外部世界交互:
- 调用 API(天气、搜索、数据库)
- 执行代码(Python 解释器)
- 操作文件(读写、转换)
- 发送通知(邮件、消息)
我们需要让 AI 能决定何时调用什么工具,并处理返回结果。
需求 6:文档处理(Document Loaders)
AI 经常需要处理各种格式的外部文档:
- PDF、Word、Excel
- 网页、数据库
- 音视频(转录)
我们需要统一加载和分割文档的方式。
需求 7:检索增强生成(RAG)
当模型不知道答案时,需要从外部知识库检索相关信息:
- 把文档切成小块
- 转成向量存入数据库
- 根据问题检索相关块
- 把检索结果作为上下文交给模型
这是解决"模型知识有限"和"处理超长文档"的核心方法。
需求 8:智能体(Agent)
有时候你不知道任务需要几步完成。让 AI 自己决定:
- 分析任务
- 决定需要什么工具
- 调用工具获取信息
- 基于结果决定下一步
我们需要让 AI 拥有自主决策能力。
第三步:LangChain 的核心设计原理
基于以上需求,LangChain 的设计思路就很清晰了:
核心原理 1:组件化(Modularity)- 一切皆可组合
LangChain 把 AI 应用拆解成最基本的组件,每个组件解决一个单一问题:
| 组件类型 | 作用 | 例子 |
|---|---|---|
| Models | 与大模型交互的统一接口 | OpenAI、Claude、LLaMA |
| Prompts | 管理和结构化提示词 | PromptTemplate、ChatPromptTemplate |
| Memory | 存储和检索对话历史 | BufferMemory、VectorStoreMemory |
| Chains | 把多个组件串联起来 | LLMChain、SequentialChain |
| Tools | AI 可调用的外部功能 | SearchTool、CalculatorTool |
| Agents | 自主决策使用哪些工具 | ReActAgent、PlanAndExecuteAgent |
| Document Loaders | 加载各种格式的文档 | PDFLoader、WebBaseLoader |
| Vector Stores | 存储和检索向量 | Chroma、FAISS、Pinecone |
| Output Parsers | 解析和格式化模型输出 | JSONParser、PydanticParser |
这些组件像乐高积木,你可以自由组合,构建复杂的应用。
核心原理 2:提示词模板化(Prompt Templating)- 结构化提示词
与其用字符串拼接,LangChain 提供结构化的提示词模板:
# 不好的方式:字符串拼接
prompt = f"你是一个{role}。请回答这个问题:{question}"
# LangChain 的方式:结构化模板
from langchain.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个{role},擅长用{style}的风格回答问题。"),
("human", "我的问题是:{question}"),
("ai", "让我思考一下..."),
("human", "请直接回答,不需要思考过程"),
])
# 使用时传入变量
formatted_prompt = prompt.format_messages(
role="历史老师",
style="生动有趣",
question="解释一下工业革命的影响"
)
为什么有效?
- 把提示词结构从代码中分离出来,易于维护
- 支持多轮对话的结构化表达
- 变量注入清晰,避免字符串拼接错误
核心原理 3:链式组合(Chaining)- 把组件串成流水线
LangChain 的核心概念是"链"(Chain):一个链可以包含多个步骤,每个步骤的输出是下一个步骤的输入。
from langchain.chains import LLMChain, SimpleSequentialChain
# 链1:生成一个笑话
chain1 = LLMChain(
llm=llm,
prompt=PromptTemplate.from_template("讲一个关于{topic}的笑话")
)
# 链2:评价这个笑话
chain2 = LLMChain(
llm=llm,
prompt=PromptTemplate.from_template("评价这个笑话:{joke}。给出 1-10 的评分并解释。")
)
# 串联起来
overall_chain = SimpleSequentialChain(chains=[chain1, chain2])
result = overall_chain.run("程序员")
为什么有效?
- 把复杂任务分解成简单步骤
- 每个步骤可以单独测试和优化
- 支持多种组合方式(顺序、条件、映射)
核心原理 4:记忆抽象(Memory Abstraction)- 多种记忆方式
LangChain 提供多种记忆实现,适应不同场景:
# 1. 缓冲区记忆:记住最近几轮对话
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(k=5) # 记住最近5轮
# 2. 向量存储记忆:把历史存入向量库,检索相关部分
from langchain.memory import VectorStoreRetrieverMemory
memory = VectorStoreRetrieverMemory(retriever=retriever)
# 3. 摘要记忆:把历史总结成摘要
from langchain.memory import ConversationSummaryMemory
memory = ConversationSummaryMemory(llm=llm)
# 4. 组合记忆:多种记忆方式结合
from langchain.memory import CombinedMemory
memory = CombinedMemory(memories=[buffer_memory, summary_memory])
为什么有效? 不同的应用需要不同的记忆方式:
- 客服机器人:需要记住最近几轮对话(缓冲区)
- 个人助手:需要记住用户偏好(向量检索)
- 长对话:需要摘要来压缩信息(摘要记忆)
核心原理 5:检索增强生成(RAG)- 让模型"先查后答"
这是 LangChain 最强大的功能之一:当模型不知道答案时,从外部知识库检索相关信息。
# 1. 加载文档
loader = PDFLoader("manual.pdf")
documents = loader.load()
# 2. 分割文档
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000)
docs = text_splitter.split_documents(documents)
# 3. 创建向量存储
vectorstore = Chroma.from_documents(docs, embeddings_model)
# 4. 创建检索器
retriever = vectorstore.as_retriever()
# 5. 创建 RAG 链
from langchain.chains import RetrievalQA
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff", # 把检索到的文档"塞"进提示词
retriever=retriever
)
# 6. 提问
answer = qa_chain.run("如何设置用户权限?")
为什么有效?
- 解决知识局限:模型只能记住训练时的知识,RAG 让它能访问最新文档
- 解决长度限制:把长文档切成小块,只检索相关部分
- 可追溯:你知道模型是基于哪些文档回答的,减少幻觉
核心原理 6:工具调用(Tool Calling)- 让 AI 能动手做事
LangChain 让 AI 可以调用外部工具:
from langchain.agents import Tool, AgentExecutor, create_react_agent
# 定义工具
tools = [
Tool(
name="Search",
func=search_api.search,
description="搜索互联网获取最新信息"
),
Tool(
name="Calculator",
func=lambda x: eval(x),
description="计算数学表达式"
),
Tool(
name="Weather",
func=weather_api.get_weather,
description="查询天气"
)
]
# 创建智能体
agent = create_react_agent(llm, tools, prompt)
# 执行
agent_executor = AgentExecutor(agent=agent, tools=tools)
result = agent_executor.invoke({
"input": "北京今天天气怎么样?顺便帮我算一下 25 的平方根是多少?"
})
为什么有效?
- 扩展能力:AI 不再只是"说话",而是能"行动"
- 实时信息:通过搜索工具获取最新信息
- 精确计算:通过计算器工具避免数学错误
核心原理 7:智能体(Agent)- 让 AI 自主决策
智能体是 LangChain 最复杂的组件:它不是按固定流程执行,而是让 AI 自己决定下一步做什么。
from langchain.agents import create_react_agent
from langchain.agents import AgentExecutor
# ReAct 模式:Reason + Act
# 1. 思考:我需要查天气
# 2. 行动:调用天气工具
# 3. 观察:得到天气数据
# 4. 思考:还需要查航班吗?
# 5. 行动:调用航班工具
# 6. 思考:信息够了,可以回答
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = agent_executor.invoke({
"input": "我明天要去北京开会,帮我看看天气适合穿什么,再查一下最近的航班"
})
为什么有效?
- 灵活性:不需要预先定义所有步骤
- 适应性:根据中间结果调整后续行动
- 解决复杂问题:多步推理+工具调用结合
核心原理 8:回调系统(Callbacks)- 可观测性
LangChain 提供完整的回调系统,让你能监控每一步的执行:
from langchain.callbacks import StdOutCallbackHandler, FileCallbackHandler
# 控制台输出
handler = StdOutCallbackHandler()
# 文件日志
file_handler = FileCallbackHandler("execution.log")
# 执行时可传入回调
chain.run(input="问题", callbacks=[handler, file_handler])
可以看到:
- 调用了什么模型?花了多少 token?
- 检索了哪些文档?相似度分数?
- 智能体想了什么?调了什么工具?
- 每一步花了多长时间?
为什么有效? 调试 AI 应用比传统应用更难,因为是非确定性的。回调系统让你能追踪执行过程,理解 AI 为什么这样回答。
第四步:用简单比喻理解 LangChain
想象 LangChain 是一个智能厨房:
- Models:你的厨师(可以是中国厨师、法国厨师、素食厨师,但他们都用同样的方式听你指令)
- Prompts:菜谱(不是随口说"做道菜",而是有步骤、有配料的完整菜谱)
- Memory:厨师的记忆力(记得你上次喜欢什么口味,记得今天已经做过什么菜)
- Chains:烹饪流程(洗菜→切菜→炒菜→装盘,每一步有先后顺序)
- Tools:厨房工具(刀、锅、烤箱、秤,厨师需要时会用)
- Agents:自主厨师(你只说"做一顿健康的晚餐",他决定做什么菜、用什么工具、按什么顺序)
- Document Loaders:食材采购员(去不同地方采购:菜市场、超市、网上)
- Vector Stores:食材冷库(把食材切好分类存放,需要时快速取出)
- RAG:先查菜谱再做菜(不确定的菜先翻菜谱书,找到相关步骤再动手)
你可以自己决定:
- 只用厨师(直接调用模型)
- 给厨师菜谱(提示词模板)
- 给厨师流程(链)
- 给厨师工具(工具)
- 让厨师自己决定(智能体)
LangChain 就是帮你组装这个智能厨房的框架。
第五步:LangChain 的本质是什么?
用第一性原理来看,LangChain 的本质是:一个用于构建基于大语言模型应用的组件化编排框架。
这个定义包含几个关键点:
1. 组件化
它不重新发明轮子,而是把 AI 应用开发中反复出现的模式抽象成可复用的组件:
- 模型调用
- 提示词管理
- 记忆存储
- 文档处理
- 工具调用
- 决策逻辑
2. 编排
它的核心不是组件本身,而是如何把这些组件组合起来:
- 链式编排:固定流程
- 智能体编排:动态决策
- 回调编排:可观测性
3. 框架
它提供的是骨架和规范,不是完整的应用:
- 定义了组件接口
- 提供了标准实现
- 允许自定义扩展
- 处理了通用问题(如 token 计数、重试、错误处理)
4. 大语言模型为中心
所有设计都围绕一个核心:让大模型更好地集成到应用中。
- 模型是"大脑"
- 工具是"手脚"
- 记忆是"短期/长期记忆"
- 检索是"外部知识库"
- 链是"思考流程"
所以,LangChain 不是"又一个 AI 工具",而是AI 应用开发的操作系统:
- 它提供了标准 API(就像操作系统提供文件系统、网络接口)
- 它管理资源(token、内存、工具)
- 它协调组件间的通信(链式调用、数据传递)
- 它提供扩展机制(自定义组件、回调)
第六步:一个完整的 LangChain 应用示例
把以上原理综合起来,一个真实的 LangChain 应用可能长这样:
# 一个智能客服系统
from langchain import ...
# 1. 加载产品文档
loader = DirectoryLoader("./product_docs/", glob="**/*.pdf")
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=1000)
chunks = splitter.split_documents(docs)
# 2. 创建向量库
vectorstore = Chroma.from_documents(chunks, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
# 3. 设置记忆(记住用户历史)
memory = ConversationSummaryMemory(llm=llm, memory_key="chat_history")
# 4. 定义工具(查订单、退货、咨询人工)
tools = [
Tool(name="OrderStatus", func=api.get_order_status, description="查询订单状态"),
Tool(name="ReturnPolicy", func=db.get_return_policy, description="获取退货政策"),
Tool(name="HumanHandoff", func=lambda x: "转接人工客服", description="转接人工")
]
# 5. 创建提示词模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是智能客服助手,基于产品文档回答问题。如果不知道,可以说需要转人工。"),
("human", "用户问题:{input}"),
("ai", "让我看看相关文档...")
])
# 6. 创建 RAG 链(先检索后回答)
rag_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=retriever,
chain_type="stuff"
)
# 7. 创建智能体(能决定用 RAG 还是工具)
agent = create_react_agent(
llm=llm,
tools=tools + [Tool(name="RAG", func=rag_chain.run, description="检索产品文档")],
prompt=prompt
)
# 8. 执行
agent_executor = AgentExecutor(agent=agent, tools=tools, memory=memory)
response = agent_executor.invoke({"input": "我的订单延迟了,能退货吗?"})
这个例子展示了:
- 文档加载与分割
- 向量检索(RAG)
- 记忆管理
- 工具定义
- 提示词模板
- 智能体决策
- 链式组合
总结:LangChain 的三大价值
用第一性原理推导,LangChain 提供了三大核心价值:
价值一:抽象化(Abstraction) 把复杂的大模型交互抽象成简单一致的接口。你不用关心不同模型的 API 差异,不用手动处理 token 计数,不用重复实现记忆机制。
价值二:组合化(Composition) 把 AI 应用拆解成可组合的积木块。你可以像搭乐高一样,把检索、记忆、工具、提示词组合成复杂的应用流程。
价值三:自动化(Automation) 把固定的 AI 交互流程变成可重复执行的程序。从"每次写提示词"到"写一次代码,反复运行",从"手动操作"到"智能体自主决策"。
掌握了 LangChain,你就掌握了把大模型从聊天机器人升级为真正的应用程序的方法。它不只是工具,更是思维框架:如何用组件化的方式思考 AI 应用开发。