Files
aihot/DESIGN.md
2026-05-24 01:16:07 +08:00

336 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 医药新闻聚合系统 — 设计方案
> 版本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 | — | 异步 HTTPHTML 解析 |
| 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 个工作日** |