# 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. 环境配置 复制示例配置并修改: ```bash cp .env.example .env ``` 编辑 `.env`,至少配置: ```bash 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 运行(推荐) ```bash docker-compose up -d --build ``` 服务将运行在 `http://localhost:7331`,Web UI 直接通过该地址访问。 ### 3. 本地开发 启动后端: ```bash python -m venv .venv source .venv/bin/activate pip install -r requirements.txt uvicorn main:app --reload --port 7331 ``` 启动前端(新终端): ```bash cd frontend npm install npm run dev ``` 前端开发服务器运行在 `http://localhost:7332`,代理到后端 `http://localhost:7331`。 ## 核心流程 服务启动后: 1. 自动初始化 SQLite 数据库。 2. 若 `app_settings` 表为空,使用 `.env` 中的值初始化默认配置。 3. 若 `taxonomy` 表为空,调用 LLM 生成分类/标签/打分规则(仅一次)。 4. 启动定时任务: - **摘要任务**:每 `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 `。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,避免耦合。 ## 配置说明 配置分两层: 1. **环境变量(`.env`)**:首次启动时的默认值,Docker 运行时使用。 2. **数据库配置(`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