Files
daily-paper/README.md
T
Rain-Bus 0d293422ac feat: enhance UI, refactor services, improve templates and tests
- Replace image_extractor with pdf_image_extractor service
- Enhance pi_client with expanded API capabilities
- Improve summarizer service with additional features
- Update admin routes with more endpoints
- Add login page template
- Enhance detail page with comprehensive layout
- Improve search and trends pages
- Update base template with additional elements
- Refactor tests for better coverage
- Add validate_summary script
- Update project configuration and dependencies
2026-06-07 19:38:58 +08:00

244 lines
8.7 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.
# HF Daily Papers — 中文论文导览站
> 每日自动抓取 HuggingFace Daily Papers,调用 AI 生成结构化中文解读,提供本地 Web 应用用于浏览、搜索、收藏与管理。
---
## 功能特性
- **每日抓取**:按日期拉取 HuggingFace Daily Papers,提取元数据并入库,自动去重与重试。
- **AI 中文总结**:下载 PDF,调用 `pi` CLI 为每篇论文生成结构化中文解读(动机、方法、结果、局限性等),完成后清理临时文件。
- **浏览与详情**:首页按日期导航、论文详情页展示元数据与总结,提供未总结论文的英文原文回退。
- **搜索**:基于 SQLite FTS5 的关键词搜索(BM25 排序、片段高亮),覆盖标题、摘要、作者、标签与总结正文。
- **语义搜索**(可选):ChromaDB 向量数据库实现相似度搜索,优雅降级至 FTS5。
- **论文对比**:并排对比最多 5 篇论文的 12 个结构化字段。
- **趋势看板**:Chart.js 驱动的可视化统计(日论文量、Top 标签、投票分布、总结完成率)。
- **个人化**:收藏、阅读状态、个人笔记与阅读列表。
- **RSS 订阅**:最近 7 天论文的 RSS 2.0 输出,支持标签过滤。
- **管理后台**:Token 鉴权的手动抓取、总结、清扫、删除与日志查看接口。
- **定时调度**APScheduler 内嵌调度,默认每日 08:00 自动抓取与总结(TaskLock 防重)。
- **LaTeX 图片提取**:下载 arXiv 源码,扫描 `.tex` 文件提取论文图片用于详情页展示。
- **HTMX 局部更新**:收藏切换等操作无需整页刷新。
- **键盘快捷键**`Ctrl+K``/` 聚焦搜索框。
---
## 技术栈
| 层级 | 技术 |
|------|------|
| 后端 | Python 3.12+ · FastAPI · Uvicorn |
| 模板 | Jinja2(服务端渲染) |
| 前端 | HTMX · 原生 JS · Chart.js · 自定义 CSS"kami" 纸质风格) |
| 数据库 | SQLite + SQLAlchemy · SQLite FTS5(全文搜索) |
| AI 总结 | `pi` CLI(外部工具) |
| 语义搜索 | ChromaDB(可选) |
| 调度 | APScheduler(内嵌单进程) |
| CLI | Typer |
| 测试 | pytest · pytest-asyncio |
| 构建 | HatchlingPEP 517 |
---
## 项目结构
```
paper/
├── README.md
├── .env.example
├── pyproject.toml
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI 入口(lifespan 管理)
│ ├── config.py # pydantic-settings 配置加载
│ ├── database.py # SQLAlchemy 引擎、会话与 FTS5
│ ├── models.py # 11 个 ORM 模型
│ ├── utils.py # 共享工具函数
│ ├── cli.py # Typer CLIcrawl / summarize / init-db
│ │
│ ├── routes/ # 页面与 API 路由
│ │ ├── __init__.py
│ │ ├── pages.py # 首页、日期页、论文详情
│ │ ├── admin.py # Token 鉴权管理接口
│ │ ├── search.py # 搜索、阅读列表、RSS
│ │ ├── user.py # 收藏、阅读状态、笔记 API
│ │ ├── trends.py # 趋势看板
│ │ └── compare.py # 论文对比页
│ │
│ ├── services/ # 业务逻辑层
│ │ ├── __init__.py
│ │ ├── crawler.py # HuggingFace API 爬虫
│ │ ├── summarizer.py # AI 总结编排
│ │ ├── searcher.py # FTS5 + 语义搜索
│ │ ├── schemas.py # Pydantic 总结校验
│ │ ├── cleaner.py # 临时文件清理 + 日期范围删除
│ │ ├── scheduler.py # APScheduler 每日管线
│ │ ├── user_data.py # 收藏、阅读状态、笔记
│ │ ├── embedder.py # ChromaDB 向量索引
│ │ ├── trends.py # 趋势统计聚合
│ │ ├── pdf_downloader.py # PDF + LaTeX 源码下载
│ │ ├── pi_client.py # pi CLI 封装 + JSON 提取
│ │ └── image_extractor.py # LaTeX 图片提取
│ │
│ ├── templates/ # Jinja2 模板
│ │ ├── base.html
│ │ ├── index.html
│ │ ├── detail.html
│ │ ├── search.html
│ │ ├── reading_list.html
│ │ ├── compare.html
│ │ ├── trends.html
│ │ ├── admin_logs.html
│ │ └── partials/paper_card.html
│ │
│ └── static/
│ ├── css/style.css # 自定义 CSSkami 风格)
│ └── js/app.js # 键盘快捷键
├── data/ # 运行时数据(已 gitignore
│ ├── db/papers.db # SQLite 数据库
│ ├── papers/{arxiv_id}/ # 长期资产(meta.json / summary.json / 图片)
│ ├── tmp/{arxiv_id}/ # 临时下载(流程完成后清理)
│ └── chroma/ # ChromaDB 向量库(可选)
├── scripts/
│ ├── init_db.py # 数据库初始化
│ └── manual_crawl.py # 手动抓取脚本
├── tests/ # 9 个测试模块
│ ├── conftest.py # 测试夹具(内存 DB、样本数据)
│ └── test_*.py # 各模块测试
└── logs/ # 运行日志
```
---
## 快速开始
### 1. 准备环境
- Python **3.12+**
- 可选:[`pi`](https://www.npmjs.com/package/@mariozechner/pi-coding-agent) CLI(用于 AI 总结)
### 2. 安装依赖
```bash
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
```
### 3. 配置环境变量
```bash
cp .env.example .env
# 编辑 .env,至少修改 ADMIN_TOKEN
```
关键配置项:
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `APP_HOST` / `APP_PORT` | `127.0.0.1` / `8000` | 服务监听地址 |
| `APP_DEBUG` | `false` | 调试模式(开启 uvicorn reload |
| `BASE_URL` | `http://127.0.0.1:8000` | 站点根 URL(用于 RSS 生成) |
| `APP_TIMEZONE` | `Asia/Shanghai` | 时区 |
| `ADMIN_TOKEN` | `change-me` | **必须修改** — 管理接口鉴权 |
| `HF_API_BASE` | `https://huggingface.co/api` | HuggingFace API 地址 |
| `HF_PROXY` | — | HTTP 代理 |
| `TOP_N` | `20` | 每日抓取 Top N 论文 |
| `HTTP_TIMEOUT_SECONDS` | `30` | HTTP 请求超时 |
| `HTTP_MAX_RETRIES` | `3` | HTTP 最大重试次数 |
| `PI_BIN` | — | `pi` CLI 路径 |
| `SUMMARY_SKILL` | `daily-paper-summary` | pi 总结技能名 |
| `SUMMARY_CONCURRENCY` | `3` | 最大并行总结数 |
| `SUMMARY_TIMEOUT_SECONDS` | `300` | 单篇总结超时 |
| `SUMMARY_MAX_RETRIES` | `1` | 总结最大重试次数 |
| `SCHEDULER_ENABLED` | `false` | 启用每日自动抓取 |
| `SCHEDULE_HOUR` / `SCHEDULE_MINUTE` | `8` / `0` | 定时任务时间(APP_TIMEZONE |
| `APP_WORKERS` | `1` | Uvicorn worker 数(必须为 1 |
| `DATABASE_URL` | `sqlite:///data/db/papers.db` | 数据库路径 |
| `CHROMA_ENABLED` | `false` | 启用语义搜索 |
| `CHROMA_DIR` | `data/chroma` | ChromaDB 数据目录 |
| `EMBED_API_BASE` | — | Embedding API 地址 |
| `EMBED_API_KEY` | — | Embedding API Key |
| `EMBED_MODEL` | — | Embedding 模型名 |
| `EMBED_DIMENSIONS` | `0` | 向量维度 |
### 4. 初始化数据库
```bash
python scripts/init_db.py
# 或:python -m app.cli init-db
```
### 5. 启动服务
```bash
uvicorn app.main:app --host 127.0.0.1 --port 8000
```
> 调度器依赖单 worker:不可使用 `--workers > 1`,否则每日任务会被重复触发。
打开浏览器访问 `http://127.0.0.1:8000` 即可。
---
## 常用命令
### 手动抓取指定日期
```bash
python scripts/manual_crawl.py 2025-01-15
# 或
python -m app.cli crawl 2025-01-15 --top 20
```
### 手动触发总结
```bash
# 单篇
python -m app.cli summarize 2401.01234
# 批量(所有待总结论文)
python -m app.cli summarize
```
### 管理接口(Token 鉴权)
```bash
# 抓取今日论文
curl -X POST "http://127.0.0.1:8000/admin/crawl" \
-H "Authorization: Bearer $ADMIN_TOKEN"
# 批量总结
curl -X POST "http://127.0.0.1:8000/admin/summarize" \
-H "Authorization: Bearer $ADMIN_TOKEN"
# 单篇总结
curl -X POST "http://127.0.0.1:8000/admin/summarize/2401.01234" \
-H "Authorization: Bearer $ADMIN_TOKEN"
```
### 运行测试
```bash
pytest
```
---
## 安全提示
- `ADMIN_TOKEN` 是管理接口的唯一鉴权凭证,请使用强随机值并妥善保管。
- 默认仅监听 `127.0.0.1`,如需内网访问请配合反向代理与 HTTPS。
- 项目面向本地 / 内网部署,不包含多用户账号体系与公网防护。
---
## 许可证
本项目仅供学习与个人使用,请遵守 HuggingFace、arXiv 与上游论文作者的相关条款。