LangChain 完全学习手册:看完就能上手

🦜⛓️ LangChain 完全学习手册:看完就能上手

本文基于 LangChain v1.x,包含 LCEL、RAG、Agent 等核心内容,代码均可直接运行。适合有 Python 基础、想动手做 AI 应用的开发者。


目录


一、LangChain 是什么

1.1 它解决的问题

在 LangChain 出现之前,做一个 AI 应用需要手写大量基础代码:

  • 每接一个 LLM(OpenAI、Anthropic、Google...),都要单独写对接逻辑
  • 对话历史要自己拼,每次都要手动处理上下文
  • Prompt 写死在代码里,根本没法复用
  • 想让 AI 调工具、查数据库?从零实现调度逻辑
  • RAG 完整流程要写几百行胶水代码

结果 80% 时间在搞基础设施,真正的 AI 逻辑只占 20%。

LangChain 把这些通用模式全都抽象成了可复用的组件,你只需要关心自己的业务逻辑。

1.2 核心能力一览

功能 解决的问题
统一模型接口 换 GPT-4、Claude、Gemini、本地 Llama,只改一行配置
Prompt 模板系统 像写函数一样写 Prompt,支持变量、Few-shot
链式调用(LCEL) 用 `
内置记忆管理 自动管理对话历史,多种策略开箱即用
RAG 全套工具 文档加载、切割、向量化、检索一条龙
Agent 框架 让 AI 自主调用工具、搜索、执行代码

类比一下:LangChain 之于 AI 开发,就像 Django 之于 Web 开发------不是语言,是让你更快出活儿的框架。

1.3 LangChain 生态

现在 LangChain 已经是个完整生态,三个主要产品:

产品 定位 什么时候用
🦜 LangChain 核心框架 快速构建 LLM 应用、RAG、简单 Agent
🕸 LangGraph Agent 编排引擎 复杂多步骤 Agent、状态机工作流
🔭 LangSmith 调试与监控 线上 Trace 记录、质量评估

本文专注核心框架,LangGraph 和 LangSmith 单独成文。


二、环境安装与配置

2.1 安装

LangChain 是模块化的,按需安装:

bash 复制代码
# 核心框架(必装)
pip install langchain
​
# 按你用的模型选一个
pip install langchain-openai       # GPT 系列
pip install langchain-anthropic    # Claude 系列
pip install langchain-google-genai # Gemini 系列
pip install langchain-ollama       # 本地模型
​
# RAG 相关
pip install langchain-community    # 社区扩展,含大量文档加载器
pip install chromadb               # 本地向量数据库
​
# 环境变量
pip install python-dotenv

2.2 配置 API Key

项目根目录建一个 .env 文件:

ini 复制代码
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx
ANTHROPIC_API_KEY=sk-ant-xxxxxxxx

记得把 .env 加进 .gitignore,别把 Key 传上去。

代码里加载:

csharp 复制代码
from dotenv import load_dotenv
load_dotenv()

2.3 跑通第一个程序

python 复制代码
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
​
load_dotenv()
​
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)
response = llm.invoke([HumanMessage(content="用一句话解释什么是 LangChain")])
print(response.content)

看到 AI 回复就说明环境 OK 了。

想换 Claude?只需改两行,其他完全不动:

ini 复制代码
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-opus-4-5")
# 后面代码一模一样

这就是统一接口的价值。


三、六大核心概念详解

3.1 模型(Models)

现在用的几乎都是 ChatModel,接受消息列表,返回 AI 消息。

ini 复制代码
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
from langchain_ollama import ChatOllama
​
gpt = ChatOpenAI(
    model="gpt-4o-mini",
    temperature=0.7,  # 0=确定,1=有创意
    max_tokens=1000,
)
​
claude = ChatAnthropic(model="claude-opus-4-5", temperature=0)
​
# 本地模型(需要先装并运行 Ollama)
local = ChatOllama(model="llama3.2")
​
# 三个用法完全一样
result = gpt.invoke("你好")
print(result.content)  # .content 拿到文本

3.2 Prompt 模板

别把 Prompt 写死在字符串里,用模板:

makefile 复制代码
from langchain_core.prompts import ChatPromptTemplate
​
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一名专业的 {language} 开发专家。"),
    ("human", "请解释 {topic} 的概念,并给出代码示例。"),
])
​
# 填充变量
messages = prompt.invoke({
    "language": "Python",
    "topic": "装饰器",
})
​
response = llm.invoke(messages)
print(response.content)

好处很直接:变量可以动态传入,Prompt 可以复用,单测也好写。

3.3 LCEL 链式调用(重点)

LCEL(LangChain Expression Language)是最核心的设计,用 | 管道符把组件串起来:

ini 复制代码
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
​
llm = ChatOpenAI(model="gpt-4o-mini")
prompt = ChatPromptTemplate.from_template("请用中文简洁介绍:{topic}")
parser = StrOutputParser()  # 把 AIMessage 转成纯字符串
​
# 组合成链:输入 → Prompt → LLM → 解析
chain = prompt | llm | parser
​
# 单次调用
result = chain.invoke({"topic": "量子计算"})
​
# 批量处理
results = chain.batch([
    {"topic": "机器学习"},
    {"topic": "深度学习"},
    {"topic": "强化学习"},
])
​
# 流式输出(打字机效果)
for chunk in chain.stream({"topic": "神经网络"}):
    print(chunk, end="", flush=True)

链中每个组件都有 invoke / batch / stream 方法,可以自由组合。

3.4 输出解析器

AI 默认输出文本,解析器把它转成 Python 对象:

python 复制代码
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain.output_parsers import PydanticOutputParser
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

# 定义你想要的结构
class MovieReview(BaseModel):
    title: str = Field(description="电影名")
    score: int = Field(description="评分 1-10")
    summary: str = Field(description="一句话评价")

parser = PydanticOutputParser(pydantic_object=MovieReview)
llm = ChatOpenAI(model="gpt-4o-mini")

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是影评专家。请按要求格式输出。\n{format_instructions}"),
    ("human", "评价电影:{movie}"),
])

chain = prompt | llm | parser
review = chain.invoke({
    "movie": "星际穿越",
    "format_instructions": parser.get_format_instructions()
})

print(review.title)    # 星际穿越
print(review.score)    # 9(整数,不是字符串)
print(review.summary)  # 震撼人心的科幻巨作...

3.5 记忆(Memory)

默认每次 invoke() 是独立的,AI 不记得上文。加记忆的最简单方式是手动维护历史列表:

ini 复制代码
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage

llm = ChatOpenAI(model="gpt-4o-mini")

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个友好的 AI 助手。"),
    MessagesPlaceholder(variable_name="history"),  # 历史消息插入点
    ("human", "{input}"),
])

chain = prompt | llm
history = []

def chat(user_input):
    response = chain.invoke({"input": user_input, "history": history})
    history.append(HumanMessage(content=user_input))
    history.append(AIMessage(content=response.content))
    return response.content

print(chat("我叫小明"))            # 你好,小明!...
print(chat("你还记得我叫什么?"))  # 当然,你叫小明!

3.6 检索器(Retrievers)

RAG 的核心组件,根据问题找相关文档:

ini 复制代码
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document

docs = [
    Document(page_content="LangChain 是构建 AI 应用的框架"),
    Document(page_content="LCEL 使用 | 管道符组合组件"),
    Document(page_content="向量数据库存储文本的数学表示"),
]

# 自动向量化并存入数据库
vectorstore = Chroma.from_documents(docs, OpenAIEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})

# 语义检索
results = retriever.invoke("什么是管道符?")
for doc in results:
    print(doc.page_content)

四、RAG 实战:让 AI 回答你的私有文档

4.1 RAG 是什么

RAG(Retrieval-Augmented Generation)解决的问题:让 AI 回答训练数据之外的内容,比如公司内部文档、最新资料、私人笔记。

流程分两个阶段:

离线索引(只做一次):文档 → 切块 → 向量化 → 存数据库

在线查询(每次问答):用户提问 → 检索相关块 → 连同问题传给 LLM → 得到答案

4.2 完整实现

python 复制代码
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_core.documents import Document

load_dotenv()

# 1. 准备文档(实际场景换成 PyPDFLoader 加载 PDF)
documents = [
    Document(page_content="""
    公司假期政策:
    - 年假:入职满一年后 10 天,每加一年 +1 天,最多 15 天
    - 病假:每年 10 天,需提供医院证明
    - 婚假:3 天(提前 2 周申请)
    - 产假:女员工 128 天,男员工陪产假 15 天
    """, metadata={"source": "hr_policy.txt"}),
    Document(page_content="""
    报销流程:
    1. 保存所有发票原件
    2. 在 OA 系统填写报销申请
    3. 直属上级审批(500 元以上需总监审批)
    4. 财务审核,5 个工作日内打款
    报销上限:差旅费单次最高 5000 元
    """, metadata={"source": "expense_policy.txt"}),
]

# 2. 切割文档
splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,    # 每块最多 500 字符
    chunk_overlap=50,  # 块间重叠 50 字符,防止语义断裂
)
chunks = splitter.split_documents(documents)

# 3. 向量化并存入数据库
vectorstore = Chroma.from_documents(chunks, OpenAIEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

# 4. 构建 RAG Chain
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

prompt = ChatPromptTemplate.from_messages([
    ("system", """你是公司的 HR 助手,只根据提供的文档回答问题。
如果文档中没有相关信息,直接说「文档中未找到相关信息」,不要编造。

参考文档:
{context}"""),
    ("human", "{question}"),
])

def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

# 5. 问问题
questions = [
    "入职满两年有几天年假?",
    "报销超过多少需要总监审批?",
    "公司有没有年终奖?",  # 文档里没有的
]

for q in questions:
    print(f"\n问:{q}")
    print(f"答:{rag_chain.invoke(q)}")

4.3 常用文档加载器

加载器 用途
PyPDFLoader PDF 文件(需 pip install pypdf
WebBaseLoader 网页内容
TextLoader 纯文本 .txt
CSVLoader CSV 数据文件
DirectoryLoader 批量加载整个文件夹
UnstructuredWordDocumentLoader Word 文档
GitLoader Git 仓库代码文件

五、Agent:让 AI 自主使用工具

5.1 Chain vs Agent

Chain 的执行路径是固定的(A → B → C)。

Agent 不同,它让 LLM 自己决定下一步做什么:要不要调工具、调哪个、拿到结果后怎么处理,一直循环到得出最终答案。

典型的 ReAct 循环:接收问题 → 思考 → 行动(调工具)→ 观察结果 → 继续思考...

5.2 创建带工具的 Agent

python 复制代码
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents import create_tool_calling_agent, AgentExecutor

load_dotenv()

# 定义工具,docstring 是关键------AI 靠它决定用哪个工具
@tool
def get_weather(city: str) -> str:
    """获取指定城市的当前天气。参数:city(城市名,如'北京')"""
    data = {
        "北京": "晴天,25°C,湿度 40%",
        "上海": "多云,28°C,湿度 65%",
        "广州": "小雨,30°C,湿度 85%",
    }
    return data.get(city, f"{city} 暂无数据")


@tool
def calculate(expression: str) -> str:
    """计算数学表达式。参数:expression(如 '2+3*4')"""
    try:
        return f"{expression} = {eval(expression)}"
    except Exception as e:
        return f"计算出错:{e}"


# 创建 Agent
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
tools = [get_weather, calculate]

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个有用的助手,可以使用工具帮助用户。"),
    ("human", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"),  # Agent 思考过程
])

agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,    # 打印中间过程,调试用
    max_iterations=5,
)

result = agent_executor.invoke({
    "input": "北京今天天气如何?另外 15 × 23 + 7 等于多少?"
})
print(result["output"])
# Agent 会自动决定调两个工具,然后综合回答

5.3 内置工具

不用自己造轮子,LangChain 有大量现成工具:

工具 功能
DuckDuckGoSearchRun 免费网络搜索,无需 Key
TavilySearchResults 高质量网络搜索(需 Tavily Key)
WikipediaQueryRun 查询维基百科
PythonREPLTool 执行 Python 代码
RequestsGetTool 发起 HTTP 请求
SQLDatabaseTool 查询 SQL 数据库
python 复制代码
from langchain_community.tools import DuckDuckGoSearchRun

search = DuckDuckGoSearchRun()
print(search.invoke("LangChain 最新版本"))

六、生产环境最佳实践

6.1 容错与 Fallback

ini 复制代码
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic

# 主模型挂了自动切备用
primary = ChatOpenAI(model="gpt-4o")
backup = ChatAnthropic(model="claude-opus-4-5")

robust_llm = primary.with_fallbacks([backup])

6.2 流式输出

python 复制代码
chain = prompt | llm | StrOutputParser()

# 同步流式
for chunk in chain.stream({"question": "解释机器学习"}):
    print(chunk, end="", flush=True)

# 异步(FastAPI 场景)
async def stream_response(question: str):
    async for chunk in chain.astream({"question": question}):
        yield chunk

6.3 向量数据库持久化

向量化有费用,做一次存磁盘,下次直接读:

ini 复制代码
import os
from langchain_community.vectorstores import Chroma

PERSIST_DIR = "./chroma_db"

if not os.path.exists(PERSIST_DIR):
    vectorstore = Chroma.from_documents(
        documents=chunks,
        embedding=OpenAIEmbeddings(),
        persist_directory=PERSIST_DIR,
    )
else:
    # 直接从磁盘加载,无需重新向量化
    vectorstore = Chroma(
        persist_directory=PERSIST_DIR,
        embedding_function=OpenAIEmbeddings(),
    )

6.4 开启请求缓存

相同输入不重复调 API,省钱省时间:

python 复制代码
from langchain.globals import set_llm_cache
from langchain.cache import SQLiteCache

set_llm_cache(SQLiteCache(database_path=".langchain.db"))
# 之后相同的请求直接走缓存

6.5 常见报错

错误 解决方法
AuthenticationError API Key 未设置或过期,检查 .envload_dotenv()
RateLimitError 请求频率过高,加 time.sleep() 或用指数退避
ContextWindowExceededError 输入 Token 太多,减小 chunk_size,或只保留最近几轮历史
OutputParserException AI 没按格式输出,Prompt 里加更明确的格式指令
ModuleNotFoundError 缺对应的包,按报错提示 pip install

七、完整项目:智能客服系统

综合前面所有知识,搭一个支持 RAG + 对话记忆 + 流式输出的智能客服:

python 复制代码
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_core.messages import HumanMessage, AIMessage
from langchain_core.documents import Document

load_dotenv()

# 初始化知识库
product_docs = [
    Document(page_content="超级充电宝 ProMax:20000mAh,65W 快充,380g,299 元,保修 1 年"),
    Document(page_content="退换货:7 天无理由退货,30 天内质量问题免费换新,保留原包装"),
    Document(page_content="使用注意:避免高温,不可拆卸,禁止飞机托运"),
]

chunks = RecursiveCharacterTextSplitter(chunk_size=300, chunk_overlap=30).split_documents(product_docs)
vectorstore = Chroma.from_documents(chunks, OpenAIEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0, streaming=True)

prompt = ChatPromptTemplate.from_messages([
    ("system", """你是智能客服。严格基于以下文档回答,文档中没有的内容回复「请联系人工客服」。

产品文档:
{context}"""),
    MessagesPlaceholder(variable_name="history"),
    ("human", "{question}"),
])

chat_history = []

rag_chain = (
    {
        "context": retriever | (lambda docs: "\n".join(d.page_content for d in docs)),
        "question": RunnablePassthrough(),
        "history": lambda _: chat_history,
    }
    | prompt | llm | StrOutputParser()
)

# 对话循环
print("智能客服已启动(输入 quit 退出)")
while True:
    user_input = input("\n你:").strip()
    if user_input.lower() == "quit":
        break

    print("客服:", end="")
    full_response = ""
    for chunk in rag_chain.stream(user_input):
        print(chunk, end="", flush=True)
        full_response += chunk
    print()

    chat_history.append(HumanMessage(content=user_input))
    chat_history.append(AIMessage(content=full_response))

    # 只保留最近 6 轮,防止 Token 超限
    if len(chat_history) > 12:
        chat_history = chat_history[-12:]

这个项目可以继续扩展:

  • 把知识库换成真实 PDF(PyPDFLoader
  • Chroma 换成云端向量库(Pinecone / Weaviate)
  • 包成 FastAPI 接口对外提供服务
  • 接 LangSmith 监控线上效果

八、速查手册

常用 Import

python 复制代码
# 模型
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_anthropic import ChatAnthropic
from langchain_ollama import ChatOllama

# Prompt
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

# 输出解析
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain.output_parsers import PydanticOutputParser

# 消息
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage

# Runnables
from langchain_core.runnables import RunnablePassthrough, RunnableLambda

# 文档处理
from langchain_core.documents import Document
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 向量库
from langchain_community.vectorstores import Chroma, FAISS

# 文档加载器
from langchain_community.document_loaders import PyPDFLoader, WebBaseLoader, TextLoader

# Agent
from langchain_core.tools import tool
from langchain.agents import create_tool_calling_agent, AgentExecutor

模型参数

参数 说明
temperature 0~2,越低越确定,越高越有创意。问答用 0,写作用 0.7+
max_tokens 最大输出 Token 数
model 模型名,如 gpt-4o-mini / claude-opus-4-5
streaming True 开启流式输出
timeout 请求超时秒数
max_retries 自动重试次数,默认 2

TextSplitter 参数

参数 说明
chunk_size 每块最大字符数,Q&A 场景 500-1000
chunk_overlap 块间重叠字符,建议 chunk_size 的 10%
separators 切割优先级,默认 ['\n\n', '\n', ' ', '']

推荐学习路径

  • Week 1:读完本文 → 跑通所有示例 → 独立实现简单 RAG
  • Week 2:实现带记忆的对话 → 自定义工具 → 第一个 Agent
  • Week 3:深入 LangGraph(复杂 Agent)→ 接入 LangSmith
  • Week 4:完整项目 → 部署 API(FastAPI + LangServe)

官方文档:docs.langchain.com · GitHub:github.com/langchain-a...

相关推荐
橙序员小站2 小时前
当所有人都在做 Agent,我想聊聊被遗忘的基础设施
后端·开源·aigc
Memory_荒年2 小时前
TiDB:当 MySQL 遇上分布式,生了个“超级混血儿”
java·数据库·后端
一步一个脚印一个坑2 小时前
用 APM 全链路追踪,29ms 内定位到 Docker 部署的 SSL 配置错误
javascript·后端·监控
孟健2 小时前
OpenAI 收购 Astral:AI 编程不止写代码了,它开始吃掉整条 Python 工具链
ai编程
aircrushin2 小时前
端到端AI决策架构如何重塑实时协作体验?
前端·javascript·后端
苦瓜小生2 小时前
【黑马点评学习笔记 | 实战篇 】| 6-Redis消息队列
redis·笔记·后端
Aawy1202 小时前
Python生成器(Generator)与Yield关键字:惰性求值之美
jvm·数据库·python
爱吃的小肥羊3 小时前
ChatGPT、Claude、Gemini,到底该给谁交钱?这是我的深度测评
aigc·openai·ai编程
沐硕3 小时前
《基于改进协同过滤与多目标优化的健康饮食推荐系统设计与实现》
java·python·算法·fastapi·多目标优化·饮食推荐·改进协同过滤