常见用例
RAG 系统
基于 LangGraph 构建检索增强生成 (Retrieval-Augmented Generation) 系统
📚 学习目标
学完这篇文章后,你将能够:
- 理解 RAG 的基本工作流程
- 构建包含“检索”、“评分”、“生成”等步骤的 LangGraph
- 实现“自适应 RAG”:根据检索质量决定是否重新检索
前置知识
在开始学习之前,建议先阅读:
你需要了解:
- 向量数据库和 Embedding 的基础概念
1️⃣ 什么是 RAG?
RAG (Retrieval-Augmented Generation) 通过在生成回答前先检索相关文档,解决了 LLM 知识过时和幻觉的问题。
经典 RAG 流程
2️⃣ 使用 LangGraph 构建 RAG
LangGraph 的优势在于它可以让 RAG 流程更加灵活,不仅仅是线性的“检索->生成”。
状态定义
import { Annotation } from '@langchain/langgraph';
import { Document } from '@langchain/core/documents';
const RAGState = Annotation.Root({
question: Annotation<string>(),
documents: Annotation<Document[]>({
reducer: (_current, update) => update,
default: () => [],
}),
answer: Annotation<string>(),
});[!NOTE] 生产级 RAG 的“难点”不在 Graph,而在索引构建:chunking、embedding、向量库、metadata、增量更新。
节点实现
import { ChatOpenAI } from '@langchain/openai';
import { HumanMessage, SystemMessage } from '@langchain/core/messages';
const model = new ChatOpenAI({ model: 'gpt-4o-mini', temperature: 0 });
const retrieveNode = async (state: typeof RAGState.State) => {
const docs = await vectorStore.similaritySearch(state.question, 4);
return { documents: docs };
};
const generateNode = async (state: typeof RAGState.State) => {
const context = state.documents
.map((d, i) => `[${i + 1}] ${d.pageContent}`)
.join('\n\n');
const messages = [
new SystemMessage('你是严谨的知识库助手。只基于给定 Context 回答,并引用编号。'),
new HumanMessage(`Context:\n${context}\n\nQuestion: ${state.question}`),
];
const response = await model.invoke(messages);
return { answer: String(response.content) };
};代码解析:
- 把每个文档加上编号
[1] [2] ...,你更容易在答案里做引用。 - System Prompt 明确“只基于 Context”,能显著降低幻觉。
3️⃣ 进阶:自适应 RAG (Adaptive RAG)
我们可以引入一个“评分节点”来评估检索到的文档是否真的与问题相关。
流程图
代码逻辑
import { Command } from '@langchain/langgraph';
const gradeDocumentsNode = async (state) => {
const { documents, question } = state;
const validDocs = [];
for (const doc of documents) {
const score = await graderModel.invoke({...}); // 让 LLM 打分
if (score.isRelevant) validDocs.push(doc);
}
if (validDocs.length === 0) {
return new Command({ goto: "rewrite_query" });
}
return { documents: validDocs };
};为了避免死循环,建议加两层保护:
recursionLimit:给整个 Graph 一个硬上限retry_count:在 state 里累计重写次数,超过阈值后降级(例如改用 Web Search 工具)
💡 练习题
- 思考题:在自适应 RAG 中,如果系统陷入了“检索 -> 不相关 -> 重写 -> 检索 -> 不相关”的死循环怎么办?(提示:使用状态中的
retry_count字段或recursionLimit)。 - 操作题:实现一个简单的 Corrective RAG (CRAG),当检索结果不佳时,回退到使用 Web Search 工具。
📚 参考资源
官方文档
✅ 总结
本章要点:
- LangGraph 让 RAG 可以拥有复杂的控制流(如循环、条件分支)。
- 自适应 RAG 通过引入反馈环路(Feedback Loop)显著提高了问答质量。
下一步:我们将探讨如何利用 LangGraph 进行数据分析。
登录以继续阅读
解锁完整文档、代码示例及更多高级功能。