- 后端 API(Flask + Gunicorn) - RAG 引擎(混合检索 + 云端 Reranker + 引用溯源) - 文档解析(MinerU + 多格式支持) - Docker 生产部署配置 - 排除前端项目、敏感配置、模型文件
138 lines
14 KiB
Plaintext
138 lines
14 KiB
Plaintext
RAG 检索流程(从用户输入到回答生成)
|
||
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ 1. 用户输入问题 │
|
||
│ "蓄水以来逐年发电量" │
|
||
└─────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ 2. 意图分析 (core/intent_analyzer.py) │
|
||
│ ├── 问题改写:指代消解、省略补全 │
|
||
│ ├── use_context:是否使用历史上下文 │
|
||
│ ├── need_retrieval:是否需要检索知识库 │
|
||
│ └── 重复提问强制检索(新增规则) │
|
||
└─────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ 3. 混合检索 (core/engine.py - search_knowledge) │
|
||
│ │
|
||
│ 3.1 向量检索 │
|
||
│ query_vector = embedding_model.encode(query) │
|
||
│ text_results = collection.query(query_embeddings, n_results=100) │
|
||
│ │
|
||
│ 3.2 图片独立召回(P0 新增) │
|
||
│ image_results = collection.query( │
|
||
│ where={'chunk_type': {'$in': ['image', 'chart', 'table']}}, │
|
||
│ n_results=5 # 独立控制图片数量 │
|
||
│ ) │
|
||
│ │
|
||
│ 3.3 BM25 关键词检索(可选) │
|
||
│ bm25_results = bm25_index.search(query, top_k=100) │
|
||
│ │
|
||
│ 3.4 RRF 融合 │
|
||
│ fused_results = reciprocal_rank_fusion([text, image, bm25]) │
|
||
│ │
|
||
│ 3.5 MMR 去重 │
|
||
│ fused_results = _apply_mmr(query, fused_results, top_k=30) │
|
||
│ │
|
||
│ 3.6 Rerank 重排序 │
|
||
│ final_results = rerank_results(query, fused_results, top_k=15) │
|
||
└─────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ 4. 检索结果处理 (api/chat_routes.py) │
|
||
│ │
|
||
│ 4.1 构建 contexts │
|
||
│ for each result: │
|
||
│ if 图片切片: │
|
||
│ doc = meta['full_description'] # 使用完整描述(P1) │
|
||
│ else: │
|
||
│ doc = result['document'] │
|
||
│ contexts.append({'doc': doc, 'meta': meta}) │
|
||
│ │
|
||
│ 4.2 懒加载增强(可选) │
|
||
│ enhance_retrieved_chunks(contexts, query, kb_name) │
|
||
│ └── 对无 VLM 描述的图片生成 VLM 描述 │
|
||
└─────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ 5. 图片选择 (api/chat_routes.py - select_images) │
|
||
│ │
|
||
│ 5.1 意图检测 │
|
||
│ - 精确图号查询:"图2.3" → MAX_IMAGES=2, MIN_SCORE=5.0 │
|
||
│ - 弱图片意图:"发电量图" → MAX_IMAGES=1 │
|
||
│ - 普通查询 → MAX_IMAGES=2 │
|
||
│ │
|
||
│ 5.2 提取图表引用(从 top 5 文本块) │
|
||
│ referenced_figures = {'2.3': {来源文件}} │
|
||
│ │
|
||
│ 5.3 图片打分 │
|
||
│ for each image in contexts: │
|
||
│ score = score_image_relevance(query, meta, doc) │
|
||
│ └── 图号匹配 +10 分 │
|
||
│ └── 关键词匹配 +2 分/个 │
|
||
│ └── 章节匹配 +1.5 分 │
|
||
│ └── 引用匹配 +8 分(需章节相关) │
|
||
│ │
|
||
│ 5.4 图文关联补充(P2 新增) │
|
||
│ for text_chunk in top 5: │
|
||
│ for fig_num in text_chunk['referenced_images']: │
|
||
│ 查找对应的图片切片并补充到结果中 │
|
||
│ │
|
||
│ 5.5 返回 top N 图片 │
|
||
│ return scored_images[:MAX_IMAGES] │
|
||
└─────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ 6. 构建 LLM Prompt │
|
||
│ │
|
||
│ 6.1 文本上下文 │
|
||
│ context_text = "\n\n".join([ctx['doc'] for ctx in contexts[:5]]) │
|
||
│ │
|
||
│ 6.2 图片信息 │
|
||
│ if selected_images: │
|
||
│ image_info = "【可用图片】\n" + 图片描述列表 │
|
||
│ │
|
||
│ 6.3 最终 Prompt │
|
||
│ enhanced_context = context_text + image_info │
|
||
└─────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ 7. LLM 生成回答 │
|
||
│ │
|
||
│ for token in engine.generate_answer_stream(query, enhanced_context): │
|
||
│ yield token # 流式输出 │
|
||
└─────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ 8. 返回结果 │
|
||
│ { │
|
||
│ "type": "finish", │
|
||
│ "answer": "完整回答文本", │
|
||
│ "sources": [...], // 引用来源 │
|
||
│ "images": [...] // 精选图片 │
|
||
│ } │
|
||
└─────────────────────────────────────────────────────────────────────────┘
|
||
|
||
关键优化点总结
|
||
|
||
┌──────┬──────────────────┬────────────────────────────────────┐
|
||
│ 阶段 │ 优化 │ 效果 │
|
||
├──────┼──────────────────┼────────────────────────────────────┤
|
||
│ 检索 │ P0: 图片独立召回 │ 图片保证进入候选池 │
|
||
├──────┼──────────────────┼────────────────────────────────────┤
|
||
│ 入库 │ P1: 双字段存储 │ 短摘要用于检索,完整描述用于上下文 │
|
||
├──────┼──────────────────┼────────────────────────────────────┤
|
||
│ 入库 │ P2: 图文关联索引 │ 文本命中时补充关联图片 │
|
||
├──────┼──────────────────┼────────────────────────────────────┤
|
||
│ 选择 │ 章节相关性检查 │ 避免不相关图片加分 │
|
||
├──────┼──────────────────┼────────────────────────────────────┤
|
||
│ 意图 │ 重复提问强制检索 │ 避免复用错误上下文 │
|
||
└──────┴──────────────────┴────────────────────────────────────┘ |