LangChain 1.0 & LangGraph 1.0 完整知识点手册
LangChain 1.0 & LangGraph 1.0 完整知识点手册
本手册整理自 LangChain1.0-Langgraph1.0-Learning 学习资料,涵盖从基础到高级的完整知识体系。
目录
Phase 1: 基础知识
1.1 模型调用
核心概念
init_chat_model 是 LangChain 1.0 中用于初始化聊天模型的统一接口。
基本语法
from langchain.chat_models import init_chat_model
model = init_chat_model(
"provider:model_name", # 提供商:模型名称
api_key="your-api-key", # API 密钥(可选,可从环境变量读取)
temperature=0.7, # 温度参数(可选)
max_tokens=1000, # 最大 token 数(可选)
)支持的提供商格式
# Groq
"groq:llama-3.3-70b-versatile"
"groq:mixtral-8x7b-32768"
# OpenAI
"openai:gpt-4"
"openai:gpt-3.5-turbo"
# Anthropic
"anthropic:claude-sonnet-4-5-20250929"invoke 方法 - 三种输入格式
格式 1:纯字符串(最简单)
response = model.invoke("你的问题或指令")
print(response.content)格式 2:字典列表(推荐)
messages = [
{"role": "system", "content": "系统提示"},
{"role": "user", "content": "用户消息"},
{"role": "assistant", "content": "AI回复"}, # 可选,用于对话历史
]
response = model.invoke(messages)格式 3:消息对象列表(类型安全)
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
messages = [
SystemMessage(content="系统提示"),
HumanMessage(content="用户消息"),
]
response = model.invoke(messages)invoke 返回值详解
response = model.invoke("Hello")
# 主要内容
response.content # str - AI 的回复文本
response.response_metadata # dict - 响应元数据
response.id # str - 消息唯一 ID
# Token 使用情况
usage = response.response_metadata.get('token_usage', {})
print(f"提示 tokens: {usage.get('prompt_tokens')}")
print(f"完成 tokens: {usage.get('completion_tokens')}")
print(f"总计 tokens: {usage.get('total_tokens')}")完整示例代码
import os
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
# 加载环境变量
load_dotenv()
# 初始化模型
model = init_chat_model(
"groq:llama-3.3-70b-versatile",
api_key=os.getenv("GROQ_API_KEY"),
temperature=0.7,
max_tokens=1000
)
# 简单调用
response = model.invoke("什么是机器学习?")
print(response.content)
# 带系统提示的调用
messages = [
{"role": "system", "content": "你是一个专业的 Python 导师"},
{"role": "user", "content": "什么是装饰器?"}
]
response = model.invoke(messages)
print(response.content)1.2 提示词模板
核心概念
提示词模板将提示词结构与数据分离,提高可维护性和可复用性。
PromptTemplate - 简单文本模板
from langchain_core.prompts import PromptTemplate
# 方法 1:from_template(推荐)
template = PromptTemplate.from_template(
"将以下文本翻译成{language}:\n{text}"
)
# 使用模板
prompt = template.format(language="法语", text="Hello, how are you?")
print(prompt)
# 方法 2:显式指定变量
template = PromptTemplate(
input_variables=["product", "feature"],
template="为{product}写一句广告语,重点突出{feature}特点。"
)ChatPromptTemplate - 聊天消息模板
from langchain_core.prompts import ChatPromptTemplate
# 使用元组格式(推荐)
template = ChatPromptTemplate.from_messages([
("system", "你是一个{role},擅长{skill}"),
("user", "{question}")
])
messages = template.format_messages(
role="编程导师",
skill="用简单语言解释复杂概念",
question="什么是递归?"
)
response = model.invoke(messages)部分变量(Partial Variables)
# 预填充某些固定变量
base_template = ChatPromptTemplate.from_messages([
("system", "你是{department}的{role}"),
("user", "{task}")
])
# 创建 IT 部门专用模板
it_template = base_template.partial(
department="IT 部门",
role="技术支持"
)
# 现在只需要提供 task
messages = it_template.format_messages(task="解决网络问题")LCEL 链式调用
# 使用 | 运算符创建链
template = ChatPromptTemplate.from_messages([
("system", "你是{role}"),
("user", "{input}")
])
chain = template | model
# 直接调用链
response = chain.invoke({
"role": "Python 导师",
"input": "什么是装饰器?"
})
print(response.content)1.3 消息类型与对话管理
三种消息类型
| 角色 | 字典格式 | 对象格式 | 用途 |
|---|---|---|---|
| System | {"role": "system", ...} | SystemMessage(...) | 系统提示 |
| User | {"role": "user", ...} | HumanMessage(...) | 用户输入 |
| Assistant | {"role": "assistant", ...} | AIMessage(...) | AI 回复 |
核心难点:对话历史管理
关键规则:每次调用必须传递完整的对话历史!
❌ 错误做法
# 第一次
r1 = model.invoke("我叫张三")
# 第二次(没传历史)
r2 = model.invoke("我叫什么?") # AI 不记得!✅ 正确做法
conversation = []
# 第一次
conversation.append({"role": "user", "content": "我叫张三"})
r1 = model.invoke(conversation)
# 关键:保存 AI 回复
conversation.append({"role": "assistant", "content": r1.content})
# 第二次(传递完整历史)
conversation.append({"role": "user", "content": "我叫什么?"})
r2 = model.invoke(conversation) # AI 记得!对话历史优化
def keep_recent_messages(messages, max_pairs=3):
"""
保留最近的 N 轮对话
max_pairs: 保留的对话轮数(每轮 = user + assistant)
"""
# 分离 system 和对话
system_msgs = [m for m in messages if m.get("role") == "system"]
conversation = [m for m in messages if m.get("role") != "system"]
# 只保留最近的
recent = conversation[-(max_pairs * 2):]
# 返回:system + 最近对话
return system_msgs + recent1.4 自定义工具
@tool 装饰器
from langchain_core.tools import tool
@tool
def get_weather(city: str) -> str:
"""
获取指定城市的天气信息
参数:
city: 城市名称,如"北京"、"上海"
返回:
天气信息字符串
"""
# 你的实现
return "晴天,温度 15°C"关键要点
| 必需项 | 说明 |
|---|---|
@tool 装饰器 | 声明这是一个工具 |
| docstring | AI 读这个来理解工具用途 ⚠️ 非常重要! |
| 类型注解 | 参数和返回值的类型 |
返回 str | 工具应该返回字符串 |
多参数工具
@tool
def calculator(operation: str, a: float, b: float) -> str:
"""
执行数学计算
参数:
operation: "add", "subtract", "multiply", "divide"
a: 第一个数字
b: 第二个数字
"""
operations = {
"add": lambda x, y: x + y,
"subtract": lambda x, y: x - y,
"multiply": lambda x, y: x * y,
"divide": lambda x, y: x / y if y != 0 else "错误:除数不能为零"
}
result = operations.get(operation, lambda x, y: "未知操作")(a, b)
return f"{a} {operation} {b} = {result}"可选参数工具
from typing import Optional
@tool
def web_search(query: str, num_results: Optional[int] = 3) -> str:
"""
搜索网页
参数:
query: 搜索关键词
num_results: 返回结果数量,默认 3
"""
# 实现搜索逻辑
return f"找到 {num_results} 条关于 '{query}' 的结果"工具绑定到模型
# 绑定工具到模型
model_with_tools = model.bind_tools([get_weather, calculator])
# AI 可以决定是否调用工具
response = model_with_tools.invoke("北京天气如何?")
# 检查 AI 是否要调用工具
if response.tool_calls:
print("AI 想调用工具:", response.tool_calls)
else:
print("AI 直接回答:", response.content)1.5 Agent 创建
核心概念
Agent = 模型 + 工具 + 自动决策
create_agent 基本用法
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
agent = create_agent(
model=init_chat_model("groq:llama-3.3-70b-versatile"),
tools=[tool1, tool2],
system_prompt="Agent 的行为指令" # 可选
)
response = agent.invoke({
"messages": [{"role": "user", "content": "问题"}]
})
# 获取最终回答
final_answer = response['messages'][-1].contentAgent 执行循环
用户问题 (HumanMessage)
↓
AI 决定 (AIMessage with tool_calls)
↓
执行工具 (ToolMessage)
↓
最终答案 (AIMessage)多轮对话 Agent
from langgraph.checkpoint.memory import MemorySaver
# 创建带记忆的 Agent
agent = create_agent(
model=model,
tools=[calculator],
system_prompt="你是一个有帮助的助手。",
checkpointer=MemorySaver() # 添加内存
)
# 使用 thread_id 来保持对话
config = {"configurable": {"thread_id": "conversation-1"}}
# 第一轮
response1 = agent.invoke(
{"messages": [{"role": "user", "content": "10 加 5 等于多少?"}]},
config=config
)
# 第二轮(记忆自动保持)
response2 = agent.invoke(
{"messages": [{"role": "user", "content": "再乘以 3 呢?"}]},
config=config
)1.6 Agent 执行循环
查看完整执行过程
response = agent.invoke({
"messages": [{"role": "user", "content": "25 乘以 8 等于多少?"}]
})
# 显示完整的消息历史
for i, msg in enumerate(response['messages'], 1):
print(f"\n--- 消息 {i} ({msg.__class__.__name__}) ---")
if hasattr(msg, 'content'):
print(f"内容:{msg.content}")
if hasattr(msg, 'tool_calls') and msg.tool_calls:
print(f"工具调用:{msg.tool_calls}")流式输出
# 使用 .stream() 实时输出
for chunk in agent.stream({"messages": [{"role": "user", "content": "问题"}]}):
# 实时处理每个步骤
print(chunk)Phase 2: 中级主题
2.1 内存管理
核心概念
内存 = Agent 记住对话历史的能力
没有内存(默认)
agent = create_agent(model=model, tools=[])
# 第一轮
agent.invoke({"messages": [{"role": "user", "content": "我叫张三"}]})
# 第二轮 - 不记得第一轮!
response = agent.invoke({"messages": [{"role": "user", "content": "我叫什么?"}]})
# AI 会说"不知道"添加内存
from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver
# 创建 Agent 时添加 checkpointer
agent = create_agent(
model=model,
tools=[],
checkpointer=InMemorySaver() # 添加内存
)
# 调用时指定 thread_id
config = {"configurable": {"thread_id": "conversation_1"}}
# 第一轮
agent.invoke(
{"messages": [{"role": "user", "content": "我叫张三"}]},
config=config
)
# 第二轮 - 记得第一轮!
response = agent.invoke(
{"messages": [{"role": "user", "content": "我叫什么?"}]},
config=config
)
# AI 会说"你叫张三"多会话管理
# 会话 1 - Alice
config_alice = {"configurable": {"thread_id": "user_alice"}}
agent.invoke({"messages": [...]}, config_alice)
# 会话 2 - Bob(完全独立)
config_bob = {"configurable": {"thread_id": "user_bob"}}
agent.invoke({"messages": [...]}, config_bob)2.2 上下文管理
问题:对话历史会无限增长
- 消息越来越多
- 超过模型的 token 限制
- 响应变慢、成本增加
解决方案:修剪对话历史
def trim_conversation(messages, max_tokens=4000):
"""修剪对话历史,保持在 token 限制内"""
# 保留 system 消息
system_msgs = [m for m in messages if m.get("role") == "system"]
conversation = [m for m in messages if m.get("role") != "system"]
# 从最新的消息开始保留
trimmed = []
current_tokens = 0
for msg in reversed(conversation):
msg_tokens = len(msg.get("content", "")) // 4 # 粗略估算
if current_tokens + msg_tokens > max_tokens:
break
trimmed.insert(0, msg)
current_tokens += msg_tokens
return system_msgs + trimmed2.3 检查点持久化
InMemorySaver 的限制
- ✅ 同一进程内有效
- ❌ 程序重启后丢失
- ❌ 不同进程无法共享
SQLite 持久化(后续学习)
from langgraph.checkpoint.sqlite import SqliteSaver
# 使用 SQLite 持久化
with SqliteSaver.from_conn_string("checkpoints.db") as checkpointer:
agent = create_agent(
model=model,
tools=tools,
checkpointer=checkpointer
)2.4 结构化输出
使用 Pydantic 定义输出结构
from pydantic import BaseModel, Field
from typing import List
class PersonInfo(BaseModel):
"""人物信息结构"""
name: str = Field(description="人物姓名")
age: int = Field(description="年龄")
skills: List[str] = Field(description="技能列表")
# 让模型输出结构化数据
model_with_structure = model.with_structured_output(PersonInfo)
result = model_with_structure.invoke("介绍一下 Elon Musk")
print(result.name) # "Elon Musk"
print(result.age) # 52
print(result.skills) # ["创业", "工程", ...]2.5 RAG 基础
核心概念
RAG (Retrieval-Augmented Generation) = 检索增强生成
RAG 工作流程:
1. 离线:文档 → 分割 → 嵌入 → 存入向量数据库
2. 在线:用户查询 → 检索相关文档 → 提供给 LLM → 生成答案完整实现
# 1. 文档加载
from langchain_community.document_loaders import TextLoader
loader = TextLoader("document.txt", encoding="utf-8")
documents = loader.load()
# 2. 文本分割
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每块最大字符数
chunk_overlap=50, # 块之间的重叠
)
chunks = splitter.split_documents(documents)
# 3. 向量嵌入
from langchain_huggingface import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2" # 免费模型
)
# 4. 存入 Pinecone
from langchain_pinecone import PineconeVectorStore
vectorstore = PineconeVectorStore.from_documents(
documents=chunks,
embedding=embeddings,
index_name="my-index"
)
# 5. 检索
docs = vectorstore.similarity_search("查询文本", k=3)
# 6. 创建 RAG Agent
from langchain.agents import create_agent
from langchain_core.tools import tool
@tool
def search_kb(query: str) -> str:
"""搜索知识库"""
docs = vectorstore.similarity_search(query, k=3)
return "\n\n".join([doc.page_content for doc in docs])
agent = create_agent(
model=model,
tools=[search_kb],
system_prompt="使用 search_kb 工具检索信息,然后回答问题。"
)2.6 RAG 进阶
混合搜索
# 向量搜索 + 关键词搜索
results = vectorstore.similarity_search(
query="查询",
k=3,
filter={"category": "tech"} # 元数据过滤
)重排序(Reranking)
# 先检索更多结果,然后重排序
initial_results = vectorstore.similarity_search(query, k=10)
reranked_results = reranker.rerank(query, initial_results, top_k=3)Phase 3: 高级主题
3.1 LangGraph 基础
核心概念
LangGraph 使用图(Graph) 来组织工作流:
- 节点(Nodes):处理单元
- 边(Edges):连接节点的路径
- 状态(State):在节点之间传递的数据
基本用法
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
# 1. 定义状态
class State(TypedDict):
messages: Annotated[list, add_messages] # 消息列表,自动累加
current_step: str
# 2. 定义节点
def process_node(state: State) -> dict:
# 处理逻辑
return {"current_step": "completed"}
# 3. 创建图
graph = StateGraph(State)
graph.add_node("process", process_node)
graph.add_edge(START, "process")
graph.add_edge("process", END)
# 4. 编译并运行
app = graph.compile()
result = app.invoke({"messages": [], "current_step": "start"})条件边
def route_function(state: State) -> str:
"""根据状态决定下一个节点"""
if state["current_step"] == "need_research":
return "researcher"
else:
return "writer"
graph.add_conditional_edges(
"supervisor",
route_function,
{
"researcher": "researcher_node",
"writer": "writer_node"
}
)3.2 多 Agent 协作
监督者模式(Supervisor Pattern)
┌──────────────┐
│ Supervisor │
│ (协调者) │
└──────┬───────┘
┌───────────┼───────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Agent A │ │ Agent B │ │ Agent C │
│(研究员) │ │ (编辑) │ │(审核员) │
└─────────┘ └─────────┘ └─────────┘完整实现
from typing import TypedDict, Annotated, Literal
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
# 定义状态
class TeamState(TypedDict):
task: str
messages: Annotated[list, add_messages]
research_result: str
draft: str
final_content: str
next_agent: str
# 监督者节点
def supervisor(state: TeamState) -> dict:
"""决定下一步由哪个 Agent 处理"""
if not state.get("research_result"):
next_agent = "researcher"
elif not state.get("draft"):
next_agent = "writer"
elif not state.get("final_content"):
next_agent = "editor"
else:
next_agent = "complete"
return {"next_agent": next_agent}
# 研究员 Agent
def researcher(state: TeamState) -> dict:
"""收集和整理信息"""
# 使用 LLM 进行研究
response = model.invoke([
{"role": "system", "content": "你是一个研究员"},
{"role": "user", "content": state["task"]}
])
return {"research_result": response.content}
# 作家 Agent
def writer(state: TeamState) -> dict:
"""撰写内容"""
response = model.invoke([
{"role": "system", "content": "你是一个作家"},
{"role": "user", "content": f"根据研究资料写作:{state['research_result']}"}
])
return {"draft": response.content}
# 编辑 Agent
def editor(state: TeamState) -> dict:
"""审核和优化"""
response = model.invoke([
{"role": "system", "content": "你是一个编辑"},
{"role": "user", "content": f"审核优化:{state['draft']}"}
])
return {"final_content": response.content}
# 路由函数
def route_to_agent(state: TeamState) -> Literal["researcher", "writer", "editor", "complete"]:
return state["next_agent"]
# 构建图
graph = StateGraph(TeamState)
# 添加节点
graph.add_node("supervisor", supervisor)
graph.add_node("researcher", researcher)
graph.add_node("writer", writer)
graph.add_node("editor", editor)
# 添加边
graph.add_edge(START, "supervisor")
graph.add_conditional_edges(
"supervisor",
route_to_agent,
{
"researcher": "researcher",
"writer": "writer",
"editor": "editor",
"complete": END
}
)
graph.add_edge("researcher", "supervisor")
graph.add_edge("writer", "supervisor")
graph.add_edge("editor", "supervisor")
# 编译并运行
app = graph.compile()
result = app.invoke({"task": "写一篇关于 AI 的文章", "messages": []})3.3 条件路由
动态分支
def classifier(state: State) -> dict:
"""分类器:识别任务类型"""
response = model.invoke([
{"role": "system", "content": "分类任务:billing/technical/general"},
{"role": "user", "content": state["query"]}
])
return {"category": response.content.strip().lower()}
def route_to_specialist(state: State) -> Literal["billing", "technical", "general"]:
return state["category"]
graph.add_conditional_edges(
"classifier",
route_to_specialist,
{
"billing": "billing_agent",
"technical": "technical_agent",
"general": "general_agent"
}
)3.4 多模态处理
图像输入
from langchain_core.messages import HumanMessage
# 传递图像 URL
message = HumanMessage(content=[
{"type": "text", "text": "这张图片里有什么?"},
{"type": "image_url", "image_url": {"url": "https://example.com/image.jpg"}}
])
response = model.invoke([message])文件处理
from langchain_community.document_loaders import PyPDFLoader
# 加载 PDF
loader = PyPDFLoader("document.pdf")
pages = loader.load()
# 处理每一页
for page in pages:
print(page.page_content)3.5 LangSmith 集成
配置
# .env
LANGSMITH_API_KEY=your-key
LANGSMITH_TRACING=true
LANGSMITH_PROJECT=my-project追踪和监控
# 自动追踪所有 LLM 调用
response = model.invoke("Hello")
# 在 LangSmith Dashboard 查看:
# - Token 使用
# - 延迟
# - 成本
# - 调用链3.6 错误处理
重试机制
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=4, max=10)
)
def call_with_retry(messages):
return model.invoke(messages)降级处理
def safe_invoke(messages, fallback_model=None):
"""安全的模型调用,带降级"""
try:
return model.invoke(messages)
except Exception as e:
print(f"主模型失败: {e}")
if fallback_model:
return fallback_model.invoke(messages)
return AIMessage(content="抱歉,服务暂时不可用")附录:快速参考
常用导入
# 模型
from langchain.chat_models import init_chat_model
# 提示词
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
# 消息
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
# 工具
from langchain_core.tools import tool
# Agent
from langchain.agents import create_agent
# 内存
from langgraph.checkpoint.memory import InMemorySaver
# LangGraph
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
# 文档加载
from langchain_community.document_loaders import TextLoader, PyPDFLoader
# 文本分割
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 嵌入
from langchain_huggingface import HuggingFaceEmbeddings
# 向量存储
from langchain_pinecone import PineconeVectorStore环境配置
# .env 文件
GROQ_API_KEY=your-groq-key
OPENAI_API_KEY=your-openai-key
PINECONE_API_KEY=your-pinecone-key
LANGSMITH_API_KEY=your-langsmith-key安装依赖
pip install langchain langchain-groq langchain-openai langgraph langsmith
pip install langchain-huggingface langchain-pinecone pinecone-client
pip install langchain-text-splitters langchain-community
pip install python-dotenv pydantic本手册整理自 LangChain1.0-Langgraph1.0-Learning 学习资料