LangChain — RAG 构建知识库(实操)
VipRAG 是一个面向小规模正式服务的中文医学指南检索增强生成(RAG)项目。系统使用在线 MinerU 解析 PDF、DashScope 生成文本向量、Qdrant 检索、MySQL 保存文档与任务 状态,并通过千问生成带来源的回答。以《中国心血管病风险评估和管理指南.pdf》做为知识库,构建RAG系统,模拟生产环境,部署成多人使用、长期运行的 FastAPI 服务,直接采用 Qdrant 向量库
LangChain — RAG 构建知识库(理论)
Python 项目部署(Linux)
各大向量数据库对比(Vector Database)
环境要求
- Python 3.12+
- MySQL 5.7
- Qdrant v1.18.3
- MinerU API 令牌
- DashScope API 密钥,供文本嵌入和千问使用
项目不需要 GPU
项目构建
项目分两个部分知识库构建、用户问答
可以理解成,把上次搞的 Dify — Chatflow - 文档知识库 用代码手搓了一遍
知识库构建 → 上传 PDF → FastAPI → MySQL ingestion_job
↓
独立 Worker
↓
MinerU API → Markdown 缓存
↓
LangChain 切分 → DashScope Embeddings
↓
Qdrant
用户问题 → DashScope Embeddings → Qdrant 检索 → 千问 → 答案与来源
FastAPI 和入库工作进程是两个独立进程。PDF 解析不会占用 API 请求,也不会因 API 重启而丢失。MinerU 返回的 ZIP 和 Markdown 会保存在 data,重新向量化时无需 再次消耗 MinerU 额度。
知识库构建
![]() |
![]() |
| 知识库构建 | 用户提问 |
FastAPI
- 上传文件
- 生成以 document_id (UUID) 命名的目录,用于存放文件
- 将文件流存到 documents/document_id 目录中
- 计算 SHA-256 去重
- 验证 PDF 签名
- 调用 repository 保存元数据, ingestion_jobs.status = JobStatus.PENDING 供 独立Worker切片
独立 Worker
- 读取 .env 配置
- 构建 Qdrant Client、Embedding、Qwen、MinerU 等对象
- 创建 data 数据目录、MySQL 表结构
- 任务处理(将文档切分成文本块,存入向量库)
4.1 查询 ingestion_jobs 表 status=PENDING 且 attempts < max_attempts 的待处理记录(job),按时间排序,取最早的一个进行后续处理
4.2 根据 job.document_id 查询 documents 表,形成 JobWorkItem 对象。并将 ingestion_jobs、documents 表字段 status 标记成 PROCESSING,如果没查到将该job记录标记成 job.status = JobStatus.FAILED,
4.3 调用 MinerU 解析 PDF → 得到 Markdown、Archive -> 存到 data/documents 目录: full.md、mineru-result.zip
4.4 将 Markdown 通过递归字符切分(RecursiveCharacterTextSplitter)切分成文本块(Chunks)
4.5 调用 Embedding 模型(text-embedding-v4)生成向量
4.6 将文本块、向量,构建成 points 存入 Qdrant 向量数据库
4.7 将 ingestion_jobs 任务数据状态标记成 JobStatus.SUCCEEDED - 如果第4步处理失败,并且没有达到重试上限,将 status 设成 PENDING,如果达到重试上限,status 设成 FAILED,该任务不再继续
- 继续任务处理(重复第4步),如果没有任务停N秒钟
状态变化为:
pending → processing → indexing → ready
↘ failed
只有状态为 ready 的文档才应视为可查询。重复上传内容完全相同的 PDF 会根据SHA-256 返回已有文档,不会再次调用 MinerU。
用户问答
- 问题向量化 ──► embed_query(question)
- 向量检索 ──► search(knowledge_base_id, query_vector, top_k)
- 上下文裁剪 ──► fit_context(chunks) [控制token长度]
- 构建提示 ──► build_context(selected)
- 千问生成答案 ──► generate(question, context)
- 返回结果 + 来源标注
数据模型
MySQL 保存 knowledge_bases、documents 和 ingestion_jobs。文档由知识库与SHA-256 共同标识,因此重复上传具有幂等性。文档状态在 pending、processing、indexing、ready 或 failed 之间转换。任务保留供应商任务 ID、尝试次数和经过清理的错误信息。
每个 Qdrant 点包含分块文本以及 knowledge_base_id、document_id、document_version、filename、title_path、MinerU 提供时的页码信息、chunk_index、content_hash 和 status。检索按知识库和 status=active 过滤。
组件
- config: 验证环境配置且不暴露密钥。
- database: 管理异步 SQLAlchemy 引擎、会话和 MySQL 模型。
- documents: 接收 PDF、计算内容哈希、创建幂等入库任务并报告任务状态。
- mineru: 向 MinerU 提交本地 PDF、轮询异步任务、下载并解压 Markdown 结果,
将供应商失败映射为领域错误。 - ingestion: 领取任务、持久化解析产物、切分 Markdown、批量生成向量、向 Qdrant
更新或插入点,并发布文档版本。 - retrieval: 对问题生成向量,并仅检索指定知识库中的活动分块。
- generation: 构建受约束的医学指南提示词并调用 Qwen。
- api: 将领域结果和失败转换为稳定的 HTTP 响应。
UV安装
忽略安装过程,Windows可参考: Windows 安装 UV
初始项目
D:\OpenSource\Python\VipRAG>uv --version
uv 0.9.18 (0cee76417 2025-12-16)
D:\OpenSource\Python\VipRAG>uv python install 3.12
Python 3.12 is already installed
D:\OpenSource\Python\VipRAG>uv init -p 3.12
Initialized project `deploydemo`
D:\OpenSource\Python\VipRAG>uv run main.py
Using CPython 3.12.12
Creating virtual environment at: .venv
Hello from viprag!
D:\OpenSource\Python\VipRAG>
本地开发
uv sync
uv run pytest -q
uv run uvicorn app.main:app --reload
另开终端启动入库工作进程:
uv run python -m app.worker
本地直接运行时需要自行启动 MySQL 和 Qdrant,并将 .env 中的主机名从 Compose
服务名改为本机地址。
API
| 方法 | 路径 | 用途 |
|---|---|---|
GET |
/health/live |
进程存活检查 |
GET |
/health/ready |
运行时依赖已装配 |
POST |
/api/v1/knowledge-bases/{id}/documents |
上传 PDF |
GET |
/api/v1/documents/{id} |
查询入库状态 |
POST |
/api/v1/answer |
检索并生成回答 |
上传文件
{knowledge_base_id} 用户自己定义 如:cardiovascular
curl.exe -X POST "http://localhost:8000/api/v1/knowledge-bases/{knowledge_base_id}/documents" `
-F "file=@app/resources/中国心血管病风险评估和管理指南.pdf;type=application/pdf"

返回:
{
"document_id": "b86beaf7-fe81-4ed8-8492-9fb7dfafdb39",
"knowledge_base_id": "vipsoft",
"filename": "中国心血管病风险评估和管理指南.pdf",
"status": "pending",
"version": 1,
"created": true,
"error_message": null
}
Worker 解析文档

切块后入Qdrant向量库

查询文档状态
curl.exe "http://localhost:8000/api/v1/documents/{document_id}"

用户提问
curl.exe -X POST "http://localhost:8000/api/v1/answer" `
-H "Content-Type: application/json" `
-d '{"knowledge_base_id":"{knowledge_base_id}","question":"心血管疾病膳食营养有哪些?"}'

源码地址
本文来自博客园,作者:VipSoft 转载请注明原文链接:https://www.cnblogs.com/vipsoft/p/22065225


浙公网安备 33010602011771号