# 中华药典 AI Agent 方案文档

> 版本：v1.2.0  
> 最后更新：2026-07-11  
> 项目代号：Pharmacopoeia AI

---

## 项目概述

为「开邻药惠购」微信小程序新增 AI 药典查询功能，面向药店医师、营业员和医生，提供基于《中华人民共和国药典》及 NMPA 官方数据的权威、及时、准确的药品信息查询服务。后续扩展为执业药师考试学习辅导平台。

### 核心目标

| 目标 | 说明 |
|------|------|
| **权威** | 数据源自药典原文 + NMPA 官方，AI 回答必须带来源引用 |
| **及时** | 爬虫增量更新，药典修订第一时间同步 |
| **准确** | RAG 强约束，不编造、不推测，置信度低时明示 |
| **可用** | 自然语言交互，三秒内返回结果，SSE 流式输出 |

---

## 技术栈

| 层级 | 技术 | 说明 |
|------|------|------|
| **小程序** | uni-app | 存量项目，增量开发 AI 模块 |
| **后端** | Python FastAPI | AI/ML 生态最完善 |
| **数据库** | PostgreSQL 16 + Redis | 结构化数据 + 缓存/限流 |
| **向量库** | pgvector (PostgreSQL 扩展) | 与主库一体，免维护，Milvus 等价能力 |
| **Embedding** | BGE-M3 | 中文最优，1024维 + 稀疏向量 |
| **重排序** | BGE-Reranker-v2-m3 | Cross-Encoder 精排 |
| **LLM（当前）** | Qwen API（阿里云百炼 DashScope） | OpenAI 兼容，qwen-max / qwen-plus，中文能力强 |
| **LLM（后期）** | Qwen3-35B-A3B 本地部署 | MoE 模型，激活 3B，推理成本低 |
| **推理框架** | vLLM | 高吞吐，Continuous Batching |
| **爬虫** | Scrapy + Selenium | 数据采集 |
| **管理后台** | Vue3 + Vite | 数据管理 / 反馈审核 |
| **部署** | Docker Compose → K8s | 渐进式部署 |

---

## 整体架构

```
┌────────────────────────────────────────────────────────┐
│        微信小程序 "开邻药惠购"（uni-app 存量 + AI 增量）   │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────────┐  │
│  │ 现有首页  │  │ 药品浏览  │  │ ✨ AI 药典查询（新增） │  │
│  │ +入口按钮 │  │ +问 AI   │  │   自然语言对话式查询   │  │
│  └──────────┘  └──────────┘  └──────────┬───────────┘  │
└──────────────────────────────────────────┼────────────┘
                                           │ HTTPS (SSE)
┌──────────────────────────────────────────▼────────────┐
│                   Nginx API 网关                        │
└─────────┬────────────────────────────────┬────────────┘
          │                                │
┌─────────▼──────────────┐   ┌────────────▼─────────────┐
│   FastAPI 后端服务       │   │   管理后台 (Vue3)         │
│  - JWT 鉴权 (微信登录)   │   │  - 数据导入管理          │
│  - 对话会话管理          │   │  - 反馈审核              │
│  - SSE 流式推送         │   │  - 知识库更新            │
│  - 限流 & 安全护栏       │   │  - 用量统计              │
└─────────┬──────────────┘   └──────────────────────────┘
          │
┌─────────▼──────────────────────────────────────────────┐
│                   RAG 引擎（核心）                       │
│                                                         │
│  用户问题 → 意图分类 → 混合检索 → 重排序 → LLM 生成      │
│               │          │          │          │        │
          │          ┌────▼────┐ ┌───▼────┐ ┌──▼────┐ ┌───▼────┐  │
          │          │ 药品查询 │ │向量检索 │ │BGE   │ │ Qwen  │  │
          │          │ 用法咨询 │ │BM25检索│ │Rerank│ │ API   │  │
│          │ 法规条款 │ │关键词  │ │      │ │        │  │
│          │ 考试答疑 │ └───┬────┘ └──────┘ └────────┘  │
│          └─────────┘     │                              │
│              ┌───────────▼─────────────┐               │
│              │ 知识库 (Milvus + PG)     │               │
│              │ ┌─────────────────────┐ │               │
│              │ │ 药典药品条目（向量）   │ │               │
│              │ │ 考试知识点（向量）     │ │               │
│              │ │ 结构化元数据 (PG)     │ │               │
│              │ └─────────────────────┘ │               │
│              └─────────────────────────┘               │
└─────────────────────────────────────────────────────────┘
```

---

## 目录结构

```
pharmacopoeia-ai/
│
├── backend/                        # FastAPI 后端
│   ├── app/
│   │   ├── api/
│   │   │   ├── chat.py             # SSE 流式对话
│   │   │   ├── drug.py             # 药品 CRUD
│   │   │   ├── auth.py             # 微信登录 / JWT
│   │   │   ├── exam/               # ✨ 学习模块（预留）
│   │   │   │   ├── chapter.py      #     章节知识点
│   │   │   │   ├── practice.py      #     刷题
│   │   │   │   ├── exam_qa.py      #     考试答疑
│   │   │   │   └── progress.py     #     学习进度
│   │   │   └── admin.py            # 管理后台 API
│   │   │   └── admin_knowledge.py    # 知识库维护 CRUD API
│   │   ├── core/
│   │   │   ├── config.py           # Pydantic Settings
│   │   │   ├── security.py         # JWT / 限流
│   │   │   └── llm_client.py       # DeepSeek / Qwen 统一调用
│   │   ├── rag/
│   │   │   ├── retriever.py        # 混合检索（向量 + BM25）
│   │   │   ├── retriever_exam.py   # 考试场景检索
│   │   │   ├── reranker.py         # BGE-Reranker-v2-m3
│   │   │   ├── prompt.py           # 多场景 Prompt 模板
│   │   │   └── intent.py           # 意图分类路由
│   │   ├── models/
│   │   │   ├── drug.py             # 药品 ORM
│   │   │   ├── conversation.py     # 对话 / 消息
│   │   │   ├── user.py             # 用户
│   │   │   ├── knowledge_point.py  # ✨ 知识点
│   │   │   ├── question.py         # ✨ 题目
│   │   │   └── user_progress.py    # ✨ 学习进度
│   │   └── main.py                 # FastAPI 入口
│   ├── alembic/                    # 数据库迁移
│   ├── requirements.txt
│   └── Dockerfile
│
├── data-pipeline/                  # 数据采集 & 处理管道
│   ├── crawlers/
│   │   ├── spider.py               # Scrapy 基础框架
│   │   ├── nmpa_spider.py          # NMPA 药品数据采集
│   │   ├── pharmacopoeia.py        # 药典 PDF 解析
│   │   └── exam_outline.py         # ✨ 考试大纲采集
│   ├── processors/
│   │   ├── chunker.py              # 药品条目切片
│   │   ├── knowledge_chunker.py    # ✨ 知识点切片
│   │   ├── question_generator.py   # ✨ AI 自动出题
│   │   ├── embedder.py             # BGE-M3 向量化
│   │   └── cleaner.py              # 文本清洗纠错
│   ├── schemas/
│   │   ├── drug_schema.json        # 药品数据结构
│   │   ├── knowledge_point.json    # ✨ 知识点结构
│   │   └── question_schema.json    # ✨ 题目结构
│   ├── docker-compose.yml
│   └── requirements.txt
│
├── miniprogram/                    # uni-app 微信小程序增量
│   ├── pages/
│   │   └── ai-yaodian/             # ✨ AI 药典查询页面
│   │       └── index.vue
│   ├── components/
│   │   └── ai-chat/                # ✨ 可复用 AI 对话组件
│   │       └── index.vue
│   ├── api/
│   │   └── ai.js                   # ✨ AI 模块 API
│   └── utils/
│       └── sse.js                  # ✨ SSE 流式接收
│
├── admin/                          # 管理后台 (Vue3)
│   ├── src/
│   │   ├── App.vue
│   │   ├── views/
│   │   │   ├── Dashboard.vue
│   │   │   ├── KnowledgeBase.vue
│   │   │   └── Feedback.vue
│   │   └── router/
│   │       └── index.js
│   ├── package.json
│   └── vite.config.js
│
├── deploy/                         # 部署配置
│   ├── nginx.conf
│   ├── supervisord.conf
│   └── k8s/                        # 后期 K8s 配置
│
├── docker-compose.yml              # 全栈一键启动
├── .env.example
├── .gitignore
├── SCHEME.md                       # 本文档
└── README.md
```

---

## 数据方案

### 数据来源

| 来源 | 数据类型 | 采集方式 | 优先级 |
|------|---------|---------|--------|
| NMPA 药品数据库 | 批准文号、说明书、备案 | Scrapy + Selenium | P0 |
| 药典 PDF | 正文内容（需已购买版权） | PyMuPDF 解析 | P0 |
| 省药监局公告 | 地方标准、补充批件 | API 接口 | P1 |
| 执业药师考试大纲 | 章节、考点分布 | 公开文档解析 | P2 |
| 历年真题 | 题目及答案 | 公开资料整理 | P2 |
| 丁香园/用药助手 | 药品说明书 | 公开 API（有限度） | P2 |

### 爬虫策略

- **频率控制**：2-5 秒/次，尊重 robots.txt
- **反爬对抗**：User-Agent 池 + 代理 IP 池轮换
- **增量采集**：按批准文号 / 更新时间差量，每日增量调度
- **容错**：失败重试 3 次 + 断点续传
- **监控**：爬虫健康状态告警，数据量异常检测

### 药典 PDF 解析流程

```
PDF 原文件
  → PyMuPDF 提取文本 + 坐标信息
  → 基于字体/位置识别标题层级（部/类/品种）
  → 正则匹配药品条目边界（"×××" 品种名称标记）
  → 结构化输出 JSON
```

**输出 schema：**

```json
{
  "drug_id": "H20000001",
  "name": "阿莫西林",
  "name_cn": "阿莫西林",
  "name_en": "Amoxicillin",
  "name_pinyin": "Amoxilin",
  "category": "化学药",
  "subcategory": "β-内酰胺类抗生素",
  "sections": {
    "性状": "白色或类白色结晶性粉末...",
    "鉴别": "(1) 取本品...",
    "检查": "酸度 取本品...",
    "含量测定": "照高效液相色谱法...",
    "类别": "β-内酰胺类抗生素",
    "贮藏": "遮光，密封保存",
    "制剂": "阿莫西林片、阿莫西林胶囊..."
  },
  "source": {
    "version": "2020年版",
    "volume": "二部",
    "page": "567-569",
    "entry_id": "Amoxicillin-2020-2"
  }
}
```

### 切片策略

| 内容类型 | 切片方式 | 理由 |
|---------|---------|------|
| 药品条目 | 按条目为单位（非固定长度） | 保证药品信息完整性 |
| 凡例/通则 | 按小标题切分 | 长篇法规需分段检索 |
| 考试知识点 | 按大纲章节切分 | 学习场景需要章节粒度 |

每个 chunk 附带元数据：药品名、分类、来源、版本、页码、章节、难度等级（考试场景）等。

### 向量化

- 模型：BGE-M3（BAAI），1024 维，支持稠密 + 稀疏向量
- 批次大小：32 条 / batch
- 更新策略：增量 Embedding，只处理新增 / 变更的 chunk

---

## RAG 引擎设计

### 意图分类

| 意图类型 | 路由策略 | 检索权重 |
|---------|---------|---------|
| 药品查询 | 精确匹配优先 + 语义兜底 | 向量 0.4 + BM25 0.6 |
| 用法用量 | 语义检索为主 | 向量 0.7 + BM25 0.3 |
| 法规条款 | BM25 关键词为主 | 向量 0.3 + BM25 0.7 |
| 综合 | 混合融合 | 向量 0.5 + BM25 0.5 |
| 考试答疑 | 按科目/章节过滤 + 语义检索 | 向量 0.6 + BM25 0.4 |

### 混合检索流程

```
用户问题
  → 意图分类（药品查询/用法咨询/法规条款/考试答疑）
  → 多路召回：
     ├── 向量检索（Milvus, Top-50）
     ├── BM25 关键词检索（PG 全文索引, Top-50）
     └── 结构化字段过滤（分类/章节/版本）
  → 融合去重
  → BGE-Reranker-v2-m3 重排序（Top-10）
  → 上下文完整性校验（确保药品条目不截断）
  → 送入 LLM
```

### Prompt 模板

**药品查询场景：**

```
你是中华药典AI助手，服务于药店医师和执业药师。
知识来源：最新版《中华人民共和国药典》及NMPA官方数据。

回答规则：
1. 必须严格基于提供的【药典原文】回答，不得添加原文没有的信息
2. 每个回答必须引用来源标注（药典版本/部/页码）
3. 若检索内容不足以回答问题，必须明确告知"药典中未找到相关内容"
4. 涉及处方药必须加注"请在医师指导下使用"
5. 回答格式：结论 → 原文引用 → 来源标注

【药典原文】
{检索到的上下文}

【用户问题】
{用户输入}
```

**考试辅导场景（预留）：**

```
你是执业药师考试辅导助手。你擅长将复杂的药典知识以易理解的方式讲解，
帮助考生掌握考点。知识来源：最新版《中华人民共和国药典》及执业药师考试大纲。

回答规则：
1. 基于检索到的药典原文和考试大纲知识点作答
2. 解释要通俗易懂，举一反三，对比归纳
3. 标注该知识点的考试频率和重点程度
4. 注重原理讲解而非死记硬背
5. 引用来源（药典版本/部/页/大纲章节）

【参考内容】
{检索到的上下文}

【用户问题】
{用户输入}
```

### 安全护栏

| 层级 | 措施 | 说明 |
|------|------|------|
| **输入过滤** | 敏感词检测 + 无关提问识别 | 拒绝非药典相关 + 违法提问 |
| **检索校验** | 检索相关性阈值 > 0.5 | 低于阈值则提示"未找到" |
| **输出校验** | 来源引用格式正则匹配 | 缺失引用则告警 + 标记低置信度 |
| **内容审核** | 违禁词二次过滤 | 政治敏感 / 违法药物信息拦截 |
| **免责声明** | 固定附加文案 | "本回答仅供参考，请以药典原文为准" |

---

## 学习模块设计（Phase 4 开发，当前预留）

### 核心功能

| 功能 | 描述 | 数据依赖 |
|------|------|---------|
| 章节化学习 | 按考试大纲展示知识点树，逐章学习 | knowledge_point 表 |
| AI 答疑 | 考试场景 RAG 检索，教学型回答 | 知识点向量库 |
| 智能出题 | LLM 自动生成 A/B/X 型题 + 解析 | 知识点 + 药典原文 |
| 刷题模式 | 顺序刷题 / 随机组卷 / 错题重做 | 题库 + 答题记录 |
| 错题集 | 按科目/章节分类，AI 分析薄弱点 | 答题记录表 |
| 模拟考试 | 按真实考试比例组卷，限时作答 | 审核通过的题库 |
| 考点预测 | 历年考点频率统计 + AI 趋势分析 | 历年真题数据 |
| 学习进度 | 章节完成度 / 正确率 / 学习时长 | user_progress 表 |

### 题库生成策略

```
知识点 + 药典原文
  → LLM 提取关键考点
  → 生成题干 + 正确答案 + 干扰项（需有迷惑性）
  → 自动验证：答案必须在原文中找到明确依据
  → 标注来源和知识点关联
  → 人工抽检审核（首次 100%，后续 10% 抽检）
  → 上线 + 用户反馈闭环淘汰低质量题
```

### 题库 Schema

```json
{
  "question_id": "Q202401001",
  "type": "A",                    // A型（单选）/ B型（配伍）/ X型（多选）
  "subject": "药学专业知识一",
  "chapter": "第01章 药品与药品质量标准",
  "difficulty": 3,
  "content": "关于阿莫西林的叙述，错误的是？",
  "options": [
    "A. 属于半合成青霉素",
    "B. 抗菌谱包括革兰阳性菌和阴性菌",
    "C. 口服吸收不受食物影响",
    "D. 与丙磺舒合用可延长半衰期"
  ],
  "answer": "C",
  "explanation": "阿莫西林口服吸收良好，但食物对吸收有轻微影响...",
  "knowledge_points": ["KP-01001", "KP-01005"],
  "source": "药典2020版 二部 P567-569",
  "audited": true,
  "frequency": "高频"
}
```

---

## 部署方案

### 初期（DeepSeek API 阶段）— 单机部署

```
┌────────────────────────────────────┐
│  4C 16G Linux 服务器 (x2，主备)     │
│                                    │
│  Primary:                          │
│  ├── Nginx (HTTPS + WAF)           │
│  ├── FastAPI (uvicorn x4 workers)  │
│  ├── PostgreSQL 16                 │
│  ├── Milvus Lite (向量库)          │
│  ├── Redis (缓存 / 限流)           │
│  └── Celery Worker (异步任务)      │
│                                    │
│  Standby:                          │
│  ├── PG 流复制（只读副本）           │
│  └── Milvus 定期备份               │
│                                    │
│  LLM: DeepSeek API (云端)          │
└────────────────────────────────────┘
```

### 后期（本地 Qwen 阶段）— GPU 服务器

```
┌────────────────────────────────────┐
│  GPU 推理服务器                     │
│  ├── 2× NVIDIA 4090 (24GB ×2)     │
│  ├── vLLM 推理框架                 │
│  └── Qwen3-35B-A3B (INT8 量化)    │
│      全量 ~70GB / INT8 ~35GB       │
│      2×4090 48GB 可支撑             │
│      预计并发 50-100 QPS           │
└────────────────────────────────────┘
```

---

## 成本估算

| 阶段 | 项目 | 月成本（元） | 备注 |
|------|------|------------|------|
| 初期 | 云服务器 (4C16G x2) | ~800 | 主备 |
| 初期 | Qwen API（阿里云百炼） | ~2,500 | 10万用户，90万次/月 |
| 初期 | CDN + 对象存储 + 其他 | ~500 | - |
| 初期 | **合计** | **~3,800** | - |
| | | | |
| 后期 | 云服务器 | ~800 | 不变 |
| 后期 | GPU 服务器 (2×4090) | ~3,000 | 按月租用 |
| 后期 | Qwen API（备用） | ~200 | 减少到 5 万次/月 |
| 后期 | **合计** | **~4,000** | 成本下降后持平 |

**Qwen API 成本测算（qwen-max）：**

| 指标 | 数值 |
|------|------|
| 用户总量 | 100,000 |
| 日活率 | 10% |
| 人均查询次数 | 3 次/天 |
| 月查询总量 | 900,000 次 |
| 单次输入 tokens | ~3,000 |
| 单次输出 tokens | ~500 |
| 月输入 tokens | 2,700M |
| 月输出 tokens | 450M |
| 输入单价 | ¥2.5 / 百万 tokens |
| 输出单价 | ¥10 / 百万 tokens |
| 月费用 | 2,700×2.5 + 450×10 ≈ 11,250 元 |

> 注：以上为 qwen-max 定价。实际可选用 qwen-plus（输入 ¥0.8/百万 tokens，输出 ¥2/百万 tokens）将成本降至约 3,000 元/月。

---

## 知识库维护 API

管理后台提供完整的 RESTful 接口，支持随时增删改查知识库内容：

### 药品管理
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/admin/knowledge/drugs` | 分页列表（支持关键词搜索、分类筛选） |
| GET | `/admin/knowledge/drugs/{id}` | 药品详情 |
| POST | `/admin/knowledge/drugs` | 新增药品 |
| PUT | `/admin/knowledge/drugs/{id}` | 更新药品 |
| DELETE | `/admin/knowledge/drugs/{id}` | 删除（软删除） |
| POST | `/admin/knowledge/drugs/import` | 批量导入（JSON/CSV） |
| POST | `/admin/knowledge/drugs/reindex` | 重建向量索引（全量/指定ID） |

### 知识点管理
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/admin/knowledge/knowledge-points` | 分页列表（按科目/章节/难度/频率筛选） |
| GET | `/admin/knowledge/knowledge-points/{id}` | 知识点详情 |
| POST | `/admin/knowledge/knowledge-points` | 新增知识点 |
| PUT | `/admin/knowledge/knowledge-points/{id}` | 更新知识点 |
| DELETE | `/admin/knowledge/knowledge-points/{id}` | 删除 |
| POST | `/admin/knowledge/knowledge-points/import` | 批量导入 |

### 题库管理
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/admin/knowledge/questions` | 分页列表（按科目/章节/题型/审核状态筛选） |
| GET | `/admin/knowledge/questions/{id}` | 题目详情 |
| POST | `/admin/knowledge/questions` | 新增题目 |
| PUT | `/admin/knowledge/questions/{id}` | 更新题目 |
| DELETE | `/admin/knowledge/questions/{id}` | 删除 |
| POST | `/admin/knowledge/questions/import` | 批量导入 |
| POST | `/admin/knowledge/questions/batch-audit` | 批量审核 |
| POST | `/admin/knowledge/questions/generate` | AI 根据知识点自动出题 |

### 知识库统计
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/admin/knowledge/stats` | 库总量、各分类统计、向量索引状态 |

---

## 分阶段实施计划

### Phase 1：骨架搭建（当前）
- [ ] 项目骨架生成（约 40 个文件）
- [ ] Docker Compose 全栈环境
- [ ] FastAPI 基础框架 + 路由注册
- [ ] 数据库模型（含考试模块预留）
- [ ] uni-app 小程序 AI 模块增量
- [ ] 管理后台骨架

### Phase 2：数据采集 & 知识库
- [ ] NMPA 爬虫开发 + 反爬对抗
- [ ] 药典 PDF 解析 + 结构化入库
- [ ] 切片 + BGE-M3 向量化
- [ ] Milvus 知识库构建
- [ ] 考试大纲知识点梳理标注
- [ ] 数据质量校验

### Phase 3：RAG 引擎 + AI 药典查询上线
- [ ] 混合检索实现
- [ ] BGE-Reranker 重排序
- [ ] Qwen API Prompt 工程调优
- [ ] 评测集 + 准确率测试（目标 >95%）
- [ ] 小程序 AI 问药页面开发
- [ ] 限流 / 安全护栏
- [ ] 压力测试 + 小程序审核

### Phase 4：学习模块开发
- [ ] 章节化知识点学习
- [ ] AI 自动出题 + 题库管理
- [ ] 刷题 / 错题集 / 模拟考试
- [ ] AI 考试答疑
- [ ] 学习进度追踪 + 考点分析
- [ ] 上线审核

---

## 关键风险 & 应对

| 风险 | 影响 | 应对 |
|------|------|------|
| **药典数据版权** | 法律风险 | 仅使用已购买授权的正版药典；NMPA 公开数据为主 |
| **爬虫被封** | 数据中断 | IP 代理池 + 频率控制 + 多源备份 |
| **AI 幻觉编造** | 安全风险 | RAG 强约束 + 引用校验 + 置信度阈值 |
| **医疗合规审核** | 上线受阻 | 已有资格证书；固定免责声明；不提供处方建议 |
| **小程序审核** | 上线延期 | 参考医疗类小程序审核规则；内容审核前置 |
| **本地模型推理性能** | 用户体验差 | vLLM + 量化 + GPU 规格充分；留 Qwen API 兜底 |

---

## 变更记录

| 版本 | 日期 | 变更内容 |
|------|------|---------|
| v1.2.0 | 2026-07-11 | RAG 链路打通（pgvector 向量检索 + DashScope Embedding + Qwen LLM 端到端）；意图分类优化；新增 DATA_GUIDE.md / CRAWLER_ASSESSMENT.md / MINIPROGRAM_INTEGRATION.md 三份操作文档 |
| v1.1.0 | 2026-07-11 | LLM 切换为 Qwen API（阿里云百炼 DashScope）；新增知识库维护 CRUD API（药品/知识点/题库管理、批量导入、向量重建索引）；更新成本估算 |
| v1.0.0 | 2026-07-11 | 初始版本，包含完整方案和 Phase 1 骨架计划 |
