架构·3 min read·Click Reader Team
Click Workflow:把一个看似简单的功能拆成 7 步
EPUB 解析 → 摘抄打分 → 视觉基因 → 风格选择 → 批量生图 → 热点定位 → 渲染阅读。每一步独立、可观测、可重跑。
为什么不是"一键生成"
把一本书自动配上数百张高质量插画,听起来像一个功能,但工程上一定要拆。
理由:
- 每步成本不一样 —— LLM 打分一次 0.001 元;图片生成一次 0.05 元;视觉签名要调 VLM。把它们做成一个黑盒会让任何小问题需要重跑全流程。
- 每步可独立优化 —— 摘抄质量差时只重跑摘抄;风格不合时只重跑风格选择。
- 每步可独立观测 —— 你能看到一本书具体在哪一步耗了多久、什么数据进 / 什么数据出。
所以 Click Workflow 是 7 个独立服务(实际上是 7 个 stage 的 orchestrator),不是一个端到端 API。
7 步是哪 7 步
| Step | 名称 | 干什么 | 用什么模型 |
|---|---|---|---|
| 0 | upload | EPUB 上传到 Supabase Storage | — |
| 1 | parse | 解析章节 + 段落(含元数据) | cheerio + jsdom |
| 2 | excerpt | LLM 给每个句子做"是否值得画"打分(0-10) | Qwen / DeepSeek |
| 3 | signature | 生成 BookSignature(11 维视觉基因) | Qwen-VL(封面)+ Qwen(文本) |
| 4 | generate | 选风格 + 增强 prompt + 调图模型批量生图 | DeepSeek 选风格,Wan / Qwen-Image 出图 |
| 5 | persist | 把临时 URL 持久化到 OSS / Supabase Storage | — |
| 6 | render | 用 fuzzy match 把图精确锚定到原文段落 + 渲染 HTML | fuzzball |
每一步:
- 有独立的 HTTP 服务(因此可以单独重启 / 调度 / 扩缩容)
- 有独立的状态字段(在 Supabase 里)
- 失败可重试,状态持久化(orchestrator.py 里管理 workflow_state.json)
一个真实的例子
跑《教育》(Tara Westover) 这本书:
Step 1 parse: 32 章节,2 分 18 秒
Step 2 excerpt: 1834 个句子打分,平均得分 4.2,挑出 287 个 ≥ 7 的"值得画"
Step 3 signature: era=20世纪美国乡村, palette=褪色棕黄, vibe=怀旧而压抑
Step 4 generate: AI 自动选了「Russian Realist」「Ambient Photography」
两个风格交替,287 张图,1 小时 40 分钟
Step 5 persist: 全部下载到阿里云 OSS,平均 280KB / 张
Step 6 render: 287 张图全部成功锚定到原文段落
最后产出是 32 篇带"互动点"的 HTML 章节。
为什么对运维友好
整个流程跑下来:
- 任意一步失败,可以从那一步
--resume续跑 - 每步独立超时(excerpt 2h, generate 4h, persist 1h, render 30min)
- 每步独立日志(
logs/wf_xxx_stepN_*.log)
所以即使 LLM 服务偶尔抽风,也只会损失那一步的结果,不会让一本书的几小时生图白跑。
如果你对其中某一步具体怎么实现感兴趣,欢迎在 Gallery 里看看实际产出, 或写信到 hi@ima-read.com 索要 demo。