背景
传统 RAG 实现通常为线性流程:
python
docs = retriever.invoke(query)
answer = llm.invoke(prompt + docs)
该模式在原型阶段有效,但在生产环境中存在以下问题:
- 幻觉风险高(LLM 在上下文不足时生成虚构内容);
- 鲁棒性差(单点失败导致整个请求中断);
- 不可观测(无法定位问题是检索召回不足还是生成逻辑错误)。
LangGraph v1.0 提供状态化工作流编排能力,将 RAG 建模为有向图,支持并行、重试、持久化与全链路追踪,适用于生产部署。
架构设计
将 RAG 拆解为以下节点:
css
用户查询
↓
[并行检索] → 内部知识库 | Web 搜索 | 业务 API
↓
[合并去重] → 统一候选集(去重、加权、时间衰减)
↓
[Reranker] → 精筛 top-k 相关片段
↓
[Generator] → 引用感知生成
↓
[Eval/Trace] → 上报 LangSmith
每个节点职责单一,支持独立优化、监控与故障隔离。
核心能力
1. 多源并行检索
使用 LangGraph 的多入口边实现并发分支:
python
builder.add_edge(START, "kb_retrieve")
builder.add_edge(START, "web_search")
builder.add_edge(START, "api_fetch")
builder.add_edge("kb_retrieve", "merge")
builder.add_edge("web_search", "merge")
builder.add_edge("api_fetch", "merge")
merge 节点聚合结果,执行内容去重(基于哈希或元数据)、来源权重分配和时效性调整。
2. Reranker 抑制幻觉
向量检索召回的 top-k 结果常包含噪声。引入 reranker 节点进行精排:
python
def rerank_node(state: RAGState):
scores = cross_encoder.predict(
query=state["query"],
documents=[d.page_content for d in state["candidates"]]
)
top_docs = select_top_n(state["candidates"], scores, n=5)
return {"top_docs": top_docs}
实测可减少 80% 上下文长度,显著降低幻觉率。
3. RetryPolicy 与持久化 Checkpoint
为外部依赖节点配置重试策略:
python
retry_policy=RetryPolicy(max_attempts=3, backoff_factor=2.0)
启用持久化 checkpoint 支持中断恢复:
python
from langgraph.checkpoint.sqlite import SqliteSaver
checkpointer = SqliteSaver.from_conn_string("rag.db")
graph = builder.compile(checkpointer=checkpointer)
适用于长流程、人工审核或高可用场景。
4. 分层缓存优化成本
- Provider Prompt Cache :对静态 system prompt 启用模型提供商缓存(如 AWS Bedrock
cachePoint); - Query-Level Cache :使用 Redis 缓存
(query_hash, doc_ids) → answer,避免重复计算。
5. LangSmith 全链路追踪
上报以下数据用于评估:
- 原始查询;
- 检索文档 ID 与相似度分数;
- Reranker 打分结果;
- 最终生成内容。
通过 LangSmith 计算两类关键指标:
- 幻觉率:生成内容中未被检索结果支持的陈述比例;
- 错误率:回答与事实不符或未正确响应问题的比例。
二者需分别监控:所有幻觉均为错误,但错误不一定是幻觉(如答非所问、逻辑错误)。
完整实现示例
python
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.types import RetryPolicy
from langgraph.checkpoint.sqlite import SqliteSaver
class RAGState(TypedDict, total=False):
query: str
candidates: list
top_docs: list
answer: str
def retrieve_node(state: RAGState):
return {"candidates": vectorstore.similarity_search(state["query"], k=50)}
def rerank_node(state: RAGState):
top_docs = reranker.select_top_k(state["candidates"], state["query"], k=5)
return {"top_docs": top_docs}
def generate_node(state: RAGState):
context = "\n\n".join(
f"[{i}] {d.page_content}"
for i, d in enumerate(state["top_docs"], 1)
)
prompt = f"仅使用以下片段回答,并标注引用编号:\n{context}\n\n问题: {state['query']}"
return {"answer": llm.invoke(prompt)}
# 构建图
builder = StateGraph(RAGState)
builder.add_node("retrieve", retrieve_node, retry_policy=RetryPolicy(max_attempts=3))
builder.add_node("rerank", rerank_node)
builder.add_node("generate", generate_node)
builder.add_edge(START, "retrieve")
builder.add_edge("retrieve", "rerank")
builder.add_edge("rerank", "generate")
builder.add_edge("generate", END)
# 编译并启用持久化
graph = builder.compile(checkpointer=SqliteSaver.from_conn_string("checkpoints.db"))
# 调用
result = graph.invoke({"query": "如何实现单点登录?"})
print(result["answer"])
工程建议
- HyDE(Hypothetical Document Embeddings):对模糊查询,先生成假设文档再检索,提升召回;
- 时间感知检索:对时效性内容引入时间衰减因子;
- 人类审查节点:在高风险领域插入人工审核环节;
- 流式输出:启用 token-by-token streaming 提升用户体验与实时监控能力。
总结
LangGraph 将 RAG 从脚本升级为可运维系统。通过节点化、状态持久化、并行编排与全链路观测,可构建高可靠、低幻觉、易迭代的生产级 RAG 架构。RAG 的竞争已进入工程化阶段,LangGraph 是当前最优的编排基础设施之一。