# LearnAgent
**Repository Path**: samsom/learn-agent
## Basic Information
- **Project Name**: LearnAgent
- **Description**: 一个分阶段学习 LangChain、LangGraph 和 MCP 框架的实践项目,从基础 LLM 调用到构建完整的 RAG、Agent 及多 Agent 协作系统。
- **Primary Language**: Python
- **License**: MulanPSL-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2026-07-17
- **Last Updated**: 2026-09-15
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# LangChain & LangGraph 学习项目
一个分阶段学习 LangChain、LangGraph 和 MCP 框架的实践项目,从基础 LLM 调用到构建完整的 RAG、Agent 及多 Agent 协作系统。
## 项目结构
```
LearnProject/
├── .env # 环境变量配置(API Key)
├── .gitignore
├── file/
│ └── test.txt # RAG 测试文档
├── README.md
├── langChain_base/ # LangChain 基础学习
│ ├── stage1.py # 基础 LLM 调用
│ ├── stage2.py # 提示词模板
│ ├── stage3.py # 输出解析器与链式调用
│ ├── stage4.py # 对话历史管理
│ ├── stage5.py # RAG(检索增强生成)
│ └── stage6.py # 工具与 Agent
├── langGraph_base/ # LangGraph 基础学习
│ ├── stage_graph_1.py # State/Node/Edge 基础
│ ├── stage_graph_2.py # 条件分支路由
│ ├── stage_graph_3.py # 手动构建 ReAct Agent
│ ├── stage_graph_4.py # Human-in-the-loop
│ └── stage_graph_5.py # 多 Agent 协作
├── langGraph_mcp/ # LangGraph MCP 学习
│ ├── mcp_math_server.py # MCP 数学服务器
│ ├── mcp_weather_server.py # MCP 天气服务器
│ ├── stage_mcp_single.py # 单 MCP 服务器集成
│ └── stage_mcp_multi.py # 多 MCP 服务器集成
└── smart_assistant/ # 综合实战
└── main.py # 智能助手系统(整合所有知识点)
```
## 环境要求
- Python 3.8+
- 智谱 AI API Key(或其他兼容 OpenAI 接口的大模型 API)
## 安装依赖
```bash
# LangChain 基础依赖
pip install langchain langchain-openai langchain-community langchain-text-splitters langgraph chromadb python-dotenv
# LangGraph MCP 额外依赖
pip install mcp langchain-mcp-adapters
```
## 配置
在项目根目录创建 `.env` 文件,填入你的 API Key:
```
OPENAI_API_KEY=your_api_key_here
```
## 学习阶段
### Stage 1:基础 LLM 调用
演示如何使用 `ChatOpenAI` 调用大语言模型。
**知识要点:**
- `load_dotenv()`:从 `.env` 文件加载环境变量,避免硬编码 API Key
- `ChatOpenAI`:LangChain 的聊天模型封装,兼容 OpenAI 接口格式
- `model`:指定模型名称,此处使用智谱 GLM-4-Flash
- `base_url`:自定义 API 端点,可对接第三方兼容服务
- `temperature`:控制输出随机性,0 为确定性输出,1 为高随机性
- `invoke()`:同步调用模型,返回 `AIMessage` 对象
- `.content`:从 `AIMessage` 中提取纯文本内容
```bash
python stage1.py
```
### Stage 2:提示词模板
使用 `ChatPromptTemplate` 构建可复用的提示词模板,支持变量替换。
**知识要点:**
- `ChatPromptTemplate.from_messages()`:从消息列表创建模板
- 消息角色:`system`(系统指令)、`human`(用户输入)、`ai`(助手回复)
- `{变量名}`:模板占位符,调用时传入字典进行替换
- 模板与模型解耦:同一模板可复用于不同模型
- `.invoke(dict)`:将变量填入模板,生成最终消息列表
```bash
python stage2.py
```
### Stage 3:链式调用(LCEL)
通过管道符 `|` 将 prompt、llm、parser 串联成一个完整的处理链。
**知识要点:**
- LCEL(LangChain Expression Language):LangChain 的声明式链式语法
- 管道符 `|`:将组件串联,前一个组件的输出作为后一个的输入
- `StrOutputParser()`:将 `AIMessage` 转为纯字符串,简化后续处理
- 链式调用优势:代码简洁、易于组合、支持流式输出
- `chain.invoke()`:一次调用跑完整个流程
```bash
python stage3.py
```
### Stage 4:对话历史
使用 `RunnableWithMessageHistory` 和 `InMemoryChatMessageHistory` 实现多轮对话记忆。
**知识要点:**
- `MessagesPlaceholder`:在模板中预留历史消息插入位置
- `InMemoryChatMessageHistory`:内存中的对话历史存储
- `RunnableWithMessageHistory`:自动管理对话历史的包装器
- `session_id`:会话标识符,不同 ID 对应不同对话历史
- `get_session_history`:回调函数,根据 session_id 返回对应的历史存储
- 工作流程:调用前自动读取历史 → 拼入 prompt → 调用模型 → 自动保存新历史
```bash
python stage4.py
```
### Stage 5:RAG(检索增强生成)
文档加载 → 文本分割 → 向量存储 → 检索 → 生成回答。
**知识要点:**
- **文档加载**:`TextLoader` 读取本地文本文件,返回 `Document` 对象
- **文本分割**:`RecursiveCharacterTextSplitter` 按语义递归分割长文本
- `chunk_size`:每个文本块的最大字符数
- `chunk_overlap`:相邻块的重叠字符数,保持上下文连贯
- **向量嵌入**:`OpenAIEmbeddings` 将文本转为向量表示
- **向量存储**:`Chroma` 本地向量数据库,存储和检索嵌入向量
- **检索器**:`as_retriever()` 创建检索接口,`k=3` 返回最相关的 3 个文档块
- **RAG 链**:`retriever | format_docs` 检索文档 → `RunnablePassthrough` 透传问题 → 模型生成答案
```bash
python stage5.py
```
### Stage 6:工具与 Agent
使用 `@tool` 装饰器定义工具,通过 `create_react_agent` 创建能自主调用工具的 Agent。
**知识要点:**
- `@tool` 装饰器:将普通函数转为 LangChain 工具
- **docstring 的关键作用**:Agent 根据文档字符串判断何时调用该工具
- `create_react_agent`:创建 ReAct 模式的 Agent
- **ReAct 循环**:思考(Thought)→ 行动(Action)→ 观察(Observation)→ 循环
- `temperature=0`:让 Agent 决策更稳定、确定性更强
- Agent 优势:可根据任务自主选择工具,无需硬编码调用逻辑
- 输入输出:通过 `messages` 列表交互,格式为 `[("human", "问题")]`
```bash
python stage6.py
```
---
## LangGraph 基础学习阶段
### Stage Graph-1:State/Node/Edge 基础
理解 LangGraph 的三要素:State(状态)、Node(节点)、Edge(边)。
**类比理解:**
- **State** = 工作台上的工件(所有节点共享的数据)
- **Node** = 工人(处理数据的函数)
- **Edge** = 流水线(连接工人之间的传送带)
- **Graph** = 整条流水线蓝图
**知识要点:**
- `State(TypedDict)`:用 TypedDict 定义状态结构,所有节点共享
- `Node 函数`:接收 State 作为参数,返回要更新的字段字典
- `StateGraph(State)`:图的构建器,传入 State 类型定义
- `add_node("name", func)`:添加节点,起一个名字
- `add_edge(START, "node")`:添加边,定义执行顺序
- `START` / `END`:LangGraph 内置的特殊节点,表示入口和出口
- `compile()`:把构建器变成可执行的图对象
- `graph.invoke(state)`:运行图,传入初始 State
```python
# stage_graph_1.py 核心代码
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
input: str
result: str
def greeting_node(state: State) -> dict:
return {"result": f"你好!你说了:{state['input']}"}
graph_builder = StateGraph(State)
graph_builder.add_node("greeting", greeting_node)
graph_builder.add_edge(START, "greeting")
graph_builder.add_edge("greeting", END)
graph = graph_builder.compile()
result = graph.invoke({"input": "Hello", "result": ""})
```
### Stage Graph-2:条件分支路由
根据 State 中的数据决定走哪条路,实现动态路由。
**知识要点:**
- `add_conditional_edges(起点, 判断函数, {返回值: 目标节点})`:条件分支
- **判断函数**:接收 State,返回字符串(路由标识)
- **路由映射**:字典形式,判断函数返回值 → 目标节点名
- 支持多路分支:math / translate / chat 等
```python
# 条件分支核心代码
def route_by_category(state: State) -> str:
return state["category"] # "math" / "translate" / "chat"
graph_builder.add_conditional_edges(
"classify", # 从 classify 节点出发
route_by_category, # 用这个函数决定走哪条路
{ # 返回值 → 目标节点 的映射
"math": "math",
"translate": "translate",
"chat": "chat",
}
)
```
### Stage Graph-3:手动构建 ReAct Agent
用 LangGraph 手动实现 ReAct 循环(思考 → 行动 → 观察 → 循环),理解底层原理。
**知识要点:**
- **循环能力**:LangGraph 的核心优势,LangChain 的 Chain 做不到
- `Annotated[list, add_messages]`:消息列表的更新方式是「追加」而非「替换」
- `llm.bind_tools([...])`:把工具绑定到 LLM,让 LLM 知道有哪些工具可用
- `response.tool_calls`:LLM 返回的工具调用请求列表
- `ToolMessage`:包装工具执行结果的消息类型
- **条件循环**:`should_continue` 函数判断是否需要继续调用工具
```python
# ReAct 循环核心代码
def think_node(state: State) -> dict:
response = llm.invoke(state["messages"])
return {"messages": [response]} # 追加 AI 回复(可能包含 tool_calls)
def act_node(state: State) -> dict:
tool_messages = []
for tool_call in state["messages"][-1].tool_calls:
result = TOOLS[tool_call["name"]].invoke(tool_call["args"])
tool_messages.append(ToolMessage(content=str(result), tool_call_id=tool_call["id"]))
return {"messages": tool_messages}
def should_continue(state: State) -> str:
if hasattr(state["messages"][-1], "tool_calls") and state["messages"][-1].tool_calls:
return "act" # 继续调用工具
return END # 给出最终回答
# act 完成后回到 think(形成循环!)
graph_builder.add_edge("act", "think")
```
### Stage Graph-4:Human-in-the-loop
在图执行过程中暂停,等待人类确认后再继续。
**使用场景:**
- 发邮件前让人类确认内容
- 执行敏感操作前要求审批
- 让人类选择下一步方向
**知识要点:**
- `interrupt(value)`:暂停点,图执行到此处会暂停,返回值展示给审批人
- `Command(resume=value)`:恢复执行,传入的值成为 `interrupt()` 的返回值
- `MemorySaver`:内存检查点,保存暂停时的状态(生产环境用数据库)
- `graph.stream()` + `interrupt()`:流式执行,遇到 interrupt 自动暂停
- `thread_id`:检查点按 thread_id 保存状态,支持多会话隔离
```python
# Human-in-the-loop 核心代码
from langgraph.checkpoint.memory import MemorySaver
from langgraph.types import interrupt, Command
def human_approval_node(state: State) -> dict:
decision = interrupt({
"question": "请确认是否执行?",
"plan": state["plan"]
})
# decision 的值来自 Command(resume=...) 传入的内容
return {"approved": decision.lower() == "yes"}
memory = MemorySaver()
graph = graph_builder.compile(checkpointer=memory)
config = {"configurable": {"thread_id": "task_001"}}
# 第一次运行:执行到 interrupt 处暂停
for event in graph.stream(initial_state, config):
if "__interrupt__" in event:
print("图已暂停,等待人类确认...")
# 恢复执行
for event in graph.stream(Command(resume="yes"), config):
...
```
### Stage Graph-5:多 Agent 协作
多个 Agent 协作完成复杂任务,主管分配任务,工人执行,最后汇总。
**架构:**
```
用户问题 → 主管 Agent(分类)→ 路由到对应 Agent → 汇总输出
├─ 研究员 → 写手 → 审稿人
├─ 通用 Agent
└─ ...
```
**知识要点:**
- **主管 Agent**:分析问题,决定任务类型(research / write / review / general)
- **专业 Agent**:每个节点是一个专业 Agent(研究员、写手、审稿人)
- **多级路由**:主管分类后路由,研究员完成后再次路由
- **检查点**:`MemorySaver` 保存执行历史,支持多轮对话
- **State 设计**:包含各 Agent 的结果字段,支持结果传递
```python
# 多 Agent 协作核心代码
graph_builder.add_conditional_edges(
"supervisor",
route_task,
{"general": "general", "researcher": "researcher", "reviewer": "reviewer"}
)
graph_builder.add_conditional_edges(
"researcher",
after_research,
{"writer": "writer", "reviewer": "reviewer"}
)
graph_builder.add_edge("writer", "reviewer")
graph_builder.add_edge("reviewer", "merge")
graph_builder.add_edge("merge", END)
```
### Stage Graph 运行说明
```bash
# 基础概念
python stage_graph_1.py
# 条件分支
python stage_graph_2.py
# ReAct Agent
python stage_graph_3.py
# Human-in-the-loop
python stage_graph_4.py
# 多 Agent 协作
python stage_graph_5.py
```
---
## LangGraph MCP 学习阶段
### Stage MCP-1:MCP 服务器基础
使用 `FastMCP` 创建 MCP 服务器,暴露工具(Tools)、资源(Resources)和提示词模板(Prompts)。
**知识要点:**
- **MCP(Model Context Protocol)**:模型上下文协议,标准化 AI 模型与外部工具/数据源的交互方式
- **FastMCP**:快速创建 MCP 服务器的高级封装类
- **工具(Tools)**:可执行的函数,客户端可以调用(如计算、查询)
- `@mcp.tool()` 装饰器:将函数注册为 MCP 工具
- **docstring 的关键作用**:Agent 根据**文档字符串**判断何时调用该工具
- **资源(Resources)**:只读数据,客户端可以读取但不能修改
- `@mcp.resource("uri://pattern")` 装饰器:注册资源端点
- URI 模式支持参数化:`greeting://{name}`
- **提示词模板(Prompts)**:预定义的 prompt,客户端可以直接获取使用
- `@mcp.prompt()` 装饰器:注册提示词模板
- **传输方式**:
- `stdio`:标准输入输出,适合本地运行
- `streamable-http`:HTTP 协议,适合远程服务
```python
# mcp_math_server.py 核心代码
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Math")
@mcp.tool()
def add(a: int, b: int) -> int:
"""计算两个整数的和"""
return a + b
@mcp.resource("config://math")
def get_config() -> str:
"""返回数学服务器的配置信息"""
return "Math MCP Server v1.0"
@mcp.prompt()
def math_assistant_prompt(question: str) -> str:
"""数学助手的提示词模板"""
return f"请解答:{question}"
if __name__ == "__main__":
mcp.run(transport="stdio")
```
### Stage MCP-2:MCP 客户端集成(单服务器)
使用 LangGraph 的 `create_react_agent` 连接单个 MCP 服务器,调用其中的工具。
**知识要点:**
- `StdioServerParameters`:配置 MCP 服务器连接参数(命令、参数、环境变量)
- `stdio_client`:异步上下文管理器,自动启动 MCP 服务器进程并建立通信
- `ClientSession`:MCP 客户端会话,负责与服务器进行协议交互
- `session.initialize()`:初始化连接(握手),必须在使用前调用
- `load_mcp_tools()`:将 MCP 工具转换为 LangChain 工具格式,供 Agent 使用
- **资源与提示词的发现**:
- `session.list_resources()`:列出服务器提供的所有资源
- `session.list_prompts()`:列出服务器提供的所有提示词模板
- `session.read_resource(uri)`:读取指定资源的内容
- **异步执行**:整个流程使用 `asyncio`,支持异步调用
```python
# stage_mcp_single.py 核心代码
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
server_params = StdioServerParameters(
command="python",
args=["mcp_math_server.py"],
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
# 加载 MCP 工具为 LangChain 格式
tools = await load_mcp_tools(session)
# 创建 Agent
agent = create_react_agent(model=llm, tools=tools, prompt=prompt)
# 调用 Agent
result = await agent.ainvoke({"messages": [("human", "3加5等于多少?")]})
```
### Stage MCP-3:多 MCP 服务器集成
使用 `MultiServerMCPClient` 同时连接多个 MCP 服务器,实现跨服务器的工具调用。
**知识要点:**
- **MultiServerMCPClient**:管理多个 MCP 服务器连接的客户端
- **配置格式**:字典形式,每个服务器一个配置项
- `stdio` 模式:指定 `command` 和 `args`,客户端自动启动服务器
- `streamable_http` 模式:指定 `url`,需手动启动服务器
- **身份认证**:远程服务可通过 `headers` 传递 API Key
- **client.get_tools()**:汇总所有服务器的工具,自动去重和合并
- **混合调用**:Agent 可根据需要调用任意服务器的工具,无需关心工具来源
- **多轮对话**:通过传递历史消息列表实现上下文连续的对话
```python
# stage_mcp_multi.py 核心代码
from langchain_mcp_adapters.client import MultiServerMCPClient
client = MultiServerMCPClient({
"math": {
"command": "python",
"args": ["mcp_math_server.py"],
"transport": "stdio",
},
"weather": {
"url": "http://127.0.0.1:8000/mcp",
"transport": "streamable_http",
},
"dream": {
"url": "https://open.bigmodel.cn/api/mcp-broker/proxy/dream-interpretation/mcp",
"transport": "streamable_http",
"headers": {"Authorization": f"Bearer {API_KEY}"},
},
})
async with client:
tools = await client.get_tools()
agent = create_react_agent(model=llm, tools=tools, prompt=prompt)
```
### Stage MCP 运行说明
**数学服务器(stdio,自动启动):**
```bash
# 单服务器测试
python stage_mcp_single.py
# 多服务器测试(数学服务器会自动启动)
python stage_mcp_multi.py
```
**天气服务器(streamable-http,需手动启动):**
```bash
# 终端1:启动天气服务器
python mcp_weather_server.py
# 终端2:启动多服务器测试
python stage_mcp_multi.py
```
---
## 综合实战:智能助手系统
整合所有知识点,构建一个完整的智能助手系统。
### 架构设计
```
用户问题
↓
主管 Agent(分类)
├─ math ──────→ 数学 Agent(MCP 工具 + ReAct 循环)
├─ research ──→ 研究员 → 写手 → 人工审批 ─┬─ 通过 → 汇总
│ └─ 退回 → 修改 → 重新审批
└─ chat ──────→ 闲聊 Agent
↓
汇总节点
↓
最终输出
```
### 整合的知识点
| 模块 | 使用的知识 |
|------|-----------|
| **State** | TypedDict + Annotated[list, add_messages] 追加模式 |
| **Node** | 主管、数学Agent、研究员、写手、审稿人、审批、修改、汇总 |
| **Edge** | 条件分支路由、循环边 |
| **MCP** | MultiServerMCPClient 连接多个服务器 |
| **Memory** | MemorySaver 检查点保存状态 |
| **Human-in-the-loop** | interrupt() + Command(resume) 人工审批 |
| **ReAct** | 数学Agent 手动实现思考→行动→观察循环 |
| **多Agent** | 主管分配 + 专业Agent执行 + 汇总 |
### 核心代码结构
```python
# 1. MCP 服务器配置
mcp_client = MultiServerMCPClient({
"math": {"command": "python", "args": ["mcp_math_server.py"], "transport": "stdio"},
"weather": {"url": "http://127.0.0.1:8000/mcp", "transport": "streamable_http"},
})
# 2. State 定义
class State(TypedDict):
messages: Annotated[list, add_messages]
question: str
task_type: str
approved: bool
retry_count: int
final_output: str
...
# 3. 节点定义
def supervisor_node(state): ... # 主管分类
def math_agent_node(state): ... # 数学Agent(MCP + ReAct)
def researcher_node(state): ... # 研究员
def writer_node(state): ... # 写手
def human_review_node(state): ... # 人工审批(interrupt)
def revise_node(state): ... # 根据反馈修改
def merge_node(state): ... # 汇总
# 4. 条件路由
graph_builder.add_conditional_edges("supervisor", route_task, {...})
graph_builder.add_conditional_edges("human_review", check_approval, {...})
# 5. 循环边
graph_builder.add_edge("revise", "human_review") # 修改后重新审批
# 6. 编译(带检查点)
memory = MemorySaver()
graph = graph_builder.compile(checkpointer=memory)
```
### 运行说明
```bash
# 1. 启动天气服务器(可选)
python ../langGraph_mcp/mcp_weather_server.py
# 2. 运行智能助手
python main.py
```
---
## LangChain 知识图谱
### 整体架构
```mermaid
graph TB
subgraph "应用层"
Agent["Agent 智能体"]
Chain["Chain 处理链"]
end
subgraph "核心模块"
LLM["LLM/ChatModel
大语言模型"]
Prompt["PromptTemplate
提示词模板"]
Parser["OutputParser
输出解析器"]
end
subgraph "记忆模块"
Memory["Memory
对话记忆"]
History["ChatMessageHistory
消息历史"]
end
subgraph "数据模块"
Loader["DocumentLoader
文档加载器"]
Splitter["TextSplitter
文本分割器"]
Embedding["Embeddings
向量嵌入"]
VectorStore["VectorStore
向量数据库"]
Retriever["Retriever
检索器"]
end
subgraph "工具模块"
Tool["Tool
工具"]
Toolkit["Toolkit
工具集"]
end
LLM --> Chain
Prompt --> Chain
Parser --> Chain
Memory --> Chain
Retriever --> Chain
Tool --> Agent
LLM --> Agent
Loader --> Splitter
Splitter --> Embedding
Embedding --> VectorStore
VectorStore --> Retriever
```
### 模块关系图
```mermaid
graph LR
subgraph "输入处理"
A[用户输入] --> B[PromptTemplate]
B --> C[格式化消息]
end
subgraph "模型调用"
C --> D[ChatModel]
D --> E[AIMessage]
end
subgraph "输出处理"
E --> F[OutputParser]
F --> G[结构化输出]
end
subgraph "记忆存储"
D --> H[Memory]
H --> I[历史记录]
I --> B
end
subgraph "外部知识"
J[文档] --> K[Loader]
K --> L[Splitter]
L --> M[Embedding]
M --> N[VectorStore]
N --> O[Retriever]
O --> B
end
subgraph "工具调用"
P[Tool] --> Q[Agent]
Q --> D
D --> Q
end
```
### 核心概念详解
#### 1. 模型层(Models)
| 概念 | 说明 | 本项目示例 |
|------|------|-----------|
| **LLM** | 纯文本输入输出的基础大模型 | - |
| **ChatModel** | 对话格式的聊天模型 | `ChatOpenAI` |
| **Embedding** | 文本转向量的嵌入模型 | `embedding-3` |
```python
# 模型调用流程
llm = ChatOpenAI(model="glm-4-flash")
response = llm.invoke("Hello") # → AIMessage
```
#### 2. 提示词层(Prompts)
| 概念 | 说明 | 关键类 |
|------|------|--------|
| **PromptTemplate** | 纯文本模板 | `PromptTemplate` |
| **ChatPromptTemplate** | 对话消息模板 | `ChatPromptTemplate` |
| **MessagesPlaceholder** | 历史消息占位符 | `MessagesPlaceholder` |
```python
# 模板变量替换
prompt = ChatPromptTemplate.from_messages([
("system", "你是{role}助手"),
("human", "{question}")
])
messages = prompt.invoke({"role": "幽默", "question": "为什么天是蓝的?"})
```
#### 3. 输出解析层(Output Parsers)
| 概念 | 说明 | 适用场景 |
|------|------|---------|
| **StrOutputParser** | 转为纯字符串 | 简单文本输出 |
| **JsonOutputParser** | 转为JSON格式 | 结构化数据 |
| **PydanticOutputParser** | 转为Pydantic对象 | 强类型校验 |
#### 4. 记忆层(Memory)
| 概念 | 说明 | 存储方式 |
|------|------|---------|
| **ChatMessageHistory** | 原始历史存储 | 内存/数据库 |
| **RunnableWithMessageHistory** | 自动管理包装器 | 回调函数 |
| **session_id** | 会话隔离标识 | 字符串 |
```python
# 记忆管理流程
store = {}
def get_history(session_id):
if session_id not in store:
store[session_id] = InMemoryChatMessageHistory()
return store[session_id]
chain_with_memory = RunnableWithMessageHistory(chain, get_history)
```
#### 5. 数据层(Data)
```mermaid
graph LR
A[DocumentLoader
加载文档] --> B[TextSplitter
分割文本]
B --> C[Embeddings
向量化]
C --> D[VectorStore
存储向量]
D --> E[Retriever
检索相关文档]
style A fill:#e1f5fe
style B fill:#e1f5fe
style C fill:#e1f5fe
style D fill:#e1f5fe
style E fill:#e1f5fe
```
| 概念 | 说明 | 常用实现 |
|------|------|---------|
| **DocumentLoader** | 加载各种格式文档 | `TextLoader`, `PyPDFLoader` |
| **TextSplitter** | 文本分块处理 | `RecursiveCharacterTextSplitter` |
| **Embeddings** | 文本转向量 | `OpenAIEmbeddings`, `HuggingFaceEmbeddings` |
| **VectorStore** | 向量数据库 | `Chroma`, `FAISS`, `Pinecone` |
| **Retriever** | 相似度检索 | `vectorstore.as_retriever()` |
#### 6. 链式调用(LCEL)
```python
# LCEL 核心语法
chain = prompt | llm | parser
# 分支结构
from langchain_core.runnables import RunnableParallel
branch = RunnableParallel(
context=retriever | format_docs,
question=RunnablePassthrough()
)
# 带记忆的链
chain_with_memory = RunnableWithMessageHistory(
chain, get_history, input_messages_key="input", history_messages_key="history"
)
```
#### 7. 工具与代理(Tools & Agents)
```mermaid
graph TB
A[用户请求] --> B[Agent]
B --> C{需要工具?}
C -->|是| D[选择Tool]
D --> E[执行Tool]
E --> F[获取结果]
F --> B
C -->|否| G[直接回答]
subgraph "Tool类型"
H[calculator]
I[word_count]
J[get_current_time]
end
D --> H
D --> I
D --> J
style B fill:#fff3e0
style D fill:#e8f5e9
```
| 概念 | 说明 | 关键组件 |
|------|------|---------|
| **@tool** | 函数转工具装饰器 | `langchain_core.tools` |
| **Agent** | 自主决策的智能体 | `create_react_agent` |
| **ReAct** | 思考-行动-观察循环 | Thought → Action → Observation |
| **Tool Description** | 工具功能描述 | docstring |
### 完整数据流
```mermaid
sequenceDiagram
participant U as 用户
participant P as PromptTemplate
participant M as ChatModel
participant O as OutputParser
participant Mem as Memory
participant R as Retriever
U->>P: 发送问题
P->>P: 填充模板变量
Note over P: 插入历史消息
Mem-->>P: 提供历史记录
R-->>P: 提供相关文档
P->>M: 发送格式化消息
M->>M: 生成回答
M->>O: 返回AIMessage
O->>O: 解析为字符串
O->>Mem: 保存对话历史
O->>U: 返回最终结果
```
### 包结构对照
| 包名 | 用途 | 本项目使用 |
|------|------|-----------|
| `langchain-core` | 核心抽象和基础组件 | PromptTemplate, StrOutputParser |
| `langchain-openai` | OpenAI API封装 | ChatOpenAI, OpenAIEmbeddings |
| `langchain-community` | 第三方集成 | TextLoader, Chroma |
| `langchain-text-splitters` | 文本分割工具 | RecursiveCharacterTextSplitter |
| `langgraph` | Agent编排框架 | create_react_agent |
## 技术栈
- **LangChain** - LLM 应用开发框架
- **LangGraph** - Agent 编排框架
- **MCP** - 模型上下文协议
- **ChromaDB** - 向量数据库
- **智谱 GLM-4-Flash** - 大语言模型
---
## LangGraph 知识图谱
### LangGraph 核心概念
```mermaid
graph TB
subgraph "三要素"
State["State
状态(共享数据)"]
Node["Node
节点(处理函数)"]
Edge["Edge
边(执行顺序)"]
end
subgraph "核心能力"
Conditional["条件分支
add_conditional_edges"]
Loop["循环
act → think"]
Checkpoint["检查点
MemorySaver"]
HumanLoop["Human-in-the-loop
interrupt + Command"]
end
subgraph "应用模式"
SimpleChain["简单链
START → A → B → END"]
Branch["分支
A → 条件 → B/C/D"]
ReActAgent["ReAct Agent
think ⇄ act"]
MultiAgent["多 Agent
主管 → 工人 → 汇总"]
end
State --> Node
Node --> Edge
Edge --> Conditional
Edge --> Loop
Checkpoint --> HumanLoop
Conditional --> Branch
Loop --> ReActAgent
```
### LangGraph 与 LangChain 对比
| 特性 | LangChain Chain | LangGraph |
|------|----------------|-----------|
| **执行流程** | 线性(A→B→C) | 任意图结构 |
| **循环** | ❌ 不支持 | ✅ 支持 |
| **条件分支** | 有限支持 | 完整支持 |
| **状态管理** | 外部管理 | 内置 State |
| **Human-in-the-loop** | 不支持 | ✅ 支持 |
| **检查点** | 不支持 | ✅ 支持 |
### LangGraph 执行流程
```mermaid
sequenceDiagram
participant U as 用户
participant G as Graph
participant S as State
participant N1 as Node A
participant N2 as Node B
participant CP as Checkpoint
U->>G: invoke(initial_state)
G->>S: 加载 State
G->>N1: 执行 Node A
N1->>S: 更新 State
G->>CP: 保存检查点
G->>N2: 执行 Node B
N2->>S: 更新 State
G->>CP: 保存检查点
G->>U: 返回最终 State
```
---
## LangGraph MCP 知识图谱
### MCP 架构概览
```mermaid
graph TB
subgraph "MCP 客户端"
Agent["LangGraph Agent"]
Client["MCP Client"]
end
subgraph "MCP 服务器"
S1["Math Server
(stdio)"]
S2["Weather Server
(streamable-http)"]
S3["Dream Server
(远程 HTTP)"]
end
subgraph "MCP 能力"
Tools["Tools
可执行函数"]
Resources["Resources
只读数据"]
Prompts["Prompts
提示词模板"]
end
Agent --> Client
Client --> S1
Client --> S2
Client --> S3
S1 --> Tools
S1 --> Resources
S1 --> Prompts
S2 --> Tools
S3 --> Tools
```
### MCP 传输方式对比
| 传输方式 | 适用场景 | 启动方式 | 通信协议 |
|---------|---------|---------|---------|
| **stdio** | 本地服务 | 客户端自动启动 | 标准输入输出 |
| **streamable-http** | 远程服务 | 手动启动 | HTTP |
### MCP 工具调用流程
```mermaid
sequenceDiagram
participant U as 用户
participant A as Agent
participant C as MCP Client
participant S as MCP Server
participant T as Tool
U->>A: 发送请求
A->>A: 分析需要调用工具
A->>C: 调用工具
C->>S: 发送 MCP 请求
S->>T: 执行工具函数
T->>S: 返回结果
S->>C: 返回 MCP 响应
C->>A: 返回工具结果
A->>A: 整合结果生成回答
A->>U: 返回最终答案
```
### MCP 核心概念
| 概念 | 说明 | 用途 |
|------|------|------|
| **Tools** | 可执行的函数 | 计算、查询、操作 |
| **Resources** | 只读数据端点 | 获取配置、读取数据 |
| **Prompts** | 预定义的提示词模板 | 标准化对话流程 |
| **Transport** | 通信方式 | stdio / streamable-http |
### MCP 与 LangChain 集成
```python
# 完整集成流程
from langchain_mcp_adapters.tools import load_mcp_tools
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
# 1. 配置 MCP 服务器
client = MultiServerMCPClient({...})
# 2. 加载工具
tools = await client.get_tools()
# 3. 创建 Agent
agent = create_react_agent(model=llm, tools=tools, prompt=prompt)
# 4. 调用
result = await agent.ainvoke({"messages": [("human", "问题")]})
```