基于私有数据的中文知识问答与错题重点系统。使用 BGE-M3 进行向量化、Milvus 保存和检索向量,支持 TXT、Markdown、Word、PDF 文档。
问答遵循固定顺序:先检索个人知识库;相似度达到阈值时依据私有资料回答;证据不足时再调用通用大模型。大模型补充的答案会明确标记,只有用户点击确认后才会写入个人知识库。
知识快问支持多会话记忆。会话与消息持久化在 MySQL 中,后续追问会结合最近对话理解指代和省略,同时仍以本轮检索到的私有资料作为事实依据。网页端可以新建、切换和删除历史会话。
integrated_qa_system/
├── config.ini # 所有模块的统一配置
├── base/
│ ├── config.py # 配置加载与环境变量覆盖
│ └── logger.py # 控制台与滚动文件日志
├── rag_qa/
│ ├── core/
│ │ ├── document_processor.py # 文档校验、解析、分块
│ │ ├── prompts.py # RAG 与错题提示模板
│ │ ├── query_classifier.py # 查询类型识别
│ │ ├── strategy_selector.py # 分类对应的检索策略
│ │ ├── vector_store.py # BGE-M3 与 Milvus
│ │ └── rag_system.py # RAG 编排核心
│ ├── storage/
│ │ ├── database.py # SQLite 文档与错题数据
│ │ └── mysql_chat_memory.py # MySQL 会话与消息数据
│ ├── web/
│ │ ├── main.py # FastAPI 接口
│ │ ├── schemas.py # API 数据模型
│ │ └── static/ # Web 页面
│ └── main.py # 独立 CLI 入口
├── logs/
│ └── app.log # 运行日志(首次运行生成)
├── tests/
├── requirements.txt
└── run.py # IDE 兼容启动入口
所有默认配置位于 config.ini:
[milvus]:本地 Milvus Lite 或远程 Milvus 地址[mysql]:会话记忆数据库地址、账号、库名和字符集[embedding]:BGE-M3 模型、设备、维度和批量大小[llm]:OpenAI 兼容接口,可连接 Ollama、vLLM、LM Studio 等[retrieval]:各类问题的召回数量和阈值[fallback]:知识库不足时是否调用大模型,以及确认写回目录[ocr]:PDF OCR 开关、模式、渲染 DPI 和文字质量阈值[documents]:分块和上传限制[server]:Web 服务地址[logging]:日志级别与滚动策略
config.ini 只保存可公开的默认值。真实密钥和远程数据库令牌必须使用环境变量提供,不要写入配置文件、README、日志或提交记录。支持的敏感配置包括 LLM_API_KEY、LLM_BASE_URL、LLM_MODEL、MILVUS_URI、MILVUS_TOKEN 和 MYSQL_PASSWORD。
PowerShell 当前终端配置示例:
$env:LLM_API_KEY = "替换为你自己的密钥"
$env:LLM_BASE_URL = "https://api.deepseek.com"
$env:MYSQL_PASSWORD = "替换为你的 MySQL 密码"
D:\DevTools\Anaconda3\python.exe run.pyLinux/macOS 示例:
export LLM_API_KEY="替换为你自己的密钥"
export LLM_BASE_URL="https://api.deepseek.com"
export MYSQL_PASSWORD="替换为你的 MySQL 密码"
python run.py环境变量只需在运行服务的环境中设置。仓库中的 api_key 和 token 应始终保持为空。
服务首次启动时会自动创建配置的 MySQL 数据库、chat_sessions 和 chat_messages 表,因此数据库账号需要具备建库和建表权限。
若使用本地 Ollama,可在 config.ini 配置:
[llm]
base_url = http://127.0.0.1:11434/v1
api_key = ollama
model = qwen2.5:7b
temperature = 0.1api_key 为空时系统不会调用大模型;知识库没有答案时会明确提示尚未配置。云端模型可通过环境变量提供密钥。
PDF 入库默认使用 auto 模式:正常文字层直接解析;扫描页、空白文字层或乱码页先由 PyMuPDF 渲染,再使用 RapidOCR + ONNXRuntime 识别。这样可以修复异常中文字体映射,同时保留正常 PDF 中的代码和可复制文本。
[ocr]
enabled = true
mode = auto
dpi = 180
min_text_chars = 80
bad_char_ratio = 0.08
min_score = 0.50mode = always 会 OCR 所有 PDF 页面,耗时较长;mode = off 完全关闭 OCR。OCR 在上传工作线程中执行,不会阻塞 FastAPI 事件循环。
cd D:\WorkSpace\study\rag
D:\DevTools\Anaconda3\python.exe -m pip install -r requirements.txt入库:
D:\DevTools\Anaconda3\python.exe rag_qa\main.py store D:\资料\教材.pdf --category java
D:\DevTools\Anaconda3\python.exe rag_qa\main.py store D:\资料\hot100.md --category hot100查询:
D:\DevTools\Anaconda3\python.exe rag_qa\main.py query "这份教材的重点是什么?"列出文档:
D:\DevTools\Anaconda3\python.exe rag_qa\main.py documentsD:\DevTools\Anaconda3\python.exe rag_qa\main.py serve也可以在 IDE 中直接运行 run.py。访问 http://127.0.0.1:8000。
QueryClassifier 将查询分为事实、总结、对比、错题和通用类型。StrategySelector 随后选择对应策略:事实问题强调精确度;总结和对比问题扩大召回并进行多文档平衡;错题查询召回更多相关知识点。
资料领域分为 java、hot100、general。上传时可明确选择,也可使用 auto 自动识别。由大模型生成并经确认写回的资料,其 source_type 为 llm_generated,页面会显示“AI 回答”标识。
D:\DevTools\Anaconda3\python.exe -m pytest -q