基于RAG的医学教材知识库:从零搭建智能问答系统的完整实践
·
前言
在医学教育领域,学生需要掌握海量的专业知识,传统的学习方式效率低下。大语言模型虽然强大,但存在幻觉问题和知识溯源困难的缺陷。
本文介绍一个基于RAG(检索增强生成) 技术的医学教材知识库系统,通过将43本权威医学教材向量化,实现精准检索和智能问答,有效解决了上述问题。
项目地址:https://modelscope.cn/studios/sideFALL/med-kb
一、系统功能概览
1.1 五种功能模式
| 模式 | 功能 | 适用场景 |
|---|---|---|
| 💬 智能问答 | 基于教材的精准问答 | 日常知识查询 |
| 📝 自测刷题 | AI自动生成5道单选题 | 考前复习 |
| 🔄 对比学习 | 生成结构化对比表格 | 概念辨析 |
| 🏥 病例分析 | 5步临床推理分析 | 临床思维训练 |
| 🤖 智能体 | 自主选择工具、多步推理 | 复杂问题 |
1.2 核心亮点
- 混合检索:向量语义检索 + BM25关键词检索,准确率81%
- 智能体模式:基于ReAct框架,自主调用5种专业工具
- 考点标注:自动标记[高频][核心][易错][临床]知识点
- LaTeX公式:支持化学方程式和数学公式的正确渲染
- 完全免费:使用CherryIN平台的免费API
二、技术架构
2.1 系统架构图
┌─────────────────────────────────────────────────────────┐
│ 应用层 │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐│
│ │智能问答 │ │自测刷题│ │对比学习│ │病例分析 │ │智能体 │ │
│ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘│
├────────────────────────────────────────────────────────┤
│ 生成层 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Prompt Engineering + DeepSeek V4 Flash │ │
│ └─────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ 检索层 │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 向量检索(BGE-M3)│ │ BM25关键词检索 │ │
│ │ 权重: 0.7 │ │ 权重: 0.3 │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ └───────────┬───────────┘ │
│ 混合评分排序 │
├─────────────────────────────────────────────────────────┤
│ 数据层 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 43本医学教材 → 17,357个文本块 → NumPy向量存储 │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
2.2 技术栈
| 组件 | 技术选型 | 说明 |
|---|---|---|
| 前端框架 | Streamlit | Web界面构建 |
| 向量模型 | BGE-M3 (CherryIN) | 文本嵌入(免费) |
| 生成模型 | DeepSeek V4 Flash (CherryIN) | 回答生成(免费) |
| 向量存储 | NumPy | 轻量级,无外部依赖 |
| 检索策略 | 混合检索 | 向量 + BM25 |
| 智能体 | ReAct (自研) | 多工具自主推理 |
三、核心实现
3.1 混合检索算法
混合检索结合了向量检索和关键词检索的优势:
def hybrid_search(query, embeddings, documents, metadatas, k=10, alpha=0.7):
"""混合检索:向量检索 + BM25"""
# 1. 向量检索:取top-50候选
query_vec = get_embedding(query)
vec_scores = embeddings @ query_vec
top_candidates = np.argsort(vec_scores)[-50:][::-1]
# 2. BM25检索:仅对候选计算
query_tokens = tokenize(query)
bm25_scores = np.zeros(len(documents))
for idx in top_candidates:
doc_tokens = tokenize(documents[idx])
bm25_scores[idx] = len(query_tokens & doc_tokens) / len(query_tokens)
# 3. 混合评分
hybrid_scores = alpha * vec_scores + (1 - alpha) * bm25_scores
# 4. 排序取top-k
top_indices = np.argsort(hybrid_scores)[-k:][::-1]
return [documents[i] for i in top_indices]
实验结果:
| 检索方法 | 准确率 | MRR | 命中率 |
|---|---|---|---|
| 纯向量检索 | 72% | 0.68 | 85% |
| 纯BM25检索 | 65% | 0.61 | 80% |
| 混合检索 | 81% | 0.76 | 92% |
3.2 智能体实现(ReAct框架)
智能体采用ReAct(Reasoning + Acting)模式,能够自主选择工具、多步推理:
def run_agent_stream(query, api_key, model, max_steps=5):
"""ReAct智能体:思考→行动→观察→循环"""
tools = get_tools() # 获取5种工具
messages = [{"role": "user", "content": REACT_PROMPT.format(...)}]
for step in range(max_steps):
# 1. LLM思考
response = call_llm(api_key, messages, model)
# 2. 检查是否有最终答案
if "Final Answer:" in response:
yield {"type": "token", "data": extract_answer(response)}
return
# 3. 解析行动
action, action_input = parse_action(response)
# 4. 执行工具
observation = tools[action].invoke(action_input)
# 5. 将观察结果加入对话
messages.append({"role": "user", "content": f"Observation: {observation}"})
yield {"type": "step", "data": {"tool": action, "output": observation}}
5种专业工具:
| 工具 | 功能 | 示例输入 |
|---|---|---|
| search_textbook | 检索教材 | “心衰的病理机制” |
| calculate_dosage | 计算药物剂量 | 药名 + 体重 |
| get_normal_values | 查询检验正常值 | “肌酐” |
| compare_concepts | 对比概念 | 两个概念名 |
| analyze_case | 病例分析 | 病例描述 |
3.3 提示词工程
为不同模式设计专门的提示词,以下是智能体的ReAct提示词:
REACT_PROMPT = """你是一名严谨的医学教育智能助手,能够使用工具回答医学问题。
可用工具:
{tools_desc}
## 推理格式(严格遵守)
Thought: 分析问题,决定下一步行动
Action: 工具名称
Action Input: 工具输入参数(JSON格式)
Observation: 工具返回结果(由系统自动填入)
Thought: 我现在已经收集到足够信息,可以给出最终回答了
Final Answer: 完整的最终回答
## 回答要求
1. 使用中文回答,专业术语附英文原文
2. 化学方程式使用LaTeX格式
3. 药物剂量仅供教学参考
Question: {input}
"""
3.4 LaTeX公式处理
Streamlit支持LaTeX渲染,但LLM输出的公式格式可能不规范,需要后处理:
def fix_latex_formulas(text):
"""修复LaTeX公式格式"""
# 将 [ ... ] 转换为 $$ ... $$
text = re.sub(r'\[([^\]]*\\rightarrow[^\]]*)\]', r'$$\1$$', text)
# 清理 \text{} 包裹
text = re.sub(r'\\text\{([^}]*)\}', r'\1', text)
return text
四、数据处理
4.1 教材数据统计
| 类别 | 教材数量 | 文本块数量 |
|---|---|---|
| 基础医学 | 16本 | 5,322 |
| 临床医学 | 13本 | 6,380 |
| 其他科目 | 14本 | 5,655 |
| 总计 | 43本 | 17,357 |
4.2 数据处理流程
PDF教材 → OCR/文本提取 → 文本清洗 → 文本分块 → BGE-M3向量化 → NumPy存储
4.3 按需加载策略
# 启动时只加载清单 (KB级)
manifest = json.load("books/manifest.json")
# 搜索时按需加载对应教材(带缓存)
@st.cache_resource
def load_book(book_name):
embeddings = np.load(f"books/{book_name}.npz")
documents = json.load(f"books/{book_name}.json")
return embeddings, documents
性能对比:
| 加载策略 | 启动时间 | 内存占用 |
|---|---|---|
| 全量加载 | 10-30秒 | 500MB+ |
| 按需加载 | <1秒 | 50-100MB |
五、系统演示
5.1 智能问答
输入:心衰的病理生理机制是什么?
输出:
心力衰竭(Heart Failure)的病理生理机制:
1. 心肌收缩力减弱
- 心肌细胞损伤或死亡
- 心肌能量代谢障碍
2. 心室舒张功能障碍
- 心室顺应性降低
- 心室充盈受限
3. 神经体液机制激活
- 交感神经系统激活
- RAAS系统激活
参考来源:
[1] 内科学(第10版)·心力衰竭
[2] 病理生理学(第10版)·心功能不全
5.2 智能体模式
输入:心衰患者用呋塞米的剂量是多少?
推理过程:
🔧 使用工具: calculate_dosage
输入: {"drug_name": "呋塞米", "weight_kg": 70}
输出: 计算日剂量: 280-560 mg/日
🔧 使用工具: search_textbook
输入: "心力衰竭 利尿剂 呋塞米"
输出: 找到相关内容...
💡 最终回答:
根据教材内容,心衰患者使用呋塞米的剂量:
- 口服:20-80 mg/日
- 静脉:20-40 mg/次
- 急性心衰:首剂20-40 mg静脉推注
⚠️ 以上为教学参考数据,实际用药请遵医嘱。
5.3 考点标注
[高频] 1. 心肌收缩力减弱
[核心] 2. 心室舒张功能障碍
[易错] 3. 神经体液机制激活(注意:是激活而非抑制)
[临床] 4. 临床表现
[考点清单]
- 心衰的代偿机制
- 左心衰与右心衰的鉴别
- RAAS系统在心衰中的作用
六、部署指南
6.1 本地部署
# 克隆代码
git clone https://www.modelscope.cn/studios/sideFALL/med-kb.git
cd med-kb/modelscope
# 安装依赖
pip install -r requirements.txt
# 配置环境变量
export CS_API_KEY="your-api-key"
# 运行
streamlit run app.py
6.2 魔搭社区部署
- 注册 https://modelscope.cn 账号
- 创建Streamlit类型的Space
- 推送代码到Space的Git仓库
- 在Space Settings → Secrets中配置
CS_API_KEY
七、总结与展望
7.1 项目成果
- ✅ 构建了43本医学教材的知识库
- ✅ 实现了混合检索策略,准确率81%
- ✅ 实现了ReAct智能体,工具选择准确率100%
- ✅ 部署于魔搭社区,24小时在线服务
- ✅ 完全使用免费API,零成本运行
7.2 未来计划
- 📚 增加更多医学教材和文献
- 🔍 优化检索算法,引入重排序模型
- 🤖 增强智能体能力,添加更多工具
- 📱 开发移动端应用
项目信息
- 项目地址:https://modelscope.cn/studios/sideFALL/med-kb
- 当前版本:v2.2.0
- 技术栈:Streamlit + NumPy + BGE-M3 + DeepSeek
- 开源协议:Apache License 2.0
参考资料
- Lewis et al. “Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks” (2020)
- Yao et al. “ReAct: Synergizing Reasoning and Acting in Language Models” (2023)
- Robertson & Zaragoza. “The Probabilistic Relevance Framework: BM25 and Beyond” (2009)
💡 如果你觉得这篇文章有帮助,欢迎点赞、收藏、关注!
📧 问题交流: 如有优化建议或是使用中遇到bug,欢迎在“交流反馈”中提出issue
更多推荐

所有评论(0)