336 lines
13 KiB
Markdown
336 lines
13 KiB
Markdown
# 医药新闻聚合系统 — 设计方案
|
||
|
||
> 版本:v1.0 | 日期:2026-05-24
|
||
|
||
---
|
||
|
||
## 一、项目目标
|
||
|
||
每日自动抓取全网中英文医药新闻(约 100 条),经 AI 深度加工后精选 10 条,以网页形式展示,未来对接微信小程序。
|
||
|
||
---
|
||
|
||
## 二、整体架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ 定时调度器 │
|
||
│ APScheduler (每日 06:00) │
|
||
└───────────────────────┬─────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ 抓取层 Crawler │
|
||
│ RSS Fetcher │ HTTP Scraper │ NewsAPI Client │
|
||
│ (中文源) │ (备用) │ (英文源) │
|
||
└───────────────────────┬─────────────────────────────┘
|
||
↓ 原始新闻 (~100条/天)
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ 数据库 PostgreSQL │
|
||
│ raw_news │ processed_news │ llm_config │
|
||
│ │ news_sources │ system_logs │
|
||
└───────────────────────┬─────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ AI 处理流水线 │
|
||
│ 1. 相关性过滤(去除非医药内容) │
|
||
│ 2. 去重(相似度检测) │
|
||
│ 3. 摘要生成(中文,150字) │
|
||
│ 4. 观点提炼(核心结论/影响) │
|
||
│ 5. 关键词提取(5-8个标签) │
|
||
│ 6. 重要性评级(1-10分 + 理由) │
|
||
│ 7. 分类标注(4个类别) │
|
||
│ 8. 精选 TOP 10 │
|
||
└───────────────────────┬─────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ FastAPI 后端 │
|
||
│ 读者 API │ 管理员 API │
|
||
│ GET /news │ POST /admin/llm-config │
|
||
│ GET /news/{id} │ GET /admin/sources │
|
||
│ GET /news/featured │ POST /admin/trigger-crawl │
|
||
└───────────────────────┬─────────────────────────────┘
|
||
↓
|
||
┌───────────────┴───────────────┐
|
||
↓ ↓
|
||
┌──────────────┐ ┌──────────────────┐
|
||
│ Vue 3 前端 │ │ 未来:微信小程序 │
|
||
│ 读者页 + 管理 │ │ (复用同一 API) │
|
||
└──────────────┘ └──────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 三、技术栈
|
||
|
||
| 层级 | 技术 | 版本 | 说明 |
|
||
|------|------|------|------|
|
||
| 任务调度 | APScheduler | 3.x | 每日定时触发,支持手动触发 |
|
||
| 爬虫 | httpx + BeautifulSoup4 | — | 异步 HTTP,HTML 解析 |
|
||
| RSS 解析 | feedparser | — | 解析 RSS/Atom 订阅源 |
|
||
| AI 调用 | 统一适配层(见下) | — | 支持多 LLM 提供商切换 |
|
||
| 后端框架 | FastAPI | 0.11x | 异步,自动生成 OpenAPI 文档 |
|
||
| 数据库 | PostgreSQL 16 | — | 主存储,支持全文搜索 |
|
||
| ORM | SQLAlchemy 2 + Alembic | — | 数据模型 + 迁移 |
|
||
| 前端框架 | Vue 3 + Vite | — | 组合式 API |
|
||
| UI 组件库 | Element Plus | — | 中文生态好,适配小程序迁移 |
|
||
| 部署 | Docker Compose | — | 容器化,国内服务器一键启动 |
|
||
|
||
---
|
||
|
||
## 四、LLM 适配层设计
|
||
|
||
> 国内服务器无法直连 Claude API,需要支持可切换的 LLM 提供商。
|
||
|
||
```python
|
||
# 统一接口,后端只调用这一层
|
||
class LLMClient:
|
||
provider: str # "openai" | "anthropic" | "qwen" | "deepseek" | "custom"
|
||
api_key: str
|
||
base_url: str # 支持自定义 endpoint(代理/国内镜像)
|
||
model: str
|
||
|
||
async def complete(self, messages: list, response_format="json") -> str:
|
||
# 内部适配不同 provider 的 SDK/HTTP 接口
|
||
...
|
||
```
|
||
|
||
**支持的 LLM 提供商(管理页可配置):**
|
||
|
||
| 提供商 | 说明 | 推荐模型 |
|
||
|--------|------|----------|
|
||
| DeepSeek | 国内可直连,性价比高 | deepseek-chat |
|
||
| 通义千问 (Qwen) | 阿里云,国内服务器友好 | qwen-plus |
|
||
| OpenAI 兼容 | 走代理或第三方中转 | gpt-4o-mini |
|
||
| Anthropic Claude | 走代理 | claude-sonnet-4-6 |
|
||
| 自定义 Endpoint | 私有部署模型 | 自填 |
|
||
|
||
---
|
||
|
||
## 五、数据库模型
|
||
|
||
```sql
|
||
-- 新闻来源配置
|
||
news_sources (
|
||
id, name, url, type ENUM('rss','scrape'),
|
||
language ENUM('zh','en'), category, is_active,
|
||
created_at, updated_at
|
||
)
|
||
|
||
-- 原始抓取数据
|
||
raw_news (
|
||
id, source_id, title, url, raw_content,
|
||
published_at, crawled_at,
|
||
status ENUM('pending','processed','skipped','error')
|
||
)
|
||
|
||
-- AI 处理后数据
|
||
processed_news (
|
||
id, raw_news_id,
|
||
title_zh, -- 中文标题(英文原文翻译或原标题)
|
||
summary, -- 中文摘要(150字)
|
||
opinion, -- 核心观点/影响(100字)
|
||
keywords TEXT[], -- 关键词数组
|
||
importance_score, -- 重要性 1-10
|
||
importance_reason, -- 评分理由
|
||
category ENUM('药品监管','临床研究','行业动态','政策法规'),
|
||
is_featured BOOL, -- 是否入选当日 TOP 10
|
||
featured_rank, -- TOP 10 排名
|
||
processed_at
|
||
)
|
||
|
||
-- LLM 配置(管理页维护)
|
||
llm_config (
|
||
id, name, provider, api_key, base_url,
|
||
model_name, is_active, created_at
|
||
)
|
||
|
||
-- 系统运行日志
|
||
system_logs (
|
||
id, event_type, message, details JSONB, created_at
|
||
)
|
||
```
|
||
|
||
---
|
||
|
||
## 六、AI 处理 Prompt 设计
|
||
|
||
每条新闻用一次 LLM 调用,返回结构化 JSON:
|
||
|
||
```
|
||
你是医药行业资深分析师。请分析以下新闻,返回 JSON 格式结果。
|
||
|
||
新闻标题:{title}
|
||
新闻内容:{content}
|
||
新闻语言:{zh|en}
|
||
|
||
请返回:
|
||
{
|
||
"is_medical_related": true/false, // 是否与医药相关
|
||
"title_zh": "中文标题",
|
||
"summary": "中文摘要(100-150字)",
|
||
"opinion": "核心观点或行业影响(50-100字)",
|
||
"keywords": ["关键词1", ..., "关键词5"],
|
||
"importance_score": 1-10,
|
||
"importance_reason": "评分理由(30字内)",
|
||
"category": "药品监管|临床研究|行业动态|政策法规"
|
||
}
|
||
|
||
评分标准:
|
||
9-10: 重大政策/突破性研究/重要监管决定
|
||
7-8: 行业重要动态,影响范围广
|
||
5-6: 常规行业新闻,有一定参考价值
|
||
1-4: 普通资讯,信息价值有限
|
||
```
|
||
|
||
**TOP 10 精选策略:**
|
||
1. 过滤掉 `is_medical_related = false`
|
||
2. 按 `importance_score` 降序排列
|
||
3. 每个 category 至少保留 1 条(保证多样性)
|
||
4. 最终取前 10 条
|
||
|
||
---
|
||
|
||
## 七、新闻数据来源(初始列表)
|
||
|
||
### 中文 RSS 源
|
||
| 来源 | URL | 类别 |
|
||
|------|-----|------|
|
||
| 国家药监局 | https://www.nmpa.gov.cn/rss | 药品监管 |
|
||
| 丁香园 | https://www.dxy.cn/rss | 临床研究 |
|
||
| 医学界 | https://www.yxj.org.cn/rss | 行业动态 |
|
||
| 健康时报 | http://www.jksb.com.cn/rss | 行业动态 |
|
||
|
||
### 英文 RSS 源
|
||
| 来源 | URL | 类别 |
|
||
|------|-----|------|
|
||
| STAT News | https://www.statnews.com/feed | 临床研究 |
|
||
| FiercePharma | https://www.fiercepharma.com/rss/xml | 行业动态 |
|
||
| FDA News | https://www.fda.gov/about-fda/contact-fda/stay-informed/rss-feeds/fda-news-feed/rss.xml | 药品监管 |
|
||
| PubMed (医药) | https://pubmed.ncbi.nlm.nih.gov/rss/... | 临床研究 |
|
||
|
||
> 注:以上 URL 需在开发时验证可用性,部分需要爬虫替代 RSS。
|
||
|
||
---
|
||
|
||
## 八、目录结构
|
||
|
||
```
|
||
ai_news_v1/
|
||
├── backend/
|
||
│ ├── app/
|
||
│ │ ├── main.py # FastAPI 入口
|
||
│ │ ├── config.py # 环境变量配置
|
||
│ │ ├── database.py # DB 连接
|
||
│ │ ├── models/
|
||
│ │ │ ├── news.py
|
||
│ │ │ ├── source.py
|
||
│ │ │ └── llm_config.py
|
||
│ │ ├── api/
|
||
│ │ │ ├── news.py # 读者 API
|
||
│ │ │ └── admin.py # 管理 API
|
||
│ │ ├── crawler/
|
||
│ │ │ ├── rss_fetcher.py # RSS 抓取
|
||
│ │ │ └── http_fetcher.py # HTTP 爬取(备用)
|
||
│ │ ├── ai/
|
||
│ │ │ ├── llm_client.py # 统一 LLM 适配层
|
||
│ │ │ ├── processor.py # AI 处理流水线
|
||
│ │ │ └── selector.py # TOP 10 精选逻辑
|
||
│ │ └── scheduler.py # APScheduler 定时任务
|
||
│ ├── alembic/ # 数据库迁移
|
||
│ ├── requirements.txt
|
||
│ └── Dockerfile
|
||
├── frontend/
|
||
│ ├── src/
|
||
│ │ ├── views/
|
||
│ │ │ ├── NewsReader.vue # 读者主页
|
||
│ │ │ ├── NewsDetail.vue # 新闻详情
|
||
│ │ │ └── Admin.vue # 管理后台
|
||
│ │ ├── components/
|
||
│ │ │ ├── NewsCard.vue
|
||
│ │ │ └── FeaturedBadge.vue
|
||
│ │ └── api/
|
||
│ │ └── index.ts # API 调用封装
|
||
│ ├── package.json
|
||
│ └── Dockerfile
|
||
├── docker-compose.yml
|
||
├── docker-compose.prod.yml
|
||
├── .env.example
|
||
└── DESIGN.md # 本文档
|
||
```
|
||
|
||
---
|
||
|
||
## 九、API 接口设计
|
||
|
||
### 读者端
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/news/featured` | 当日精选 TOP 10 |
|
||
| GET | `/api/news?date=&category=&page=` | 新闻列表(分页) |
|
||
| GET | `/api/news/{id}` | 新闻详情 |
|
||
| GET | `/api/news/dates` | 有数据的日期列表 |
|
||
|
||
### 管理端(需 Bearer Token 鉴权)
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET/POST | `/api/admin/llm-config` | 查看/更新 LLM 配置 |
|
||
| GET | `/api/admin/sources` | 新闻源列表 |
|
||
| POST | `/api/admin/sources` | 添加新闻源 |
|
||
| PUT | `/api/admin/sources/{id}` | 启用/禁用新闻源 |
|
||
| POST | `/api/admin/crawl/trigger` | 手动触发抓取 |
|
||
| GET | `/api/admin/logs` | 查看运行日志 |
|
||
| GET | `/api/admin/stats` | 今日抓取统计 |
|
||
|
||
---
|
||
|
||
## 十、前端页面设计
|
||
|
||
### 读者主页
|
||
- 顶部:Logo + 今日日期 + 上次更新时间
|
||
- 主区:精选 TOP 10 卡片列表,每张卡片含:
|
||
- 重要性评分角标(红/橙/蓝)
|
||
- 中文标题
|
||
- AI 摘要(折叠展开)
|
||
- 核心观点
|
||
- 关键词标签
|
||
- 来源 + 原文链接
|
||
- 侧边栏(或 Tab):按分类筛选、历史日期切换
|
||
|
||
### 管理后台
|
||
- LLM 配置面板:provider 选择、API Key、Base URL、模型名、连接测试按钮
|
||
- 新闻源管理:表格 + 启用/禁用开关 + 添加
|
||
- 手动触发:一键触发今日抓取 + 进度显示
|
||
- 运行日志:最近 100 条日志,带时间戳和级别
|
||
|
||
---
|
||
|
||
## 十一、部署方案
|
||
|
||
```yaml
|
||
# docker-compose.yml 核心服务
|
||
services:
|
||
db: # PostgreSQL
|
||
backend: # FastAPI
|
||
frontend: # Vue (Nginx 静态托管)
|
||
scheduler: # APScheduler (可合并入 backend)
|
||
```
|
||
|
||
**国内服务器注意事项:**
|
||
- LLM API 如需访问境外服务,在服务器配置出口代理,或选用 DeepSeek/Qwen 等国内可直连的模型
|
||
- pip/npm 镜像切换为阿里云/清华源
|
||
|
||
---
|
||
|
||
## 十二、开发阶段划分
|
||
|
||
| 阶段 | 内容 | 预估工作量 |
|
||
|------|------|-----------|
|
||
| Phase 1 | DB 模型 + FastAPI 骨架 + LLM 适配层 | 2天 |
|
||
| Phase 2 | RSS 抓取 + AI 处理流水线 + 定时任务 | 3天 |
|
||
| Phase 3 | 读者前端(主页 + 详情) | 2天 |
|
||
| Phase 4 | 管理后台前端 | 2天 |
|
||
| Phase 5 | Docker 部署 + 联调测试 | 1天 |
|
||
| 合计 | | **约 10 个工作日** |
|