feat: initial project structure
- Add FastAPI app with paper browsing UI and REST API - Add crawler service and database models - Add scripts for DB init and manual crawl - Add docs (api-and-ui, data-model, services) - Add requirements and project config
This commit is contained in:
@@ -0,0 +1,269 @@
|
||||
# 服务模块详解
|
||||
|
||||
> 本文档描述各服务模块的职责、输入输出、失败处理和实现约束。
|
||||
|
||||
---
|
||||
|
||||
## 1. 爬虫服务
|
||||
|
||||
**职责**:从 HuggingFace Daily Papers 获取论文列表,写入元数据。PDF 不在抓取阶段长期保存。
|
||||
|
||||
### 数据源
|
||||
|
||||
- Daily Papers API:`GET https://huggingface.co/api/daily_papers?date=YYYY-MM-DD`
|
||||
- PDF:`https://arxiv.org/pdf/{arxiv_id}.pdf`(总结阶段按需下载)
|
||||
- 源码(后续增强):`https://arxiv.org/e-print/{arxiv_id}`
|
||||
|
||||
HuggingFace 官方 Hub API 文档说明 `/api/daily_papers` 支持 `date` 查询参数。
|
||||
|
||||
### 规则
|
||||
|
||||
- `arxiv_id` 是唯一键。
|
||||
- 重复抓取同一天时,已有论文只更新 upvotes、标签等可变元数据,不重复插入。
|
||||
- 网络请求必须设置 timeout、User-Agent、重试次数。
|
||||
- API 返回空列表时记录成功日志,不视为失败。
|
||||
- 抓取阶段不下载 PDF;总结阶段 PDF 下载失败时更新 `asset_status=failed` 和 `summary_status.error_type=pdf_download_failed`。
|
||||
|
||||
### 接口
|
||||
|
||||
```python
|
||||
async def fetch_daily(date: str, top_n: int) -> list[PaperMeta]: ...
|
||||
async def upsert_papers(papers: list[PaperMeta]) -> list[Paper]: ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. AI 总结服务
|
||||
|
||||
**职责**:调用 pi CLI,把单篇论文转成结构化中文总结。
|
||||
|
||||
### 调用原则
|
||||
|
||||
- 一篇论文一次 pi 调用。
|
||||
- 并发数由 `SUMMARY_CONCURRENCY` 控制,默认 3。
|
||||
- 单篇超时由 `SUMMARY_TIMEOUT_SECONDS` 控制,默认 300 秒。
|
||||
- pi 路径通过 `PI_BIN` 配置,当前可以先使用宿主机路径;跑通后再抽象部署方式。
|
||||
- PDF 在总结开始前按需下载到 `data/tmp/{arxiv_id}/paper.pdf`,总结成功或失败后清理。
|
||||
|
||||
### 调用示例
|
||||
|
||||
```bash
|
||||
pi -p --skill daily-paper-summary \
|
||||
"请深度解读以下论文,并按指定 JSON schema 输出:
|
||||
@data/papers/2401.12345/meta.json
|
||||
@data/tmp/2401.12345/paper.pdf"
|
||||
```
|
||||
|
||||
### 流程
|
||||
|
||||
```text
|
||||
取 pending 论文
|
||||
-> 下载 PDF 到 data/tmp/{arxiv_id}/paper.pdf
|
||||
-> status=processing
|
||||
-> 调 pi
|
||||
-> 提取 JSON
|
||||
-> Pydantic 校验
|
||||
-> 写 summary.json
|
||||
-> 写 paper_summaries / paper_tags / papers_fts
|
||||
-> status=done
|
||||
-> 清理 PDF/源码临时文件
|
||||
```
|
||||
|
||||
失败时保存 raw output、更新 `summary_status`,并清理下载文件。
|
||||
|
||||
PDF 下载失败不调用 pi,直接记录 `pdf_download_failed` 并进入重试流程。
|
||||
|
||||
---
|
||||
|
||||
## 3. 搜索服务
|
||||
|
||||
**职责**:MVP 提供 FTS5 关键词搜索;后续接入 ChromaDB 语义搜索。
|
||||
|
||||
### FTS5 搜索
|
||||
|
||||
索引字段:
|
||||
|
||||
- 英文标题
|
||||
- 中文标题
|
||||
- 英文摘要
|
||||
- 作者
|
||||
- 标签
|
||||
- 中文总结正文
|
||||
|
||||
应用层负责同步 FTS:
|
||||
|
||||
```python
|
||||
def build_fts_document(paper: Paper, summary: PaperSummary | None) -> FtsDocument:
|
||||
summary_text = ""
|
||||
if summary:
|
||||
summary_text = " ".join([
|
||||
summary.one_line or "",
|
||||
summary.motivation_problem or "",
|
||||
summary.motivation_goal or "",
|
||||
summary.method_overview or "",
|
||||
summary.method_key_idea or "",
|
||||
" ".join(summary.results_main or []),
|
||||
])
|
||||
return FtsDocument(...)
|
||||
```
|
||||
|
||||
### ChromaDB 语义搜索(后续)
|
||||
|
||||
接入时要求:
|
||||
|
||||
- `CHROMA_ENABLED=true` 才初始化。
|
||||
- embedding API 失败不能影响总结入库。
|
||||
- embedding 维度和配置不匹配时记录日志并跳过。
|
||||
- 使用当前 ChromaDB 官方 API 重新确认查询和过滤语法后实现。
|
||||
|
||||
---
|
||||
|
||||
## 4. 页面渲染服务
|
||||
|
||||
**职责**:从 SQLite 读取数据并渲染 Jinja2 模板。
|
||||
|
||||
kami 只作为风格参考:
|
||||
|
||||
- 参考纸张质感、留白、字体层级和墨蓝强调色。
|
||||
- 不调用 kami,不依赖 kami 生成页面。
|
||||
- CSS 放在 `app/static/css/style.css`,按本项目页面实际结构维护。
|
||||
|
||||
页面必须支持降级状态:
|
||||
|
||||
- 无总结:显示英文元数据和“AI 总结尚未生成”。
|
||||
- 总结失败:显示错误类型和手动重跑入口。
|
||||
- degraded/low:显示提示,但仍展示已有内容。
|
||||
|
||||
---
|
||||
|
||||
## 5. 用户数据服务
|
||||
|
||||
**职责**:本地个人化数据,无账号体系。
|
||||
|
||||
功能:
|
||||
|
||||
- 收藏/取消收藏。
|
||||
- 阅读状态:`unread`、`skimmed`、`read_summary`、`read_full`。
|
||||
- 个人 Markdown 笔记。
|
||||
- 阅读列表:按收藏、状态、标签、日期筛选。
|
||||
|
||||
所有用户数据跟随论文删除一起删除。
|
||||
|
||||
---
|
||||
|
||||
## 6. 清理和删除服务
|
||||
|
||||
**职责**:清理临时文件,并支持管理员手动删除指定日期范围内的数据。
|
||||
|
||||
### 临时文件清理
|
||||
|
||||
触发时机:
|
||||
|
||||
- 单篇总结成功后。
|
||||
- 单篇总结失败后。
|
||||
- 每日任务结束后兜底扫描 `data/tmp/`。
|
||||
|
||||
### 手动删除
|
||||
|
||||
接口:
|
||||
|
||||
```python
|
||||
async def delete_papers_by_date_range(
|
||||
date_start: date,
|
||||
date_end: date,
|
||||
include_notes: bool = True,
|
||||
) -> DeleteResult: ...
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 删除前统计目标论文数量。
|
||||
- 删除 DB 记录、FTS 索引、本地文件。
|
||||
- 删除失败时记录具体 arXiv ID 和错误。
|
||||
- 日期范围必须有限制,避免误删全部数据;管理接口需要二次确认参数。
|
||||
|
||||
---
|
||||
|
||||
## 7. 调度服务
|
||||
|
||||
**职责**:自动执行每日抓取和总结。
|
||||
|
||||
### 约束
|
||||
|
||||
- 应用以单 worker 运行。
|
||||
- `APP_WORKERS` 必须为 1,或 `SCHEDULER_ENABLED=false`。
|
||||
- 启动时检查运行中任务,避免重复执行。
|
||||
- 同一日期同一任务使用数据库锁或日志状态防重入。
|
||||
- 推荐使用 `task_locks` 表;抢锁失败时,自动任务跳过,管理接口返回 409。
|
||||
|
||||
### 每日流程
|
||||
|
||||
```text
|
||||
08:00
|
||||
-> 按 APP_TIMEZONE 计算 today
|
||||
-> crawl(date=today)
|
||||
-> summarize pending papers
|
||||
-> cleanup tmp files
|
||||
-> write logs
|
||||
```
|
||||
|
||||
手动触发方式:
|
||||
|
||||
- CLI:`python -m app.cli crawl --date YYYY-MM-DD`
|
||||
- API:`POST /admin/crawl`
|
||||
|
||||
---
|
||||
|
||||
## 8. 管理和安全服务
|
||||
|
||||
**职责**:保护所有有副作用的管理操作。
|
||||
|
||||
### 鉴权
|
||||
|
||||
管理接口必须要求 `ADMIN_TOKEN`:
|
||||
|
||||
```text
|
||||
Authorization: Bearer <ADMIN_TOKEN>
|
||||
```
|
||||
|
||||
受保护接口:
|
||||
|
||||
- `POST /admin/crawl`
|
||||
- `POST /admin/summarize/{arxiv_id}`
|
||||
- `POST /admin/summarize`
|
||||
- `POST /admin/cleanup`
|
||||
- `POST /admin/delete`
|
||||
- `GET /admin/logs`
|
||||
|
||||
如果 `ADMIN_TOKEN` 为空或为默认值 `change-me`,应用启动时应警告;如果 `APP_HOST` 不是 `127.0.0.1`,应拒绝启动或要求显式确认。
|
||||
|
||||
用户数据接口默认仅面向本地使用。如果 `APP_HOST=127.0.0.1`,收藏、阅读状态、笔记接口不额外要求 token;如果绑定到非本地地址,应启用 same-origin 检查或要求 `ADMIN_TOKEN`,避免内网其他人修改本地笔记。
|
||||
|
||||
---
|
||||
|
||||
## 9. RSS 服务
|
||||
|
||||
**职责**:输出最近论文的 RSS Feed。
|
||||
|
||||
MVP 只做 `/rss.xml`:
|
||||
|
||||
- 默认最近 7 天。
|
||||
- 支持 `?tag=RAG`。
|
||||
- 有中文标题则用中文标题,否则用英文标题。
|
||||
- 详情链接指向本站 `/paper/{arxiv_id}`。
|
||||
|
||||
Atom 和 JSON Feed 作为后续增强。
|
||||
|
||||
---
|
||||
|
||||
## 10. 后续增强服务
|
||||
|
||||
这些能力暂不进入 MVP:
|
||||
|
||||
- LaTeX 图片提取。
|
||||
- ChromaDB 语义搜索。
|
||||
- 相似论文推荐。
|
||||
- 趋势看板。
|
||||
- 论文对比页。
|
||||
|
||||
实现前需要重新评估数据量、API 成本、页面复杂度和验收标准。
|
||||
Reference in New Issue
Block a user