LangChain CRAG 深度剖析:检索纠错到底怎么纠的?幻觉检测每次都查吗?
LangChain CRAG 深度剖析检索纠错到底怎么纠的幻觉检测每次都查吗普通 RAG 是检索 → 生成一条路走到底——检索回来的文档可能根本不相关模型照样硬着头皮编答案。Corrective RAGCRAG号称能自我纠错但纠错到底纠的是什么是改答案还是改检索幻觉检测是不是每次都调 LLM本文拆开 langchainrust 的 CRAG 实现逐行讲清楚整条纠错链路。一、CRAG 全流程6 步状态机CRAG 的核心逻辑是一个状态机6 步走完1. 检索(retrieve) → 向量检索拿回 N 篇文档 2. 评分(grade_documents) → LLM 给每篇文档打相关度分 3. 纠错(correct) → 平均分低于阈值? 触发纠错 4. 过滤(filter) → 扔掉低于阈值的文档 5. 生成(generate) → 基于过滤后的文档生成答案 6. 幻觉检测(hallucination) → LLM 检查答案有没有依据下面逐步拆解。二、评分LLM 怎么判断文档相不相关评分不是算余弦相似度是让 LLM 读文档后判断。评分 PromptYou are a document relevance grader. Given a user query and a document, determine if the document is relevant. Query: {query} Document: {document_content} Respond in this exact format: Relevance: [relevant/irrelevant] Score: [0.0 to 1.0] Reasoning: [brief explanation]LLM 返回类似Relevance: relevant, Score: 0.9, Reasoning: 文档直接描述了...代码再解析。解析规则4 种情况LLM 回了什么得分说明有明确数字Score: 0.750.75直接取最可靠含relevant不含irrelevant0.8默认相关分含irrelevant0.2默认不相关分啥都没有模糊响应0.4故意低于阈值标记is_ambiguous这里有个坑模糊响应给 0.4 是 v0.5.1 才调的。早期版本给 0.5恰好等于旧阈值也是 0.5导致 LLM 说不清时——纠不纠全看运气。改成 0.4 后模糊就触发纠错保守策略宁多纠不漏纠。评分是并行的4 篇文档不是串行评是用join_all并行调 4 次 LLMletfutures:Vec_documents.iter().map(|doc|self.grade(query,doc)).collect();letresultsjoin_all(futures).await;// 4 次同时发出延迟 ≈ 1 次 LLM 调用的时间不是 4 倍。三、纠错纠的不是答案是检索这是 CRAG 最核心的设计。当平均分低于阈值默认 0.6触发correct()ifstate.avg_scoreself.grade_threshold{// 默认 0.6self.correct(mutstate).await?;}纠错不是改答案是换一种方式重新检索。correct()做四件事3.1 生成 3 个备选查询让 LLM 把原问题换个问法生成 3 个变体Generate 3 alternative versions of the following query to improve retrieval coverage. Original query: {query} Each alternative should approach the information need from a different angle.比如原问题Rust 和 Go 的区别LLM 可能生成Rust 与 Go 语言特性对比Go 和 Rust 性能差异分析Rust Go 适用场景选择为什么要换问法向量检索有角度偏差——同一个意思换个说法可能检索不到。多角度提问能提高召回。3.2 用备选查询并行检索 去重3 个查询各检索 4 篇 → 最多 12 篇 → 按前 200 字符判重合并letretrieve_futures:Vec_alternatives.iter().map(|q|self.retriever.retrieve(q,self.retrieve_k)).collect();letall_resultsjoin_all(retrieve_futures).await;// 3 路并行letmutseen_contentHashSet::new();fordocinall_results{ifseen_content.insert(doc.content[..200]){// 按内容去重merged_docs.push(doc);}}3.3 联网搜索兜底可选如果配了 web 搜索工具还会去网上搜一次补料ifletSome(tool)self.web_fallback{letweb_resulttool.run(state.current_query.clone()).await?;state.web_resultsSome(web_result);}3.4 重新评分纠错后还会再评一轮分确保新文档的质量self.grade_documents(state).await?;// 对新文档重新打分不是换回来就直接用要验证新检索的文档确实更好。四、过滤宁可没文档不留烂文档纠错后低于阈值的文档直接扔掉letfiltered:Vec(Document,f64)state.documents.iter().zip(state.grade_scores.iter()).filter(|(_,score)|scoreself.grade_threshold).collect();// 全不达标 → 宁可空也不留烂文档误导生成letsource_docsiffiltered.is_empty(){Vec::new()}else{filtered};这是个重要设计宁可没文档生成我不知道也不要用烂文档生成看似合理实则胡编的答案。五、生成评分理由也喂给模型生成答案时不只喂文档还把评分时 LLM 说的为什么这篇相关也塞进 promptletcontextbuild_context(source_docs,state.web_results,...);letreasoning_textformat_reasoning(source_docs,reasoning);// 评分理由letuser_messagebuild_generate_prompt(context,reasoning_text,state.query);这样生成模型能理解每篇文档的价值更好地组织答案。另外有个Token 预算截断build_context()按分数从高到低排超预算的低分文档直接丢letmutsorted:Vec_docs.iter().collect();sorted.sort_by(|a,b|b.1.partial_cmp(a.1)...);// 按分降序for(doc,_score)insorted{iftoken_countentry_tokensmax{continue;// 超预算直接跳过}...}六、幻觉检测每次都查且最好用另一个模型生成答案后最后一步是幻觉检测——检查答案是不是编的。什么是幻觉LLM 没有可靠资料时会一本正经地胡编。问张三的生日文档没写它可能编一个1985 年 3 月 12 日。这就是幻觉。怎么检测把文档 答案一起喂给 LLM让它以怀疑态度核查You are a skeptical fact-checking assistant. Be skeptical. Is the above answer fully grounded in and supported by the provided context? - grounded if every claim is directly supported - not grounded if any information is not found in or contradicted by the context解析 LLM 回复ifwords 包含not grounded或unsupported{state.groundedfalse;// 判定编的}elseifwords 包含grounded或yes{state.groundedtrue;// 判定有据}else{state.groundedfalse;// 模糊 → 默认当编的保守}三个关键设计点① 为什么用独立 LLM生成答案和检测幻觉默认用同一个 LLM。问题是模型倾向于认同自己的输出——自己写的自己看当然觉得对这就是自检偏差。所以可以注入独立 LLM 做检测letagentCorrectiveRAGAgent::new(main_llm,retriever).with_grader_llm(checker_llm);// 用另一个模型检测代码里letgrader_llmself.grader_llm.unwrap_or(self.llm);// 优先独立 LLM没配就用主 LLM向后兼容。② 检测失败不中断检测本身调用失败网络断了、限流了不会让整个流程崩而是降级标记grounded falsematchgrader_llm.chat_with_system(...).await{Ok(r)r,Err(_){state.groundedfalse;// 标记未验证不报错returnOk(());}}答案照常返回只是标了未验证。③ 结果怎么用CRAGResult.grounded告诉调用方答案有没有经过验证letresult:CRAGResultagent.invoke(问题).await?;if!result.grounded{// 答案可能不靠谱提示用户或走别的策略}七、灵魂拷问每次都调 LLM 吗调几次这是性能和成本的核心问题。数一下invoke()一次的 LLM 调用步骤调 LLM次数1. 检索❌向量检索不调 LLM2. 评分✅每篇文档 1 次4 篇 4 次并行3. 纠错触发时✅生成备选查询 1 次 重评分 ~4 次并行 web 1 次4. 过滤❌纯逻辑5. 生成✅1 次6. 幻觉检测✅1 次如果开启最少几次文档质量好不纠错评分 4 次 生成 1 次 幻觉检测 1 次 6 次最多几次触发纠错 联网搜索评分 4 次 生成备选查询 1 次 重评分 4 次 web 1 次 生成 1 次 幻觉检测 1 次 ≈ 12 次没有缓存代码里没有上次评分过就跳过的缓存机制每次invoke()都完整跑一遍。但有两个优化评分并行join_all4 次同时发不是串行等备选查询检索并行3 路同时搜所以实际延迟 ≈ 几个 LLM 往返不是十几次串行相加。八、完整链路一图流用户提问 │ ▼ [1] 检索 ─── 向量检索 N 篇文档 │ ▼ [2] 评分 ─── LLM 并行给每篇打分4 次并行调用 │ ▼ 平均分 0.6? ├─ 否 ───────────────────────────────────┐ │ │ ├─ 是 → [3] 纠错 │ │ ├─ 生成 3 个备选查询1 次 LLM │ │ ├─ 并行检索 去重3 路并行 │ │ ├─ 联网搜索兜底可选1 次 │ │ └─ 重新评分~4 次 LLM 并行 │ │ │ ▼ ▼ [4] 过滤 ─── 扔掉低分文档宁可空不留烂 │ ▼ [5] 生成 ─── 文档 评分理由 → LLM 生成答案1 次 │ ▼ [6] 幻觉检测 ── 文档 答案 → LLM 怀疑式核查1 次 │ └─ 优先用独立 LLM避免自检偏差 │ └─ 失败不中断标记 groundedfalse │ ▼ 输出 CRAGResult ├─ answer: 答案 ├─ grounded: 是否有据幻觉检测结论 ├─ sources: 来源文档 ├─ grade_scores: 各文档评分 └─ grade_reasoning: 评分理由九、一句话总结CRAG 的纠错不是改答案是改检索——评分发现检索回来的文档不行就换个问法重新搜、去网上搜搜到更好的文档后再生成。最后还用最好独立的LLM 验一遍答案是不是胡编的。代价是 LLM 调用次数多6~12 次但换来了可观测的质量信号grounded字段和更高的答案可靠性。十、什么时候该用 CRAG适合对答案准确性要求高、容忍延迟的场景客服质检、医疗法律咨询检索质量不稳定文档库杂、向量模型一般需要质量信号做后续决策groundedfalse时转人工不适合实时聊天6~12 次 LLM 调用延迟太高成本敏感的大规模批处理调用量翻倍简单 FAQ普通 RAG 足够CRAG 是杀鸡用牛刀仓库github.com/atliliw/langchainrust

相关新闻

Ryujinx终极指南:如何快速配置高性能Switch模拟器

Ryujinx终极指南:如何快速配置高性能Switch模拟器

Ryujinx终极指南:如何快速配置高性能Switch模拟器 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx Ryujinx是一款用C#编写的高性能Nintendo Switch模拟器,让你在…

2026/10/13 16:55:29 阅读更多 →
基于机器学习的网络安全拓扑可视化分析系统 —— Cluster Intelligence

基于机器学习的网络安全拓扑可视化分析系统 —— Cluster Intelligence

**摘要**:本文介绍了一款基于 Next.js D3.js 构建的网络流量安全分析可视化系统。该系统通过 **Louvain 社区发现算法**自动划分网络安全域,利用 **Isolation Forest(隔离森林)算法**实现无监督异常检测,并以力导向图…

2026/10/13 16:55:13 阅读更多 →
校园讲解设备按功率选错了,声场适配才是隐形分水岭

校园讲解设备按功率选错了,声场适配才是隐形分水岭

【文章概述】之前做过几个学校的项目,都是看起来很简单但落地翻车的类型。需求一句话:参观的时候前面的人讲,后面的人听。校方立项的时候关注的都是续航、音量、覆盖范围,这些在招标参数表上能对比的东西。设备到了现场实地跑一趟…

2026/10/1 16:40:19 阅读更多 →

最新新闻

精仿百度搜索源码搜猫V9.0部署实战:从环境配置到搜索调优

精仿百度搜索源码搜猫V9.0部署实战:从环境配置到搜索调优

简介:精仿百度搜索引擎的搜猫V9.0正式版商业版整站源码,面向网站开发者、PHP学习者以及需要快速搭建搜索类站点的用户,解决从零开发搜索系统成本高、周期长的问题。交付形式为zip压缩包,大小约15.97MB,包内包含完整的站…

2026/10/13 16:55:44 阅读更多 →
用AI端到端交付内部工具:实操复盘与避坑指南

用AI端到端交付内部工具:实操复盘与避坑指南

先说结论:这个项目确实交付了——我用 AI 端到端交付了整个内部工具,全程没写几行代码,上线后在内网跑了两个多月,用户没有骂娘。仓库里我亲手敲的部分,数下来大约一百行出头,剩下的全是一条条 AI 生成、我…

2026/10/13 16:55:44 阅读更多 →
四机两区系统MATLAB建模与风电调频控制实现全流程

四机两区系统MATLAB建模与风电调频控制实现全流程

风电并网研究绕不开一个老家伙——四机两区系统。我第一次在MATLAB里搭这个模型的时候,心里其实有点犯嘀咕:都什么年代了,怎么还在用几十年前的标准测试拓扑?结果真正做完一次频率跌落仿真、把风电调频控制算法加进去之后&#xf…

2026/10/13 16:55:44 阅读更多 →
28335自带SPI驱动AD2S1210:旋变解码通信全流程解析

28335自带SPI驱动AD2S1210:旋变解码通信全流程解析

简介:面向使用28335自带SPI驱动AD2S1210的嵌入式开发者,这份资源提供基于SPI模块的通信参考实现,解决旋变数字转换器配置与数据读取的落地问题,适合电机控制、伺服驱动等场景的入门与移植参考。压缩包共2个文件,包含1个…

2026/10/13 16:55:44 阅读更多 →
GOCI2波段手册全解读:从波段表到月球辐射定标与在轨监测

GOCI2波段手册全解读:从波段表到月球辐射定标与在轨监测

简介:GOCI2说明手册聚焦第二代静止轨道海洋水色成像仪波段设计,面向海洋遥感科研人员、卫星数据处理工程师及相关专业学生。系统梳理了传感器波段设置、辐射性能指标与硬件组成,助读者理解各通道中心波长、带宽、标称辐射亮度、最大海洋辐射亮…

2026/10/13 16:55:44 阅读更多 →
虚拟机+Linux入门:从安装配置到快照恢复的完整指南

虚拟机+Linux入门:从安装配置到快照恢复的完整指南

直接学Linux的人,十有八九第一堂课都是在装虚拟机。我自己当年学Linux,一开始直接拿一台老笔记本去装系统,结果分区的时候手一抖,把资料盘给格了,那种酸爽至今记忆犹新。后来老老实实按部就班用虚拟机,才发…

2026/10/13 16:54:42 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →