778ccefb220dc7730833dfa4571ee0307167c683
后端 - 新增 app/task_progress.py 线程安全进度注册表 - 任务改为后台线程异步执行(_run_task_background),手动触发立即返回 task_key - 6 个任务函数(summarizer/tagger/scorer/deduplicator/brief/taxonomy)循环内上报进度 - scheduler 定时任务同步上报进度(trigger=scheduled) - 新增 GET /api/tasks/progress 与 POST /api/tasks/progress/reset 接口 - 新增 POST /api/test-connection 接口连通性测试(独立短超时客户端) - 修复 ai_client/rss_client 配置在 import 时固化的 bug(改为 property 运行时读取 settings), 导致实际任务用 .env 假 key 调 LLM 401 - 修复 ai_client 对 reasoning 模型(MiniMax-M3 等)输出 <think> 块的 JSON 解析失败 - 修复 taxonomy bootstrap:LLM 超时(改用 300s 专用 client)、MiniMax 输出审查 (精简样本仅标题 + 约束生成中性类目名)、失败误报 success(改抛异常如实标记) - 修复 models.py 双外键关系映射启动崩溃(显式 foreign_keys) - 修复 main.py SPA 路由 404、ArticleOut.published_at 序列化 500 - 移除 lifespan 同步 bootstrap 阻塞启动,改由 scheduler 后台异步执行 前端 - Deep Ink 高对比度暗色主题重构,修复 Element Plus 暗色模式对比度问题 - Tasks 页面任务进度实时展示(进度条/阶段/计数/状态/触发来源)+ 1.5s 轮询 - 接口测试面板(rssKeeper / LLM 连通性 + 延迟) - 修复 nextJobs jobId 映射 bug 部署与文档 - Dockerfile 优化(BuildKit 缓存挂载、预编译 wheel、去 gcc、阿里云镜像源) - 新增 API.md 接口文档 Co-Authored-By: Claude <noreply@anthropic.com>
dataClean
dataClean 是 rssKeeper 的下游数据清洗与加工服务,负责:
- 为无摘要或摘要过短的 RSS 文章生成 AI 摘要
- 维护本地 分类/标签/打分规则表,初始由 AI 生成,后续按规则执行
- 对文章自动 分类、打标签
- 计算三维度分数:热度、重要性、多源重复性
- 基于 URL 和 内容相似度去重
- 生成每日简报(Markdown 文件 + 结构化 JSON/API)
- 提供 Web UI 可视化展示结果并管理配置
技术栈
- 后端:Python 3.12 + FastAPI + SQLAlchemy 2.0 + SQLite + APScheduler
- 前端:Vue 3.4 + Element Plus 2.6 + Vite 5 + Axios
- AI:OpenAI API 兼容客户端
- 去重:scikit-learn(TF-IDF 相似度)
快速开始
1. 环境配置
复制示例配置并修改:
cp .env.example .env
编辑 .env,至少配置:
RSSKEEPER_BASE_URL=http://localhost:7329
OPENAI_API_KEY=sk-xxx
OPENAI_BASE_URL=https://api.openai.com/v1
OPENAI_MODEL=gpt-4o-mini
# 生产环境务必设置 API Token,Web UI 右上角可输入该 Token 后调用受保护接口
API_TOKEN=your-strong-token-here
# CORS 允许来源,逗号分隔;生产环境请填写具体域名
CORS_ALLOWED_ORIGINS=https://dataclean.example.com
2. Docker 运行(推荐)
docker-compose up -d --build
服务将运行在 http://localhost:7331,Web UI 直接通过该地址访问。
3. 本地开发
启动后端:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --reload --port 7331
启动前端(新终端):
cd frontend
npm install
npm run dev
前端开发服务器运行在 http://localhost:7332,代理到后端 http://localhost:7331。
核心流程
服务启动后:
- 自动初始化 SQLite 数据库。
- 若
app_settings表为空,使用.env中的值初始化默认配置。 - 若
taxonomy表为空,调用 LLM 生成分类/标签/打分规则(仅一次)。 - 启动定时任务:
- 摘要任务:每
SUMMARIZE_INTERVAL_MINUTES分钟(默认 60)拉取最近文章并补充 AI 摘要。 - 分类/打分/去重任务:每
TAG_SCORE_INTERVAL_MINUTES分钟(默认 1440,即 24 小时)执行。 - 每日简报:每天
08:00生成昨日/当日简报。
- 摘要任务:每
Web UI 功能
| 页面 | 功能 |
|---|---|
| 仪表盘 | 统计卡片、分类分布、最近简报、定时任务下次执行时间 |
| 文章列表 | 搜索、分类/标签筛选、代表文章过滤、分页、综合分排序 |
| 文章详情 | AI 摘要、标签分类、热度/重要性/重复度/综合分、原文链接 |
| 每日简报 | 简报列表、按分类聚合展示、重新生成 |
| 分类体系 | 分类/标签/打分规则查看、手动触发 AI 重新生成 |
| 任务管理 | 手动触发摘要/分类/去重/简报任务 |
| 系统配置 | 查看和修改所有配置项,保存到数据库,重启后生效 |
API 接口
| 接口 | 说明 |
|---|---|
GET /health |
健康检查 |
GET /api/articles |
查询加工后文章(返回 {items, total}) |
GET /api/articles/{id} |
单篇详情 |
GET /api/briefs |
简报列表 |
GET /api/briefs/{date} |
指定日期简报(YYYY-MM-DD) |
POST /api/briefs/{date}/regenerate |
手动重新生成简报(需 Token) |
GET /api/taxonomy |
分类/标签/规则列表 |
POST /api/taxonomy/bootstrap?force=true |
手动触发/重置分类体系(需 Token) |
POST /api/tasks/summarize |
手动触发摘要任务(需 Token,互斥锁) |
POST /api/tasks/tag-score-dedup |
手动触发分类/去重/打分任务(需 Token,互斥锁) |
POST /api/tasks/brief |
手动触发简报生成任务(需 Token,互斥锁) |
GET /api/settings |
获取所有可编辑配置(需 Token) |
PUT /api/settings/{key} |
更新单个配置(需 Token) |
PUT /api/settings |
批量更新配置(需 Token) |
POST /api/settings/reset |
重置为 .env 默认值(需 Token) |
GET /api/stats |
仪表盘统计数据 |
目录结构
dataClean/
├── main.py # FastAPI 入口
├── config.py # 环境变量配置
├── database.py # SQLite 连接
├── models.py # SQLAlchemy 模型
├── scheduler.py # APScheduler 定时任务
├── Dockerfile # 多阶段构建(含前端)
├── docker-compose.yml
├── requirements.txt
├── .env.example
├── README.md
├── app/ # 后端业务模块
│ ├── rss_client.py
│ ├── ai_client.py
│ ├── taxonomy.py
│ ├── summarizer.py
│ ├── tagger.py
│ ├── scorer.py
│ ├── deduplicator.py
│ ├── brief.py
│ └── settings_manager.py
├── tests/ # 后端测试
└── frontend/ # Vue 3 Web UI
├── package.json
├── vite.config.js
├── index.html
└── src/
├── main.js
├── App.vue
├── router/
├── api/
├── style.css
└── views/
安全说明
- API Token:生产环境请务必设置
API_TOKEN。所有写入类接口(修改配置、触发任务、重新生成分类/简报)都需要在请求头携带Authorization: Bearer <token>。Web UI 右上角提供 Token 输入框。 - CORS:默认不启用跨域 credentials。生产环境请通过
CORS_ALLOWED_ORIGINS设置具体域名,避免*+allow_credentials=True的安全风险。 - 容器权限:Dockerfile 已使用非 root 用户
app(uid=1000)运行服务。
与 rssKeeper 的关系
- dataClean 只读调用 rssKeeper 的外部 API(
/api/v1/external/*)。 - 所有加工结果(AI 摘要、标签、分数、去重组、简报)存储在 dataClean 本地 SQLite 中。
- 不回写 rssKeeper,避免耦合。
配置说明
配置分两层:
- 环境变量(
.env):首次启动时的默认值,Docker 运行时使用。 - 数据库配置(
app_settings表):通过 Web UI 修改后保存到这里,重启服务后生效。
详见 .env.example。关键配置:
| 变量 | 默认值 | 说明 |
|---|---|---|
RSSKEEPER_BASE_URL |
http://localhost:7329 |
rssKeeper 服务地址 |
OPENAI_API_KEY |
- | LLM API Key |
OPENAI_MODEL |
gpt-4o-mini |
模型名 |
SUMMARIZE_INTERVAL_MINUTES |
60 | 摘要任务间隔 |
TAG_SCORE_INTERVAL_MINUTES |
1440 | 分类/打分/去重任务间隔 |
DAILY_BRIEF_HOUR / MINUTE |
8 / 0 | 简报生成时间 |
TITLE_SIMILARITY_THRESHOLD |
0.85 | 标题相似度阈值 |
CONTENT_SIMILARITY_THRESHOLD |
0.80 | 内容相似度阈值 |
API_TOKEN |
- | API 鉴权 Token(为空不启用鉴权) |
CORS_ALLOWED_ORIGINS |
- | CORS 允许来源,逗号分隔 |
后续扩展
- 接入 rssKeeper 前端展示 enriched 数据
- 支持多语言摘要
- 接入向量数据库做语义检索
- 根据用户反馈调整 taxonomy 规则
- 引入 Alembic 数据库迁移
- Web UI 迁移到 TypeScript
Description
Languages
Python
60%
Vue
27.7%
CSS
8%
JavaScript
2.9%
Dockerfile
0.9%
Other
0.5%