Files
rag/docs/Agentic_RAG完整指南.md
lacerate551 cb75b9b274 fix(boundary): 修复多库边界问题、版本管理及删除清理
多库检索与存储修复:
- RRF 融合去重改用 (collection, chunk_id) 复合键,修复同名文件结果被吞
- DocStore 存储路径加 collection 前缀,修复跨库同名切片数据覆盖
- search_multiple 去重改用复合键
- chunk_id 解析改用 rsplit 兼容下划线文件名

上传与版本管理修复:
- 同名文件上传改为覆盖模式,自动清理旧切片
- 修复首次上传不创建版本记录
- 修复覆盖上传版本号回退到 v1
- sync ADDED 分支改用动态版本号生成
- _generate_version_id 改为基于全部版本递增
- 废止/恢复操作同步 SQLite 版本记录
- mark_document_as_superseded 改为仅更新 SQLite

删除清理修复:
- 删除文档时同步清理 SQLite 版本记录和变更日志
- 删除向量库时同步清理该库所有版本记录
- cleanup 改为清理 SQLite 记录而非 ChromaDB

测试:
- test_version_management.py: 27 条版本管理单元测试
- test_edge_cases.py: 28 条边界用例测试
- test_upload_dedup.py: 5 条上传去重测试
- e2e_risk_test.py: 27 条端到端风险测试

文档:
- 新增风险边界问题修复注意事项.md(面向后端的对接文档)
- 新增向量库边界风险分析.md
- 更新多篇现有文档
2026-06-04 23:58:44 +08:00

43 KiB
Raw Blame History

Agentic RAG 完整指南

版本: v3.2(模型/Reranker/管线更新) 生产入口: api/chat_routes.py::rag()core/engine.py(轻量编排,当前启用) 备用编排: core/agentic.py::AgenticRAG.process() + 8 个 Mixin完整决策循环未接线 最后更新: 2026-06-04

⚠️ 项目存在两套编排,生产 /rag 走的不是 AgenticRAG——详见下方「一·五、两套编排路径」。

一、功能概述

Agentic RAG 是一个智能问答系统,基于 Mixin 模式组合 8 个功能模块,具备以下核心能力:

功能 说明 Mixin 模块
意图分析 LLM 驱动的查询改写 + 双层判断(是否需要检索) IntentAnalyzer(独立模块)
查询重写 口语化→专业术语、实体补全、指代消解 QueryRewriteMixin
混合检索 向量检索 + BM25 + RRF 融合 + Rerank 重排 SearchMixinRAGEngine
多源融合 知识库 + 网络搜索,智能处理冲突 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.pyrag()generate() core/agentic.pyAgenticRAG.process()
编排者 chat_routes 自己的流程代码 AgenticRAG8 个 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.pyquality_assessor.pyreasoning_reflector.pyloop_guard.py 以及 8 个 agentic_* Mixin 只被 core/agentic.py import;而 AgenticRAG 实例虽在 api/__init__.py:90 启动时创建,但其唯一读取入口 _get_agentic_rag() 零调用
  • 这不是死代码可删AgenticRAG 在启动时被实例化(直接删会导致启动报错),且 _extract_rich_mediascripts/test_rag_image_recall.py 使用。它是「一套更重、更完整、目前未启用的 Agentic 决策闭环」,未来可选择接入。

🔬 如何验证「系统现在到底走哪套流程」

方法 1看开发环境 SSE 调试事件(最直接)

/ragIS_DEV=True 时会发出一串只有 chat_routes 编排才会发的调试事件,收到它们即证明走的是生产路径:

# 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 事件序列,生产路径会依次出现这些 typeAgenticRAG.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 timingsourcescitations
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.pyAgenticRAG.process() 第一行加 logger.warning("AgenticRAG.process CALLED"),重启后发 /rag 请求——该日志不会触发,即证明生产不走 AgenticRAG

方法 4静态确认调用链

grep -rn "_get_agentic_rag()" --include="*.py" .   # 仅定义,无调用者 → AgenticRAG 实例未被请求使用
grep -rn "\.process(" --include="*.py" api/         # /rag、/chat 均无 .process() 调用

二、系统架构

⚠️ 注意:下方 2.1「整体架构图」描绘的是备用路径 AgenticRAG.process() 的完整设计;当前生产 /rag 的实际流程见上方「一·五」及本节 2.3「生产 /rag 实际流程」。

2.1 整体架构图

┌─────────────────────────────────────────────────────────────────────┐
│                          用户输入                                    │
└────────────────────────────┬────────────────────────────────────────┘
                             ↓
┌─────────────────────────────────────────────────────────────────────┐
│                    意图分析 (IntentAnalyzer)                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐             │
│  │  改写查询    │  │  双层判断    │  │  子查询拆分  │             │
│  │  (指代消解)  │  │  (是否检索)  │  │  (对比/推理) │             │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘             │
└─────────┼──────────────────┼──────────────────┼─────────────────────┘
          ↓                  ↓                  ↓
    ┌──────────┐    ┌──────────────────────────────────────────┐
    │ 直接回答 │    │           AgenticRAG.process()             │
    │ (LLM)    │    │  1. 元问题检查                            │
    └──────────┘    │  2. 查询重写 (QueryRewriteMixin)         │
                    │  3. 知识库检索 (RAGEngine.search_knowledge)│
                    │  4. 上下文压缩 (ContextMixin)             │
                    │  5. 网络搜索 (SearchMixin, 可选)         │
                    │  6. 图谱检索已废弃graph/ 目录已清空)         │
                    │  7. 融合答案生成 (AnswerMixin)            │
                    │  8. 幻觉验证 (AnswerMixin)               │
                    │  9. 富媒体提取 (RichMediaMixin)           │
                    │  10. 引用标注 (CitationMixin)             │
                    └────────────────────┬─────────────────────┘
                                         ↓
┌─────────────────────────────────────────────────────────────────────┐
│                        检索层 (RAGEngine)                            │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐             │
│  │  向量检索    │  │  BM25 检索   │  │  FAQ 独立召回 │             │
│  │  (语义匹配)  │  │ (关键词匹配) │  │  (精准命中)   │             │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘             │
│         └─────────────────┼─────────────────┘                      │
│                           ↓                                         │
│                   ┌──────────────┐                                  │
│                   │  RRF 融合    │  ← 动态权重(查询类型/长度驱动)│
│                   └──────┬───────┘                                  │
│                          ↓                                          │
│  ┌───────────┐  ┌──────────────┐  ┌──────────────┐               │
│  │ 废止过滤  │→ │  Rerank 重排 │→ │  MMR 去重    │               │
│  └───────────┘  │  (云端API)   │  └──────┬───────┘               │
│                 └──────┬───────┘          ↓                       │
│  ┌───────────┐  ┌──────────────┐  ┌──────────────┐               │
│  │ FAQ 加权  │→ │  黑名单过滤  │→ │  时间衰减    │               │
│  └───────────┘  └──────────────┘  └──────┬───────┘               │
│                                            ↓                       │
│  ┌───────────────┐  ┌──────────────┐                              │
│  │ 上下文扩展    │→ │ 自适应 TopK  │                              │
│  └───────────────┘  └──────────────┘                              │
└─────────────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────────────┐
│                    答案生成 (LLM 流式)                               │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  整合多源信息 + 标注来源 + 处理冲突 + 引用编号 + SSE 流式输出 │ │
│  └────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘

2.2 Mixin 组合架构

class AgenticRAG(
    QueryRewriteMixin,    # 查询重写:口语化→专业术语、实体补全
    SearchMixin,          # 检索功能:网络搜索
    AnswerMixin,          # 答案生成:融合回答、幻觉验证
    CitationMixin,        # 引用处理:来源标注、引用编号
    RichMediaMixin,       # 富媒体:图片/表格提取
    QualityMixin,         # 质量评估:多维评估
    ContextMixin,         # 上下文处理:压缩、过滤
    MetaQuestionMixin     # 元问题:文件列表、权限查询
):
    ...

注:以上 2.1 / 2.2 是 AgenticRAG(备用路径)的设计。当前生产 /rag 不实例化走这条链,实际流程见下方 2.3。

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: finishanswer + sources + citations + images + timing
    └─[异常] 发 SSE: error

与备用路径AgenticRAG.process的差异:生产路径没有置信度门控、多维质量评估、推理反思、循环防护、幻觉验证这几步——它们只存在于 AgenticRAG.process()


三、意图分析流程

3.1 IntentAnalyzer 双层判断

意图分析由 core/intent_analyzer.pyIntentAnalyzer 类完成,采用 LLM 驱动 的双层判断:

用户输入 + 对话历史
    ↓
┌─────────────────────────────────────────────┐
│        IntentAnalyzer.analyze()              │
│                                              │
│  Step 1: 查询改写                            │
│    - 指代消解:"那请假呢" → "出差相关请假流程"│
│    - 省略补全:"标准" → "差旅报销标准"        │
│    - 语义缓存:相似问题复用结果               │
│                                              │
│  Step 2: 双层判断                            │
│    - 第一层:历史上下文是否可答?              │
│    - 第二层:是否需要外部知识(检索)?        │
│                                              │
│  Step 3: 子查询拆分(对比/推理类)            │
│    - "年假和调休的区别" → ["年假规定", "调休规定"]│
└─────────────────────────────────────────────┘
    ↓
    IntentAnalysis:
      - rewritten_query: 改写后的查询
      - use_context: 是否使用上下文
      - need_retrieval: 是否需要检索
      - sub_queries: 子查询列表
      - intent: factual/comparison/reasoning/instruction/other

3.2 QueryClassifier 规则分类

core/query_classifier.py 提供无 LLM 调用的快速规则分类:

查询类型 说明 示例
META 元问题(文件列表、权限) "有哪些文档?"
REALTIME 实时信息 "今天天气"
SIMPLE 简单单属性查询 "出差标准"
FACT 事实查询 "差旅补贴标准是多少"
ENUMERATION 枚举/清单/条款 "严禁哪些情形"
COMPARISON 比较分析 "年假和调休的区别"
PROCESS 流程指引 "如何申请调岗"
FILE_SPECIFIC 特定文件内查询 "xxx.pdf中有哪些图片"

四、检索管线详解

4.1 完整检索流程

search_knowledge(query, top_k=30)
  │
  ├─ 1. 查询缓存检查 → 命中则直接返回
  │
  ├─ 2. 子查询并行检索(如有 sub_queries
  │     └─ 各子查询独立检索后合并去重
  │
  ├─ 3. 查询拆分QueryDecomposer
  │     └─ 对比/推理类查询自动拆分
  │
  ├─ 4. 查询扩展QueryExpansion
  │     └─ 同义词/语义扩展threshold=0.8
  │
  ├─ 5. 多知识库检索USE_MULTI_KB=True
  │     ├─ 各向量库并行检索ThreadPoolExecutor
  │     ├─ 每个库: 向量检索 + BM25 + 图片独立召回
  │     ├─ FAQ 集合独立召回
  │     └─ RRF 融合
  │
  ├─ 6. 废止切片过滤status != "active"
  │
  ├─ 7. 章节过滤(查询提到章节时优先匹配)
  │
  ├─ 8. ★ Rerank 重排 ★(云端 DashScope qwen3-rerank 或本地 BGE
  │      └─ rerank_results(query, results, top_k)
  │      └─ 由 RERANK_BACKEND 控制local/cloud/fallback
  │
  ├─ 9. MMR 去重
  │     ├─ 语义向量版MMR_USE_EMBEDDING=True
  │     └─ 文本 Jaccard 版MMR_USE_EMBEDDING=False生产推荐
  │
  ├─ 10. FAQ 分数加权Score Boosting
  │
  ├─ 11. 黑名单过滤(负反馈降权)
  │
  ├─ 12. 时间衰减Time Decay
  │
  ├─ 13. 上下文扩展Rerank 后,补充相邻切片)
  │
  ├─ 14. 自适应 TopK根据置信度调整返回数量
  │
  └─ 15. 缓存写入 → 返回结果

4.2 混合检索代码示例

# 向量检索(语义相似)
vector_results = collection.query(query_embeddings=[query_vector], n_results=recall_k)

# BM25 检索(关键词匹配)
bm25_results = bm25_index.search(query, top_k=recall_k)

# FAQ 独立召回
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"]}})

# RRF 融合(动态权重)
fused = reciprocal_rank_fusion([vector_results, bm25_results], weights=[vector_w, bm25_w])

# Rerank 重排(云端 DashScope qwen3-rerank 或本地 BGE
reranked = rerank_results(query, fused, top_k=15)

# MMR 去重
mmr_results = mmr_rerank(query_emb, reranked, top_k=30, lambda_param=0.5)

4.3 RRF 融合算法

RRF分数 = Σ (权重 / (k + 排名位置))

示例k=60
文档A: 向量排名1 → 0.5/(60+1) = 0.00820
       BM25排名3 → 0.5/(60+3) = 0.00794
       总分 = 0.01614

动态权重策略:
- 短查询(<15字: BM25权重↑ (0.6), 向量权重↓ (0.4)
- 长查询(>50字: 向量权重↑ (0.7), BM25权重↓ (0.3)
- 查询类型驱动: FACT→BM25优先, PROCESS→向量优先

4.4 Rerank 重排

后端: 支持三种模式,由 RERANK_BACKEND 环境变量控制

RERANK_BACKEND 说明
"cloud" 仅使用云端 DashScope qwen3-rerank API
"local" 仅使用本地 BAAI/bge-reranker-baseCrossEncoder / ONNX
"fallback" 优先云端,失败时自动回退本地(推荐生产环境)

云端 Reranker推荐:

# config.py
RERANK_BACKEND = os.getenv("RERANK_BACKEND", "local")       # local / cloud / fallback
RERANK_CLOUD_MODEL = "qwen3-rerank"                          # DashScope 云端 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                                    # 云端请求超时(秒)

CloudReranker 类(core/engine.py)封装 DashScope 的 /compatible-api/v1/reranks 接口,提供与本地 CrossEncoder.predict() / ONNXReranker.predict() 一致的调用接口。

本地 Reranker备选:

def rerank_results(self, query, results, top_k=5):
    pairs = [(query, doc) for doc in results['documents'][0]]
    scores = self.reranker.predict(pairs)  # CrossEncoder / ONNXReranker / CloudReranker
    sorted_indices = np.argsort(scores)[::-1]
    # 返回 top_k 个最高分结果

调用位置: core/engine.pysearch_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/confidence_gate.py 基于 Reranker 分数判断检索结果质量:

检索结果 → Reranker 计算置信度 → 阈值判断 → 决策
                                      │
                    ┌─────────────────┼─────────────────┐
                    ↓                 ↓                 ↓
               PASS (≥0.4)     REWRITE (0.2~0.4)   WEB_SEARCH (<0.2)
               继续生成        查询重写            网络搜索补救

阈值配置:

  • PASS_THRESHOLD = 0.2: 通过阈值(低于此值需要补救)
  • GOOD_THRESHOLD = 0.4: 良好阈值(高质量结果)
  • EXCELLENT_THRESHOLD = 0.7: 优秀阈值

六、AgenticRAG 主流程

6.1 process() 方法

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() 引用标注

七、API 调用方式

7.1 SSE 流式问答(主要接口)

curl -X POST http://localhost:5001/rag \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer mock-token-admin" \
  -d '{
    "query": "出差补助标准是什么?",
    "chat_history": []
  }'

响应格式: SSEServer-Sent Events流式返回

event: token
data: {"text": "根据"}

event: token
data: {"text": "规定"}

...

event: finish
data: {"answer": "完整答案", "sources": [...], "citations": [...], "images": [...], "duration_ms": 3200}

7.2 代码调用

from core.engine import get_engine

# 初始化引擎
engine = get_engine()

# 检索
result = engine.search_knowledge("出差补助标准是什么?", top_k=10)

# 流式生成答案
for token in engine.generate_answer_stream(query, context, history=history):
    print(token, end="", flush=True)

7.3 AgenticRAG 调用

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']}")

八、配置说明

8.1 LLM 配置

# config.py
DASHSCOPE_API_KEY = "your-api-key"          # 通义千问 API
DASHSCOPE_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"
DASHSCOPE_MODEL = "qwen3.6-flash"           # 文本生成模型(主力 LLM
INTENT_MODEL = "qwen-turbo"                 # 意图分析模型(轻量快速)
VLM_MODEL = "qwen-vl-plus"                  # 视觉语言模型(图片描述)
RAG_CHAT_MODEL = "qwen3.6-flash"            # RAG 对话模型

8.2 检索参数

# 混合检索
USE_MULTI_KB = True              # 多向量库模式
USE_HYBRID_SEARCH = True         # 向量 + BM25 混合检索
VECTOR_WEIGHT = 0.5              # 向量检索权重
BM25_WEIGHT = 0.5                # BM25 检索权重
RAG_SEARCH_TOP_K = 30            # 最终返回结果数
RAG_SEARCH_CANDIDATES = 100      # 候选池大小
RECALL_MULTIPLIER = 3            # 候选池最小倍数

# 重排序
USE_RERANK = True                # 启用重排序
RERANK_BACKEND = "local"         # "local"=本地模型, "cloud"=云端API, "fallback"=优先云端失败回退本地
RERANK_CLOUD_MODEL = "qwen3-rerank"  # 云端 Rerank 模型DashScope API
RERANK_CANDIDATES = 20           # 送入重排序的候选数
RERANK_TOP_K = 15                # 重排序后保留数
RERANK_USE_ONNX = True           # ONNX 加速(仅本地模式,环境变量控制,默认开启)

# RRF 融合
RRF_K = 60                       # RRF 常数
DYNAMIC_RRF_ENABLED = True       # 动态权重

# MMR 去重
MMR_ENABLED = True
MMR_USE_EMBEDDING = False        # True=语义向量False=文本Jaccard相似度生产推荐
MMR_TOP_K = 30                   # MMR 保留数
MMR_LAMBDA = 0.5                 # 相关性 vs 多样性权衡

8.3 缓存配置

# 查询结果缓存
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 设备配置

DEVICE = "auto"                  # auto / cuda / cpu / cuda:0
EMBEDDING_DEVICE = DEVICE        # 向量模型设备
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元问题处理
├── bm25_index.py            #   BM25Index关键词检索
├── chunker.py               #   文本分块器
├── mmr.py                   #   MMR 去重(语义向量版 + 文本 Jaccard 版)
├── query_classifier.py      #   QueryClassifier规则快速分类
├── intent_analyzer.py       #   IntentAnalyzerLLM 意图分析)
├── 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            #   循环防护
├── llm_budget.py            #   LLM 调用预算控制
├── llm_utils.py             #   LLM 调用工具函数
├── semantic_cache.py        #   语义缓存
├── cache.py                 #   三层缓存管理器Query/Embedding/Rerank
├── status_codes.py          #   状态码定义
└── constants.py             #   公共常量

knowledge/                   # 知识库管理
├── manager.py               #   KnowledgeBaseManager7 个 Mixin 组合)
├── router.py                #   KnowledgeBaseRouter智能知识库路由
├── sync.py                  #   KnowledgeSyncService文件变更监控+增量向量化)
├── base.py                  #   知识库基类定义
├── collection.py            #   集合CollectionCRUD 操作
├── document.py              #   文档管理(上传/删除/状态流转)
├── document_versions.py     #   文档版本管理
├── chunk.py                 #   分块操作(创建/查询/更新)
├── index.py                 #   索引管理BM25 构建/重建)
├── search.py                #   知识库内搜索
├── processing.py            #   文档处理流水线(解析→分块→向量化)
├── permission.py            #   权限控制(角色/部门级访问控制)
├── lazy_enhance.py          #   延迟增强(按需生成摘要/关键词)
└── cleanup.py               #   清理操作(孤立切片/过期数据)

api/                         # API 路由层
├── __init__.py              #   create_app() 工厂
├── chat_routes.py           #   /chat, /rag(SSE), /search
├── kb_routes.py             #   /collections
├── document_routes.py       #   /documents/*
├── sync_routes.py           #   /sync
├── session_routes.py        #   /sessions会话管理
├── image_routes.py          #   /images图片访问/上传)
├── feedback_routes.py       #   /feedback用户反馈/点赞/踩)
├── auth_routes.py           #   /auth认证/登录/Token
├── audit_routes.py          #   /audit审计日志
└── response_utils.py        #   响应工具函数

services/                    # 业务服务层
├── session.py               #   会话管理服务
├── feedback.py              #   反馈处理服务
└── outline.py               #   大纲生成服务

graph/                       # 已清空Graph RAG 不再使用)

auth/                        # 认证与安全
├── gateway.py               #   API 网关认证
└── security.py              #   安全工具Token 验证/权限检查)

repositories/                # 数据持久层
├── session_repo.py          #   会话仓储接口
├── sqlite_session_repo.py   #   SQLite 会话仓储实现
└── stateless_session_repo.py #  无状态会话仓储

parsers/                     # 文档解析器
├── mineru_parser.py         #   MinerU PDF/DOCX/PPTX 解析
├── excel_parser.py          #   Excel 解析
├── txt_parser.py            #   纯文本解析
├── image_extractor.py       #   图片提取器(从文档中提取/处理图片)
└── pdf_mineru.py            #   MinerU PDF 辅助入口

exam_pkg/                    # 出题系统
├── api.py                   #   出题/批阅 API
├── generator.py             #   试题生成Dify 工作流)
├── grader.py                #   试卷批阅
├── manager.py               #   出题管理器(核心业务逻辑)
└── local_db.py              #   本地数据库SQLite

tools/                       # 运维/分析工具
├── export_chunks.py         #   导出切片
├── llm_evaluator.py         #   LLM 评估器
├── chunk_analyzer.py        #   切片质量分析
├── chunk_metrics.py         #   切片指标统计
├── chunk_report.py          #   切片报告生成
├── clean_vector_store.py    #   清理向量库
├── rebuild_pdf_vectors.py   #   重建 PDF 向量
└── upload_test_files.py     #   上传测试文件

deploy/                      # 部署配置
├── Dockerfile               #   开发环境 Docker
├── Dockerfile.prod          #   生产环境 Docker
├── docker-compose.yml       #   开发环境编排
├── docker-compose.prod.yml  #   生产环境编排
├── nginx.conf               #   Nginx 反向代理配置
├── gunicorn.conf.py         #   Gunicorn WSGI 配置
└── wsgi.py                  #   WSGI 入口

config/                      # 运行时配置
└── banned_words.txt         #   敏感词库

十、与传统 RAG 对比

特性 传统 RAG Agentic RAG (当前)
意图判断 IntentAnalyzer LLM 双层判断
查询改写 口语化→专业术语 + 实体补全 + 指代消解
检索方式 单一向量检索 向量 + BM25 + FAQ + 图片独立召回
融合算法 RRF 动态权重融合
去重 MMR 语义去重
重排序 云端 qwen3-rerank API支持本地 BGE 回退)
问题分解 自动拆分对比/推理类查询
闲聊处理 意图分析自动判断
网络搜索 可选支持Serper API
知识图谱 可选支持Neo4j已废弃graph/ 目录已清空)
幻觉验证 基于参考信息的答案验证
置信度门控 Reranker 分数驱动,低分触发补救
缓存 三层缓存 + 语义缓存
自适应 TopK 固定 top_k 根据置信度动态调整
上下文理解 多轮对话 + 历史上下文
响应时间 ~2秒 ~3-8秒取决于 Rerank + LLM

十一、Rerank 性能分析

11.1 Rerank 调用路径

Rerank 在系统中有 两个独立调用路径

路径 位置 说明
主检索管线 engine.rerank_results() RRF 融合后、MMR 去重前执行,对候选重排取 top_k
置信度门控 confidence_gate._compute_scores() 直接调用 reranker.predict(),可能重复推理

11.2 性能瓶颈

瓶颈 严重程度 说明
Rerank 缓存命中率偏低 🟡 rerank_results() 已正确调用缓存读写,但缓存 key 基于 query + sorted(doc_ids) 精确匹配RRF 融合产出稍有不同就无法命中
置信度门控重复推理 🟡 同一 query+documents 可能被 Rerank 两次(当前仅备用路径使用,暂未影响生产)
无性能计时 🟡 已修复:rerank_results() 现返回 _rerank_time_ms 计时字段
查询分类器策略未生效 🟢 QueryClassifier 定义的差异化 rerank 参数未传递到引擎

11.3 Rerank 配置参数

配置项 默认值 说明
USE_RERANK True 总开关
RERANK_BACKEND "local" 后端选择:local=本地模型, cloud=云端API, fallback=优先云端失败回退本地
RERANK_CLOUD_MODEL "qwen3-rerank" 云端 Rerank 模型名称DashScope API
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_CANDIDATES 20 送入 Rerank 的候选数
RERANK_TOP_K 15 Rerank 后保留数
RERANK_USE_ONNX True(环境变量默认) ONNX 加速开关(仅本地模式)
RERANK_DEVICE 跟随 DEVICE 设备选择(仅本地模式)
RERANK_THRESHOLD 0.3 上下文过滤阈值
RERANK_CACHE_ENABLED True 缓存开关(已在 rerank_results() 中使用)

十二、最佳实践

12.1 何时使用 Agentic RAG

推荐使用

  • 复杂问题需要多轮检索
  • 用户表达模糊需要改写
  • 需要区分闲聊和知识问答
  • 需要多轮对话记忆
  • 需要引用来源和幻觉验证

不推荐使用

  • 简单明确的问题(用 /search 接口更快)
  • 对响应时间极度敏感的场景

12.2 性能优化

# 减少迭代次数
rag = AgenticRAG(max_iterations=2)

# 禁用网络搜索
rag = AgenticRAG(enable_web_search=False)

# ONNX 加速默认已开启;如有兼容性问题可关闭(环境变量)
# RERANK_USE_ONNX=false

# 使用轻量 MMR文本相似度代替语义向量
# config.py: MMR_USE_EMBEDDING = False

12.3 调试技巧

# 查看检索调试信息
result = engine.search_knowledge("问题", top_k=10)
debug = result.get('_debug', {})
for step in debug.get('steps', []):
    print(f"步骤: {step['name']}, 详情: {step}")

附加篇Agentic RAG 深入优化与工作机制

一、Agentic RAG 的核心架构

Agentic RAG 构建了动态的决策闭环,核心组件包括:

  • 意图分析器LLM 驱动的双层判断,替代硬编码规则
  • 查询重写器:口语化→专业术语、实体补全、指代消解
  • 混合检索引擎:向量 + BM25 + FAQ + 图片独立召回 + RRF 融合
  • MMR 去重平衡相关性与多样性Rerank 后进一步精炼结果
  • Rerank 重排:云端 qwen3-rerank API 精确排序,支持本地 BGE 回退
  • 置信度门控Reranker 分数驱动,低分触发补救流程
  • 幻觉验证:基于参考信息验证答案,防止 LLM 编造

二、分阶段优化策略

1. 检索前:优化查询质量

  • 智能查询重写:口语化表述 → 精准检索术语
  • 复杂问题分解:对比/推理类查询自动拆分为子查询
  • 意图分析LLM 双层判断,避免不必要的检索

2. 检索中:提升召回精准度

  • 多路召回与融合:向量 + BM25 + FAQ + 图片独立召回
  • 动态 RRF 权重:查询类型/长度驱动的权重调整
  • MMR 去重Rerank 后进一步精炼平衡相关性与多样性召回100 → Rerank取15 → MMR精炼
  • Rerank 重排:云端 qwen3-rerank 精排,置信度门控过滤低质量结果

3. 检索后:质量评估与自我迭代

  • 多维质量评估:相关性/完整性/准确性/覆盖面
  • 推理反思:检查推理过程中未验证的假设
  • 分层补救:低置信度 → 查询重写 → 网络搜索

三、系统级优化

1. 避免"循环检索"陷阱

  • 循环防护器(loop_guard.py):最多允许 N 次重写检索
  • 置信度递增检查:连续两次无提升则终止

2. 平衡智能性与效率

  • 轻量级决策模型:意图分析使用低温度、少 token 的 LLM 调用
  • 三层缓存Query Cache + Embedding Cache + Rerank Cache
  • 语义缓存相似查询复用结果threshold=0.92
  • LLM 预算控制:MAX_LLM_CALLS_PER_QUERY = 2

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 社区