Commit Graph

31 Commits

Author SHA1 Message Date
Mavis
6da59da934 chore(docker): 所有容器加 logging rotation(max-size 10m, max-file 3, 总 30MB/容器) 2026-06-09 10:52:51 +08:00
Mavis
8d73f4fb28 fix(llm+worker+deploy): 兼容老 prompt 模板 + 消除 startup_run 日志噪音
- enrichment: 新增 _safe_format (基于 _SafeDict),缺失占位符保留原样不抛 KeyError。
  _enrich_format / _enrich_classify / _enrich_image / _enrich_commentary
  全部走 _safe_format,数据库里老 prompt(不支持 {body})不再让整条 article 卡住。
  复现: 388183 classify 一直 KeyError,enrichment_loop 反复重试它,316 篇全卡在 n/a。
- workers.__main__: startup_run 从 IntervalTrigger(minutes=0) 改成 DateTrigger
  (只跑一次),消除 'maximum number of running instances reached' 刷屏 WARNING。
- deploy_pull: 改 _connect 自动识别 RSA / Ed25519 / ECDSA key(原硬编码 Ed25519Key)
2026-06-08 21:20:43 +08:00
Mavis
380e8b124e feat(llm): 排版容器固定CSS + 插图用正文第一段 + 适中尺寸
- enrichment._enrich_format:把排版好的段落包到带固定 CSS 的 <div class=article-body> 里
  (font: system-ui / 17px / line-height 1.7 / color #3e3e3e / p margin-bottom 1.5em)
  CSS 同时内联到 style 属性,前端 .article-body 全局类做兑底
- enrichment._enrich_image:prompt 改用 body_zh_text 的第一段(原为 title);
  新增 {body} 占位符,image_prompt_template 默认模板同步改写
- 插图尺寸写死为 768x512(适中);image_size 字段保留供用户手改但默认行为不依赖它
- 分类明确多标签(2-5 个),提示词加 {body} 变量,容错读 categories/tags 两种 key
- AdminLlmSettings.vue:placeholder / 变量说明同步更新
2026-06-08 20:53:21 +08:00
Mavis
82a92032bb fix(scripts): backfill_body 也回填翻译过但 body 短的文章(让 worker 重译) 2026-06-08 16:09:22 +08:00
Mavis
4cc5d41e39 fix(orm): Article 模型加 body_zh_formatted/image_ai_url/4 个 *_status 字段(同步 0002 migration) 2026-06-08 16:08:39 +08:00
Mavis
35c0da1670 feat(scripts): 新增 backfill_body.py 回填 body 短的文章(重新抓全文) 2026-06-08 15:59:14 +08:00
Mavis
a5548d6e64 fix(fetcher): fulltext 抓取用真实浏览器 UA,绕过 NHK 等 403 2026-06-08 15:55:30 +08:00
Mavis
6b5828c1c0 fix(translation): 规范化 BCP-47 lang_src(避免 en-gb/zh-cn 等被 TMT 拒) 2026-06-08 15:49:03 +08:00
Mavis
e83d7f4285 docs: 重写 README,详细覆盖 LLM 增强 / 数据模型 / 开发部署工作流 / 运维工具 2026-06-08 14:54:56 +08:00
Mavis
8d2c0855ac feat(scripts): 新增 deploy_pull.py 远程服务器拉取/回滚工具(免密) 2026-06-08 14:44:09 +08:00
Mavis
38609ff36f feat(ui): 新增 LLM 智能增强设置页 + 路由/侧栏 + ArticleDetail 展示排版/分类/插图/点评 2026-06-08 14:24:25 +08:00
Mavis
ba2298da0a chore: 集成 LLM 增强 — config/main/articles schema/workers + .env.example 加 Agnes 配置 2026-06-08 14:24:23 +08:00
Mavis
ffd667f0dc feat(llm): 新增 LLM 智能增强服务(Agnes client + 4 项 enrichment 任务 + admin API + migration) 2026-06-08 14:24:00 +08:00
Mavis
40be1e6861 feat(scripts): 新增 server_init.py 远程服务器初始化工具(推公钥+7项运维,幂等可重跑) 2026-06-08 11:13:50 +08:00
Mavis
97c370c58c refactor(scripts): push_ssh_key 改用 SSH fingerprint 去重,ed25519 优先 2026-06-08 11:13:49 +08:00
Mavis
9328f02a1f chore(scripts): 忽略并撤追踪 scripts/_*.py 临时调试脚本 2026-06-08 11:13:31 +08:00
Mavis
523c82f7a5 fix: NHK 源配置改 ja(seed 写错了); translate_article 加强 lang_src 兜底 2026-06-08 00:54:02 +08:00
Mavis
639562593e fix: 翻译失败/降级文本不再写 cache(避免 30 天污染)
之前 service.translate 写 cache 无条件,导致:
- 第一次翻译失败时,'[翻译失败: ...]' 占位符被写进 cache
- 30 天内相同文本的请求(新文章 title 与老文章 title 相同时)全部返回占位符
- 触发 200+ 文章 title_zh 字段被永久污染

修法:仅在 engine ∈ {tencent, nllb, cache} 且文本不含错误标记时,才写 cache。
2026-06-08 00:48:36 +08:00
Mavis
9862a92423 perf: 翻译独立后台循环(1 篇/秒)+ Semaphore 1
之前 fetch_one_source 入库后立即调翻译(可能并发触发腾讯 TMT 限速)
改为独立 translation_loop 后台循环:
- 完全不和 RSS 抓取并行
- 1 篇/秒节拍(Semaphore 1 + sleep 1.0)
- 没活时空闲 5 秒再轮询
- pending/failed 都重试
2026-06-08 00:27:09 +08:00
Mavis
e79cfaa5f7 fix: articles.py get_article 链式 await coroutine 报错(.first()) 2026-06-08 00:19:03 +08:00
Mavis
cc02d39d29 fix: 翻译主流程失败时 raise(不再返回占位符); add_usage TTL 用 replace(day=1) 防 0 TTL 2026-06-07 23:58:13 +08:00
Mavis
501713a3e8 fix: deps.py 修 await chain (3 处 .scalars()) 2026-06-07 23:38:04 +08:00
Mavis
3ebf280278 fix: pipeline INSERT 去掉不存在的 translate_to 字段 2026-06-07 23:32:13 +08:00
Mavis
30acd6af54 fix: create_user 默认 role=owner(而非 member) 2026-06-07 23:27:52 +08:00
Mavis
ce903ac58e fix: 修剩余的 (await ...)).scalar_one_or_none() 链式 + bookmark 2026-06-07 23:25:53 +08:00
Mavis
5109d6f824 fix: API 全部改用显式两步走 await session.execute + result.scalars()
之前 (await ...).scalars() 链式在 SQLAlchemy 2.0 async 下报
'coroutine' has no attribute 'scalars' 错误。改为先 await 拿 result
再 .scalars(),这是 SQLAlchemy 2.0 推荐的 async 写法。
2026-06-07 23:22:56 +08:00
Mavis
2e75985a3c fix: healthz 路径改成 /api/v1/healthz(归到 API 前缀下) 2026-06-07 23:15:33 +08:00
Mavis
eaa4aa6604 fix: Caddy 用 handle_path 自动 strip /api 前缀
之前的 reverse_proxy /api/* 直接转发保留路径,导致 api 收到 /api/v1/articles
而实际路由是 /v1/articles(API_PREFIX)。改用 handle_path。
2026-06-07 23:13:51 +08:00
Mavis
6635b8fea8 fix: enum 写入 PG 用 value 而非 name
Source/SourceKind、UserRole、SubscriptionMatch 三个 enum 改用 values_callable
保证 PG 看到 'rss' / 'owner' / 'any' 等小写 value,而非 'RSS' 大写 name。
seed_sources 同步改为显式字符串。
2026-06-07 23:11:32 +08:00
Mavis
427e1f5cf2 fix: 前端类型修复(@types/node + vite-env.d.ts + ufw SSHD_PORT)
- frontend: 加 @types/node / vite/client 类型声明
- frontend: tsconfig 加 types: [node, vite/client]
- scripts: deploy_remote.sh 用 sg docker + dc() 函数避免引号问题
- scripts: deploy_remote.sh ufw 改用 \ 变量
2026-06-07 23:04:06 +08:00
Mavis
60b062daf2 feat: initial MVP - FastAPI backend + Vue3 frontend + docker-compose
- backend: FastAPI + SQLAlchemy 2.0(async) + asyncpg + Alembic
- 7 API routes: auth/me/articles/sources/bookmarks/subscriptions/admin
- models: User/Source/Article/Bookmark/Subscription/ApiToken
- services: RSS fetcher (feedparser) + Tencent TMT translator with quota + cache + local NLLB fallback
- workers: APScheduler + asyncio pipeline (fetch -> dedupe -> insert -> translate)
- seed scripts: create_user, seed_sources (5 RSS: Reuters/BBC/Al Jazeera/NHK/DW)
- frontend: Vue 3 + Vite + Naive UI + Pinia + vue-router
- pages: Login, Feed (24h), ArticleDetail, Sources, Bookmarks, AdminSources
- deploy: docker-compose (postgres/redis/api/worker/frontend/caddy)
- docs: README, DEPLOY, architecture, acceptance
2026-06-07 21:51:01 +08:00