传智教育 EduRAG 智慧问答系统
基于 RAG(Retrieval-Augmented Generation,检索增强生成)的 IT 教育领域智能问答系统。系统融合传统检索、向量检索与大语言模型,面向黑马程序员(传智教育)的课程咨询场景,支持多模态文档接入、流式问答与对话历史管理。
Rag的作用
i. 解决知识时效性问题
ii. 减少幻觉(Hallucination)
iii. 领域适应性更强
iv. 数据隐私与可控性
v. 成本与效率优化
vi. 可解释性提升
一、项目简介
本项目面向 IT 教育咨询场景,能够针对用户提问,按"精确匹配 → 知识库检索 → 通用大模型"的优先级给出回答,并支持流式输出、多轮对话、学科过滤与效果评估。系统同时是一个面向教学的 RAG 完整链路示例,涵盖文档加载、分层切块、混合检索、重排序、意图识别、策略路由、效果评估等关键环节。
核心特性
- 三层问答架构:BM25 + Redis/MySQL 精确匹配 → 向量 RAG 检索 → LLM 通用知识兜底
- 多模态文档加载:PDF(含 OCR)、PPT/PPTX、DOCX、图片(OCR)、Markdown、TXT
- 分层切块(父子块):父块提供上下文,子块用于精准检索
- 混合检索 + 重排序:BGE-M3 稠密 + 稀疏向量混合检索,BGE-Reranker 重排序
- 查询意图分类:基于 BERT 微调的二分类(通用知识 / 专业咨询)
- 多检索策略:直接检索、HyDE 假设问题、子查询拆分、回溯问题简化(由 LLM 自动选择)
- 流式输出:基于 WebSocket 的逐 Token 流式回答
- 对话历史:MySQL 持久化,保留最近 5 轮上下文
- 学科过滤:支持 ai / java / test / ops / bigdata 等学科过滤
- 效果评估:集成 RAGAS 进行忠实度、答案相关性等指标评估
- 性能测试:基于 Locust 的 HTTP 与 WebSocket 压测
二、系统架构
用户提问
│
▼
┌──────────────────────────────────────────────────────────┐
│ 第一层:日常问候识别 (正则模板匹配) │
│ 命中 → 直接返回模板回复 │
└──────────────────────────────────────────────────────────┘
│ 未命中
▼
┌──────────────────────────────────────────────────────────┐
│ 第二层:BM25 + Redis/MySQL 精确匹配 │
│ Redis 缓存命中 / BM25 softmax 相似度 ≥ 阈值 → 返回答案 │
└──────────────────────────────────────────────────────────┘
│ 未找到可靠答案
▼
┌──────────────────────────────────────────────────────────┐
│ 第三层:RAG 系统 │
│ 1. BERT 意图分类 (通用知识 / 专业咨询) │
│ ├─ 通用知识 → 直接调用 LLM │
│ └─ 专业咨询 ↓ │
│ 2. LLM 策略选择 (直接 / HyDE / 子查询 / 回溯) │
│ 3. BGE-M3 混合检索 (稠密 + 稀疏) → BGE-Reranker 重排序 │
│ 4. 组装 Prompt (上下文 + 历史 + 问题) → LLM 流式生成 │
└──────────────────────────────────────────────────────────┘
三、项目结构
Itcast_qa_system/
├── app.py # FastAPI 服务入口 (HTTP + WebSocket)
├── new_main.py # 集成问答系统 + CLI 交互入口
├── config.ini # 配置文件 (MySQL/Redis/Milvus/LLM/检索参数)
├── requirements-windows.txt # Windows 依赖
├── requirements-mac.txt # Mac 依赖
├── locust_test.py # Locust 性能测试脚本
│
├── base/ # 基础模块
│ ├── config.py # 配置加载 (读取 config.ini)
│ └── logger.py # 日志配置
│
├── mysql_qa/ # 第二层:BM25 精确匹配问答
│ ├── db/mysql_client.py # MySQL 客户端 (问题/答案存取)
│ ├── cache/redis_client.py # Redis 客户端 (缓存问答与分词结果)
│ ├── retrieval/bm25_search.py# BM25 检索 (softmax 归一化 + 阈值过滤)
│ ├── utils/preprocess.py # 文本预处理 (分词)
│ ├── data/JP学科知识问答.csv # 学科问答原始数据
│ └── sql_main.py # 独立 MySQL 问答入口
│
├── rag_qa/ # 第三层:RAG 检索增强生成
│ ├── rag_main.py # RAG 独立入口 (数据处理/查询模式)
│ ├── core/ # RAG 核心逻辑
│ │ ├── rag_system.py # RAG 系统 (非流式版本)
│ │ ├── new_rag_system.py # RAG 系统 (流式 + 对话历史版本)
│ │ ├── vector_store.py # 向量存储 (Milvus 混合检索 + 重排序)
│ │ ├── document_loader.py # 文档加载入口 (按扩展名分发)
│ │ ├── document_processor.py# 文档分层切块 (父块/子块)
│ │ ├── query_classifier.py # BERT 查询意图分类器 (含训练)
│ │ ├── strategy_selector.py# LLM 检索策略选择器
│ │ ├── prompts.py # Prompt 模板 (RAG/HyDE/子查询/回溯)
│ │ ├── train_bert.py # BERT 分类模型训练脚本
│ │ ├── bert_query_classifier/ # 微调后的 BERT 意图分类模型
│ │ └── output/ # 训练 checkpoint
│ ├── edu_document_loaders/ # 多模态文档加载器
│ │ ├── edu_pdfloader.py # PDF 加载 (PyMuPDF + OCR)
│ │ ├── edu_pptloader.py # PPT/PPTX 加载
│ │ ├── edu_docloader.py # DOCX 加载 + OCR 工具
│ │ └── edu_imgloader.py # 图片加载 (OCR)
│ ├── edu_text_spliter/ # 文本切分器
│ │ ├── edu_chinese_recursive_text_splitter.py # 中文递归切分
│ │ └── edu_model_text_spliter.py # 模型切分 (BERT 文档分割)
│ ├── models/ # 预训练模型
│ │ ├── bge-m3/ # BGE-M3 嵌入模型 (稠密+稀疏)
│ │ ├── bge-reranker-large/ # BGE-Reranker 重排序模型
│ │ └── nlp_bert_document-segmentation_chinese-base/ # 文档分割模型
│ ├── classify_data/ # 意图分类训练数据 (大模型生成)
│ ├── rag_assesment/ # RAGAS 效果评估
│ │ ├── ragas_evaluate.py # RAGAS 评估脚本
│ │ └── rag_evaluate_data.json
│ └── data/ # RAG 知识库源文档
│ ├── ai_data/ # AI 学科资料 (PDF/MD)
│ └── samples/ # 多模态样本 (PDF/PPTX/DOCX/PNG/ZIP)
│
├── static/ # 前端页面
│ ├── index.html # 问答 Web 界面
│ └── src/App.jsx # React 组件
│
├── docker/ # Docker 编排
│ ├── milvus_redis/docker-compose.yml # Milvus + etcd + minio + Redis
│ └── mysql/docker-compose.yml # MySQL
│
├── logs/ # 运行日志
├── demo/ # 教学示例 (FastAPI/Logging/Redis)
└── notebooks/ # Jupyter 笔记本 (模型/工具探索)
四、技术栈
| 类别 | 技术 / 模型 |
|---|---|
| Web 框架 | FastAPI + Uvicorn + WebSocket |
| 大语言模型 | 阿里云 DashScope(通义千问 Qwen 系列,OpenAI 兼容接口) |
| 向量数据库 | Milvus 2.4 |
| 嵌入模型 | BGE-M3(稠密 + 稀疏 + ColBERT,1024 维) |
| 重排序模型 | BGE-Reranker-Large(CrossEncoder) |
| 意图分类 | BERT(bert-base-chinese 微调,2 分类) |
| 文档分割 | nlp_bert_document-segmentation_chinese-base |
| 关系数据库 | MySQL(问答库 + 对话历史) |
| 缓存 | Redis(问答缓存 + 分词缓存) |
| OCR | RapidOCR(onnxruntime / paddle) |
| 文档解析 | PyMuPDF、python-pptx、python-docx |
| 检索算法 | rank-bm25(BM25Okapi) |
| 效果评估 | RAGAS |
| 性能测试 | Locust |
| 前端 | HTML + React(App.jsx) |
五、环境准备
1. Python 依赖
# Windows
pip install -r requirements-windows.txt
# macOS
pip install -r requirements-mac.txt
2. 基础服务部署
使用 Docker Compose 启动 Milvus、Redis、etcd、MinIO:
cd docker/milvus_redis
docker-compose up -d
MySQL 可使用本地实例或自行通过 docker/mysql/docker-compose.yml 启动。
3. 配置文件
编辑根目录 config.ini,按需修改:
[mysql]:主机、账号、密码、数据库(默认库subjects_kg)[redis]:主机、端口、密码[milvus]:主机、端口、数据库名、集合名[llm]:模型名(如qwen3-max)、dashscope_api_key、dashscope_base_url[retrieval]:父块大小、子块大小、重叠、retrieval_k、candidate_m[app]:valid_sources(学科列表)、客服电话
注意:
DASHSCOPE_API_KEY优先从环境变量API_KEY读取(见base/config.py)。建议通过set API_KEY=sk-xxxxx(Windows)或export API_KEY=sk-xxxxx(Mac/Linux)注入,避免硬编码。
六、数据准备
1. 初始化 MySQL 问答库
将学科问答数据导入 jpkb 表(字段:学科名称、问题、答案):
from mysql_qa.db.mysql_client import MySQLClient
client = MySQLClient()
client.create_table()
client.insert_data('mysql_qa/data/JP学科知识问答.csv')
2. 构建向量知识库
将 rag_qa/data/<学科>_data/ 下的文档加载、切块、编码并写入 Milvus:
from rag_qa.core.vector_store import VectorStore
from rag_qa.core.document_processor import process_documents
vs = VectorStore() # 建表/加载集合
docs = process_documents('rag_qa/data/ai_data') # 文档读取 + 父子块切分
vs.add_documents(docs) # BGE-M3 编码 + 写入 Milvus
或通过 rag_qa/rag_main.py 的数据处理模式批量处理所有学科:
from rag_qa.rag_main import main
main(query_mode=False, directory_path='rag_qa/data')
七、启动方式
方式一:Web 服务(推荐)
启动 FastAPI 服务,提供 HTTP 与 WebSocket 接口及前端页面:
python app.py
- 服务地址:
http://localhost:8003 - 前端页面:浏览器访问
http://localhost:8003/ - API 文档:
http://localhost:8003/docs
方式二:CLI 交互模式
python new_main.py
在终端中输入问题进行交互式问答,支持学科过滤与对话历史查看。
方式三:独立 RAG 模式
python rag_qa/rag_main.py
仅使用 RAG 系统进行查询(不经过 BM25 层)。
八、API 接口
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | / |
前端问答页面 |
| POST | /api/create_session |
创建新会话,返回 session_id |
| POST | /api/query |
非流式查询(问候/BM25 命中直接返回;需 RAG 时提示走 WebSocket) |
| WS | /api/stream |
WebSocket 流式查询,逐 Token 返回 |
| GET | /api/history/{session_id} |
获取指定会话历史 |
| DELETE | /api/history/{session_id} |
清除指定会话历史 |
| GET | /api/sources |
获取支持的学科类别 |
| GET | /health |
健康检查 |
WebSocket 消息格式
客户端发送:
{"query": "AI学科学费是多少?", "source_filter": "ai", "session_id": "xxx"}
服务端返回(按序):
{"type": "start", "session_id": "xxx"}
{"type": "token", "token": "片段...", "session_id": "xxx"}
{"type": "end", "session_id": "xxx", "is_complete": true, "processing_time": 1.23}
九、模型训练
1. BERT 意图分类模型
意图分类用于区分"通用知识"与"专业咨询",决定是否触发 RAG 检索。
- 训练数据:
rag_qa/classify_data/(由大模型生成的 JSONL/JSON) - 训练脚本:
rag_qa/core/query_classifier.py或rag_qa/core/train_bert.py - 模型输出:
rag_qa/core/bert_query_classifier/
from rag_qa.core.query_classifier import QueryClassifier
clf = QueryClassifier(model_path='bert-base-chinese')
clf.train_model(data_file='rag_qa/classify_data/training_data_1000.json')
训练数据生成流程可参考 rag_qa/classify_data/数据生成与效果评估.md(可借助 Coze / Dify 智能体生成 + 质量过滤 + 自动评估)。
十、效果评估与性能测试
1. RAGAS 评估
使用 RAGAS 从忠实度(faithfulness)、答案相关性(answer_relevancy)、上下文相关性(context_precision)、上下文召回率(context_recall)四个维度评估 RAG 效果:
cd rag_qa/rag_assesment
python ragas_evaluate.py
评估数据:rag_evaluate_data.json,结果输出:ragas_evaluation_results.csv。
2. Locust 性能测试
模拟并发用户,压测 HTTP /api/query 与 WebSocket /api/stream,并记录首 Token 响应时间、Token 间隔与总耗时:
locust -f locust_test.py
访问 http://localhost:8089 配置并发数并启动测试,结果保存至 token_response_times.csv。
十一、关键参数说明
| 参数 | 配置项 | 默认值 | 说明 |
|---|---|---|---|
| BM25 相似度阈值 | bm25_search.search(threshold) |
0.85 | softmax 归一化后得分 ≥ 阈值才采纳 |
| 父块大小 | retrieval.parent_chunk_size |
1200 | 父块字符数(提供上下文) |
| 子块大小 | retrieval.child_chunk_size |
300 | 子块字符数(用于检索) |
| 块重叠 | retrieval.chunk_overlap |
50 | 切块重叠字符数 |
| 检索数量 | retrieval.retrieval_k |
3 | 混合检索 Top-K |
| 最终候选 | retrieval.candidate_m |
2 | 重排序后最终上下文数量 |
| 对话历史轮数 | new_main.py |
5 | MySQL 保留最近 5 轮 |
| 最大 Prompt 长度 | new_rag_system.py |
4096 | 超长截断 |
十二、注意事项
- 模型文件较大:
rag_qa/models/下的 BGE-M3、BGE-Reranker 等模型体积较大,需单独下载放置。 - GPU 加速:支持 CUDA / MPS 自动检测,无 GPU 时回退 CPU(编码与推理较慢)。
- OCR 依赖:PDF/图片 OCR 依赖 RapidOCR,首次加载模型需要一定时间。
- 配置安全:生产环境请勿将真实密钥写入
config.ini,建议统一通过环境变量注入。 - 学科扩展:新增学科需在
config.ini的valid_sources中添加,并在rag_qa/data/下创建<学科>_data目录放入文档后重新构建向量库。