LangChain LCEL 框架¶
⚠️ 时效性说明:本章涉及前沿模型/价格/榜单等信息,可能随版本快速变化;请以论文原文、官方发布页和 API 文档为准。
✅ 核验说明(2026-03-26):本章已按 LangChain 当前官方文档与 OpenAI 最新模型指南复核。正文中的 OpenAI 示例默认模型统一更新为
gpt-5.4;轻量示例使用gpt-5-mini。
📖 章节导读¶
前置知识: Python 基础、大模型应用概述(第 1 章)、 Prompt 工程(第 2 章)
LangChain 是一个用于构建大模型应用的工程框架。本章聚焦 LCEL ( LangChain Expression Language )主线,结合链路编排、工具调用与可观测性,系统讲解 LangChain 现代用法。
🎯 学习目标¶
- 理解 LangChain 的核心概念
- 掌握 LangChain 的核心组件
- 学会使用 LangChain 构建应用
- 了解 LangChain 的高级特性
- 掌握大厂面试中的相关问题
8.1 LangChain 概述¶
8.1.1 什么是 LangChain¶
定义:LangChain 是一个用于构建大模型应用的开源框架,提供了一套标准化的组件和接口,简化了大模型应用的开发。
核心价值:
- 模块化:提供可复用的组件
- 标准化:统一的接口和规范
- 易用性:简化开发流程
- 可扩展:易于扩展和定制
- 生态丰富:丰富的集成和工具
为什么使用 LangChain:
- 提高效率:减少重复开发
- 降低门槛:简化复杂任务
- 最佳实践:提供最佳实践参考
- 社区支持:活跃的社区和文档
- 持续更新:快速跟进最新技术
8.1.2 LangChain 架构¶
核心架构:
核心模块:
- Models:模型接口
- Prompts:提示管理
- Chains:链式调用
- Agents:智能代理
- Memory:记忆管理
- Tools:工具集成
- Indexes:索引管理
- Callbacks:回调机制
8.1.3 安装和配置¶
安装(2026-03-25 已核):
# 核心包(以 2026-03-25 的 PyPI 最新稳定版为准)
pip install -U langchain==1.2.13
pip install -U langchain-core==1.2.20
pip install -U langgraph==1.1.3
# 模型提供商与常用扩展(按需安装)
pip install -U langchain-openai
pip install -U langchain-anthropic
pip install -U langchain-google-genai
pip install -U langchain-community
pip install -U langchain-text-splitters
说明:
langchain、langchain-core、langgraph当前都已进入 1.x 版本线。旧教程里凡是写着langgraph 0.3.x的内容,都应按当前官方文档重新核对。
版本检查:
import langchain
import langchain_core
import langgraph
print(f"langchain: {langchain.__version__}")
print(f"langchain-core: {langchain_core.__version__}")
print(f"langgraph: {langgraph.__version__}")
配置:
import os
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
# 设置API密钥
os.environ['OPENAI_API_KEY'] = 'your-api-key'
# 初始化模型
llm = ChatOpenAI(
model_name="gpt-5.4",
temperature=0.7
)
# 初始化嵌入模型
embeddings = OpenAIEmbeddings(
openai_api_key='your-api-key'
)
8.2 LangChain 核心组件¶
8.2.1 Models¶
LLM 模型:
from langchain_openai import ChatOpenAI, OpenAI
from langchain_anthropic import ChatAnthropic
from langchain_google_genai import ChatGoogleGenerativeAI
# OpenAI Chat模型
chat = ChatOpenAI(
model_name="gpt-5.4",
temperature=0.7,
max_tokens=1000
)
# OpenAI 经济型模型
llm = ChatOpenAI(
model="gpt-5-mini",
temperature=0.7
)
# Anthropic模型
# 请替换为你当前账户与地区实际可用的 Claude 模型 ID
claude = ChatAnthropic(
model="your_available_claude_model",
temperature=0.7
)
# Google模型
# 请替换为当前可用的 Gemini 模型 ID
gemini = ChatGoogleGenerativeAI(
model="your_available_gemini_model",
temperature=0.7
)
# 使用模型
response = chat.invoke("你好!")
print(response.content)
嵌入模型:
from langchain_openai import OpenAIEmbeddings
from langchain_huggingface import HuggingFaceEmbeddings
# OpenAI嵌入
openai_embeddings = OpenAIEmbeddings(
openai_api_key='your-api-key'
)
# HuggingFace嵌入
hf_embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2"
)
# 生成嵌入
text = "这是一段示例文本"
embedding = openai_embeddings.embed_query(text)
print(f"嵌入维度: {len(embedding)}")
8.2.2 Prompts¶
Prompt 模板:
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate, MessagesPlaceholder
# 基础Prompt模板
template = """
你是一个专业的{role}。
请回答以下问题: {question}
"""
prompt = PromptTemplate(
template=template,
input_variables=["role", "question"]
)
# 使用模板
formatted_prompt = prompt.format(
role="技术顾问",
question="什么是机器学习?"
)
print(formatted_prompt)
# ChatPrompt模板
chat_template = ChatPromptTemplate.from_messages([
("system", "你是一个{role}。"),
("user", "{question}")
])
chat_prompt = chat_template.format_messages(
role="技术顾问",
question="什么是机器学习?"
)
print(chat_prompt)
# 使用MessagesPlaceholder
messages_template = ChatPromptTemplate.from_messages([
("system", "你是一个助手。"),
MessagesPlaceholder(variable_name="history"),
("user", "{input}")
])
Few-shot Prompt:
from langchain_core.prompts import FewShotPromptTemplate
from langchain_core.prompts import PromptTemplate
# 定义示例
examples = [
{
"question": "苹果是什么?",
"answer": "苹果是一种水果,也可以指苹果公司。"
},
{
"question": "香蕉是什么?",
"answer": "香蕉是一种热带水果,富含钾元素。"
}
]
# 定义示例模板
example_prompt = PromptTemplate(
input_variables=["question", "answer"],
template="问题: {question}\n答案: {answer}"
)
# 创建Few-shot Prompt
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
prefix="以下是一些示例:",
suffix="\n问题: {input}\n答案:",
input_variables=["input"],
example_separator="\n\n"
)
# 使用
formatted = few_shot_prompt.format(input="橙子是什么?")
print(formatted)
8.2.3 Chains¶
⚠️ 弃用警告:
LLMChain、SimpleSequentialChain、SequentialChain等旧版链 API 已在 LangChain 0.1+版本中弃用,将在未来版本中移除。请使用 LCEL ( LangChain Expression Language )替代,它提供更简洁的语法和更好的性能。
为什么 LCEL 比旧版 Chain 更好?
LCEL 使用 Python 的 | 管道运算符组合组件(类似 Unix 管道 cat file | grep pattern),核心优势: - 统一接口:所有组件都实现 Runnable 协议,拥有 invoke()、stream()、batch() 等标准方法,可以自由组合 - 自动优化:LCEL 运行时自动处理并行执行、类型转换、错误传播,无需手动编排 - 一流流式支持:任何 LCEL 链都自动支持 .stream() 和 .astream(),无需额外代码 - 可观测性:每一步的输入/输出自动记录,便于调试和监控
LCEL 链(推荐,替代已弃用的 LLMChain ):
# 使用LCEL(LangChain Expression Language)创建链
chain = prompt | chat
# 运行链
result = chain.invoke({
"role": "技术顾问",
"question": "什么是机器学习?"
})
print(result)
顺序链( LCEL 管道语法):
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
# 第一个链: 生成介绍
prompt1 = PromptTemplate.from_template("简要介绍{topic}。")
chain1 = prompt1 | chat | StrOutputParser()
# 第二个链: 提取要点
prompt2 = PromptTemplate.from_template(
"基于以下介绍,列出3个要点:\n{introduction}"
)
chain2 = prompt2 | chat | StrOutputParser()
# LCEL组合: 管道串联
overall_chain = (
{"introduction": chain1, "topic": RunnablePassthrough()}
| RunnablePassthrough.assign(points=chain2)
)
# 运行
result = overall_chain.invoke("机器学习")
print(result["introduction"])
print(result["points"])
路由链( LCEL + RunnableBranch ):
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableBranch, RunnableLambda
# 路由分类器
router_prompt = PromptTemplate.from_template(
"""判断以下问题的类型,只输出 tech 或 general:
问题: {input}
类型:"""
)
router_chain = router_prompt | chat | StrOutputParser()
# 目标链
tech_chain = PromptTemplate.from_template("作为技术专家回答: {input}") | chat | StrOutputParser()
general_chain = PromptTemplate.from_template("作为助手回答: {input}") | chat | StrOutputParser()
# LCEL路由
def route(info):
route_type = info["route"].strip().lower() # 链式调用:strip去除空白
if "tech" in route_type:
return tech_chain.invoke({"input": info["input"]})
return general_chain.invoke({"input": info["input"]})
full_chain = (
{"route": router_chain, "input": lambda x: x["input"]} # lambda匿名函数
| RunnableLambda(route)
)
# 使用
result = full_chain.invoke({"input": "什么是Transformer?"})
print(result)
8.2.4 Memory¶
对话缓冲记忆( LCEL + RunnableWithMessageHistory ):
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
# 创建带记忆的Prompt
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个有帮助的AI助手。"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
chain = prompt | chat
# 记忆存储(按session_id隔离)
message_store = {}
def get_session_history(session_id: str):
if session_id not in message_store:
message_store[session_id] = InMemoryChatMessageHistory()
return message_store[session_id]
# 带记忆的链
conversation = RunnableWithMessageHistory(
chain,
get_session_history,
input_messages_key="input",
history_messages_key="history"
)
config = {"configurable": {"session_id": "user-001"}}
# 对话
response1 = conversation.invoke({"input": "你好!"}, config=config)
print(f"AI: {response1.content}")
response2 = conversation.invoke({"input": "我叫小明"}, config=config)
print(f"AI: {response2.content}")
response3 = conversation.invoke({"input": "我叫什么名字?"}, config=config)
print(f"AI: {response3.content}")
# 查看记忆
print("\n对话历史:")
for msg in message_store["user-001"].messages:
print(f"{msg.type}: {msg.content}")
摘要记忆(用 LLM 压缩历史):
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
class SummarizingChatHistory:
"""当对话超过阈值时自动摘要压缩"""
def __init__(self, llm, max_messages=10):
self.llm = llm
self.max_messages = max_messages
self.messages = []
self.summary = ""
def add_message(self, message):
self.messages.append(message)
if len(self.messages) > self.max_messages:
self._summarize()
def _summarize(self):
"""LLM生成摘要,替代旧消息"""
history_text = "\n".join(
f"{m.type}: {m.content}" for m in self.messages[:-2]
)
summary_prompt = f"请用1-2句话概括以下对话:\n{history_text}"
result = self.llm.invoke(summary_prompt)
self.summary = result.content
self.messages = self.messages[-2:] # 只保留最近2轮
def get_messages(self):
msgs = []
if self.summary:
msgs.append(SystemMessage(content=f"之前的对话摘要: {self.summary}"))
msgs.extend(self.messages)
return msgs
# 使用
history = SummarizingChatHistory(llm=chat, max_messages=6)
history.add_message(HumanMessage(content="介绍一下机器学习"))
result = chat.invoke(history.get_messages())
print(f"AI: {result.content}")
history.add_message(AIMessage(content=result.content))
记忆窗口(只保留最近 N 轮):
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个有帮助的助手。"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
chain = prompt | chat
# 带窗口限制的记忆
class WindowedChatHistory(InMemoryChatMessageHistory):
"""K窗口记忆:只保留最近k轮对话"""
def __init__(self, k=2):
super().__init__() # super()调用父类方法
self.k = k
def add_message(self, message):
super().add_message(message)
# 每轮对话=2条消息(human+AI),保留k轮
if len(self.messages) > self.k * 2:
self.messages = self.messages[-(self.k * 2):]
store = {}
def get_windowed_history(session_id):
if session_id not in store:
store[session_id] = WindowedChatHistory(k=2)
return store[session_id]
conversation = RunnableWithMessageHistory(
chain, get_windowed_history,
input_messages_key="input",
history_messages_key="history"
)
config = {"configurable": {"session_id": "user-002"}}
# 多轮对话
for i in range(5):
user_input = input("用户: ")
response = conversation.invoke({"input": user_input}, config=config)
print(f"AI: {response.content}")
8.2.5 Tools¶
内置工具(使用 LangGraph create_react_agent ):
from langchain_community.tools import TavilySearchResults
from langchain_community.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper
from langgraph.prebuilt import create_react_agent
# 创建工具
search_tool = TavilySearchResults(max_results=3)
wiki_tool = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())
tools = [search_tool, wiki_tool]
# 创建ReAct Agent(LangGraph推荐方式)
agent = create_react_agent(chat, tools)
# 运行
result = agent.invoke({"messages": [{"role": "user", "content": "最新的AI技术进展是什么?"}]})
print(result["messages"][-1].content) # [-1]负索引取最后一个元素
自定义工具:
from langchain_core.tools import BaseTool
from typing import Type
from pydantic import BaseModel, Field
class CalculatorInput(BaseModel): # Pydantic BaseModel:自动数据验证和序列化
"""计算器输入"""
expression: str = Field(description="数学表达式")
class CalculatorTool(BaseTool):
"""计算器工具"""
name = "calculator"
description = "用于计算数学表达式"
args_schema: Type[BaseModel] = CalculatorInput
def _run(self, expression: str) -> str:
"""运行工具(使用AST安全解析)"""
import ast
try: # try/except捕获异常,防止程序崩溃
tree = ast.parse(expression, mode='eval')
for node in ast.walk(tree):
if not isinstance(node, (ast.Expression, ast.BinOp, ast.UnaryOp, # isinstance检查类型
ast.Constant, ast.Add, ast.Sub, ast.Mult,
ast.Div, ast.Mod, ast.Pow, ast.USub)):
return f"计算错误: 不允许的表达式"
result = eval(compile(tree, '<expr>', 'eval'), {"__builtins__": {}}, {})
return str(result)
except Exception as e:
return f"计算错误: {str(e)}"
async def _arun(self, expression: str) -> str: # async def定义协程函数
"""异步运行"""
return self._run(expression)
# 使用工具
calculator = CalculatorTool()
result = calculator._run("2 + 3 * 4")
print(f"计算结果: {result}")
# 添加到LangGraph Agent
from langgraph.prebuilt import create_react_agent
tools = [calculator]
agent = create_react_agent(chat, tools)
result = agent.invoke({"messages": [{"role": "user", "content": "计算 2 + 3 * 4"}]})
print(result["messages"][-1].content)
8.3 LangChain 高级应用¶
8.3.1 RAG 应用¶
使用 LangChain 构建 RAG( LCEL 链):
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
# 加载文档
loader = TextLoader("document.txt")
documents = loader.load()
# 分割文档
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
splits = text_splitter.split_documents(documents)
# 创建向量存储
vectorstore = Chroma.from_documents(
documents=splits,
embedding=embeddings
)
# 创建检索器
retriever = vectorstore.as_retriever(
search_kwargs={"k": 3}
)
# LCEL构建RAG链(替代已弃用的RetrievalQA)
prompt = ChatPromptTemplate.from_template(
"""基于以下上下文回答问题。如果上下文中没有相关信息,请说“我无法根据提供的信息回答”。
上下文: {context}
问题: {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
| chat
| StrOutputParser()
)
# 查询
query = "文档的主要内容是什么?"
answer = rag_chain.invoke(query)
print(f"答案: {answer}")
# 如需返回来源文档,可用RunnableParallel
from langchain_core.runnables import RunnableParallel
rag_with_sources = RunnableParallel(
answer=rag_chain,
sources=retriever
)
result = rag_with_sources.invoke(query)
print(f"答案: {result['answer']}")
print(f"来源: {[doc.page_content[:50] for doc in result['sources']]}")
8.3.2 Agent 应用¶
使用 LangGraph 构建 Agent(替代已弃用的 initialize_agent ):
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent
# 定义工具(注意:用@tool装饰器替代Tool类)
@tool
def search(query: str) -> str:
"""搜索工具,用于搜索信息"""
# 这里简化处理
return f"搜索结果: {query}"
@tool
def calculator(expression: str) -> str:
"""计算器工具,用于数学计算(使用AST安全解析)"""
import ast
try:
tree = ast.parse(expression, mode='eval')
for node in ast.walk(tree):
if not isinstance(node, (ast.Expression, ast.BinOp, ast.UnaryOp,
ast.Constant, ast.Add, ast.Sub, ast.Mult,
ast.Div, ast.Mod, ast.Pow, ast.USub)):
return f"计算错误: 不允许的表达式"
result = eval(compile(tree, '<expr>', 'eval'), {"__builtins__": {}}, {})
return str(result)
except Exception as e:
return f"计算错误: {str(e)}"
# 创建LangGraph ReAct Agent
tools = [search, calculator]
agent = create_react_agent(chat, tools)
# 运行Agent
result = agent.invoke(
{"messages": [{"role": "user", "content": "搜索AI技术进展并计算 2 + 3 * 4"}]}
)
# 提取最终回复
print(result["messages"][-1].content)
8.3.3 多模态应用¶
使用 LangChain 处理多模态数据:
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
# LCEL对话链
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个有帮助的AI助手。"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
chain = prompt | chat
store = {}
def get_history(sid):
if sid not in store:
store[sid] = InMemoryChatMessageHistory()
return store[sid]
conversation = RunnableWithMessageHistory(
chain, get_history,
input_messages_key="input",
history_messages_key="history"
)
# 多模态输入示例(OpenAI 多模态模型支持图片 URL / base64)
from langchain_core.messages import HumanMessage
multimodal_msg = HumanMessage(content=[
{"type": "text", "text": "请分析这张图片的内容"},
{"type": "image_url", "image_url": {
"url": "https://example.com/screenshot.png"
}}
])
response = chat.invoke([multimodal_msg])
print(f"AI: {response.content}")
8.3.4 流式处理与异步¶
流式输出(Streaming):
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
# LCEL流式链
prompt = ChatPromptTemplate.from_template("写一首关于{topic}的短诗")
chain = prompt | chat | StrOutputParser()
# 流式输出
print("=== 流式输出 ===")
for chunk in chain.stream({"topic": "人工智能"}):
print(chunk, end="", flush=True)
print() # 换行
# 异步流式
import asyncio
async def async_stream():
print("=== 异步流式输出 ===")
async for chunk in chain.astream({"topic": "春天"}):
print(chunk, end="", flush=True)
print()
# asyncio.run(async_stream()) # 在async环境中调用
异步处理(Async):
# 异步调用
async def async_invoke():
result = await chain.ainvoke({"topic": "未来"})
print(f"异步结果: {result}")
# 批量异步
async def async_batch():
topics = ["AI", "区块链", "量子计算"]
results = await chain.abatch([{"topic": t} for t in topics])
for topic, result in zip(topics, results):
print(f"{topic}: {result[:50]}...")
# asyncio.run(async_batch())
8.3.5 LCEL 高级模式¶
RunnableParallel 并行执行:
from langchain_core.runnables import RunnableParallel, RunnableLambda
# 定义多个处理分支
def analyze_sentiment(text: str) -> str:
"""情感分析"""
positive_words = ["好", "棒", "优秀", "喜欢"]
negative_words = ["差", "糟", "糟糕", "讨厌"]
pos_count = sum(1 for w in positive_words if w in text)
neg_count = sum(1 for w in negative_words if w in text)
if pos_count > neg_count:
return "正面"
elif neg_count > pos_count:
return "负面"
return "中性"
def extract_keywords(text: str) -> list:
"""关键词提取(简化版)"""
# 实际应用中可用jieba或LLM
words = text.split()
return [w for w in words if len(w) > 2][:5]
def count_words(text: str) -> int:
"""字数统计"""
return len(text.replace(" ", ""))
# 并行处理链
parallel_chain = RunnableParallel(
sentiment=RunnableLambda(analyze_sentiment),
keywords=RunnableLambda(extract_keywords),
word_count=RunnableLambda(count_words)
)
# 测试
text = "这个产品真的很棒,我非常喜欢它的设计"
result = parallel_chain.invoke(text)
print(f"情感: {result['sentiment']}")
print(f"关键词: {result['keywords']}")
print(f"字数: {result['word_count']}")
RunnablePassthrough 数据传递:
from langchain_core.runnables import RunnablePassthrough
# 保留原始输入同时添加处理结果
chain_with_context = (
{
"original": RunnablePassthrough(), # 原样传递
"uppercase": RunnableLambda(lambda x: x.upper()),
"length": RunnableLambda(len)
}
)
result = chain_with_context.invoke("hello world")
print(result)
# {'original': 'hello world', 'uppercase': 'HELLO WORLD', 'length': 11}
链式组合与重试:
from langchain_core.runnables import RunnableRetry
# 带重试的链
retry_chain = (
prompt
| chat
| StrOutputParser()
).with_retry(
stop_after_attempt=3,
wait_exponential_jitter=True,
retry_if_exception_type=(Exception,)
)
# 带超时的链
timeout_chain = chain.with_timeout(30) # 30秒超时
# 带回退的链
fallback_prompt = ChatPromptTemplate.from_template("简单回答: {question}")
fallback_chain = fallback_prompt | chat | StrOutputParser()
robust_chain = chain.with_fallback([fallback_chain])
事件回调(Callbacks):
from langchain_core.callbacks import BaseCallbackHandler
class MyCallbackHandler(BaseCallbackHandler):
"""自定义回调处理器"""
def on_llm_start(self, serialized, prompts, **kwargs):
print(f"[LLM开始] Prompts: {prompts[:50]}...")
def on_llm_end(self, response, **kwargs):
print(f"[LLM结束] Token使用: {response.llm_output}")
def on_chain_start(self, serialized, inputs, **kwargs):
print(f"[链开始] 输入: {inputs}")
def on_chain_end(self, outputs, **kwargs):
print(f"[链结束] 输出长度: {len(str(outputs))}")
# 使用回调
chain_with_callback = chain.with_config(
callbacks=[MyCallbackHandler()]
)
result = chain_with_callback.invoke({"topic": "科技"})
8.4 LangChain 最佳实践¶
8.4.1 Prompt 优化¶
最佳实践:
- 使用模板:使用 PromptTemplate 管理 Prompt
- 参数化:使用变量提高灵活性
- Few-shot:提供示例提高性能
- 明确指令:清晰说明任务要求
示例:
# 优化的Prompt模板
optimized_template = PromptTemplate(
template="""
你是一个专业的{role},拥有{experience}年经验。
任务: {task}
要求:
1. {requirement1}
2. {requirement2}
3. {requirement3}
输入: {input}
请按照以上要求完成任务。
""",
input_variables=[
"role", "experience", "task",
"requirement1", "requirement2", "requirement3", "input"
]
)
8.4.2 链优化¶
最佳实践:
- 模块化:将复杂任务分解为多个链
- 复用性:设计可复用的链组件
- 错误处理:添加错误处理机制
- 性能优化:使用缓存和批处理
示例:
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.globals import set_llm_cache
from langchain_community.cache import InMemoryCache
# 启用缓存
set_llm_cache(InMemoryCache())
# LCEL链(替代已弃用的LLMChain)
chain = optimized_template | chat | StrOutputParser()
# 运行链
result = chain.invoke({
"role": "技术顾问",
"experience": "10",
"task": "解释机器学习",
"requirement1": "使用简洁的语言",
"requirement2": "提供实际例子",
"requirement3": "避免过于专业的术语",
"input": "什么是机器学习?"
})
print(result)
8.4.3 记忆优化¶
最佳实践:
- 选择合适的记忆类型:根据场景选择
- 限制记忆大小:避免超出上下文窗口
- 定期清理:清理过期记忆
- 持久化存储:保存重要记忆
示例:
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
# LCEL对话链 + 持久化记忆
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个有帮助的助手。"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
chain = prompt | chat
# 使用文件存储记忆(也可换成Redis/PostgreSQL)
from langchain_community.chat_message_histories import FileChatMessageHistory
def get_file_history(session_id: str):
return FileChatMessageHistory(file_path=f"chat_{session_id}.json")
conversation = RunnableWithMessageHistory(
chain, get_file_history,
input_messages_key="input",
history_messages_key="history"
)
8.5 练习题¶
练习题 1:基础链¶
题目:使用 LangChain 创建一个简单的链,用于回答问题。
参考答案:
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
# 创建Prompt模板
template = PromptTemplate.from_template("回答以下问题: {question}")
# LCEL链(替代已弃用的LLMChain)
chain = template | chat | StrOutputParser()
# 运行链
result = chain.invoke({"question": "什么是机器学习?"})
print(result)
练习题 2:自定义工具¶
题目:创建一个自定义工具,用于获取天气信息。
参考答案:
from langchain_core.tools import BaseTool
from typing import Type
from pydantic import BaseModel, Field
class WeatherInput(BaseModel):
"""天气输入"""
city: str = Field(description="城市名称")
class WeatherTool(BaseTool):
"""天气工具"""
name = "weather"
description = "用于查询天气信息"
args_schema: Type[BaseModel] = WeatherInput
def _run(self, city: str) -> str:
"""运行工具"""
# 这里简化处理,实际应该调用天气API
return f"{city}的天气: 晴, 温度: 25°C"
async def _arun(self, city: str) -> str:
"""异步运行"""
return self._run(city)
8.6 面试准备¶
8.6.1 大厂面试题¶
字节跳动面试题:
- 问题:什么是 LangChain?它有什么优势?
参考答案: - LangChain 是大模型应用开发框架 - 优势: - 模块化设计 - 丰富的组件 - 简化开发 - 易于扩展 - 活跃社区
- 问题:LangChain 的核心组件有哪些?
参考答案: - Models:模型接口 - Prompts:提示管理 - Chains:链式调用 - Agents:智能代理 - Memory:记忆管理 - Tools:工具集成
腾讯面试题:
- 问题:如何使用 LangChain 构建 RAG 应用?
参考答案: - 加载文档 - 分割文档 - 创建向量存储 - 创建检索器 - 构建 RAG 链 - 查询和生成
- 问题:LangChain 的 Memory 有哪些类型?
参考答案:
⚠️ API 变更: LangChain v0.3+ 已弃用
ConversationBufferMemory等旧式 Memory 类,推荐使用ChatMessageHistory+RunnableWithMessageHistory(本文 8.2.4 节已采用新 API )。以下列出的是概念分类,生产环境请使用新 API 。
- ConversationBufferMemory:缓冲记忆
- ConversationSummaryMemory:摘要记忆
- ConversationBufferWindowMemory:窗口记忆
- ConversationKGMemory:知识图谱记忆
阿里巴巴面试题:
- 问题:如何优化 LangChain 应用的性能?
参考答案: - 使用缓存减少重复调用 - 批量处理提高效率 - 优化 Prompt 减少 Token - 选择合适的模型 - 并行处理提高速度
- 问题:在实际项目中如何应用 LangChain?
参考答案: - 需求分析:明确应用场景 - 架构设计:设计应用架构 - 组件选择:选择合适的组件 - 开发实现:实现应用功能 - 测试优化:测试和优化 - 部署监控:部署并监控
8.6.2 面试技巧¶
技巧 1:理论联系实际
结合实际项目经验,说明如何使用 LangChain 解决实际问题。
技巧 2:组件选择
说明选择 LangChain 组件的依据,展示架构设计能力。
技巧 3:最佳实践
展示 LangChain 最佳实践的应用经验。
技巧 4:性能优化
说明如何优化 LangChain 应用的性能。
📝 本章小结¶
本章系统介绍了 LangChain 框架的核心内容:
- ✅ LangChain 概述:定义、架构、安装配置
- ✅ LangChain 核心组件:Models 、 Prompts 、 Chains 、 Memory 、 Tools
- ✅ LangChain 高级应用:RAG 应用、 Agent 应用、多模态应用
- ✅ LangChain 最佳实践:Prompt 优化、链优化、记忆优化
- ✅ 练习题:基础链、自定义工具
- ✅ 面试准备:大厂面试题和解答技巧
通过本章学习,你应该能够: - 理解 LangChain 的核心概念 - 掌握 LangChain 的核心组件 - 学会使用 LangChain 构建应用 - 了解 LangChain 的高级特性 - 准备好应对大厂面试
🔗 下一步¶
下一章我们将深入学习大模型微调技术,掌握如何微调大模型以适应特定任务。
继续学习: 09-大模型微调技术.md
💡 思考题¶
-
LangChain 的核心价值是什么?
提供 LLM 应用开发的标准化抽象层,统一不同模型/工具/数据源的接口,让开发者专注业务逻辑而非胶水代码。核心价值:①模型无关(切换 GPT/Claude 只改一行) ②组件可组合(链式调用) ③生态丰富(800+集成)。目前已演进为 LangChain(核心)+LangGraph(Agent)+LangSmith(可观测)。
-
LangChain 有哪些核心组件?
①Models(LLM/ChatModel/Embedding) ②Prompts(模板+FewShot+OutputParser) ③Chains(顺序/路由/转换链) ④Memory(Buffer/Summary/向量) ⑤Retrievers(向量检索/BM25/多路) ⑥Agents(ReAct/Plan-and-Execute) ⑦Tools(搜索/计算/API 调用)。自 0.3 起 LCEL 成为主线;截至 2026-03-26,官方稳定版本线已是 LangChain 1.2.x / LangGraph 1.1.x。
-
如何使用 LangChain 构建 RAG 应用?
5 步:①文档加载(DirectoryLoader/WebLoader) ②文本分块(RecursiveCharacterTextSplitter,chunk_size=500) ③Embedding+存入向量库(Chroma/FAISS) ④构建 Retriever(similarity_search,k=4) ⑤LCEL 链({context: retriever, question} | prompt | LLM | StrOutputParser)。进阶:加 Reranker 、多路召回、 RunnableWithMessageHistory 支持多轮。
-
如何优化 LangChain 应用的性能?
①缓存(InMemoryCache/SQLiteCache 减少重复调用) ②流式输出(streaming=True 降低体感延迟) ③异步调用(achain.ainvoke) ④Prompt 压缩(减少 Token) ⑤批量处理(batch) ⑥LangSmith 追踪定位瓶颈。注意: LangChain 本身有一定抽象开销,极致性能场景可直接用 SDK 。
-
在实际项目中如何应用 LangChain?
适合:快速原型、需要多模型切换、标准 RAG/Agent 应用。不适合:极致性能要求、简单单次调用。生产建议:①用 LangGraph 替代旧版 AgentExecutor ②LangSmith 监控 Token 用量和延迟 ③Prompt 模板版本管理 ④错误处理+重试+回退。替代方案: LlamaIndex(更专注 RAG)、 Semantic Kernel(C#/.NET)。
💡 进阶补充(来源:easy-langent · 第六章 LangGraph 基础)
LangChain vs LangGraph:何时切换?¶
当应用从"线性链"演进为"需要分支、循环、状态回溯"的复杂工作流时,应从 LangChain 切换到 LangGraph:
核心维度 LangChain(LCEL) LangGraph 流程类型 线性/固定步骤 分支、循环、并行 状态管理 分散在各组件,需手动传递 统一 State 对象,字段级合并策略 循环/分支 条件判断代码,手动控制 条件边、循环边原生支持 适用场景 快速原型、简单 RAG 多 Agent 协作、合规审核、长时任务 LangGraph 三大核心概念: 1. State(状态):工作流的"共享黑板",所有节点的输入输出围绕它展开 2. Node(节点):封装具体功能(如"调用 LLM"、"执行工具"),接收 State、返回 State 更新 3. Edge(边):定义执行路径,包括普通边(固定路由)和条件边(动态路由)
Pythonfrom langgraph.graph import StateGraph, START, END from typing import TypedDict, Annotated import operator class AgentState(TypedDict): messages: Annotated[list, operator.add] graph = StateGraph(AgentState) graph.add_node("think", think_node) graph.add_node("act", act_node) graph.add_edge(START, "think") graph.add_conditional_edges("think", route_fn, {"act": "act", "end": END}) graph.add_edge("act", "think") # 循环:act → think → ... app = graph.compile()实战建议:2025 年起 LangChain 官方已将 Agent 运行时统一迁移到 LangGraph。新项目建议直接使用
langgraph构建 Agent,而非旧版AgentExecutor。🔥 实战经验(来源:easy-langent)
LangChain + LangGraph 生产级开发清单¶
- 可观测性:接入 LangSmith 追踪每次链调用的 Token 用量、延迟、错误率
- 状态持久化:LangGraph 内置
MemorySaver(开发)/SqliteSaver(生产),支持断点续跑- 人工介入(Human-in-the-loop):使用
interrupt_before在关键节点暂停,等待人工审批- 流式输出:
app.stream()/app.astream_events()实现实时 Token 级流式响应- 错误处理:在节点内
try/except+State中增加error字段,避免整个图崩溃
📚 参考资料¶
- LangChain Documentation
- LangChain GitHub Repository
- "LangChain: Building Applications with LLMs" - LangChain Team
- OpenAI Documentation
- Hugging Face Documentation
- easy-largent LangChain+LangGraph 教程(Datawhale)
最后更新日期: 2026-03-26 适用版本: LangChain 1.2.x / LangChain-Core 1.2.x / LangGraph 1.1.x