# dataset_rag
**Repository Path**: nullindex/dataset_rag
## Basic Information
- **Project Name**: dataset_rag
- **Description**: 掌鉴智库 (RAG) 是一款基于检索增强生成 (Retrieval-Augmented Generation) 技术的企业级知识库问答系统。本项目致力于构建一套集“私有知识库精准问答、实时联网信息补充、多维度结果优化”于一体的全流程智能客服解决方案,旨在实现核心知识的私有化管理、问答结果的高精准度以及业务场景的灵活适配。
- **Primary Language**: Python
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2026-08-23
- **Last Updated**: 2026-08-23
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 掌鉴智库 RAG (Dataset RAG)
基于 RAG(检索增强生成)架构的产品知识库智能问答系统,支持文档自动导入、多路混合检索、重排序与流式答案生成。
## 项目背景
**掌鉴智库** 是一个面向产品文档的智能问答系统。核心场景:企业将产品说明书、用户手册等 PDF 文档上传到系统,系统自动完成解析、向量化、入库;终端用户通过自然语言对话方式查询产品操作方式、故障排除等信息,系统从知识库中检索相关文档片段并生成准确答案。
典型使用场景:
- 用户上传「HAK 180 烫金机使用说明书.pdf」→ 系统自动入库
- 终端提问「HAK 180 烫金机怎么调节温度?」→ 系统检索相关片段 → LLM 生成答案
## 整体架构
```mermaid
flowchart LR
subgraph Import["文档导入流水线 (端口 8000)"]
A[PDF上传] --> B[MinerU解析
PDF→MD]
B --> C[图片处理
上传MinIO]
C --> D[文档分块
语义切割]
D --> E[项目名识别
LLM提取]
E --> F[BGE-M3向量化
稠密+稀疏]
F --> G[Milvus入库]
end
subgraph Query["查询检索流水线 (端口 8001)"]
H[用户提问] --> I[项目名确认
LLM提取+向量校验]
I --> J1[向量检索
dense+sparse]
I --> J2[HyDE检索
假设性文档]
I --> J3[网络搜索
百练MCP]
J1 --> K[RRF融合排序]
J2 --> K
J3 --> K
K --> L[BGE Reranker精排
+断崖截断]
L --> M[LLM答案生成
流式SSE/非流式]
end
G -.-> J1
```
## 项目结构
```
dataset_rag/
├── app/
│ ├── clients/ # 外部服务客户端
│ │ ├── milvus_utils.py # Milvus 向量数据库(混合搜索、chunk查询)
│ │ ├── mongo_history_utils.py # MongoDB 历史对话存取
│ │ ├── minio_utils.py # MinIO 对象存储
│ │ └── neo4j_utils.py # Neo4j 图数据库
│ ├── conf/ # 配置模块(@dataclass + .env)
│ │ ├── lm_config.py # LLM 模型配置
│ │ ├── embedding_config.py # BGE-M3 向量模型配置
│ │ ├── milvus_config.py # Milvus 连接配置
│ │ ├── minio_config.py # MinIO 连接配置
│ │ ├── reranker_config.py # BGE Reranker 重排序模型配置
│ │ ├── bailian_mcp_config.py # 百练 MCP 网络搜索配置
│ │ └── mineru_config.py # MinerU PDF 解析配置
│ ├── core/ # 核心工具
│ │ └── load_prompt.py # Prompt 模板加载与变量渲染
│ ├── eval/ # 评测模块(Ragas)
│ │ ├── README.md # 评测使用说明
│ │ └── run_eval.py # Ragas 评测脚本
│ ├── import_process/ # 文档导入流水线(LangGraph)
│ │ ├── agent/
│ │ │ ├── main_graph.py # 工作流编排
│ │ │ ├── state.py # 状态定义
│ │ │ └── nodes/ # 7个导入节点
│ │ └── api/
│ │ └── import_server.py # FastAPI 导入服务(端口 8000)
│ ├── lm/ # 语言模型工具
│ │ ├── embedding_utils.py # BGE-M3 向量生成(稠密+稀疏,单例模式)
│ │ ├── lm_utils.py # LLM 客户端(OpenAI 兼容接口,缓存模式)
│ │ └── reranker_utils.py # BGE Reranker 重排序模型加载
│ ├── query_process/ # 查询检索流水线(LangGraph)
│ │ ├── agent/
│ │ │ ├── main_graph.py # 工作流编排
│ │ │ ├── state.py # 状态定义
│ │ │ └── nodes/ # 7个查询节点
│ │ └── api/
│ │ └── query_server.py # FastAPI 查询服务(端口 8001)
│ ├── test/ # 测试
│ │ └── test_import_main_graph.py # 导入全流程测试
│ ├── tool/ # 工具脚本
│ │ └── download_reranker.py # 模型下载
│ └── utils/ # 通用工具
│ ├── log_utils.py # 日志(loguru)
│ ├── path_util.py # 项目路径常量
│ ├── sse_utils.py # SSE 服务端推送
│ ├── task_utils.py # 任务状态管理
│ └── ...
├── prompts/ # Prompt 模板(见下方说明)
├── output/ # 导入中间产物(按日期/任务ID组织,可定期清理)
├── .env_example # 环境变量模板
├── pyproject.toml # 项目依赖配置
└── uv.lock # 依赖锁文件
```
## Prompt 模板
系统核心行为由 `prompts/` 目录下的 6 个模板驱动:
| 文件 | 调用节点 | 用途 |
|------|----------|------|
| `rewritten_query_and_itemnames.prompt` | node_item_name_confirm | 根据历史对话提取商品名 + 重写问题 |
| `hyde_prompt.prompt` | node_search_embedding_hyde | 生成假设性答案用于 HyDE 检索 |
| `answer_out.prompt` | node_answer_output | 基于检索上下文 + 历史生成最终答案 |
| `item_name_recognition.prompt` | node_item_name_recognition | 导入时从文档分块中提取商品名 |
| `image_summary.prompt` | node_md_img | 对文档中的图片生成文字摘要 |
| `product_recognition_system.prompt` | 系统级 | 商品识别系统提示词 |
模板使用 Python `str.format(**kwargs)` 渲染变量占位符,通过 `app/core/load_prompt.py` 统一加载。
## 数据库设计
### Milvus 向量库 Collection
| Collection | 用途 | 关键字段 |
|------------|------|----------|
| `kb_chunks` | 文档切片存储 | `chunk_id`(INT64 PK), `dense_vector`, `sparse_vector`, `content`, `file_title`, `title`, `parent_title`, `item_name` |
| `kb_item_names` | 商品名向量索引 | `item_name`, `dense_vector`, `sparse_vector` |
| `kb_graph_entity_names` | 知识图谱实体名(预留) | — |
### MongoDB 对话历史
Collection 存储用户与助手的对话记录,字段包括:`session_id`, `role`(user/assistant), `text`, `rewritten_query`, `item_names`, `ts`(时间戳)。
### MinIO 对象存储
存储从文档中提取的图片文件,按 `minio_img_dir` 配置的目录组织。
## 核心流程
### 文档导入流水线(7 节点)
```
PDF上传 → node_entry(校验) → node_pdf_to_md(MinerU解析) → node_md_img(图片处理→MinIO)
→ node_document_split(语义分块) → node_item_name_recognition(LLM提取商品名)
→ node_bge_embedding(稠密+稀疏向量化) → node_import_milvus(入库)
```
分块策略:
- 粗粒度:基于 Markdown 标题层级切分,保证语义完整
- 细粒度:`RecursiveCharacterTextSplitter` 二次切分,单 chunk 上限 2000 字符(约 512-1500 token),下限 500 字符(短 chunk 合并)
- 无标题文档自动生成默认标题兜底
### 查询检索流水线(7 节点)
```
用户提问
↓
node_item_name_confirm ── 无明确商品名 → node_answer_output(返回引导提示)
↓ 有明确商品名
三路并行召回 ─┬─ node_search_embedding (问题向量 → Milvus 混合搜索, 权重 0.8:0.2)
├─ node_search_embedding_hyde (LLM生成假设答案 → 问题+答案向量检索, 权重 0.9:0.1)
└─ node_web_search_mcp (百练 MCP 联网搜索)
↓
node_rrf (同源三路 Reciprocal Rank Fusion, 权重 1.0:1.0:1.0)
↓
node_rerank (RRF+Web合并 → BGE Reranker Cross-Encoder 精排 → 断崖截断动态 Top-K)
↓
node_answer_output (组装 Prompt → LLM生成 → SSE流式推送 / 同步返回)
```
断崖截断算法参数:
- `RERANK_MAX_TOPK = 10`(硬上限)
- `RERANK_MIN_TOPK = 1`(保底值)
- `RERANK_GAP_RATIO = 0.25`(相对断崖阈值)
- `RERANK_GAP_ABS = 0.5`(绝对断崖阈值)
## 技术栈
| 类别 | 技术 | 说明 |
|------|------|------|
| **框架** | FastAPI + Uvicorn | Web API 服务 |
| **工作流** | LangGraph | 有状态 DAG 工作流编排 |
| **向量数据库** | Milvus | 混合向量检索(稠密 COSINE + 稀疏 IP) |
| **嵌入模型** | BGE-M3 (BAAI) | 稠密 1024 维 + 稀疏向量双表示,内置 L2 归一化 |
| **重排序** | BGE Reranker (FlagEmbedding) | Cross-Encoder 精排,支持归一化打分 |
| **LLM** | 通义千问 (兼容 OpenAI API) | 意图识别、HyDE 生成、答案润色 |
| **对象存储** | MinIO | 文档图片存储 |
| **历史记录** | MongoDB | 对话历史持久化 |
| **PDF 解析** | MinerU (magic-pdf) | PDF → Markdown 高精度解析 |
| **图数据库** | Neo4j | 知识图谱存储(可选) |
| **网络搜索** | 百练 MCP (Bailian) | 联网搜索补充外部信息 |
| **评测** | Ragas 0.4.3 | RAG 检索层+生成层质量评测 |
## 快速开始
### 环境要求
- Python >= 3.12
- Milvus 向量数据库
- MongoDB
- MinIO
- Neo4j(可选)
### 启动依赖服务(Docker)
```bash
# Milvus
docker run -d --name milvus-standalone \
-p 19530:19530 -p 9091:9091 \
milvusdb/milvus:latest
# MongoDB
docker run -d --name mongo \
-p 27017:27017 \
mongo:7
# MinIO
docker run -d --name minio \
-p 9000:9000 -p 9001:9001 \
-e MINIO_ROOT_USER=minioadmin -e MINIO_ROOT_PASSWORD=minioadmin \
minio/minio server /data --console-address ":9001"
```
### 安装依赖
```bash
git clone
cd dataset_rag
# 使用 uv 管理依赖(推荐)
uv sync
# 或使用 pip
pip install -e .
```
### 配置环境变量
```bash
cp .env_example .env
# 编辑 .env 文件,填入对应的 API Key 和服务地址
```
核心配置项:
| 变量 | 说明 |
|------|------|
| `ALIBABA_API_KEY` / `ALIBABA_BASE_URL` | 通义千问 API 配置 |
| `LLM_DEFAULT_MODEL` | 默认 LLM 模型名(如 `qwen3-32b`) |
| `LLM_DEFAULT_TEMPERATURE` | LLM 温度参数(默认 0.1) |
| `MILVUS_URL` | Milvus 服务地址(如 `http://localhost:19530`) |
| `CHUNKS_COLLECTION` | 切片集合名(默认 `kb_chunks`) |
| `ITEM_NAME_COLLECTION` | 商品名集合名(默认 `kb_item_names`) |
| `MONGO_URL` / `MONGO_DB_NAME` | MongoDB 连接配置 |
| `MINIO_ENDPOINT` / `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY` | MinIO 配置 |
| `BGE_M3_PATH` | BGE-M3 模型路径(本地路径或 `BAAI/bge-m3` 自动下载) |
| `BGE_DEVICE` | 运行设备(`cpu` 或 `cuda:0`) |
| `BGE_FP16` | 是否开启半精度(GPU 建议 1,CPU 必须 0) |
| `BGE_RERANKER_LARGE` | BGE Reranker 模型路径 |
| `BGE_RERANKER_DEVICE` | Reranker 运行设备 |
| `BGE_RERANKER_FP16` | Reranker 半精度开关 |
| `MCP_DASHSCOPE_BASE_URL` | 百练 MCP 网络搜索地址 |
| `MINERU_API_TOKEN` / `MINERU_BASE_URL` | MinerU PDF 解析服务 |
### 启动服务
```bash
# 启动文档导入服务(端口 8000)
python -m app.import_process.api.import_server
# 启动查询服务(端口 8001)
python -m app.query_process.api.query_server
```
### API 端点
**导入服务 (端口 8000):**
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/import` | 文件上传页面 |
| POST | `/upload` | 上传文件并启动异步导入流程 |
| GET | `/status/{task_id}` | 轮询查询导入任务进度(返回 done_list / running_list) |
**查询服务 (端口 8001):**
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/health` | 健康检查 |
| GET | `/chat.html` | 对话页面 |
| POST | `/query` | 发起提问(`is_stream=true` 开启流式) |
| GET | `/stream/{session_id}` | SSE 长连接,实时接收流式答案 |
| GET | `/history/{session_id}` | 查询历史对话(支持 `limit` 参数) |
| DELETE | `/history/{session_id}` | 清除指定会话的历史记录 |
## 测试
```bash
# 导入全流程测试(需要 Milvus + BGE-M3 模型可用)
python -m app.test.test_import_main_graph
# 各节点也支持独立测试
python -m app.query_process.agent.nodes.node_item_name_confirm
python -m app.query_process.agent.nodes.node_search_embedding
python -m app.query_process.agent.nodes.node_search_embedding_hyde
python -m app.query_process.agent.nodes.node_web_search_mcp
python -m app.query_process.agent.nodes.node_rrf
python -m app.query_process.agent.nodes.node_rerank
python -m app.query_process.agent.nodes.node_answer_output
```
## 评测
```bash
# 1. 编辑评测数据集 app/eval/testset.json
# 2. 运行评测
python app/eval/run_eval.py
# 3. 查看结果 app/eval/eval_result.json
```
评测指标:
| 指标 | 评估层 | 含义 |
|------|--------|------|
| `context_precision` | 检索层 | 相关文档是否排在检索结果前列 |
| `context_relevance` | 检索层 | 检索结果与问题的相关性比例 |
| `faithfulness` | 生成层 | 答案是否忠实于检索上下文(有无编造) |
| `answer_correctness` | 生成层 | 答案与标注答案的一致性 |
## 项目特点
1. **多路召回融合**:向量检索 + HyDE 假设性检索 + 网络搜索,三路并行召回提升覆盖率
2. **混合向量检索**:BGE-M3 生成的稠密向量 + 稀疏向量,在 Milvus 中执行加权混合搜索
3. **断崖截断算法**:RRF 融合 + BGE Reranker 精排后,通过相对/绝对阈值动态确定 Top-K,避免低质文档混入
4. **流式输出**:基于 SSE(Server-Sent Events)实现答案逐字推送,支持中途断开
5. **项目名识别**:LLM 提取项目名 → Milvus 向量校验 → 评分分级(≥0.85 确认 / ≥0.6 可选 / <0.6 忽略),解决指代消歧和模糊提问
6. **完整的评测体系**:基于 Ragas 框架的检索层 + 生成层量化评估,支持自定义标注数据集
## 开发注意事项
### 模型加载
- **BGE-M3 模型较大(~2GB)**,首次运行时若未配置本地路径则会自动从 HuggingFace 下载
- 所有模型采用**单例模式**(`_bge_m3_ef`, `_reranker_model`, `_llm_client_cache`),避免重复加载
- LLM 客户端按 `(model, json_mode)` 元组缓存,不同配置互不影响
### CPU vs GPU
| 配置 | BGE_DEVICE | BGE_FP16 | 说明 |
|------|-----------|----------|------|
| GPU | `cuda:0` | `1` | 半精度加速,显存要求 ~4GB |
| CPU | `cpu` | `0` | 单精度(FP32),内存要求 ~4GB |
### 目录说明
- `output/` — 导入流程中间产物(PDF→MD 转换结果、图片等),按 `日期/任务ID/` 组织,可定期清理
- `.venv/` — Python 虚拟环境(uv 管理)
- `.env` — 敏感配置,**不要提交到 Git**
### 分块参数调整
在 `node_document_split.py` 中调整:
- `DEFAULT_MAX_CONTENT_LENGTH = 2000` — 单 chunk 最大字符数
- `MIN_CONTENT_LENGTH = 500` — 短 chunk 合并阈值