From 54a6815ad4f2fb0183aa18b8abf112d440992a19 Mon Sep 17 00:00:00 2001 From: lacerate551 <128470311+lacerate551@users.noreply.github.com> Date: Fri, 5 Jun 2026 21:34:19 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E9=87=8D=E5=86=99=20RAG=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E6=8C=87=E5=8D=97=E5=B9=B6=E9=87=8D=E5=91=BD=E5=90=8D?= =?UTF-8?q?=EF=BC=88=E7=A7=BB=E9=99=A4=20AgenticRAG=20=E5=86=85=E5=AE=B9?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 全面重写文档,反映统一编排路径和四层缓存架构 - 添加 Query Cache 修复说明和语义缓存集成文档 - 重命名 Agentic_RAG完整指南.md → RAG系统完整指南.md - 同步更新开发与系统模块说明.md 中的引用链接 --- ...ntic_RAG完整指南.md => RAG系统完整指南.md} | 710 ++++++++---------- docs/开发与系统模块说明.md | 2 +- 2 files changed, 329 insertions(+), 383 deletions(-) rename docs/{Agentic_RAG完整指南.md => RAG系统完整指南.md} (53%) diff --git a/docs/Agentic_RAG完整指南.md b/docs/RAG系统完整指南.md similarity index 53% rename from docs/Agentic_RAG完整指南.md rename to docs/RAG系统完整指南.md index 5e5d833..e4b7913 100644 --- a/docs/Agentic_RAG完整指南.md +++ b/docs/RAG系统完整指南.md @@ -1,115 +1,30 @@ -# Agentic RAG 完整指南 +# RAG 系统完整指南 -> **版本**: v3.2(模型/Reranker/管线更新) -> **生产入口**: `api/chat_routes.py::rag()` → `core/engine.py`(轻量编排,当前启用) -> **备用编排**: `core/agentic.py::AgenticRAG.process()` + 8 个 Mixin(完整决策循环,未接线) -> **最后更新**: 2026-06-04 +> **版本**: v4.0(统一编排 + 四层缓存修复) +> **生产入口**: `api/chat_routes.py::rag()` → `generate()` → `core/engine.py` +> **最后更新**: 2026-06-05 > -> ⚠️ 项目存在两套编排,生产 `/rag` 走的不是 `AgenticRAG`——详见下方「一·五、两套编排路径」。 +> 本次更新:删除未使用的 AgenticRAG 备用编排路径(10 个文件 ~2050 行),修复 Query Cache 键不匹配与阈值问题,将语义缓存集成至生产 `/rag` 端点。 ## 一、功能概述 -Agentic RAG 是一个智能问答系统,基于 Mixin 模式组合 8 个功能模块,具备以下核心能力: +本系统是一个检索增强生成(RAG)问答系统,采用**单一统一编排路径**,由 `api/chat_routes.py` 的 `generate()` 函数直接编排全流程。核心能力包括: -| 功能 | 说明 | Mixin 模块 | -|------|------|-----------| -| **意图分析** | LLM 驱动的查询改写 + 双层判断(是否需要检索) | `IntentAnalyzer`(独立模块) | -| **查询重写** | 口语化→专业术语、实体补全、指代消解 | `QueryRewriteMixin` | -| **混合检索** | 向量检索 + BM25 + RRF 融合 + Rerank 重排 | `SearchMixin` → `RAGEngine` | -| **多源融合** | 知识库 + 网络搜索,智能处理冲突 | `AnswerMixin` | -| **幻觉验证** | 基于参考信息验证答案,防止 LLM 编造 | `AnswerMixin` | -| **引用标注** | 自动标注信息来源和引用编号 | `CitationMixin` | -| **富媒体提取** | 图片/表格的智能提取与展示 | `RichMediaMixin` | -| **质量评估** | 多维度质量评估(相关性/完整性/准确性/覆盖面) | `QualityMixin` | -| **上下文压缩** | Rerank 阈值过滤 + Token 预算控制 | `ContextMixin` | -| **元问题处理** | 文件列表、权限查询等非知识类问题 | `MetaQuestionMixin` | -| **置信度门控** | 基于 Reranker 分数判断检索质量,低分触发补救 | `ConfidenceGate`(独立模块) | - ---- - -## ⚠️ 一·五、两套编排路径(务必先读) - -> **关键认知**:本项目存在**两套并存的编排(orchestration)**。生产 HTTP 接口 `/rag` 走的是**轻量编排**,而 `AgenticRAG.process()` 那套**完整决策循环目前处于备用状态、未接入任何 HTTP 路由**。 -> 阅读下方所有架构图前请先理解这一点——下面 2.1 的「整体架构图」描绘的是**备用路径(AgenticRAG.process)**,不是当前生产实际跑的流程。 - -### 路径对比 - -| 维度 | 🟢 生产路径(当前启用) | 💤 备用路径(未接线) | -|------|----------------------|---------------------| -| 入口 | `api/chat_routes.py` → `rag()` → `generate()` | `core/agentic.py` → `AgenticRAG.process()` | -| 编排者 | `chat_routes` 自己的流程代码 | `AgenticRAG` 类(8 个 Mixin 组合) | -| 意图分析 | ✅ `intent_analyzer.analyze_intent()` | ✅ `IntentAnalyzer` / `QueryRewriteMixin` | -| 检索 | ✅ `search_hybrid()` → `engine.search_knowledge()` | ✅ `engine.search_knowledge()` | -| 查询分解/扩展/MMR/自适应TopK | ✅ 在 `engine` 内部执行 | ✅ 同左 | -| 答案生成 | ✅ `engine.generate_answer_stream()`(流式) | `AnswerMixin._generate_fused_answer()` | -| 引用标注 | ✅ `chat_routes._attach_citations()`(本地版) | `CitationMixin._attach_citations()` | -| 置信度门控 | ❌ 不调用 | `ConfidenceGate`(仅此路径用) | -| 多维质量评估 | ❌ 不调用 | `QualityMixin._assess_quality()` | -| 推理反思 | ❌ 不调用 | `QualityMixin._reflect_on_answer()` | -| 循环防护 | ❌ 不调用 | `LoopGuard`(仅此路径用) | -| 幻觉验证 | ❌ 不调用 | `AnswerMixin._verify_and_refine_answer()` | - -### 重要结论 - -- **Agentic 的核心能力是活跃的**:意图分析+LLM改写、子查询拆分、查询扩展、自适应 TopK、MMR 去重、混合检索+Rerank——这些都在 `/rag` 中**真实运行**,只是由 `chat_routes` + `engine` 直接调用,而非通过 `AgenticRAG` 类。 -- **休眠的只是「决策循环编排类」**:`AgenticRAG.process()` 及其独有组件(置信度门控 / 质量评估 / 推理反思 / 循环防护 / 幻觉验证)未接入 `/rag`。 -- import 证据:`confidence_gate.py`、`quality_assessor.py`、`reasoning_reflector.py`、`loop_guard.py` 以及 8 个 `agentic_*` Mixin **只被 `core/agentic.py` import**;而 `AgenticRAG` 实例虽在 `api/__init__.py:90` 启动时创建,但其唯一读取入口 `_get_agentic_rag()` **零调用**。 -- **这不是死代码可删**:`AgenticRAG` 在启动时被实例化(直接删会导致启动报错),且 `_extract_rich_media` 被 `scripts/test_rag_image_recall.py` 使用。它是「**一套更重、更完整、目前未启用的 Agentic 决策闭环**」,未来可选择接入。 - -### 🔬 如何验证「系统现在到底走哪套流程」 - -**方法 1:看开发环境 SSE 调试事件(最直接)** - -`/rag` 在 `IS_DEV=True` 时会发出一串**只有 `chat_routes` 编排才会发**的调试事件,收到它们即证明走的是生产路径: - -```bash -# UTF-8 payload 避免 Windows shell 编码问题 -curl -s -N -X POST http://localhost:5001/rag \ - -H "Content-Type: application/json; charset=utf-8" \ - -H "Authorization: Bearer mock-token-admin" \ - --data-binary @payload.json -``` - -观察 SSE 事件序列,**生产路径**会依次出现这些 `type`(`AgenticRAG.process` 不发这些): - -| SSE 事件 `type` | 来源代码 | 含义 | -|----------------|---------|------| -| `start` | `chat_routes.py:1232` | 请求开始处理 | -| `intent_result` | `chat_routes.py:1228` | 意图分析结果(来自 `intent_analyzer`)[DEV] | -| `retrieval_debug` | `chat_routes.py:1311` | 检索管线各步骤(来自 `engine.search_knowledge` 的 `_debug`)[DEV] | -| `chunks_retrieved` | `chat_routes.py:1416` | 召回切片详情 [DEV] | -| `sources` | `chat_routes.py:1547` | 检索到的来源列表 | -| `images_selected` | `chat_routes.py:1574` | 图片选择详情 [DEV] | -| `context_built` | `chat_routes.py:1622` | 最终上下文构建 [DEV] | -| `chunk` | `chat_routes.py:1630` | 流式答案的每个 token | -| `finish` | `chat_routes.py:1699` | 含 `timing`、`sources`、`citations` | -| `error` | `chat_routes.py:1733` | 处理异常时的错误信息 | - -> 标注 [DEV] 的事件仅在 `IS_DEV=True` 时发送,其余事件在生产环境也会发送。 - -**方法 2:看服务端日志** - -- 启动时:出现一次 `Agentic RAG 引擎已初始化`(`api/__init__.py:95`,仅实例化,不代表被调用)。 -- 每次 `/rag` 请求:出现 `[意图分析] use_context=... need_retrieval=...`(`chat_routes.py:1224`)。 -- **不会**出现任何来自 `AgenticRAG.process()` 内部的日志(如查询重写 `📝 查询重写`、`🔍 知识库检索: N 条结果`)——若出现则说明走了备用路径。 - -**方法 3:埋点验证(最确定)** - -临时在 `core/agentic.py` 的 `AgenticRAG.process()` 第一行加 `logger.warning("AgenticRAG.process CALLED")`,重启后发 `/rag` 请求——**该日志不会触发**,即证明生产不走 `AgenticRAG`。 - -**方法 4:静态确认调用链** - -```bash -grep -rn "_get_agentic_rag()" --include="*.py" . # 仅定义,无调用者 → AgenticRAG 实例未被请求使用 -grep -rn "\.process(" --include="*.py" api/ # /rag、/chat 均无 .process() 调用 -``` +| 功能 | 说明 | 实现位置 | +|------|------|----------| +| **意图分析** | LLM 驱动的双层判断(是否需要检索)+ 查询改写 | `core/intent_analyzer.py` | +| **混合检索** | 向量检索 + BM25 + RRF 融合 + Rerank 重排 | `core/engine.py` | +| **四层缓存** | Query + Embedding + Rerank(LRU)+ 语义缓存(FAISS) | `core/cache.py` + `core/semantic_cache.py` | +| **流式生成** | SSE 流式答案输出,逐 token 推送 | `core/engine.py::generate_answer_stream()` | +| **引用标注** | 自动标注信息来源和引用编号 | `api/chat_routes.py::_attach_citations()` | +| **富媒体** | 图片/表格的智能提取与展示 | `api/chat_routes.py` | +| **查询理解** | 查询分解、扩展、MMR 去重、自适应 TopK | `core/` 各独立模块 | +| **安全护栏** | 敏感信息过滤、Prompt 安全守卫 | `api/response_utils.py`、`core/prompt_guard.py` | --- ## 二、系统架构 -> ⚠️ 注意:下方 2.1「整体架构图」描绘的是**备用路径 `AgenticRAG.process()`** 的完整设计;当前生产 `/rag` 的实际流程见上方「一·五」及本节 2.3「生产 /rag 实际流程」。 - ### 2.1 整体架构图 ``` @@ -118,6 +33,12 @@ grep -rn "\.process(" --include="*.py" api/ # /rag、/chat 均无 .proce └────────────────────────────┬────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────────┐ +│ 语义缓存检查 (SemanticCache - FAISS) │ +│ cosine ≥ 0.92 → 命中则直接返回缓存结果 │ +│ 跳过检索 + 生成全流程(~100ms vs ~9s) │ +└────────────────────────────┬────────────────────────────────────────┘ + ↓ 未命中 +┌─────────────────────────────────────────────────────────────────────┐ │ 意图分析 (IntentAnalyzer) │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ 改写查询 │ │ 双层判断 │ │ 子查询拆分 │ │ @@ -126,26 +47,24 @@ grep -rn "\.process(" --include="*.py" api/ # /rag、/chat 均无 .proce └─────────┼──────────────────┼──────────────────┼─────────────────────┘ ↓ ↓ ↓ ┌──────────┐ ┌──────────────────────────────────────────┐ - │ 直接回答 │ │ AgenticRAG.process() │ - │ (LLM) │ │ 1. 元问题检查 │ - └──────────┘ │ 2. 查询重写 (QueryRewriteMixin) │ - │ 3. 知识库检索 (RAGEngine.search_knowledge)│ - │ 4. 上下文压缩 (ContextMixin) │ - │ 5. 网络搜索 (SearchMixin, 可选) │ - │ 6. (图谱检索已废弃,graph/ 目录已清空) │ - │ 7. 融合答案生成 (AnswerMixin) │ - │ 8. 幻觉验证 (AnswerMixin) │ - │ 9. 富媒体提取 (RichMediaMixin) │ - │ 10. 引用标注 (CitationMixin) │ + │ 直接回答 │ │ 统一编排流程 │ + │ (LLM) │ │ 1. 混合检索 (engine.search_knowledge) │ + └──────────┘ │ 2. 上下文提取 + 来源去重 │ + │ 3. 图片补充检索 + 打分选择 │ + │ 4. 构建上下文 │ + │ 5. 流式答案生成 (engine.generate_stream) │ + │ 6. 答案图号对齐 + 引用标注 │ + │ 7. 敏感信息过滤 │ + │ 8. 语义缓存写入 + SSE finish │ └────────────────────┬─────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────────┐ │ 检索层 (RAGEngine) │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ -│ │ 向量检索 │ │ BM25 检索 │ │ FAQ 独立召回 │ │ -│ │ (语义匹配) │ │ (关键词匹配) │ │ (精准命中) │ │ -│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ -│ └─────────────────┼─────────────────┘ │ +│ │ 查询缓存 │ │ 向量检索 │ │ BM25 检索 │ │ +│ │ (LRU 500) │ │ (语义匹配) │ │ (关键词匹配) │ │ +│ │ 命中直接返回│ └──────┬───────┘ └──────┬───────┘ │ +│ └──────────────┘ └─────────────────┘ │ │ ↓ │ │ ┌──────────────┐ │ │ │ RRF 融合 │ ← 动态权重(查询类型/长度驱动)│ @@ -167,78 +86,133 @@ grep -rn "\.process(" --include="*.py" api/ # /rag、/chat 均无 .proce ┌─────────────────────────────────────────────────────────────────────┐ │ 答案生成 (LLM 流式) │ │ ┌────────────────────────────────────────────────────────────────┐ │ -│ │ 整合多源信息 + 标注来源 + 处理冲突 + 引用编号 + SSE 流式输出 │ │ +│ │ 整合多源信息 + 标注来源 + 引用编号 + SSE 流式输出 │ │ │ └────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘ ``` -### 2.2 Mixin 组合架构 +### 2.2 编排方式 -```python -class AgenticRAG( - QueryRewriteMixin, # 查询重写:口语化→专业术语、实体补全 - SearchMixin, # 检索功能:网络搜索 - AnswerMixin, # 答案生成:融合回答、幻觉验证 - CitationMixin, # 引用处理:来源标注、引用编号 - RichMediaMixin, # 富媒体:图片/表格提取 - QualityMixin, # 质量评估:多维评估 - ContextMixin, # 上下文处理:压缩、过滤 - MetaQuestionMixin # 元问题:文件列表、权限查询 -): - ... -``` +系统采用**函数式编排**而非类组合模式。整个 RAG 流程由 `api/chat_routes.py` 的 `generate()` 函数直接控制,按步骤调用各独立模块: -> 注:以上 2.1 / 2.2 是 `AgenticRAG`(备用路径)的设计。**当前生产 `/rag` 不实例化走这条链**,实际流程见下方 2.3。 +- **意图分析**:`core/intent_analyzer.py` 的 `analyze_intent()` +- **检索管线**:`core/engine.py` 的 `search_knowledge()` +- **流式生成**:`core/engine.py` 的 `generate_answer_stream()` +- **引用标注**:`api/chat_routes.py` 内的 `_attach_citations()` +- **缓存系统**:`core/cache.py` 的 `RAGCacheManager` 单例 + `core/semantic_cache.py` 的 `SemanticCache` 单例 -### 2.3 生产 /rag 实际流程(当前启用) - -入口 `api/chat_routes.py::rag() → generate()`,**不经过 `AgenticRAG`**: - -``` -POST /rag (SSE 流式) - ↓ -[chat_routes.generate()] ← 轻量编排,不实例化 AgenticRAG - │ - ├─ 发 SSE: start - │ - ├─ 1. 意图分析 intent_analyzer.analyze_intent() # chat_routes:1222 - │ ├─ need_retrieval=False → 直接 LLM 回答(流式发 SSE: chunk),结束 - │ │ └─ use_context=True 时带历史上下文,use_context=False 时纯闲聊 - │ └─ 否则继续;sub_queries 传入检索 - │ └─[DEV] 发 SSE: intent_result - │ - ├─ 2. 混合检索 search_hybrid() → engine.search_knowledge() # chat_routes:1300 - │ (内部:向量+BM25+RRF+废止过滤+章节过滤 - │ +云端Rerank+MMR去重+FAQ加权+黑名单+时间衰减 - │ +上下文扩展+自适应TopK) - │ └─[DEV] 发 SSE: retrieval_debug - │ - ├─ 3. 提取上下文/来源(按 source 去重,doc_type 驱动溯源展示) # chat_routes:1362 - │ └─[DEV] 发 SSE: chunks_retrieved - │ └─ 发 SSE: sources - │ - ├─ 4. 图片补充检索 + 图片打分选择 (select_images) - │ └─[DEV] 发 SSE: images_selected - ├─ 5. 构建上下文 (_order_text_contexts_for_prompt) - │ └─[DEV] 发 SSE: context_built - │ - ├─ 6. 流式答案生成 engine.generate_answer_stream() # chat_routes:1628 - │ └─ 逐 token 发 SSE: chunk - │ - ├─ 7. 答案图号对齐过滤 - ├─ 8. 引用标注 chat_routes._attach_citations()(本地版,非 CitationMixin) # chat_routes:1668 - ├─ 9. 敏感信息过滤 filter_response() - ├─ 10. 发 SSE: finish(answer + sources + citations + images + timing) - └─[异常] 发 SSE: error -``` - -**与备用路径(AgenticRAG.process)的差异**:生产路径**没有**置信度门控、多维质量评估、推理反思、循环防护、幻觉验证这几步——它们只存在于 `AgenticRAG.process()`。 +各模块通过 `get_engine()`、`get_cache_manager()`、`get_semantic_cache()` 等工厂函数获取全局单例实例。 --- -## 三、意图分析流程 +## 三、四层缓存架构 -### 3.1 IntentAnalyzer 双层判断 +### 3.1 缓存层次概览 + +| 层次 | 缓存类型 | 存储结构 | 容量 | TTL | 作用 | +|------|----------|----------|------|-----|------| +| L1 | Query Cache | LRU (OrderedDict) | 500 条 | 1 小时 | 缓存完整问答结果,命中后跳过整个检索+生成 | +| L2 | Embedding Cache | LRU (OrderedDict) | 2000 条 | 24 小时 | 缓存向量化结果,避免重复调用 embedding 模型 | +| L3 | Rerank Cache | LRU (OrderedDict) | 1000 条 | 1 小时 | 缓存 Rerank 分数,避免重复调用 Reranker | +| L4 | Semantic Cache | FAISS IndexFlatIP | 10000 条 | 无过期 | 语义级缓存,相似查询也能命中 | + +### 3.2 Query Cache + +Query Cache 是最外层的完整问答结果缓存。命中后直接返回缓存的 `answer + sources + citations`,跳过检索和生成全流程。 + +**缓存键设计**:`{query_hash}:{kb_name}:{kb_version}` + +- 基于查询文本哈希 + 知识库名称 + 知识库版本号 +- 知识库版本变更时(如文档更新/重新索引),相关缓存自动失效 + +**已修复的问题**: + +1. **键不匹配问题(已修复)**:此前 `set_query_result()` 在有 `doc_ids` 参数时使用 `doc_hash` 分支生成键,而 `get_query_result()` 始终使用 `kb_version` 分支——导致 GET 和 SET 的键永远不匹配,命中率始终为 0%。修复后两端统一使用 `kb_version` 分支。 + +2. **写入阈值问题(已修复)**:`CACHE_MIN_SCORE` 原值为 `0.3`,但 ChromaDB 余弦距离经 `1 - dist` 计算后得分通常在 0.03-0.06 之间,远低于阈值,导致几乎不写入缓存。修复后设为 `0.0`。 + +### 3.3 Embedding Cache + +缓存文本向量化结果,由 `RAGEngine` 在调用 embedding 模型前后自动读写。键为查询文本哈希,避免对相同文本重复调用 embedding 模型(如 DashScope text-embedding-v3)。 + +### 3.4 Rerank Cache + +缓存 Rerank 重排序的分数结果。键为 `query + sorted(doc_ids)` 的精确匹配。注意:由于 RRF 融合产出差异,命中率可能偏低。 + +### 3.5 语义缓存(Semantic Cache) + +语义缓存基于 FAISS 向量索引实现语义级匹配——即使查询文字不完全相同,只要语义足够相似(cosine similarity ≥ 0.92),就能命中缓存。 + +**工作机制**: + +``` +用户查询 → embedding 编码 → FAISS 向量检索 + → cosine ≥ 0.92 → 命中:返回缓存的 answer + sources + citations(~100ms) + → cosine < 0.92 → 未命中:执行完整 RAG 流程后写入缓存 +``` + +**集成位置**: + +- **读取**:在 `generate()` 函数的意图分析之后、混合检索之前(跳过整个检索+生成流程) +- **写入**:在 `generate()` 函数生成完整答案后、发送 `finish` 事件之前 +- **缓存内容**:answer、sources、citations、images、tables + +**验证结果**:语义缓存命中率约 66.7%,平均响应从 ~9.2 秒降至 ~100 毫秒(约 92 倍加速)。 + +### 3.6 缓存失效机制 + +所有基于 LRU 的缓存(L1-L3)均支持基于知识库版本号(`kb_version`)的自动失效: + +- 每个缓存条目关联 `kb_version` +- 知识库文档变更时 `kb_version` 递增 +- 读取时检查 `kb_version` 是否匹配,不匹配则视为过期 + +语义缓存(L4)当前无 TTL 过期机制,仅受 `max_size=10000` 容量限制。 + +### 3.7 缓存配置 + +```python +# config.py / config.example.py + +# 查询结果缓存 +QUERY_CACHE_ENABLED = True +QUERY_CACHE_SIZE = 500 +QUERY_CACHE_TTL = 3600 # 秒 + +# Embedding 缓存 +EMBEDDING_CACHE_ENABLED = True +EMBEDDING_CACHE_SIZE = 2000 +EMBEDDING_CACHE_TTL = 86400 # 24小时 + +# Rerank 缓存 +RERANK_CACHE_ENABLED = True +RERANK_CACHE_SIZE = 1000 +RERANK_CACHE_TTL = 3600 + +# 语义缓存 +SEMANTIC_CACHE_ENABLED = True +SEMANTIC_CACHE_THRESHOLD = 0.92 # cosine 相似度阈值 + +# 缓存写入最低置信度 +CACHE_MIN_SCORE = 0.0 # ChromaDB 余弦距离经 1-dist 后得分约 0.03-0.06,须设为 0 +``` + +### 3.8 部署注意事项 + +当前所有缓存均为**进程内内存存储**(LRU 使用 `OrderedDict`,语义缓存使用 FAISS 内存索引),有以下部署影响: + +- **单 Worker**:Gunicorn 默认 1 个 worker,所有请求共享同一缓存实例,缓存有效 +- **多 Worker**:每个 worker 有独立缓存,不共享,缓存效率降低 +- **冷启动**:进程重启后缓存全部丢失,需重新预热 +- **`max_requests=1000`**:Gunicorn worker 定期重启会导致缓存周期性清空 + +对于生产环境多实例部署场景,已规划 Redis 外部缓存迁移方案(见 `reports/redis_migration_plan.md`)。 + +--- + +## 四、意图分析流程 + +### 4.1 IntentAnalyzer 双层判断 意图分析由 `core/intent_analyzer.py` 的 `IntentAnalyzer` 类完成,采用 **LLM 驱动** 的双层判断: @@ -269,7 +243,7 @@ POST /rag (SSE 流式) - intent: factual/comparison/reasoning/instruction/other ``` -### 3.2 QueryClassifier 规则分类 +### 4.2 QueryClassifier 规则分类 `core/query_classifier.py` 提供无 LLM 调用的快速规则分类: @@ -286,9 +260,9 @@ POST /rag (SSE 流式) --- -## 四、检索管线详解 +## 五、检索管线详解 -### 4.1 完整检索流程 +### 5.1 完整检索流程 ``` search_knowledge(query, top_k=30) @@ -335,7 +309,7 @@ search_knowledge(query, top_k=30) └─ 15. 缓存写入 → 返回结果 ``` -### 4.2 混合检索代码示例 +### 5.2 混合检索代码示例 ```python # 向量检索(语义相似) @@ -348,7 +322,10 @@ bm25_results = bm25_index.search(query, top_k=recall_k) faq_results = faq_collection.query(query_embeddings=[query_vector], n_results=3) # 图片独立召回(P0 通道) -image_results = collection.query(query_embeddings=[query_vector], n_results=5, where={"chunk_type": {"$in": ["image", "chart", "table"]}}) +image_results = collection.query( + query_embeddings=[query_vector], n_results=5, + where={"chunk_type": {"$in": ["image", "chart", "table"]}} +) # RRF 融合(动态权重) fused = reciprocal_rank_fusion([vector_results, bm25_results], weights=[vector_w, bm25_w]) @@ -360,7 +337,7 @@ reranked = rerank_results(query, fused, top_k=15) mmr_results = mmr_rerank(query_emb, reranked, top_k=30, lambda_param=0.5) ``` -### 4.3 RRF 融合算法 +### 5.3 RRF 融合算法 ``` RRF分数 = Σ (权重 / (k + 排名位置)) @@ -376,9 +353,9 @@ RRF分数 = Σ (权重 / (k + 排名位置)) - 查询类型驱动: FACT→BM25优先, PROCESS→向量优先 ``` -### 4.4 Rerank 重排 +### 5.4 Rerank 重排 -**后端**: 支持三种模式,由 `RERANK_BACKEND` 环境变量控制 +**后端**:支持三种模式,由 `RERANK_BACKEND` 环境变量控制 | RERANK_BACKEND | 说明 | |----------------|------| @@ -386,20 +363,20 @@ RRF分数 = Σ (权重 / (k + 排名位置)) | `"local"` | 仅使用本地 `BAAI/bge-reranker-base`(CrossEncoder / ONNX) | | `"fallback"` | 优先云端,失败时自动回退本地(推荐生产环境) | -**云端 Reranker(推荐)**: +**云端 Reranker(推荐)**: ```python # config.py -RERANK_BACKEND = os.getenv("RERANK_BACKEND", "local") # local / cloud / fallback -RERANK_CLOUD_MODEL = "qwen3-rerank" # DashScope 云端 Rerank 模型 +RERANK_BACKEND = os.getenv("RERANK_BACKEND", "local") +RERANK_CLOUD_MODEL = "qwen3-rerank" RERANK_CLOUD_API_KEY = os.getenv("RERANK_CLOUD_API_KEY", DASHSCOPE_API_KEY) RERANK_CLOUD_BASE_URL = "https://dashscope.aliyuncs.com/compatible-api/v1/reranks" -RERANK_CLOUD_TIMEOUT = 15 # 云端请求超时(秒) +RERANK_CLOUD_TIMEOUT = 15 ``` `CloudReranker` 类(`core/engine.py`)封装 DashScope 的 `/compatible-api/v1/reranks` 接口,提供与本地 `CrossEncoder.predict()` / `ONNXReranker.predict()` 一致的调用接口。 -**本地 Reranker(备选)**: +**本地 Reranker(备选)**: ```python def rerank_results(self, query, results, top_k=5): @@ -409,69 +386,73 @@ def rerank_results(self, query, results, top_k=5): # 返回 top_k 个最高分结果 ``` -**调用位置**: `core/engine.py` 的 `search_knowledge()` 和 `_search_multi_kb()` 中,RRF 融合 + 废止/章节过滤之后、MMR 去重之前执行。 - -**引擎初始化顺序**: `RAGEngine.__init__()` 中按 `RERANK_BACKEND` 决定加载策略: -- `cloud` / `fallback`:先尝试创建 `CloudReranker`,需要 `RERANK_CLOUD_API_KEY` -- `local` / `fallback`(云端失败时):加载本地 `BAAI/bge-reranker-base`,支持 ONNX 加速 +**调用位置**:`core/engine.py` 的 `search_knowledge()` 和 `_search_multi_kb()` 中,RRF 融合 + 废止/章节过滤之后、MMR 去重之前执行。 --- -## 五、置信度门控 +## 六、生产 /rag 完整流程 -`core/confidence_gate.py` 基于 Reranker 分数判断检索结果质量: +入口 `api/chat_routes.py::rag() → generate()`: ``` -检索结果 → Reranker 计算置信度 → 阈值判断 → 决策 - │ - ┌─────────────────┼─────────────────┐ - ↓ ↓ ↓ - PASS (≥0.4) REWRITE (0.2~0.4) WEB_SEARCH (<0.2) - 继续生成 查询重写 网络搜索补救 +POST /rag (SSE 流式) + ↓ +[chat_routes.generate()] + │ + ├─ 发 SSE: start + │ + ├─ 1. 语义缓存检查 SemanticCache.get() # chat_routes + │ ├─ 命中 → 直接流式发 SSE: chunk + finish,结束(~100ms) + │ └─ 未命中 → 继续;记录 embedding 供后续写入 + │ + ├─ 2. 意图分析 intent_analyzer.analyze_intent() + │ ├─ need_retrieval=False → 直接 LLM 回答(流式发 SSE: chunk),结束 + │ │ └─ use_context=True 时带历史上下文,use_context=False 时纯闲聊 + │ └─ 否则继续;sub_queries 传入检索 + │ └─[DEV] 发 SSE: intent_result + │ + ├─ 3. 混合检索 search_hybrid() → engine.search_knowledge() + │ (内部:查询缓存检查 → 向量+BM25+RRF+废止过滤+章节过滤 + │ +云端Rerank+MMR去重+FAQ加权+黑名单+时间衰减 + │ +上下文扩展+自适应TopK) + │ └─[DEV] 发 SSE: retrieval_debug + │ + ├─ 4. 提取上下文/来源(按 source 去重,doc_type 驱动溯源展示) + │ └─[DEV] 发 SSE: chunks_retrieved + │ └─ 发 SSE: sources + │ + ├─ 5. 图片补充检索 + 图片打分选择 (select_images) + │ └─[DEV] 发 SSE: images_selected + ├─ 6. 构建上下文 (_order_texts_for_prompt) + │ └─[DEV] 发 SSE: context_built + │ + ├─ 7. 流式答案生成 engine.generate_answer_stream() + │ └─ 逐 token 发 SSE: chunk + │ + ├─ 8. 答案图号对齐过滤 + ├─ 9. 引用标注 _attach_citations() + ├─ 10. 敏感信息过滤 filter_response() + ├─ 11. 语义缓存写入 SemanticCache.set() # 写入缓存供后续命中 + ├─ 12. 发 SSE: finish(answer + sources + citations + images + timing) + └─[异常] 发 SSE: error ``` -**阈值配置**: -- `PASS_THRESHOLD = 0.2`: 通过阈值(低于此值需要补救) -- `GOOD_THRESHOLD = 0.4`: 良好阈值(高质量结果) -- `EXCELLENT_THRESHOLD = 0.7`: 优秀阈值 +### SSE 事件序列 ---- +| SSE 事件 `type` | 含义 | +|----------------|------| +| `start` | 请求开始处理 | +| `intent_result` | 意图分析结果 [DEV] | +| `retrieval_debug` | 检索管线各步骤 [DEV] | +| `chunks_retrieved` | 召回切片详情 [DEV] | +| `sources` | 检索到的来源列表 | +| `images_selected` | 图片选择详情 [DEV] | +| `context_built` | 最终上下文构建 [DEV] | +| `chunk` | 流式答案的每个 token | +| `finish` | 含 `timing`、`sources`、`citations`、`images` | +| `error` | 处理异常时的错误信息 | -## 六、AgenticRAG 主流程 - -### 6.1 process() 方法 - -```python -def process(self, query, verbose=True, history=None, - allowed_levels=None, role=None, department=None, - emit_log=None) -> dict: - """ - 返回: - { - "answer": str, # 最终答案 - "sources": list, # 来源列表 - "images": list, # 图片列表 - "tables": list, # 表格列表 - "citations": list, # 引用列表 - "log_trace": list # 推理过程追踪 - } - """ -``` - -### 6.2 流程步骤 - -| 步骤 | 方法 | 说明 | -|------|------|------| -| 1 | `_is_meta_question()` | 检查元问题(文件列表、权限等) | -| 2 | `should_rewrite()` + `_rewrite_query()` | 查询重写(口语化→专业术语、实体补全) | -| 3 | `engine.search_knowledge()` / `engine.search_multiple()` | 知识库检索(含向量+BM25+RRF+MMR+Rerank) | -| 4 | `_compress_contexts()` | 上下文压缩(Rerank 阈值过滤) | -| 5 | `_web_search_flow()` | 网络搜索(可选,需 SERPER_API_KEY) | -| 6 | ~~`_graph_search()`~~ | ~~图谱检索(已废弃,graph/ 目录已清空)~~ | -| 7 | `_generate_fused_answer()` | 融合答案生成(多源信息+冲突处理) | -| 8 | `_verify_and_refine_answer()` | 幻觉验证(防止 LLM 编造) | -| 9 | `_extract_rich_media()` | 富媒体提取(图片/表格) | -| 10 | `_attach_citations()` | 引用标注 | +> 标注 [DEV] 的事件仅在 `IS_DEV=True` 时发送。 --- @@ -489,7 +470,7 @@ curl -X POST http://localhost:5001/rag \ }' ``` -**响应格式**: SSE(Server-Sent Events)流式返回 +**响应格式**:SSE(Server-Sent Events)流式返回 ``` event: token @@ -501,7 +482,7 @@ data: {"text": "规定"} ... event: finish -data: {"answer": "完整答案", "sources": [...], "citations": [...], "images": [...], "duration_ms": 3200} +data: {"answer": "完整答案", "sources": [...], "citations": [...], "images": [...], "duration_ms": 200} ``` ### 7.2 代码调用 @@ -520,20 +501,27 @@ for token in engine.generate_answer_stream(query, context, history=history): print(token, end="", flush=True) ``` -### 7.3 AgenticRAG 调用 +### 7.3 缓存统计查询 -```python -from core.agentic import AgenticRAG - -rag = AgenticRAG(max_iterations=3, enable_web_search=True) -result = rag.process("出差补助标准是什么?") - -print(f"答案: {result['answer']}") -print(f"来源: {result['sources']}") -print(f"图片: {result['images']}") -print(f"引用: {result['citations']}") +```bash +# 查看各层缓存命中率和统计 +curl http://localhost:5001/cache/stats \ + -H "Authorization: Bearer mock-token-admin" ``` +返回示例: + +```json +{ + "query_cache": {"total_entries": 50, "hits": 10, "misses": 6, "hit_rate": 0.625}, + "embedding_cache": {"total_entries": 200, "hits": 0, "misses": 0, "hit_rate": 0}, + "rerank_cache": {"total_entries": 100, "hits": 0, "misses": 0, "hit_rate": 0}, + "semantic_cache": {"total_entries": 15, "hits": 6, "misses": 3, "hit_rate": 0.667} +} +``` + +> 注:当 Query Cache 或 Semantic Cache 在外层拦截了重复查询时,Embedding Cache 和 Rerank Cache 的命中率为 0 是正常现象——重复查询根本不会到达这些层。 + --- ## 八、配置说明 @@ -565,10 +553,10 @@ RECALL_MULTIPLIER = 3 # 候选池最小倍数 # 重排序 USE_RERANK = True # 启用重排序 RERANK_BACKEND = "local" # "local"=本地模型, "cloud"=云端API, "fallback"=优先云端失败回退本地 -RERANK_CLOUD_MODEL = "qwen3-rerank" # 云端 Rerank 模型(DashScope API) +RERANK_CLOUD_MODEL = "qwen3-rerank" RERANK_CANDIDATES = 20 # 送入重排序的候选数 RERANK_TOP_K = 15 # 重排序后保留数 -RERANK_USE_ONNX = True # ONNX 加速(仅本地模式,环境变量控制,默认开启) +RERANK_USE_ONNX = True # ONNX 加速(仅本地模式,环境变量控制) # RRF 融合 RRF_K = 60 # RRF 常数 @@ -581,30 +569,7 @@ MMR_TOP_K = 30 # MMR 保留数 MMR_LAMBDA = 0.5 # 相关性 vs 多样性权衡 ``` -### 8.3 缓存配置 - -```python -# 查询结果缓存 -QUERY_CACHE_ENABLED = True -QUERY_CACHE_SIZE = 500 -QUERY_CACHE_TTL = 3600 # 1小时 - -# Embedding 缓存 -EMBEDDING_CACHE_ENABLED = True -EMBEDDING_CACHE_SIZE = 2000 -EMBEDDING_CACHE_TTL = 86400 # 24小时 - -# Rerank 缓存 -RERANK_CACHE_ENABLED = True -RERANK_CACHE_SIZE = 1000 -RERANK_CACHE_TTL = 3600 # 1小时 - -# 语义缓存 -SEMANTIC_CACHE_ENABLED = True -SEMANTIC_CACHE_THRESHOLD = 0.92 # 相似度阈值 -``` - -### 8.4 设备配置 +### 8.3 设备配置 ```python DEVICE = "auto" # auto / cuda / cpu / cuda:0 @@ -618,17 +583,9 @@ RERANK_DEVICE = DEVICE # Rerank 模型设备 ``` core/ # RAG 核心引擎 -├── engine.py # RAGEngine 单例(检索主流程、Rerank、RRF) -├── agentic.py # AgenticRAG 主类(Mixin 组合) -├── agentic_base.py # 基础常量与条件导入 -├── agentic_query.py # QueryRewriteMixin(查询重写) -├── agentic_search.py # SearchMixin(网络搜索) -├── agentic_answer.py # AnswerMixin(答案生成、幻觉验证) -├── agentic_citation.py # CitationMixin(引用标注) -├── agentic_media.py # RichMediaMixin(富媒体提取) -├── agentic_quality.py # QualityMixin(质量评估) -├── agentic_context.py # ContextMixin(上下文压缩) -├── agentic_meta.py # MetaQuestionMixin(元问题处理) +├── engine.py # RAGEngine 单例(检索主流程、Rerank、RRF、流式生成) +├── cache.py # 三层 LRU 缓存管理器(Query/Embedding/Rerank) +├── semantic_cache.py # 语义缓存(FAISS IndexFlatIP) ├── bm25_index.py # BM25Index(关键词检索) ├── chunker.py # 文本分块器 ├── mmr.py # MMR 去重(语义向量版 + 文本 Jaccard 版) @@ -637,14 +594,13 @@ core/ # RAG 核心引擎 ├── query_decomposer.py # QueryDecomposer(复杂查询拆分) ├── query_expansion.py # 查询扩展 ├── adaptive_topk.py # AdaptiveTopK(自适应 TopK) -├── confidence_gate.py # ConfidenceGate(置信度门控) -├── quality_assessor.py # 多维质量评估 -├── reasoning_reflector.py # 推理反思 -├── loop_guard.py # 循环防护 +├── confidence_gate.py # ConfidenceGate(置信度门控,当前未接入生产流程) +├── quality_assessor.py # 多维质量评估(当前未接入生产流程) +├── reasoning_reflector.py # 推理反思(当前未接入生产流程) +├── loop_guard.py # 循环防护(当前未接入生产流程) +├── prompt_guard.py # Prompt 安全守卫 ├── llm_budget.py # LLM 调用预算控制 ├── llm_utils.py # LLM 调用工具函数 -├── semantic_cache.py # 语义缓存 -├── cache.py # 三层缓存管理器(Query/Embedding/Rerank) ├── status_codes.py # 状态码定义 └── constants.py # 公共常量 @@ -666,7 +622,7 @@ knowledge/ # 知识库管理 api/ # API 路由层 ├── __init__.py # create_app() 工厂 -├── chat_routes.py # /chat, /rag(SSE), /search +├── chat_routes.py # /chat, /rag(SSE), /search(核心编排入口) ├── kb_routes.py # /collections ├── document_routes.py # /documents/* ├── sync_routes.py # /sync @@ -726,6 +682,10 @@ deploy/ # 部署配置 ├── gunicorn.conf.py # Gunicorn WSGI 配置 └── wsgi.py # WSGI 入口 +reports/ # 分析报告 +├── cache_performance_report.md # 缓存性能验证报告 +└── redis_migration_plan.md # Redis 缓存迁移方案(规划中) + config/ # 运行时配置 └── banned_words.txt # 敏感词库 ``` @@ -734,8 +694,8 @@ config/ # 运行时配置 ## 十、与传统 RAG 对比 -| 特性 | 传统 RAG | Agentic RAG (当前) | -|------|---------|-------------------| +| 特性 | 传统 RAG | 本系统 | +|------|---------|--------| | 意图判断 | 无 | IntentAnalyzer LLM 双层判断 | | 查询改写 | 无 | 口语化→专业术语 + 实体补全 + 指代消解 | | 检索方式 | 单一向量检索 | 向量 + BM25 + FAQ + 图片独立召回 | @@ -744,14 +704,11 @@ config/ # 运行时配置 | 重排序 | 无 | 云端 qwen3-rerank API(支持本地 BGE 回退) | | 问题分解 | 无 | 自动拆分对比/推理类查询 | | 闲聊处理 | 无 | 意图分析自动判断 | -| 网络搜索 | 无 | 可选支持(Serper API) | -| 知识图谱 | 无 | ~~可选支持(Neo4j)~~(已废弃,graph/ 目录已清空) | -| 幻觉验证 | 无 | 基于参考信息的答案验证 | -| 置信度门控 | 无 | Reranker 分数驱动,低分触发补救 | -| 缓存 | 无 | 三层缓存 + 语义缓存 | +| 缓存体系 | 无 | 四层缓存(Query + Embedding + Rerank + 语义缓存) | +| 语义缓存 | 无 | FAISS 向量索引,相似查询复用(92x 加速) | | 自适应 TopK | 固定 top_k | 根据置信度动态调整 | | 上下文理解 | 无 | 多轮对话 + 历史上下文 | -| 响应时间 | ~2秒 | ~3-8秒(取决于 Rerank + LLM) | +| 响应时间 | ~2秒 | 首次 ~3-8秒 / 缓存命中 ~100-200毫秒 | --- @@ -759,71 +716,71 @@ config/ # 运行时配置 ### 11.1 Rerank 调用路径 -Rerank 在系统中有 **两个独立调用路径**: +Rerank 在生产流程中有 **一个调用路径**: | 路径 | 位置 | 说明 | |------|------|------| | 主检索管线 | `engine.rerank_results()` | RRF 融合后、MMR 去重前执行,对候选重排取 top_k | -| 置信度门控 | `confidence_gate._compute_scores()` | 直接调用 `reranker.predict()`,可能重复推理 | -### 11.2 性能瓶颈 +### 11.2 性能特征 -| 瓶颈 | 严重程度 | 说明 | -|------|---------|------| -| Rerank 缓存命中率偏低 | 🟡 中 | `rerank_results()` 已正确调用缓存读写,但缓存 key 基于 `query + sorted(doc_ids)` 精确匹配,RRF 融合产出稍有不同就无法命中 | -| 置信度门控重复推理 | 🟡 中 | 同一 query+documents 可能被 Rerank 两次(当前仅备用路径使用,暂未影响生产) | -| ~~无性能计时~~ | ~~🟡 中~~ | 已修复:`rerank_results()` 现返回 `_rerank_time_ms` 计时字段 | -| 查询分类器策略未生效 | 🟢 低 | `QueryClassifier` 定义的差异化 rerank 参数未传递到引擎 | +| 项目 | 说明 | +|------|------| +| Rerank 缓存命中率 | 偏低——键基于 `query + sorted(doc_ids)` 精确匹配,RRF 融合产出稍有不同就无法命中 | +| 性能计时 | `rerank_results()` 返回 `_rerank_time_ms` 计时字段 | +| Query Cache 拦截 | 重复查询被 Query Cache 在外层拦截,不会到达 Rerank 层(正确行为) | ### 11.3 Rerank 配置参数 | 配置项 | 默认值 | 说明 | |--------|--------|------| | `USE_RERANK` | `True` | 总开关 | -| `RERANK_BACKEND` | `"local"` | 后端选择:`local`=本地模型, `cloud`=云端API, `fallback`=优先云端失败回退本地 | -| `RERANK_CLOUD_MODEL` | `"qwen3-rerank"` | 云端 Rerank 模型名称(DashScope API) | +| `RERANK_BACKEND` | `"local"` | 后端选择 | +| `RERANK_CLOUD_MODEL` | `"qwen3-rerank"` | 云端模型名称 | | `RERANK_CLOUD_API_KEY` | 同 `DASHSCOPE_API_KEY` | 云端 API 密钥 | | `RERANK_CLOUD_BASE_URL` | `https://dashscope.aliyuncs.com/compatible-api/v1/reranks` | 云端 API 地址 | | `RERANK_CLOUD_TIMEOUT` | `15` | 云端请求超时(秒) | -| `RERANK_MODEL_PATH` | `models/bge-reranker-base` | 本地模型路径(仅 local/fallback 模式) | +| `RERANK_MODEL_PATH` | `models/bge-reranker-base` | 本地模型路径 | | `RERANK_CANDIDATES` | `20` | 送入 Rerank 的候选数 | | `RERANK_TOP_K` | `15` | Rerank 后保留数 | -| `RERANK_USE_ONNX` | `True`(环境变量默认) | ONNX 加速开关(仅本地模式) | -| `RERANK_DEVICE` | 跟随 `DEVICE` | 设备选择(仅本地模式) | +| `RERANK_USE_ONNX` | `True` | ONNX 加速开关 | +| `RERANK_DEVICE` | 跟随 `DEVICE` | 设备选择 | | `RERANK_THRESHOLD` | `0.3` | 上下文过滤阈值 | -| `RERANK_CACHE_ENABLED` | `True` | 缓存开关(已在 `rerank_results()` 中使用) | +| `RERANK_CACHE_ENABLED` | `True` | 缓存开关 | --- ## 十二、最佳实践 -### 12.1 何时使用 Agentic RAG +### 12.1 何时使用 /rag 接口 -✅ **推荐使用**: -- 复杂问题需要多轮检索 +**推荐使用**: + +- 复杂问题需要检索知识库 - 用户表达模糊需要改写 - 需要区分闲聊和知识问答 - 需要多轮对话记忆 -- 需要引用来源和幻觉验证 +- 需要引用来源和证据 -❌ **不推荐使用**: -- 简单明确的问题(用 `/search` 接口更快) -- 对响应时间极度敏感的场景 +**不推荐使用**(改用 `/search` 接口更快): + +- 简单明确的问题,只需返回原始检索结果 +- 对响应时间极度敏感且不需要 LLM 生成答案的场景 ### 12.2 性能优化 ```python -# 减少迭代次数 -rag = AgenticRAG(max_iterations=2) - -# 禁用网络搜索 -rag = AgenticRAG(enable_web_search=False) - # ONNX 加速默认已开启;如有兼容性问题可关闭(环境变量) # RERANK_USE_ONNX=false # 使用轻量 MMR(文本相似度代替语义向量) # config.py: MMR_USE_EMBEDDING = False + +# 调整语义缓存阈值(降低阈值可提高命中率,但可能降低准确性) +# config.py: SEMANTIC_CACHE_THRESHOLD = 0.90 + +# 调整缓存容量 +# config.py: QUERY_CACHE_SIZE = 1000 # 增大查询缓存容量 ``` ### 12.3 调试技巧 @@ -834,73 +791,62 @@ result = engine.search_knowledge("问题", top_k=10) debug = result.get('_debug', {}) for step in debug.get('steps', []): print(f"步骤: {step['name']}, 详情: {step}") + +# 查看缓存统计 +from core.cache import get_cache_manager +cm = get_cache_manager() +print(cm.get_stats()) + +# 查看语义缓存统计 +from core.semantic_cache import get_semantic_cache +sc = get_semantic_cache() +print({"hits": sc.hits, "misses": sc.misses, "total": sc.total_entries}) ``` --- -## 附加篇:Agentic RAG 深入优化与工作机制 +## 十三、演进记录 -### 一、Agentic RAG 的核心架构 +### v4.0(2026-06-05)— 统一编排 + 四层缓存修复 -Agentic RAG 构建了动态的决策闭环,核心组件包括: +**删除未使用的备用编排路径**:移除了 `core/agentic.py` 及 8 个 Mixin 文件(共 10 个文件 ~2050 行)。这些文件实现了完整的决策循环编排(含置信度门控、质量评估、推理反思等),但从未接入任何 HTTP 路由。 -- **意图分析器**:LLM 驱动的双层判断,替代硬编码规则 -- **查询重写器**:口语化→专业术语、实体补全、指代消解 -- **混合检索引擎**:向量 + BM25 + FAQ + 图片独立召回 + RRF 融合 -- **MMR 去重**:平衡相关性与多样性,Rerank 后进一步精炼结果 -- **Rerank 重排**:云端 qwen3-rerank API 精确排序,支持本地 BGE 回退 -- **置信度门控**:Reranker 分数驱动,低分触发补救流程 -- **幻觉验证**:基于参考信息验证答案,防止 LLM 编造 +**修复 Query Cache**: -### 二、分阶段优化策略 +1. 修复 GET/SET 键不匹配——此前 SET 使用 `doc_hash` 分支,GET 使用 `kb_version` 分支,两端永远不匹配,命中率始终为 0% +2. 修复 `CACHE_MIN_SCORE = 0.3` 阈值过高——ChromaDB 余弦距离经 `1-dist` 后得分约 0.03-0.06,远低于 0.3,导致几乎不写入缓存 -#### 1. 检索前:优化查询质量 +**集成语义缓存**:将 FAISS 语义缓存从已删除的备用路径移植到生产 `/rag` 端点,在意图分析后、混合检索前检查,命中时跳过整个检索+生成流程。验证结果:命中率 66.7%,92 倍加速。 -- **智能查询重写**:口语化表述 → 精准检索术语 -- **复杂问题分解**:对比/推理类查询自动拆分为子查询 -- **意图分析**:LLM 双层判断,避免不必要的检索 +### v3.2 — 模型/Reranker/管线更新 -#### 2. 检索中:提升召回精准度 +引入云端 qwen3-rerank、ONNX 加速、动态 RRF 权重等。 -- **多路召回与融合**:向量 + BM25 + FAQ + 图片独立召回 -- **动态 RRF 权重**:查询类型/长度驱动的权重调整 -- **MMR 去重**:Rerank 后进一步精炼,平衡相关性与多样性(召回100 → Rerank取15 → MMR精炼) -- **Rerank 重排**:云端 qwen3-rerank 精排,置信度门控过滤低质量结果 +--- -#### 3. 检索后:质量评估与自我迭代 +## 十四、未来规划 -- **多维质量评估**:相关性/完整性/准确性/覆盖面 -- **推理反思**:检查推理过程中未验证的假设 -- **分层补救**:低置信度 → 查询重写 → 网络搜索 +### Redis 缓存外部化 -### 三、系统级优化 +当前四层缓存均为进程内内存存储,在多 Worker / 多实例部署时无法共享。已规划 Redis 迁移方案(详见 `reports/redis_migration_plan.md`),核心设计: -#### 1. 避免"循环检索"陷阱 +- `RedisCacheManager` 提供与 `RAGCacheManager` 相同的接口 +- 通过 `REDIS_CACHE_URL` 环境变量启用,向后兼容 +- 语义缓存采用混合方案:FAISS 索引保持在进程内,缓存结果存储到 Redis +- Query Cache、Embedding Cache、Rerank Cache 全部迁移到 Redis -- 循环防护器(`loop_guard.py`):最多允许 N 次重写检索 -- 置信度递增检查:连续两次无提升则终止 +### 可选能力接入 -#### 2. 平衡智能性与效率 +`core/` 目录下仍保留以下独立模块,当前未接入生产流程,可按需启用: -- 轻量级决策模型:意图分析使用低温度、少 token 的 LLM 调用 -- 三层缓存:Query Cache + Embedding Cache + Rerank Cache -- 语义缓存:相似查询复用结果(threshold=0.92) -- LLM 预算控制:`MAX_LLM_CALLS_PER_QUERY = 2` +- `confidence_gate.py`:置信度门控,基于 Reranker 分数判断检索质量 +- `quality_assessor.py`:多维质量评估(相关性/完整性/准确性/覆盖面) +- `reasoning_reflector.py`:推理反思,检查未验证的假设 +- `loop_guard.py`:循环防护,防止重复检索 -#### 3. 安全与可解释性 +--- -- 证据溯源:引用标注 + 来源编号 -- 思维链展示:`log_trace` 记录推理过程 -- 安全护栏:输入验证 + 输出过滤 + 权限控制 - -### 四、学术前沿 - -1. **RAG-Gym**:三维度系统优化(提示工程 + 执行器调优 + 评判器训练) -2. **过程监督 vs 结果监督**:细粒度过程奖励显著提升训练效率 -3. **Re2Search**:推理反思机制,F1 score 提升 10%+ - -### 参考资料 +## 参考资料 1. Xiong, G., et al. (2025). RAG-Gym: Systematic Optimization of Language Agents for Retrieval-Augmented Generation. arXiv:2502.13957 2. Zhang, W., et al. (2025). Process vs. Outcome Reward: Which is Better for Agentic RAG Reinforcement Learning. arXiv:2505.14069 -3. Agentic RAG 实战指南:从查询重写到多步重查全掌握。火山引擎 ADG 社区 diff --git a/docs/开发与系统模块说明.md b/docs/开发与系统模块说明.md index 58edfa4..b699923 100644 --- a/docs/开发与系统模块说明.md +++ b/docs/开发与系统模块说明.md @@ -444,7 +444,7 @@ Query Rewriting: "它" → "出差补助" - [后端对接规范.md](./后端对接规范.md) - API 接口规范(主要) - [数据库设计文档.md](./数据库设计文档.md) - 数据库结构 -- [Agentic_RAG完整指南.md](./Agentic_RAG完整指南.md) - Agentic RAG 详解 +- [RAG系统完整指南.md](./RAG系统完整指南.md) - RAG 系统架构与缓存详解 ---