- 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 函数名
461 lines
20 KiB
Markdown
461 lines
20 KiB
Markdown
# 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-flash):3500-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 token,JSON 输出 ~200 token,2048 是必要预算(此前 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。
|
||
|
||
### 阶段 4:Rerank
|
||
|
||
**位置**:`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-800ms(CPU ONNX 推理)
|
||
|
||
**瓶颈分析**:
|
||
|
||
1. **CPU 推理**:CrossEncoder 是最重的 CPU 计算任务。每个 (query, doc) pair 需要一次 forward pass。20 个候选 × ~30ms/pair ≈ 600ms。
|
||
2. **max_length=512**:长文档截断到 512 token,避免 OOM 但可能丢失信息。
|
||
3. **缓存效果好**:同一查询+同一文档集合直接命中缓存。但首次查询必经此阶段。
|
||
|
||
### 阶段 5:MMR 去重
|
||
|
||
**位置**:`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,对于需要对比多个文档的查询可能不够。
|
||
|
||
### 阶段 9:LLM 流式生成 — 最大瓶颈
|
||
|
||
**位置**:`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-flash):5000-15000ms(含流式输出)。mimo-v2.5 推理模型预计 **8000-20000ms**。
|
||
|
||
**瓶颈分析**:
|
||
|
||
1. **模型延迟不可控**:LLM API 的 TTFT(首 token 时间)和 TPS(token/秒)取决于服务端负载和网络。这是整个管线中唯一无法通过代码优化的瓶颈。
|
||
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 token,3000 平衡速度与质量。
|
||
|
||
### 阶段 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 是普通 Dict,Python GIL 保护下基本安全。
|
||
|
||
### 6.4 休眠模块
|
||
|
||
以下模块当前未接入生产流程,属于**独立休眠模块**(原属 AgenticRAG 类,该类已在 v4.0 删除):
|
||
|
||
- `confidence_gate.py` — 置信度门控
|
||
- `quality_assessor.py` — 质量评估器
|
||
- `reasoning_reflector.py` — 推理反思器
|
||
- `loop_guard.py` — 循环守卫
|
||
|
||
这些模块增加了代码库的维护负担但不影响运行时性能。可按需启用。
|