Files
rag/docs/RAG性能分析报告.md
lacerate551 b966be5417 fix: 修正 RAG性能分析报告中的错误和遗漏
- INTENT_MAX_TOKENS 2048 不再标注为'浪费',推理模型思考链需 ~1000 token
- 删除 P2 建议'INTENT_MAX_TOKENS 降低 2048→512'(推理模型不可降)
- P0 优化建议标注 deepseek-v4-flash 额度已尽,需寻找替代轻量模型
- Rerank 配置补充云端 xop3qwen8breranker(讯飞云)信息
- §6.4 休眠模块:AgenticRAG 类已在 v4.0 删除,更新描述
- 阶段 7 补充两管线断裂问题:chart_contexts 降门槛、P0 安全网、答案后过滤鸡生蛋问题
- 阶段 9 补充推理模型 content 为空问题和 reasoning_content 回退机制
- 阶段 10 图片后过滤补充 _filter_images_by_answer 函数名
2026-06-22 13:08:14 +08:00

461 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RAG 知识库问答系统 — 性能分析报告
> 基于 15 题基准测试 + 代码静态分析 | 2026-06-22
>
> 基准测试环境:本地 deepseek-v4-flash 模型,服务器使用 mimo-v2.5 时延迟特征可能不同
---
## 一、完整请求管线总览
一次 `/rag/stream` 请求经历 **10 个串行阶段**每个阶段必须等待前一阶段完成后才能开始。SSE 流式响应在 LLM 生成阶段才开始产出用户可见内容,前 8 个阶段用户感知为"等待中"。
```
用户提问
├─ 0. 输入校验 & 安全过滤 ~1ms
├─ 1. 意图分析LLM 调用) ~3500-5000ms ◄── 瓶颈 #1
├─ 2. 语义缓存查找 ~50-200ms
├─ 3. 混合检索(向量+BM25+图片) ~200-600ms
├─ 4. RRF 融合 + Rerank ~300-800ms
├─ 5. MMR 去重 ~5-20ms
├─ 6. 救援管线3层 ~5-30ms
├─ 7. 图片选择 + VLM 增强 ~10-50ms
├─ 8. 上下文构建 ~5-15ms
├─ 9. LLM 流式生成 ~5000-15000ms ◄── 瓶颈 #2
└─ 10. 后处理(对齐/引用/会话存储) ~50-200ms
```
**总耗时**:典型请求 **10-20 秒**(含流式输出时间),其中 LLM 调用占 **80%以上**
---
## 二、各阶段详细分析
### 阶段 1意图分析 — 最大瓶颈之一
**位置**`core/intent_analyzer.py``analyze()` 方法
**功能**:一次非流式 LLM 调用,同时完成问题改写、指代消解、意图分类、子查询生成。
**执行流程**
```
精确缓存查找Dict, O(1)
↓ 未命中
语义缓存查找FAISS, cosine ≥ 0.92
↓ 未命中
LLM 调用非流式JSON 输出) ◄── 主要耗时
写入双层缓存 + 返回 IntentAnalysis
```
**关键参数**
| 参数 | 服务器值 | 说明 |
|------|----------|------|
| INTENT_MODEL | mimo-v2.5 | 与主模型共用,无法使用轻量模型 |
| INTENT_TEMPERATURE | 0.1 | 低温度保证确定性输出 |
| INTENT_MAX_TOKENS | 2048 | 推理模型思考链 ~1000 token + JSON 输出 ~200 token配置合理 |
| INTENT_HISTORY_WINDOW | 6 | 取最近 6 条历史消息 |
| 精确缓存上限 | 500 条 | 内存 Dict重启清零 |
| 语义缓存阈值 | 0.92 | 余弦相似度,过于严格则命中率低 |
**实测耗时**deepseek-v4-flash3500-5000ms。mimo-v2.5 因模型更大,预期 **4000-7000ms**
**瓶颈分析**
1. **非流式调用**:必须等待完整 JSON 响应才能解析,无法提前返回。这是所有阶段中唯一必须完整等待的 LLM 调用。
2. **模型过重**:意图分析本质是分类+改写任务,不需要 mimo-v2.5 这样的推理大模型。换用轻量非推理模型可减少 30-40% 延迟,但百炼 deepseek-v4-flash 额度已尽,需寻找其他可用轻量模型。
3. **MAX_TOKENS 配置合理**mimo-v2.5 是推理模型,思考链消耗 ~1000 tokenJSON 输出 ~200 token2048 是必要预算(此前 1024 导致 content 为空、全部输出进入 reasoning_content 引发解析错误)。
4. **缓存命中率低**:精确缓存 key 包含历史上下文,同一用户连续问不同问题时不会命中;语义缓存阈值 0.92 过于严格。
### 阶段 2语义缓存查找
**位置**`core/semantic_cache.py`
**功能**FAISS 向量索引,用 embedding 余弦相似度匹配历史问答,命中则跳过整个检索+生成流程。
**查找逻辑**
1.`"{query}|{collections}"` 编码为向量
2. FAISS IndexFlatIP 搜索 top-1向量已归一化内积=余弦)
3. 阈值 ≥ 0.92 → 命中
4. 验证 `cache_type == "rag_answer"`(区分意图缓存和问答缓存)
**性能**50-200ms主要是 embedding 编码耗时FAISS 搜索本身 <1ms
**瓶颈分析**:此阶段本身不慢,但受限于 0.92 的高阈值,实际命中率较低。同一个问题的不同表述方式(如"智启平台支持哪些数据源" vs "智启能对接什么数据库")余弦相似度可能在 0.85-0.91 之间,无法命中。降低阈值会引入误命中风险。
### 阶段 3混合检索
**位置**`core/engine.py``search_knowledge()`
**功能**:三路并行召回 + RRF 融合
**三路召回**
| 召回路径 | 数量 | 后端 | 耗时 |
|----------|------|------|------|
| 向量检索 | recall_k = max(20, 30×3) = 90 | ChromaDB + bge-base-zh-v1.5 (CPU) | 100-300ms |
| BM25 关键词 | top_k=30 | rank_bm25 (jieba 分词) | 10-30ms |
| 图片独立召回 | n_results=5 | ChromaDB过滤 chunk_type | 20-50ms |
**RRF 融合**Reciprocal Rank Fusion
```
score = weight / (k + rank + 1)k = 60
动态权重(按查询长度自适应):
alpha = clamp((len(query) - 15) / 35, 0, 1)
vector_weight = 0.3 + 0.4 × alpha # 短查询 0.3,长查询 0.7
bm25_weight = 1.0 - vector_weight
```
**性能**:总计 200-600ms。Embedding 编码是主要耗时CPU 推理ChromaDB 查询本身很快。
**瓶颈分析**
1. **Embedding 在 CPU 上运行**bge-base-zh-v1.5 编码 90 个候选文档需要 100-200ms。GPU 可降至 10-30ms但当前服务器未配置 GPU。
2. **召回数量偏大**`recall_k=90` 意味着 embedding 编码量大。实际 Rerank 只取 20 个,多召回的 70 个是浪费。可降低 `RECALL_MULTIPLIER` 从 3 到 2。
3. **BM25 无瓶颈**纯内存计算jieba 分词+BM25 打分共 10-30ms。
### 阶段 4Rerank
**位置**`core/engine.py``rerank_results()`
**功能**CrossEncoder 精排,对融合后的候选重打分
**服务器配置**`RERANK_BACKEND = "local"`,使用 ONNX 格式的 bge-reranker-base。云端备选为 `xop3qwen8breranker`(讯飞云 API`RERANK_BACKEND = "cloud"``"fallback"` 时启用。
**流程**
1. 检查 Rerank 缓存MD5 of query + sorted_doc_ids
2. 缓存未命中 → 调用 ONNX 推理predict(query, doc) × N
3. 按分数排序,截取 `RERANK_TOP_K=15`
**性能**
- 缓存命中:<1ms
- 缓存未命中20 个候选300-800msCPU ONNX 推理)
**瓶颈分析**
1. **CPU 推理**CrossEncoder 是最重的 CPU 计算任务。每个 (query, doc) pair 需要一次 forward pass。20 个候选 × ~30ms/pair ≈ 600ms。
2. **max_length=512**:长文档截断到 512 token避免 OOM 但可能丢失信息。
3. **缓存效果好**:同一查询+同一文档集合直接命中缓存。但首次查询必经此阶段。
### 阶段 5MMR 去重
**位置**`core/mmr.py`
**当前配置**`MMR_USE_EMBEDDING = False`(文本模式),使用 jieba 词级 Jaccard 相似度
**算法**:贪心选择,每次取与已选集合最不相似且与查询最相关的候选
**性能**5-20ms纯文本计算无 embedding 开销)
**瓶颈分析****无瓶颈**。文本模式 Jaccard 非常轻量。
### 阶段 6救援管线3 层)
**位置**`api/chat_routes.py` 内部函数 + `core/engine.py`
**第一层 — BM25 发散救援**
- 当 BM25 top-3 中的文档被 Rerank 打到极低分时,恢复其分数到 `CLUSTER_RESCUE_FLOOR=0.06`
- 防止关键词完全匹配但语义分低的文档被丢弃
**第二层 — 词法匹配救援**
- 提取查询 bigram对每个低分文档计算 bigram 匹配率
- 匹配率 > 0.35 → 提升到 floor
- 附带邻居救援:同文档 ±8 个 chunk_index 的邻居也被提升
**第三层 — 章节聚类救援**engine.py `_section_cluster_boost`
-`(source, normalized_section)` 分组
- 检测"全灭章节":所有成员分数 < min_score
- 要求 ≥ 3 成员 + ≥ 2 种 chunk_type
- 提升最强聚类的 top-3 章节,每节最多 8 个 chunk
**性能**5-30ms纯规则计算
**瓶颈分析****无瓶颈**。但在复杂表格/对比查询中,救援管线的效果直接影响回答质量。
### 阶段 7图片选择
**位置**`api/chat_routes.py``select_images()`
**评分体系**(多层叠加):
| 评分因子 | 分值 | 条件 |
|----------|------|------|
| 图号精确匹配 | +10.0 | 查询提到"图2.3"且匹配 |
| 表号精确匹配 | +10.0 | 查询提到"表1"且匹配 |
| 关键词匹配 | +2.0/词 | jieba 分词后匹配,上限 +8.0 |
| 字符重叠 | +0.2/字 | 上限 +3.0 |
| 章节匹配 | +1.5/关键词 | 图片章节与查询关键词重叠 |
| 图表类型 | +2.0 (chart) / +1.0 (image) | chunk_type 加分 |
| 引用+章节匹配 | +8.0 + 5.0 | 被文本引用且章节/来源匹配 |
| VLM 相关性 < 0.3 | -3.0 | VLM 描述与查询不相关 |
| VLM 相关性 ≥ 0.5 | +2.0 | VLM 描述与查询相关 |
| 章节距离过远 | -5.0 | section_similarity < 0.3 且非引用 |
**动态预算**
| 场景 | MAX_IMAGES | MIN_SCORE |
|------|------------|-----------|
| 精确图号查询 | 2 | 5.0 |
| 检索结果含图片数据 | 5 | 2.0 |
| 文本中有图号引用 | 3 | 2.0 |
| 默认 | 2 | 3.0 |
**性能**10-50ms规则计算 + VLM 相关性检查)
**瓶颈分析**:图片选择本身不慢。瓶颈在 **VLM 描述生成**`knowledge/lazy_enhance.py`),需要调用 VLM 模型为每张图片生成文字描述。当前设计为懒加载(首次查询时生成并缓存),首次查询可能有 60s 超时。
**两管线断裂问题**`select_images()` 独立于文本上下文管线选择图片,但图片描述可能因 `min_score` 过滤未进入 LLM 上下文。具体问题链:
1. **chart_contexts 降门槛**CrossEncoder 对图片/图表打分系统性偏低0.002-0.08 vs 文本 0.3-0.9),原 `min_score=0.05` 会过滤掉几乎所有图表。已修复为 `min_score * 0.5 = 0.025`
2. **P0 安全网**:即使降门槛后,图片描述仍可能被 `_build_context_with_budget()` 截断。安全网在 LLM 生成前检查:若 `selected_images` 的描述不在 `context_text` 中,强制追加缺失描述。日志标记为 `[P0] 图片描述未完整注入 context`
3. **答案后过滤鸡生蛋问题**`_filter_images_by_answer()` 根据 LLM 答案内容过滤图片。若 LLM 因上下文缺失而回答"未找到某图表"正确图片会被误过滤。P0 安全网可缓解此问题。
### 阶段 8上下文构建
**位置**`api/chat_routes.py``_build_context_with_budget()` / `_order_text_contexts_for_prompt()`
**预算控制**
```
CONTEXT_MAX_CHARS = 8000 # 硬上限(约 4000 token
CONTEXT_SOFT_LIMIT = 6000 # 软限制(超过后只接受高分 chunk
MAX_CONTEXT_CHUNKS = 20 # 最大切片数
```
**排序策略**
1. 枚举/对比查询:保持原文顺序,注入 `━ section ━` 分隔符
2. 普通查询:按 (source, section) 分组 → 组内按 chunk_index 排序 → 组间按 max_rerank_score 排序
3. 表格保护:即使分数低于 min_score只要同章节有高分文本 chunk表格 chunk 也保留floor = min_score × 0.3
**性能**5-15ms
**瓶颈分析****无瓶颈**。但上下文质量直接影响 LLM 生成质量。8000 字符 ≈ 4000 token对于需要对比多个文档的查询可能不够。
### 阶段 9LLM 流式生成 — 最大瓶颈
**位置**`core/engine.py``generate_answer_stream()`
**功能**:将上下文 + 历史 + 查询组装成 prompt调用 LLM 流式输出
**Prompt 结构**
```
[System] 你是一个专业的知识库问答助手...(规则指令)
[System] 参考资料context, 最多 8000 字符)
[User×N] 历史对话(最多 10 轮)
[User] 当前问题
```
**关键参数**
| 参数 | 服务器值 | 说明 |
|------|----------|------|
| MODEL | mimo-v2.5 | 主生成模型 |
| LLM_TEMPERATURE | 0.7 | 较高温度,生成更发散 |
| LLM_MAX_TOKENS | 3000 | 最大输出 token |
| LLM_TOP_P | (未设置) | 默认 1.0 |
**实测耗时**deepseek-v4-flash5000-15000ms含流式输出。mimo-v2.5 推理模型预计 **8000-20000ms**
**瓶颈分析**
1. **模型延迟不可控**LLM API 的 TTFT首 token 时间)和 TPStoken/秒)取决于服务端负载和网络。这是整个管线中唯一无法通过代码优化的瓶颈。
2. **推理模型 content 为空问题**mimo-v2.5 是推理模型,`max_tokens` 不足时思考链消耗全部预算,`content` 为空需从 `reasoning_content` 提取内容。当前 `LLM_MAX_TOKENS=3000` 足够,但若降低此值需注意思考链预算。
3. **Prompt 长度影响 TTFT**8000 字符上下文 + 10 轮历史 ≈ 6000-8000 input token。输入越长TTFT 越高。
4. **流式缓解**:用户看到第一个 token 的等待时间 = 意图分析 + 检索 + TTFT ≈ 6-12 秒。流式输出减少了感知等待,但总耗时不变。
5. **MAX_TOKENS=3000 配置合理**:推理模型思考链占用部分预算,实际回答通常 500-1500 token3000 平衡速度与质量。
### 阶段 10后处理
**功能**:答案对齐、图片过滤、引用附加、会话存储、语义缓存写入
**子步骤**
| 步骤 | 耗时 | 说明 |
|------|------|------|
| 图号引用提取 | ~5ms | 正则匹配答案中的图/表引用 |
| 图片后过滤 | ~5ms | `_filter_images_by_answer()`,根据 LLM 答案内容裁剪不相关图片 |
| 引用清理 | ~2ms | 去除 LLM 添加的 [N] 标记 |
| 引用附加 | ~10ms | 添加结构化 [ref:chunk_id] |
| 敏感内容过滤 | ~5ms | prompt_guard 检查 |
| 会话存储 | ~20-100ms | SQLite 写入 |
| 语义缓存写入 | ~10-50ms | FAISS 索引添加 |
**总计**50-200ms。**无瓶颈**。
---
## 三、缓存体系分析
### 五层缓存架构
```
精确缓存层
├─ Query Cache LRU 500, TTL 1h 最终结果缓存(含 rerank 分数)
├─ Embedding Cache LRU 2000, TTL 24h 文档向量缓存
├─ Rerank Cache LRU 1000, TTL 1h CrossEncoder 分数缓存
└─ Intent Cache Dict 500, 无 TTL 意图分析结果缓存
语义缓存层
└─ FAISS Cache max 10000, 阈值 0.92 向量化相似问答缓存
```
### 缓存命中场景
| 场景 | 命中层 | 节省时间 |
|------|--------|----------|
| 完全相同的问题 + 相同知识库 | Query Cache | 跳过整个检索(节省 ~1s |
| 相似问题(余弦 ≥ 0.92 | Semantic Cache | 跳过检索 + 生成(节省 ~10s |
| 相同文档集合被 rerank | Rerank Cache | 跳过 CrossEncoder节省 ~600ms |
| 相同文档需要 embedding | Embedding Cache | 跳过编码(节省 ~100ms |
| 相同问题(意图层面) | Intent Cache | 跳过意图分析 LLM节省 ~4s |
### 缓存问题
1. **内存存储,重启清零**:所有缓存都在进程内存中,服务重启后第一次请求全部冷启动。
2. **语义缓存阈值过高**0.92 的余弦阈值导致换一种说法就命中不了。
3. **Rerank 缓存不参与 kb_version 失效**:文档更新后 rerank 缓存可能返回旧分数。
4. **语义缓存淘汰策略粗暴**:达到 10000 上限时全量清空(`clear()`),不是 LRU。
---
## 四、瓶颈总结与优化优先级
### 耗时分布(典型请求,基于 deepseek-v4-flash 实测)
```
意图分析 ████████████████████ 25-35% ~4000ms
LLM 生成 ████████████████████████████████ 45-60% ~8000ms
检索+Rerank ████████ 10-15% ~1200ms
其他阶段 ██ 3-5% ~400ms
```
### 优化机会排序
| 优先级 | 方向 | 预期收益 | 难度 | 风险 |
|--------|------|----------|------|------|
| **P0** | 意图分析换轻量模型 | 节省 2-3s/请求 | 低 | 低(需寻找可用轻量模型,百炼 deepseek-v4-flash 额度已尽) |
| **P0** | 主模型 API 优化(换供应商/批处理) | 节省 3-5s/请求 | 中 | 中(需要评估质量) |
| **P1** | 意图分析结果缓存优化 | 重复问题节省 4s | 低 | 低 |
| **P1** | 语义缓存阈值调优0.92→0.88 | 提高命中率,节省 10s | 低 | 中(可能误命中) |
| **P2** | RECALL_MULTIPLIER 降低3→2 | 减少 embedding 编码量 ~30ms | 低 | 低 |
| **P2** | LLM_TEMPERATURE 降低0.7→0.3 | 减少发散,回答更精准 | 低 | 中(可能影响创造性) |
| **P3** | Rerank 换 GPU 推理 | 节省 ~500ms | 高(需硬件) | 低 |
| **P3** | Embedding 换 GPU 推理 | 节省 ~150ms | 高(需硬件) | 低 |
| **P3** | 语义缓存改 LRU 淘汰 | 避免全量清空抖动 | 中 | 低 |
---
## 五、配置参数速查表
### 模型与服务
| 参数 | 当前值 | 说明 |
|------|--------|------|
| DASHSCOPE_MODEL | mimo-v2.5 | 主 LLM |
| INTENT_MODEL | mimo-v2.5 | 意图分析模型 |
| VLM_MODEL | mimo-v2.5 | 图片描述模型 |
| EMBEDDING_MODEL_PATH | bge-base-zh-v1.5 | 本地 embedding |
| RERANK_BACKEND | local | 本地 ONNX rerank可选 cloud/fallback |
| RERANK_CLOUD_MODEL | xop3qwen8breranker | 云端 rerank讯飞云 API |
### 检索参数
| 参数 | 当前值 | 说明 |
|------|--------|------|
| RAG_SEARCH_TOP_K | 30 | 最终返回数 |
| RECALL_MULTIPLIER | 3 | 向量召回倍数 |
| RERANK_CANDIDATES | 20 | 送入 Rerank 的候选数 |
| RERANK_TOP_K | 15 | Rerank 后保留数 |
| RERANK_CONTEXT_MIN_SCORE | 0.05 | 最低 rerank 分数阈值 |
| MMR_TOP_K | 30 | MMR 处理后保留数 |
| MMR_LAMBDA | 0.5 | 相关性/多样性平衡 |
| MMR_USE_EMBEDDING | False | 使用 jieba Jaccard |
| RRF_K | 60 | RRF 平滑参数 |
| DYNAMIC_RRF_ENABLED | True | 按查询长度自适应权重 |
### 上下文构建
| 参数 | 当前值 | 说明 |
|------|--------|------|
| CONTEXT_MAX_CHARS | 8000 | 上下文硬上限(字符) |
| CONTEXT_SOFT_LIMIT | 6000 | 软限制(超此只接受高分) |
| MAX_CONTEXT_CHUNKS | 20 | 最大切片数 |
| MAX_HISTORY_ROUNDS | 10 | 对话历史上限 |
### LLM 生成
| 参数 | 当前值 | 说明 |
|------|--------|------|
| LLM_TEMPERATURE | 0.7 | 生成温度 |
| LLM_MAX_TOKENS | 3000 | 最大输出 token |
| LLM_TOP_P | 未设置 | 默认 1.0(不限制) |
### 缓存
| 参数 | 当前值 | 说明 |
|------|--------|------|
| QUERY_CACHE_SIZE | 500 | 查询缓存容量 |
| QUERY_CACHE_TTL | 3600s | 查询缓存有效期 |
| EMBEDDING_CACHE_SIZE | 2000 | 向量缓存容量 |
| EMBEDDING_CACHE_TTL | 86400s | 向量缓存有效期 |
| RERANK_CACHE_SIZE | 1000 | Rerank 缓存容量 |
| RERANK_CACHE_TTL | 3600s | Rerank 缓存有效期 |
| SEMANTIC_CACHE_THRESHOLD | 0.92 | 语义缓存余弦阈值 |
### 救援管线
| 参数 | 当前值 | 说明 |
|------|--------|------|
| CLUSTER_MIN_MEMBERS | 3 | 聚类最少成员数 |
| CLUSTER_MIN_TYPES | 2 | 聚类最少类型数 |
| CLUSTER_SEED_FLOOR | 0.35 | 种子分数下限 |
| CLUSTER_RESCUE_FLOOR | 0.06 | 救援后分数 |
| CLUSTER_MAX_SECTIONS | 3 | 最多救援章节数 |
| BM25_DIVERGENCE_RESCUE_ENABLED | True | BM25 发散救援开关 |
| BM25_DIVERGENCE_MAX_RANK | 3 | BM25 top-N 参与救援 |
### 置信度
| 参数 | 当前值 | 说明 |
|------|--------|------|
| CONFIDENCE_WARN_THRESHOLD | 0.15 | 低于此值:谨慎回答 |
| CONFIDENCE_CAUTION_THRESHOLD | 0.30 | 低于此值:引用原文 |
---
## 六、架构层面的潜在风险
### 6.1 单点故障
- **LLM API 单点**:所有 LLM 调用(意图分析 + 生成)都走同一个 DASHSCOPE_BASE_URL。API 限流或故障时整个服务不可用。意图分析有降级兜底(默认 need_retrieval=True但生成阶段无降级。
- **ChromaDB 单点**:向量库文件损坏时所有检索失败。已有 ChromaDB corruption 风险分析文档。
### 6.2 内存压力
- **FAISS 语义缓存**10000 条 × 768 维 float32 = ~30MB 向量数据 + 等量元数据。达到上限全量清空时可能有瞬间抖动。
- **BM25 全量加载**:所有文档的全文 + jieba 分词结果都在内存中。知识库增长时内存线性增长。
- **三层 LRU 缓存**Query(500) + Embedding(2000) + Rerank(1000) = 最多 3500 条缓存。Embedding 缓存存 768 维向量2000 条 ≈ 6MB。
### 6.3 并发安全
- gunicorn gthread 模式 2 线程 + ChromaDB 文件锁。并发写入 ChromaDB 时可能冲突。
- FAISS 语义缓存使用 RLock线程安全。
- 精确缓存使用 RLock线程安全。
- IntentAnalyzer._exact_cache 是普通 DictPython GIL 保护下基本安全。
### 6.4 休眠模块
以下模块当前未接入生产流程,属于**独立休眠模块**(原属 AgenticRAG 类,该类已在 v4.0 删除):
- `confidence_gate.py` — 置信度门控
- `quality_assessor.py` — 质量评估器
- `reasoning_reflector.py` — 推理反思器
- `loop_guard.py` — 循环守卫
这些模块增加了代码库的维护负担但不影响运行时性能。可按需启用。