Files
rag/docs/RAG数据流程.md
lacerate551 8268071fdc docs: 模型切换至 mimo-v2.5 + 文档全面更新
- config.py: INTENT_MODEL 从 deepseek-v4-flash 切换至 mimo-v2.5
- config.py: get_intent_client() 从百炼 API 切换至 mimo API
- RAG系统完整指南.md: v4.0→v4.1,新增图片检索子系统、P0安全网、
  救援管线、五层缓存架构文档;替换所有旧模型名和API地址
- RAG数据流程.md: 完全重写,匹配实际代码逻辑
- curl测试手册.md: 更新模型名和Reranker配置
- MinerU模型部署指南.md: VLM_MODEL 更新为 mimo-v2.5
- 开发与系统模块说明.md: API地址和模型名更新
- 测试指南.md: API地址和模型名更新
2026-06-21 23:11:46 +08:00

667 lines
26 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 数据流程
> 本文档基于当前代码实际逻辑梳理,详细记录 RAG 系统从用户查询到回答生成的完整数据流。
> 涵盖意图分析、混合检索、重排序、救援管道、上下文构建、图片选择与注入、LLM 生成和引用溯源等核心环节。
---
## 一、概述
### 1.1 检索管线总览
```
用户查询
┌─────────────────────────────────────────────────────────────────────────┐
│ 1. 意图分析 (intent_analyzer) │
│ 问题改写 · 指代消解 · 是否需要检索 · 重复提问检测 │
│ 模型mimo-v2.5 │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ 2. 混合检索 (engine.search_knowledge) │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ 向量检索 │ │ BM25 检索 │ │
│ │ (ChromaDB) │ │ (关键词匹配) │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ └────────┬──────────┘ │
│ ▼ │
│ RRF 融合 (Reciprocal Rank Fusion) │
│ │ │
│ 查询缓存检查 (命中则跳过 3-7 步) │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ 3. 云端 Rerank │
│ 模型xop3qwen8breranker (讯飞云) │
│ 结果缓存rerank_cache (TTL=1h, 版本失效自动清除) │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ 4. 救援管道 (chat_routes.py) │
│ BM25 分歧救援 · 词法匹配救援 · 章节聚类救援 │
│ 目的:挽救被 CrossEncoder 低估但实际相关的切片 │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ 5. 上下文构建 + 图片选择 │
│ _order_text_contexts_for_prompt · _build_context_with_budget │
│ select_images · VLM 相关性筛选 · CrossEncoder 精排 │
│ 懒加载 VLM 描述 · 图片描述注入 · P0 安全网 │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ 6. LLM 生成 │
│ 模型mimo-v2.5 │
│ 流式输出 · 置信度指令 · 引用标注 · 图片后置过滤 │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ 7. 返回结果 │
│ { answer, sources, images } │
└─────────────────────────────────────────────────────────────────────────┘
```
### 1.2 模型配置一览
| 用途 | 模型 | API 端点 | 说明 |
|------|------|----------|------|
| 主 LLM | mimo-v2.5 | xiaomimimo.com | 回答生成、上下文理解 |
| 意图分析 | mimo-v2.5 | xiaomimimo.com | 问题改写与意图判断 |
| VLM | mimo-v2.5 | xiaomimimo.com | 图片理解与描述生成 |
| 云端重排序 | xop3qwen8breranker | 讯飞云 Maas API | 替代本地 BGE-reranker |
| 向量编码 | bge-base-zh-v1.5 | 本地模型 | 查询与文档 embedding |
> 模型可通过环境变量覆盖:`DASHSCOPE_MODEL`、`INTENT_MODEL`、`VLM_MODEL`、`RERANK_CLOUD_MODEL`
### 1.3 关键配置参数
| 参数 | 默认值 | 说明 |
|------|--------|------|
| `RERANK_CONTEXT_MIN_SCORE` | 0.05 | Rerank 分数低于此值的切片不送入 LLM |
| `MAX_CONTEXT_CHUNKS` | 20 | 送给 LLM 的最大文本切片数 |
| `CONTEXT_MAX_CHARS` | 8000 | 上下文最大字符数(约 4000 token |
| `CONTEXT_SOFT_LIMIT` | 6000 | 软限制,超过后只接受高分切片组 |
| `CONFIDENCE_WARN_THRESHOLD` | 0.15 | top-3 均分低于此值时,提示 LLM 谨慎回答 |
| `CONFIDENCE_CAUTION_THRESHOLD` | 0.30 | top-3 均分低于此值时,提示 LLM 优先引用原文 |
---
## 二、请求入口
### 2.1 API 路由
**入口文件**`api/chat_routes.py`
```
POST /chat — 普通聊天(不检索知识库,直接 LLM 回答)
POST /rag — 知识库问答(检索 + LLM 生成)
POST /search — 纯检索(返回切片,不生成回答)
```
`/rag` 的核心函数 `rag()` 的职责:
1. 调用意图分析模块,获取改写后的查询与检索决策
2. 若需要检索,调用混合检索管线(`search_hybrid()`
3. 执行救援管道BM25 分歧 / 词法匹配 / 章节聚类)
4. 执行图片选择(`select_images()`
5. 构建 LLM 上下文(排序 + 预算截断 + 图片注入)
6. 调用 LLM 生成回答(流式输出)
7. 后置图片过滤(`_filter_images_by_answer()`
8. 组装最终响应(回答 + 引用来源 + 图片)
### 2.2 请求数据结构
```python
# 请求
{
"message": "用户问题",
"history": [...] # 可选:对话历史
}
# SSE 响应事件流
data: {"type": "intent_result", "data": {...}}
data: {"type": "chunks_retrieved", "data": {...}}
data: {"type": "images_selected", "data": {...}}
data: {"type": "context_built", "data": {...}}
data: {"type": "chunk", "content": "部分回答"}
data: {"type": "chunk", "content": "部分回答"}
...
data: {"type": "finish", "answer": "完整回答", "sources": [...], "images": [...]}
```
---
## 三、意图分析
**入口文件**`core/intent_analyzer.py`
**使用模型**mimo-v2.5
### 3.1 核心功能
意图分析器在检索前对用户查询进行预处理,输出结构化决策:
```python
@dataclass
class IntentAnalysis:
rewritten_query: str # 改写后的查询(指代消解、省略补全)
use_context: bool # 是否使用历史上下文
need_retrieval: bool # 是否需要检索知识库
intent: str # 意图类型factual/comparison/reasoning/instruction
sub_queries: list # 子查询列表(对比/复杂查询拆分)
```
### 3.2 处理逻辑
| 功能 | 说明 |
|------|------|
| 问题改写 | 指代消解("它" → 具体实体)、省略补全(补全缺失主语) |
| 上下文判断 | 根据对话历史决定是否需要前文信息 |
| 检索决策 | 判断是否需要查询知识库(闲聊类问题可跳过) |
| 意图分类 | 识别查询意图(事实查询/对比分析/推理/操作指导) |
| 子查询拆分 | 对比类查询拆分为多个子查询并行检索 |
| 语义缓存 | 相似度 ≥ 0.92 时复用历史意图分析结果 |
### 3.3 重复提问规则
当用户重复提问相同或相似问题时,意图分析器必须设置 `need_retrieval = true`。原因:用户可能对之前的回答不满意,或之前的回答包含错误信息,需要重新检索以获取更准确的结果。
---
## 四、检索阶段
**入口文件**`core/engine.py`
**核心函数**`search_knowledge()`
### 4.1 查询缓存检查
检索前先检查缓存,命中则直接返回历史结果,避免重复计算:
```python
cached = cache.get_query_result(query, kb_name)
if cached:
return cached
```
缓存层级5 层):
1. `query_cache` — 精确查询结果缓存
2. `embedding_cache` — embedding 向量缓存
3. `rerank_cache` — rerank 分数缓存TTL=1h知识库版本变更自动失效
4. `semantic_cache` — 语义相似查询缓存(阈值 0.92
5. `intent_exact_cache` — 意图分析精确缓存
### 4.2 向量检索
使用本地 bge-base-zh-v1.5 模型将查询编码为向量,在 ChromaDB 中执行 ANN 检索:
```python
query_vector = embedding_model.encode(query)
text_results = collection.query(
query_embeddings=[query_vector],
n_results=100 # recall_k召回候选数量
)
```
**图片独立召回**:同时对图片切片进行独立检索,保证图片有足够的召回机会:
```python
image_results = collection.query(
query_embeddings=[query_vector],
where={'chunk_type': {'$in': ['image', 'chart', 'table']}},
n_results=5
)
```
### 4.3 BM25 关键词检索
基于 BM25 算法执行关键词匹配检索,弥补向量检索在精确匹配上的不足:
```python
bm25_results = bm25_index.search(query, top_k=100)
```
### 4.4 RRF 融合
使用 Reciprocal Rank Fusion 算法将向量检索和 BM25 检索的结果进行融合排序:
```python
fused_results = reciprocal_rank_fusion(
[text_results, image_results, bm25_results],
weights=[VECTOR_WEIGHT, IMAGE_WEIGHT, BM25_WEIGHT]
)
```
### 4.5 子查询并行检索
意图分析器拆分的子查询(如对比类查询)会并行检索,结果合并后再 rerank。
---
## 五、重排序
### 5.1 云端 Rerank
**调用模型**xop3qwen8breranker讯飞云 Maas API
RRF 融合后的候选结果通过云端 Reranker 进行精排,基于查询与文档的语义相关性重新打分排序:
```python
reranked = rerank_results(query, fused_results, top_k=15)
```
**重要特征**CrossEncoder 对不同类型切片的评分分布差异显著:
| 切片类型 | 典型分数范围 | 说明 |
|----------|------------|------|
| 文本切片 | 0.3 ~ 0.99 | 正常分布 |
| 表格切片 | 0.1 ~ 0.5 | 偏低,有专用救援逻辑 |
| 图片/图表切片 | 0.002 ~ 0.08 | 系统性偏低,需要宽松阈值 |
### 5.2 Rerank 缓存
- 每个 (query, doc_id) 对的 rerank 分数独立缓存
- TTL = 1 小时
- 知识库版本号变更时自动失效
---
## 六、救援管道
**入口文件**`api/chat_routes.py`
**目的**:挽救被 CrossEncoder 低估但实际相关的切片
`_order_text_contexts_for_prompt` 之前执行,三个救援管道按顺序运行:
### 6.1 BM25 分歧救援 `_rescue_bm25_divergence`
**触发条件**BM25 排名 top-3 但 CrossEngineer 评分低于 min_score 的切片
**逻辑**BM25 是关键词精确匹配的强信号,如果 BM25 认为相关但 CE 误判,提升分数至保底值。
```python
# 配置
BM25_DIVERGENCE_RESCUE_ENABLED = True
BM25_DIVERGENCE_MAX_RANK = 3 # 仅救援 BM25 rank <= 3 的切片
```
### 6.2 词法匹配救援 `_rescue_lexical_match`
**触发条件**切片文本精确包含查询关键词bigram 匹配率 > 35%)但 CE 评分低
**逻辑**当切片文本直接包含查询中的关键词组合时说明语义相关CE 可能因为表述差异低估。
### 6.3 章节聚类救援 `_rescue_section_cluster`
**触发条件**:同一 section 内所有切片都被 min_score 过滤("全灭 section"
**逻辑**:如果同一章节的切片全部被过滤,但其他章节有切片通过,说明 CE 对该章节整体低估。为全灭 section 的切片分配保底分数0.06)。
```python
# 配置
SECTION_CLUSTER_RESCUE_ENABLED = True
CLUSTER_RESCUE_FLOOR = 0.06 # 略高于 RERANK_CONTEXT_MIN_SCORE=0.05
```
### 6.4 表格救援 `_rescue_table_chunks`
**触发条件**:查询涉及表格但上下文中没有表格数据(表格被预算截断)
**逻辑**:从被截断的切片中补回表格数据。
---
## 七、上下文构建
### 7.1 切片排序与过滤 `_order_text_contexts_for_prompt`
**核心逻辑**
1. **文本切片 + 表格切片** → 进入 `text_contexts`
2. **图片/图表切片** → 进入 `chart_contexts`(独立处理)
3. **min_score 过滤**
- `text_contexts`:使用 `RERANK_CONTEXT_MIN_SCORE`0.05
- 表格保护:同 section 内如有切片通过阈值table 切片保底分数为 `min_score * 0.3`
- `chart_contexts`:使用宽松阈值 `min_score * 0.5`0.025
- 原因CrossEncoder 对图片描述评分系统性偏低
- 实际内容相关性由 `select_images` 独立评分保证
4. **合并**`text_contexts + chart_contexts[:3]`
### 7.2 预算构建 `_build_context_with_budget`
按字符预算构建上下文文本:
1. 按 (source, section) 分组
2. 组内按 chunk_index 排序(保持原文连续性)
3. 组间按组内最高 Rerank 分数降序
4. 逐组加入直到达到 `CONTEXT_MAX_CHARS`8000
5. 超过 `CONTEXT_SOFT_LIMIT`6000后收紧准入
**特殊处理**:表格切片不受预算截断(结构化关键内容)
### 7.3 图片选择 `select_images()`
从检索结果中筛选与查询最相关的图片:
**步骤一:动态预算**
| 查询类型 | MAX_IMAGES | MIN_SCORE | 检测方式 |
|----------|------------|-----------|----------|
| 精确图号查询("图2.3" | 2 | 5.0 | 正则匹配 `图\s*(\d+\.?\d*)` |
| 有图片数据(检索含 image/chart | 5 | 2.0 | 检查检索结果 chunk_type |
| 文本引用图表 | 3 | 2.0 | 提取 top-5 文本中的图号/表号 |
| 普通查询 | 2 | 3.0 | 默认 |
**步骤二:提取图表引用**
从 top 5 文本块中提取 "见图2.3"、"如表2.2" 等引用,建立图号与来源文件的映射。
**步骤三:图片相关性打分 `score_image_relevance()`**
| 匹配项 | 加分 |
|--------|------|
| 图号精确匹配(查询中有"图2.3" | +10 分 |
| 表号精确匹配 | +10 分 |
| 关键词匹配jieba 分词) | +2 分/个,上限 8 分 |
| 字符重叠 | +0.2 分/字符,上限 3 分 |
| 章节匹配 | +1.5 分/关键词 |
| 图片类型chart | +2 分 |
| 图片类型image | +1 分 |
| 向量相似度 | +2 分(最高) |
| 引用匹配 + 章节相关 | +8 分 + 5 分 |
| VLM 相关性 < 0.3 | -3 分VLM 描述与查询不相关) |
| VLM 相关性 ≥ 0.5 | +2 分 |
| 章节不相关 | -5 分(除非被文本引用) |
**步骤四VLM 相关性筛选**
对有 VLM 描述的图片,使用关键词重叠率判断描述与查询的相关性:
- 重叠率 < 0.3:降分 -3描述与查询不相关
- 重叠率 ≥ 0.5:加分 +2
**步骤五CrossEncoder 精排**
`select_images` 候选用 CE 做语义精排:
- CE < 0直接剔除语义不相关
- CE 0~2保留但不加分弱相关
- CE > 2加分 `min((ce - 2) / 3, 1) * 5`
**步骤六:表格嵌入图片补充**
处理 `images_json` 字段的表格切片,补充表格中嵌入的图片。
**步骤七:文本引用图片补充**
从 top 5 文本块中提取 `referenced_images` 字段,补充未选中的关联图片。
**步骤八:返回 top N**
```python
scored_images.sort(key=lambda x: x['score'], reverse=True)
return scored_images[:MAX_IMAGES]
```
### 7.4 图片描述注入
**核心逻辑**:将 `select_images` 选中的图片的 `full_description` 注入到 LLM context 中。
```
context_text文本切片
+
【相关图片信息】
【图片1】VLM 完整描述来源xxx 第N页
【图片2】VLM 完整描述来源xxx 第N页
+
【回答要求】回答时请简要介绍每张图片的内容和用途。
```
**P0 安全网**(防止图片描述被过滤遗漏):
1.`selected_images` 非空但 `【相关图片信息】` 未生成 → 补注入所有选中图片描述
2. 若已有 `【相关图片信息】` 但遗漏部分图片 → 追加遗漏的描述
3. DEV 模式日志:检查所有选中图片的 ID 是否出现在 context 中
### 7.5 置信度指令
根据 top-3 切片的平均 Rerank 分数注入不同的回答指令:
| 置信度范围 | 指令 |
|-----------|------|
| < 0.15 | "参考资料与问题的相关性较低,仅基于明确信息回答,不足则说明" |
| 0.15 ~ 0.30 | "参考资料的相关性一般,优先引用资料原文,避免推测" |
| ≥ 0.30 | 无额外指令 |
---
## 八、LLM 生成
### 8.1 流式生成
使用 SSEServer-Sent Events实现流式输出
```python
for token in engine.generate_answer_stream(query, enhanced_context, history):
yield token # 逐 token 推送给前端
```
**LLM 模型**mimo-v2.5
### 8.2 System Prompt
```
你是一个严谨的知识库问答助手。
你必须且只能根据用户提供的【参考资料】回答问题。
如果参考资料中有答案,必须引用对应内容回答,并在回答末尾标注引用编号。
如果参考资料中确实没有相关信息,简短说明即可,不要编造或补充资料外的内容。
禁止使用参考资料以外的知识进行补充或推测。
【重要-表格处理规则】当用户询问表格时,必须将 Markdown 表格原样输出...
```
### 8.3 图片后置过滤 `_filter_images_by_answer`
LLM 生成回答后,根据回答内容对图片做最终过滤:
1. **候选 ≤ 1 张**:直接返回
2. **无图意图早退**:回答和查询都不含图片引用词 → 返回空
3. **图号精确豁免**:图片描述包含回答引用的具体图号/表号 → 无条件保留
4. **主题一致性**:合并查询+回答关键词,图片描述重叠 ≥ 阈值才保留
- 子章节惩罚:图片子章节与主要检索章节不一致时,阈值 +2
5. **兜底**:过滤后为空且有图片意图 → 保留分数最高的 1 张
### 8.4 回答结构
```python
{
"type": "finish",
"answer": "根据蓄水以来的统计数据,三峡电站逐年发电量呈现波动上升趋势...",
"sources": [
{
"source": "三峡公报_2022.pdf",
"page": 12,
"section": "综述 > 2.3 发电",
"chunk_id": "三峡公报_text_24"
}
],
"images": [
{
"id": "ab77281e7913.jpg",
"url": "/images/ab77281e7913.jpg",
"type": "chart",
"source": "三峡公报_2022.pdf",
"page": 12,
"description": "图2.3 柱状图2003-2022年逐年发电量",
"full_description": "...完整 VLM 描述..."
}
]
}
```
---
## 九、引用溯源
### 9.1 引用标注机制
`_attach_citations()` 负责在回答中插入引用标记,将回答内容与知识库来源关联:
```
根据统计数据[ref:三峡公报_text_24]2022年三峡电站年度发电量为787.90亿千瓦时[ref:三峡公报_table_5]。
```
### 9.2 引用数据来源
每个引用标记对应检索结果中的一个切片,包含:
| 字段 | 说明 |
|------|------|
| `source` | 源文件名 |
| `page` | 页码 |
| `section` | 章节路径 |
| `chunk_id` | 切片唯一标识 |
| `chunk_type` | 类型text / table / image / chart |
---
## 十、文档入库流程(补充参考)
> 入库流程为检索提供数据基础,以下简要说明关键环节。
### 10.1 文档解析
**入口文件**`parsers/mineru_parser.py`
**核心函数**`parse_with_mineru()`
MinerU 解析 PDF/Word/Excel 文件,输出结构化内容:
```
.data/mineru_temp/{file_hash}/
├── auto/
│ ├── {doc_name}.md # Markdown 内容
│ ├── {doc_name}_content_list.json # 结构化内容列表(核心)
│ └── images/ # 提取的图片文件
```
**content_list.json 中的条目类型**
| item_type | 处理方式 | 关键字段 |
|-----------|----------|----------|
| `text` | 文本块 | content, section_path, text_level |
| `table` | 表格 | content, table_html, image_path |
| `image` | 图片 | content(=caption), image_path, context_before/after |
| `chart` | 图表 | content(=caption), image_path, context_before/after |
### 10.2 切片入库
**入口文件**`knowledge/manager.py`
**核心函数**`add_file_to_kb()`
```
MinerUChunk 列表
├── 文本块 → 计算 embedding → 存入 ChromaDB
├── 表格块 → 生成语义增强摘要 → 存入 ChromaDB
└── 图片块 → VLM 缓存检查 → 生成描述 → 存入 ChromaDB
```
**图片描述策略**
1. 优先使用 VLM 缓存描述(由 mimo-v2.5 生成,语义更丰富)
2. 若无缓存,生成轻量描述(基于文件名 + 章节路径 + 上下文)
3. VLM 描述异步懒加载:首次检索命中时后台生成,下次查询即可使用
### 10.3 ChromaDB 存储结构
| 字段 | 类型 | 说明 |
|------|------|------|
| `ids` | str | 切片唯一标识,如 `doc.pdf_text_24` |
| `embeddings` | List[float] | 向量表示 |
| `documents` | str | 切片内容(文本/VLM 描述/摘要) |
| `metadatas` | dict | 元数据(见下表) |
**图片切片 metadata 关键字段**
```python
{
'source': '三峡公报_2022.pdf', # 源文件名
'page': 12, # 页码
'chunk_type': 'chart', # 切片类型
'section': '综述 > 2.3发电', # 章节路径
'image_path': 'ab77281e7913.jpg', # 图片文件名
'has_vlm_desc': True, # 是否有 VLM 描述
'vlm_desc': '图2.3 柱状图...', # VLM 描述内容
'chunk_id': '三峡公报_chart_5', # 切片唯一标识
'version': 'v10', # 知识库版本号
'status': 'active', # 状态
}
```
> **注意**ChromaDB metadata 中**没有** `full_description` 字段。图片的完整描述存储在 `vlm_desc` 字段或 `documents` 字段中。`full_description` 仅在 `select_images()` 运行时动态计算。
### 10.4 懒加载增强
**入口文件**`knowledge/lazy_enhance.py`
对检索命中但没有 VLM 描述的图片切片,在后台线程异步调用 VLM 生成描述:
```python
# 检索命中 → 后台线程调用 VLM → 写入文件缓存 + ChromaDB
enhance_retrieved_chunks(contexts, query, kb_name, defer_chromadb=True)
```
- **image/chart 切片**:更新 `ctx['doc']` 字段
- **table 切片**:更新 `ctx['image_description']` 字段
- **缓存目录**`.data/cache/vlm/``.data/cache/llm/`
---
## 十一、缓存系统
### 11.1 缓存层级
| 层级 | 类 | 用途 | 容量 | TTL |
|------|-----|------|------|-----|
| query_cache | LRUCache | 精确查询结果缓存 | 500 | 无 |
| embedding_cache | LRUCache | 查询 embedding 向量 | 500 | 无 |
| rerank_cache | TTLCache | Rerank 分数缓存 | 500 | 1h |
| semantic_cache | SemanticCache | 语义相似查询缓存 | 200 | 无 |
| intent_exact_cache | LRUCache | 意图分析精确缓存 | 200 | 无 |
### 11.2 缓存失效
- **版本失效**知识库版本号变更时query_cache 和 rerank_cache 自动失效
- **手动清除**`POST /cache/clear`DEV 模式)
### 11.3 缓存 API
```
GET /cache/stats — 查看缓存统计
POST /cache/clear — 清除所有缓存
```
---
## 十二、关键文件索引
| 文件 | 职责 | 关键函数/类 |
|------|------|-------------|
| `api/chat_routes.py` | API 路由与请求调度 | `rag()`, `select_images()`, `score_image_relevance()`, `_filter_images_by_answer()`, `_order_text_contexts_for_prompt()`, `_build_context_with_budget()` |
| `core/engine.py` | 检索引擎核心 | `search_knowledge()`, `rerank_results()`, `generate_answer_stream()` |
| `core/intent_analyzer.py` | 意图分析 | `analyze()`, `IntentAnalysis` |
| `core/bm25_index.py` | BM25 关键词检索 | `BM25Index.search()` |
| `core/mmr.py` | MMR 去重 | `mmr_rerank()` |
| `core/cache.py` | 缓存管理 | `RAGCacheManager`, `get_cache_manager()` |
| `core/semantic_cache.py` | 语义缓存 | `SemanticCache` |
| `core/chunker.py` | 语义分块器 | `SemanticChunker` |
| `core/llm_utils.py` | LLM 调用工具 | `call_llm()`, `call_llm_stream()` |
| `parsers/mineru_parser.py` | 文档解析 | `parse_with_mineru()`, `MinerUChunk` |
| `knowledge/manager.py` | 知识库管理 | `add_file_to_kb()`, `KBManager` |
| `knowledge/lazy_enhance.py` | 懒加载增强 | `lazy_vlm_description()`, `enhance_retrieved_chunks()` |
| `config.py` | 配置集中管理 | 模型/参数/开关 |