- 恢复 contact/README.md - 恢复 dictionary/README.md - 恢复 research/README.md - 恢复 agent_subgraphs/README.md
22 KiB
LangGraph Agent - 全能个人助手系统
该模块负责将个人助手从"查询型"升级为"全能执行型",通过 LangGraph 子图架构实现通讯录管理、智能词典、增强研究分析等核心功能。
🔧 公共工具与共享组件
三个子图共享一套统一的基础设施和通用工具,避免重复实现,确保架构一致。
公共工具架构
┌─────────────────────────────────────────────────────────────────┐
│ 公共工具层 (Shared Tools) │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │
│ │意图理解工具 │ │人工审核工具 │ │格式化输出 │ │状态管理│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────┘ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │
│ │检查点持久化 │ │条件路由 │ │LLM 调用 │ │数据库 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 子图层 (Subgraphs) │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 通讯录子图 │ │ 智能词典子图│ │ 研究分析子图│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
公共工具详解
1. 意图理解工具 (Intent Understanding Tool)
技术栈:LangChain LLM + 少样本提示词 + 结构化输出
使用方法:
from agent_subgraphs.common.intent import parse_intent
result = parse_intent(
user_input="添加张三电话13800138000",
intent_categories=["contact", "dictionary", "research", "chat"]
)
# 返回: {
# "intent_type": "contact",
# "sub_intent": "add",
# "extracted_info": {"name": "张三", "phone": "13800138000"}
# }
实现逻辑:
- 使用 LLM 进行意图分类,输出结构化 JSON
- 关键词匹配兜底(如"保存"、"添加" → contact)
- 自动提取关键信息(实体、参数)
- 支持自定义意图分类器
所有子图共用:在 agent_subgraphs/common/intent.py
2. 人工审核工具 (Human-in-the-loop Tool)
技术栈:LangGraph interrupt() + 状态持久化
使用方法:
from agent_subgraphs.common.human_loop import human_approval_node
def email_send_workflow(state: dict) -> dict:
# 生成邮件草稿...
state["pending_action"] = {"type": "email_send", "draft": draft}
return human_approval_node(state) # 挂起等待用户确认
实现逻辑:
- 使用
interrupt()触发挂起 - 支持三种操作:确认、修改、取消
- 超时自动取消(可配置超时时间)
- 用户反馈结构化存储
- 支持断点续作
共享位置:agent_subgraphs/common/human_loop.py
应用场景:
- 通讯录:邮件发送、联系人删除
- 研究分析:信息源确认、报告结构调整
- 智能词典:批量删除确认
3. 格式化输出工具 (Formatting Tool)
技术栈:Jinja2 模板 + Markdown 生成
使用方法:
from agent_subgraphs.common.format import format_output
result = format_output(
template="contact_result",
data={"contact": contact_data, "action": "added"}
)
实现逻辑:
- 预定义输出模板库
- 支持 Markdown、HTML、纯文本三种格式
- 自动处理列表、表格等复杂结构
- 支持用户自定义模板
共享位置:agent_subgraphs/common/format.py
4. 检查点持久化工具 (Checkpoint Tool)
技术栈:LangGraph CheckpointSaver + SQLite / PostgreSQL
使用方法:
from agent_subgraphs.common.checkpoint import get_checkpointer
checkpointer = get_checkpointer(db_url="sqlite:///checkpoints.db")
# 在图编译时传入
graph = workflow.compile(checkpointer=checkpointer)
实现逻辑:
- 自动在每个节点执行后保存检查点
- 支持断点续作
- 状态版本管理
- 支持查询历史状态
共享位置:agent_subgraphs/common/checkpoint.py
5. 条件路由工具 (Conditional Routing Tool)
技术栈:LangGraph 条件边 + 路由函数
使用方法:
from agent_subgraphs.common.routing import route_by_intent
def my_router(state: dict) -> str:
return route_by_intent(
state,
{
"translate": "translate_node",
"lookup": "lookup_node",
}
)
实现逻辑:
- 标准化的意图路由
- 支持复杂条件判断
- 路由函数可组合
- 自动处理默认分支
共享位置:agent_subgraphs/common/routing.py
6. LLM 调用工具 (LLM Invocation Tool)
技术栈:LangChain ChatOpenAI + 重试 + 流式输出
使用方法:
from agent_subgraphs.common.llm import call_llm, call_llm_stream
# 同步调用
result = call_llm(prompt="翻译这句话", system_prompt="你是翻译官")
# 流式调用
async for chunk in call_llm_stream(prompt="写一篇文章"):
print(chunk.content, end="")
实现逻辑:
- 统一的 LLM 调用接口
- 自动重试(指数退避)
- 支持流式和非流式
- Token 计数和监控
- 模型 fallback 机制
共享位置:agent_subgraphs/common/llm.py
7. 数据库工具 (Database Tool)
技术栈:SQLAlchemy + PostgreSQL / SQLite
使用方法:
from agent_subgraphs.common.db import get_db, add_record, query_records
# 获取 session
with get_db() as db:
# 添加记录
add_record(db, Contact, {"name": "张三", "phone": "13800138000"})
# 查询记录
contacts = query_records(db, Contact, filters={"name": "张三"})
实现逻辑:
- 统一的 ORM 会话管理
- 标准 CRUD 操作封装
- 支持事务
- 自动错误处理
共享位置:agent_subgraphs/common/db.py
8. 状态基类工具 (State Base Classes)
技术栈:TypedDict + 类型注解
使用方法:
from agent_subgraphs.common.state import BaseSubgraphState
class ContactState(BaseSubgraphState):
# 继承基础字段
contact_data: Optional[dict]
# 自定义字段...
实现逻辑:
- 预定义基础状态字段
- 类型安全
- 状态验证
- 状态合并辅助函数
共享位置:agent_subgraphs/common/state.py
公共工具目录结构
agent_subgraphs/
├── common/ # 公共工具层
│ ├── __init__.py
│ ├── intent.py # 意图理解工具
│ ├── human_loop.py # 人工审核工具
│ ├── format.py # 格式化输出工具
│ ├── checkpoint.py # 检查点持久化工具
│ ├── routing.py # 条件路由工具
│ ├── llm.py # LLM 调用工具
│ ├── db.py # 数据库工具
│ ├── state.py # 状态基类
│ └── prompts/ # 公共提示词模板
│ ├── intent.j2
│ └── format.j2
├── contact/ # 通讯录子图(简化版,使用公共工具)
├── dictionary/ # 智能词典子图(简化版,使用公共工具)
└── research/ # 研究分析子图(简化版,使用公共工具)
公共配置项
所有子图共享的配置项(在 .env 中配置):
# LLM 配置
LLM_PROVIDER=deepseek
LLM_MODEL=deepseek-chat
LLM_API_KEY=***
LLM_TEMPERATURE=0.7
LLM_MAX_TOKENS=2000
# 数据库配置
DB_URL=postgresql://user:pass@localhost/agent_db
# 检查点配置
CHECKPOINT_DB_URL=sqlite:///checkpoints.db
# 人工审核配置
HUMAN_LOOP_TIMEOUT=3600
# 格式化配置
DEFAULT_OUTPUT_FORMAT=markdown
使用公共工具开发新子图
创建新子图的步骤:
- 继承状态基类
from agent_subgraphs.common.state import BaseSubgraphState
class MySubgraphState(BaseSubgraphState):
my_field: str
- 使用公共意图理解
from agent_subgraphs.common.intent import parse_intent
def intent_node(state: MySubgraphState) -> MySubgraphState:
result = parse_intent(state["user_input"], ["my_intents])
state.update(result)
return state
- 使用公共人工审核
from agent_subgraphs.common.human_loop import human_approval_node
def my_workflow(state: MySubgraphState) -> MySubgraphState:
return human_approval_node(state)
- 使用公共格式化输出
from agent_subgraphs.common.format import format_output
def format_node(state: MySubgraphState) -> MySubgraphState:
state["final_result"] = format_output("my_template", state)
return state
📑 目录导航
- 核心功能 - 三大子图功能和技术特性
- 技术架构 - 技术栈、子图架构图、数据流
- 子图设计 - 三个核心子图的详细说明
- 状态管理 - 主状态和子状态定义
- 安全与边界 - 安全机制和边界控制
- 快速开始 - 开发环境搭建
- 实现指南 - 子图开发、工具集成
- 未来规划 - 多模态、流式输出等
🎯 核心功能
三大核心子图
| 子图模块 | 功能概述 | 关键特性 |
|---|---|---|
| 通讯录子图 | 联系人 CRUD、邮件读取与审核、外发邮件、智能嗅探 | 人工审核强制、敏感信息加密、IMAP 邮箱绑定 |
| 智能词典子图 | 翻译、查词、每日一词、专业名词提炼、生词本管理 | 联想记忆法、艾宾浩斯遗忘曲线、Anki 导出 |
| 研究分析子图 | 联网搜索、报告生成、引用溯源、可视化图表 | 人工干预点、可定制报告结构、引用验证 |
通用机制
- ✅ 人工审核(Human-in-the-loop):通用节点,用于邮件发送、重要操作前的确认
- ✅ 自动联系人嗅探:对话中出现"人名+联系方式"时,主动询问是否保存
- ✅ 流式输出:所有 LLM 生成内容均采用流式传输,提升交互体验
- ✅ 长期记忆:PostgreSQL + pgvector 实现持久化记忆和语义检索
🏗️ 技术架构
技术栈总览
| 层级 | 组件 | 技术选型 | 版本 | 说明 |
|---|---|---|---|---|
| Agent 框架 | 工作流编排 | LangGraph + LangChain | latest | 子图架构,状态机驱动 |
| LLM 服务 | 模型调用 | 智谱 AI / DeepSeek / 本地模型 | latest | 多模型路由 |
| 向量数据库 | 语义检索 | Qdrant / pgvector | v1.12+ | 对话记忆、联系人语义索引 |
| 关系数据库 | 结构化存储 | PostgreSQL | v16 | 联系人、生词本、邮件配置 |
| 邮件协议 | IMAP/SMTP | imaplib / smtplib |
内置 | 邮件读取和发送 |
| 后端框架 | API 服务 | FastAPI + Uvicorn | v0.115+ | 子图执行、状态管理 |
主图架构流程图
graph TB
Start[START] --> Intent[意图分类节点]
Intent -->|contact| ContactSubgraph[通讯录子图]
Intent -->|dictionary| DictSubgraph[智能词典子图]
Intent -->|research| ResearchSubgraph[研究分析子图]
Intent -->|chat| ChatNode[普通对话节点]
ContactSubgraph --> Final[最终响应]
DictSubgraph --> Final
ResearchSubgraph --> Final
ChatNode --> Final
Final --> End[END]
style Start fill:#e1f5ff
style Intent fill:#fff4e1
style ContactSubgraph fill:#e8f5e9
style DictSubgraph fill:#f3e5f5
style ResearchSubgraph fill:#ffebee
style Final fill:#fff9c4
子图架构总览
graph TB
MainGraph[主图<br/>MainState]
MainGraph --> ContactSub[通讯录子图<br/>ContactSubState]
MainGraph --> DictSub[词典子图<br/>DictSubState]
MainGraph --> ResearchSub[研究子图<br/>ResearchSubState]
ContactSub --> ContactNodes[内部节点<br/>parse_intent<br/>add_contact<br/>list_contacts<br/>generate_draft<br/>human_approval<br/>send_email]
DictSub --> DictNodes[内部节点<br/>translate<br/>lookup<br/>extract_terms<br/>daily_word]
ResearchSub --> ResearchNodes[内部节点<br/>decompose<br/>web_search<br/>extract_info<br/>generate_report]
ContactNodes --> PG[(PostgreSQL<br/>联系人)]
DictNodes --> PG2[(PostgreSQL<br/>生词本)]
ResearchNodes --> Qdrant[(Qdrant<br/>向量检索)]
style MainGraph fill:#e1f5ff
style ContactSub fill:#e8f5e9
style DictSub fill:#f3e5f5
style ResearchSub fill:#ffebee
状态传递机制
主状态 (MainState)
│
├─→ input: {user_input: messages[-1].content}
│
▼
子图状态 (SubState)
│
├─→ 内部处理...
│
▼
output: {messages: [AIMessage(final_result)], last_action: sub_state}
│
▼
主状态更新
📂 项目结构
Agent1/
├── agent_subgraphs/ # LangGraph 子图模块
│ ├── __init__.py
│ ├── contact/ # 通讯录子图
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── state.py # 子图状态定义
│ │ ├── graph.py # 子图构建器
│ │ ├── nodes.py # 子图节点实现
│ │ ├── tools.py # 子图工具集
│ │ └── prompts.py # 提示词模板
│ ├── dictionary/ # 智能词典子图
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── state.py
│ │ ├── graph.py
│ │ ├── nodes.py
│ │ ├── tools.py
│ │ └── prompts.py
│ └── research/ # 研究分析子图
│ ├── README.md
│ ├── __init__.py
│ ├── state.py
│ ├── graph.py
│ ├── nodes.py
│ ├── tools.py
│ └── prompts.py
├── backend/ # 现有后端模块
│ └── app/
│ ├── graph/ # 主图构建
│ │ ├── graph_builder.py # 主图 + 子图集成
│ │ └── state.py # 主状态定义
│ └── ...
└── ...
🎯 状态管理
主状态定义 (MainState)
from typing import TypedDict, List, Optional, Annotated
from langchain_core.messages import BaseMessage
from langgraph.graph import add_messages
class MainState(TypedDict):
messages: Annotated[List[BaseMessage], add_messages]
intent: str # 顶层意图:contact / dictionary / research / chat
sub_intent: str # 细分意图
# 工具通用
tool_call: Optional[dict] # 当前要执行的工具调用
tool_result: str
# 控制流
next_node: str
human_feedback: Optional[str] # 用于挂起重启
# 子图结果
last_contact_action: Optional[dict]
last_dict_action: Optional[dict]
last_research_action: Optional[dict]
状态映射函数
# 通讯录子图输入映射
def contact_input_mapper(state: MainState) -> dict:
return {
"user_input": state["messages"][-1].content,
}
# 通讯录子图输出映射
def contact_output_mapper(sub_state: dict, original: MainState) -> dict:
return {
"messages": [AIMessage(content=sub_state["final_result"])],
"last_contact_action": sub_state,
}
🎯 主图实现
主图构建器
from langgraph.graph import StateGraph, START, END
from agent_subgraphs.contact import build_contact_subgraph
from agent_subgraphs.dictionary import build_dict_subgraph
from agent_subgraphs.research import build_research_subgraph
def build_main_graph() -> StateGraph:
main_graph = StateGraph(MainState)
# 添加子图节点
main_graph.add_node(
"contact_module",
build_contact_subgraph(),
input=contact_input_mapper,
output=contact_output_mapper,
)
main_graph.add_node(
"dict_module",
build_dict_subgraph(),
input=dict_input_mapper,
output=dict_output_mapper,
)
main_graph.add_node(
"research_module",
build_research_subgraph(),
input=research_input_mapper,
output=research_output_mapper,
)
main_graph.add_node("chat_node", chat_node)
main_graph.add_node("final_response", final_response_node)
# 主图路由
main_graph.add_conditional_edges(
START,
route_main_intent,
{
"contact": "contact_module",
"dictionary": "dict_module",
"research": "research_module",
"chat": "chat_node",
}
)
# 所有路径汇聚到最终响应
main_graph.add_edge("contact_module", "final_response")
main_graph.add_edge("dict_module", "final_response")
main_graph.add_edge("research_module", "final_response")
main_graph.add_edge("chat_node", "final_response")
main_graph.add_edge("final_response", END)
return main_graph.compile()
def route_main_intent(state: MainState) -> str:
"""顶层意图分类"""
user_input = state["messages"][-1].content
# 使用 LLM 分类
# 返回 contact / dictionary / research / chat
🔒 安全与边界
安全机制
| 风险点 | 对策 | 实现位置 |
|---|---|---|
| 邮箱密码泄露 | 使用环境变量存储,永不写入日志 | agent_subgraphs/contact/tools.py |
| 恶意邮件发送 | 强制人工审核,单日发送数量限制 | 人工审核节点 |
| 联系人隐私 | 向量检索结果脱敏展示,仅交互时完整显示 | 通讯录子图节点 |
| 搜索内容安全 | 过滤成人内容,屏蔽高风险域名 | 研究子图搜索工具 |
| 敏感词输出 | 流式输出后处理过滤 | 最终响应节点 |
人工审核节点
from langgraph.graph import interrupt
def human_approval_node(state: dict) -> dict:
"""人工审核节点:挂起图,等待外部输入"""
pending_action = state["pending_action"]
# 触发中断,等待外部通过 update_state 传入 human_feedback
return interrupt(
{
"type": "human_approval",
"message": f"请确认操作:{pending_action}",
"options": ["确认", "修改", "取消"],
}
)
🚀 快速开始
环境配置
# 激活虚拟环境
source venv/bin/activate
# 安装依赖(新增)
pip install langgraph langchain-experimental
配置文件
在 .env 中新增:
# 通讯录模块
IMAP_SERVER=imap.qq.com
IMAP_PORT=993
SMTP_SERVER=smtp.qq.com
SMTP_PORT=587
EMAIL_USER=your_email@qq.com
EMAIL_PASSWORD=your_auth_code
# 词典模块
DEEPL_API_KEY=your_deepl_key
YOUDAO_API_KEY=your_youdao_key
# 研究模块
SEARCH_API_KEY=your_search_key
运行测试
from backend.app.graph.graph_builder import build_main_graph
# 编译主图
graph = build_main_graph()
# 调用子图
result = graph.invoke({
"messages": [HumanMessage(content="添加张三电话 13800138000")]
})
print(result["messages"][-1].content)
📖 实现指南
添加新子图
- 在
agent_subgraphs/下创建新文件夹 - 创建
state.py定义子图状态 - 创建
nodes.py实现子图节点 - 创建
graph.py构建子图 - 在主图
graph_builder.py中注册新子图
子图开发最佳实践
- ✅ 子图拥有独立的状态,避免与主状态命名冲突
- ✅ 使用
input/output映射函数进行状态转换 - ✅ 子图内部节点之间直接连接,主图只负责路由到子图入口
- ✅ 将工具封装在子图内部,通过节点调用
- ✅ 提供子图级别的单元测试
🎯 未来规划
Phase 1: 基础功能(当前)
- 通讯录子图完整实现
- 智能词典子图完整实现
- 研究分析子图完整实现
- 主图集成和状态管理
Phase 2: 增强功能
- 流式输出改造(所有 LLM 调用)
- 多模态语音输入(STT)
- 可视化图表生成
- Anki 生词本导出
Phase 3: 高级特性
- 智能家居控制子图
- 日程管理子图
- 更多工具集成
📚 相关文档
- 通讯录子图 README - 详细了解通讯录模块
- 智能词典子图 README - 详细了解词典模块
- 研究分析子图 README - 详细了解研究模块
- 主项目 README - 了解整体架构