# 阅读流方案讨论纪要 ## 参考来源 - Shawn Xie, 《Read Flow 2026》: ## 1. 当前目标 本项目的目标不是直接复刻文章里的整套实现,而是先按下面这条链路,逐步做出一套接近文章效果的阅读流系统: 1. 通过一层 RSS 聚合获取文章 2. 通过一个 `skill` 或 `mcp` 获取文章摘要 3. 基于规则对摘要结果进行过滤 4. 将过滤后的内容推送到知识库或其他文档组件 5. 完成消息推送 6. 最后再考虑与 OpenClaw 结合 这里的 `skill / mcp` 只是整条链路中的一个组件,当前讨论的重点是第 2 步“页面摘要能力”的设计,而不是一次性把整套系统全部落地。 --- ## 2. 内容来源分类 为了便于后续实现,内容来源建议按两个维度分类: - 按来源类型分类:这个内容来自什么渠道 - 按接入方式分类:系统用什么技术手段把它纳入统一流水线 这样做的原因是: - 同一种来源类型,可能有不同接入方式 - 同一种接入方式,可能服务多种来源 - 后面的摘要、过滤、入库更适合依赖标准化后的 source schema,而不是依赖渠道名称 ### 2.1 按来源类型分类 建议定义以下几类: - `feed` - 原生 RSS / Atom 源 - 典型例子:博客、新闻站、技术周刊、文档更新 - `converted_feed` - 原本不是 RSS,但通过第三方或自建转换后变成 feed - 典型例子:微信公众号、部分社区栏目、社交平台账号流 - `event_feed` - 更偏事件流而不是传统文章流 - 典型例子:GitHub Releases、Commits、Discussions、Changelog - `page_watch` - 没有现成 feed,需要定时轮询某个页面的更新 - 典型例子:专题页、导航页、榜单页、产品更新页 - `custom_source` - 无法直接归类,需要为特定站点写专门抓取逻辑 - 典型例子:结构特殊的网站、内部页面、非标准内容源 ### 2.2 按接入方式分类 建议定义以下几类: - `feed_direct` - 直接消费 RSS / Atom - `feed_converted` - 通过 RSSHub、wewe-rss、RSS-Bridge 等方式先转成 feed,再统一消费 - `api_backed` - 通过平台 API 获取内容,再标准化成内部 item - `html_scraped` - 直接抓取 HTML 页面,自己解析列表页和正文页 - `hybrid` - 先消费 feed 元信息,再按需回源抓正文 ### 2.3 你当前关心的几类内容如何归档 - RSS 文章 - 来源类型:`feed` - 接入方式:`feed_direct` - 优先级:最高 - 微信文章 - 来源类型:`converted_feed` - 接入方式:通常是 `feed_converted` - 优先级:高 - 其他文章 - 如果是社区栏目、论坛专题:通常归到 `converted_feed` 或 `page_watch` - 如果是普通网站更新页:通常归到 `page_watch` - 如果是 GitHub 项目更新:通常归到 `event_feed` - 如果是特殊站点:归到 `custom_source` 结论: “其他文章”不应作为最终系统里的正式分类,因为它过于宽泛,后续规则过滤会很难维护。 ### 2.4 建议的实现级分类 如果进入实现阶段,建议系统内部只保留下面这 5 类 source type: - `feed` - `converted_feed` - `event_feed` - `page_watch` - `custom_source` 同时再给每个 source item 增加一个 `content_kind` 字段,用来表达内容形态: - `article` - `thread` - `release` - `changelog` - `video` - `mixed` 这样可以把“来源渠道”和“内容形态”拆开,后面的摘要与过滤规则会更稳定。 ### 2.5 当前阶段建议先支持的来源 为了降低复杂度,第一阶段建议只支持两类: - `feed` - `converted_feed` 原因: - 它们最接近当前目标链路 - 接入成本最低 - 最容易验证第 2 步摘要和第 3 步过滤是否成立 - 暂时不需要引入复杂的页面轮询和定制抓取逻辑 --- ## 3. 系统边界的核心结论 当前最重要的不是先决定做 `Skill` 还是 `MCP`,而是先定义一个可复用的“摘要内核”。 建议的能力分层: `RSS 聚合 -> summary-core -> rule-engine -> sink -> push -> OpenClaw 编排` 其中: - `summary-core`:负责抓取页面、抽取正文、生成结构化摘要 - `rule-engine`:负责根据规则和评分过滤内容 - `sink`:负责将结果写入知识库或文档系统 - `push`:负责消息通知 - `OpenClaw`:最后作为编排层或自动化入口接入 结论:先做“能力内核”,再决定用 `MCP` 还是 `Skill` 进行封装。 --- ## 4. Skill 和 MCP 的定位 ### Skill 适合: - 人工触发 - 代理式工作流 - 提示词编排 - 让 Agent 在上下文里决定何时调用摘要流程 优点: - 实现快 - 适合探索和半自动流程 缺点: - 不适合做稳定的批处理基础设施 - 不适合承载缓存、重试、队列、状态管理 结论: `Skill` 更像“编排层”,不适合作为底层基础能力的唯一实现。 ### MCP 适合: - 将摘要能力标准化成可调用工具 - 给 OpenClaw、ChatGPT、Claude 等 Agent 统一接入 - 为后续自动化编排预留稳定接口 优点: - 接口标准化 - 易于被 Agent 调用 - 后续接 OpenClaw 更自然 缺点: - 仍然需要自己实现抓取、抽取、摘要、缓存等能力 结论: `MCP` 适合作为“能力接口层”。 ### 当前建议 推荐顺序: 1. 先做 `summary-core` 2. 再暴露成 `MCP` 3. 最后根据需要加 `Skill` 不建议一开始只做 `Skill`。 --- ## 5. 页面摘要能力应输出什么 页面摘要不要只输出一段自然语言摘要,而应该输出结构化结果,方便后面的过滤、入库和推送。 建议输出结构: ```json { "url": "https://example.com/article", "title": "文章标题", "source": "站点名", "author": "作者", "published_at": "2026-03-23T08:00:00Z", "language": "zh", "summary": "3-5句摘要", "highlights": ["要点1", "要点2", "要点3"], "keywords": ["rss", "mcp", "knowledge-base"], "topics": ["AI tools", "workflow"], "quality_flags": { "is_paywalled": false, "is_truncated": false, "is_low_content": false }, "scores": { "readability": 0.84, "novelty": 0.72, "relevance": 0.91 }, "content_hash": "xxx" } ``` 这样做的价值: - 规则过滤直接使用结构化字段 - 知识库入库更稳定 - 推送内容可按场景裁剪 - 后续可以追踪质量、去重和打分 --- ## 6. 第 2 步“页面摘要能力”的技术拆分 页面摘要不是单一步骤,而是 3 个子能力: 1. 获取页面内容 2. 抽取正文 3. 生成摘要 ### 5.1 获取页面内容 有两条常见路径: - 直接使用 RSS item 里的 `content:encoded` 或 `summary` - 根据 RSS item 的 `link` 回源抓取页面 建议策略: - 先使用 RSS 已提供的内容 - 如果内容过短、质量不够,再回源抓页面正文 这样能平衡速度和完整度。 ### 5.2 正文抽取 这是稳定性的关键环节。 候选技术: - `trafilatura` - 对博客、新闻、文档类页面较稳 - Python 生态成熟 - `readability-lxml` - 经典轻量方案 - 覆盖面广 - `Playwright + Readability` - 适合 JS 动态页面 - 成本最高,但兜底能力最强 建议组合: - 第一层:`httpx/requests + trafilatura` - 第二层:`Playwright` 作为兜底方案 不建议一开始就默认使用 Playwright。 ### 5.3 摘要生成 有两类方向: - 抽取式摘要 - 成本低 - 稳定 - 可读性通常一般 - 生成式摘要 - 更接近最终想要的“知识流”效果 - 可读性更好 - 需要更严格的结构化约束 建议: - 采用生成式摘要 - 强制模型输出 JSON Schema - 不允许自由散文式输出 这样后续流程会稳定很多。 --- ## 7. 过滤层设计 过滤层不要完全依赖 LLM 的自由判断,建议采用“两层过滤”。 ### 第一层:确定性规则 例如: - 来源白名单 / 黑名单 - 关键词规则 - 主题规则 - 语言过滤 - 最低字数要求 - 重复检测 - 发布时间窗口 - relevance 阈值 ### 第二层:可选的 LLM 判断 例如: - 是否值得进入知识库 - 更偏资讯还是方法论 - 是否符合个人关注主题 - 是否值得推送 结论: 先规则,后智能,不要反过来。 --- ## 8. 知识库与推送层设计 第 4、5 步可以统一抽象为 `sink` 和 `push`。 ### 第一阶段建议优先做的 sink - `Markdown sink` - 输出到本地目录或 Git 仓库 - 适合第一版 - 可审计、易迁移 - `Webhook sink` - 推送到 Telegram、企业微信、飞书、OpenClaw 或其他自动化入口 - 扩展性最好 ### 后续可扩展的 sink - Notion - Obsidian Vault - Logseq - 数据库 结论: 第一版不建议直接绑死在单一平台上,优先本地 Markdown + Webhook。 --- ## 9. 现在真正该先定义的接口 摘要内核建议先定义统一接口,而不是先定义 UI 或 Agent 提示词。 建议输入: - `url` - 可选 `raw_html` - 可选 `rss_content` - 可选 `user_profile` - 可选 `summary_style` 建议输出: - 结构化摘要 JSON - 原始正文文本 - 元信息 - 错误状态 只要这个接口稳定: - CLI 可以调用 - HTTP 服务可以调用 - MCP 可以调用 - OpenClaw Skill 也可以调用 这一步是整个系统里最关键的抽象。 --- ## 10. 推荐的演进路线 建议按下面顺序推进: 1. `RSS 聚合` - 先通过 FreshRSS 或现有聚合器获取文章链接 2. `summary-core` - 输入 URL,输出结构化摘要 3. `rule-engine` - 对摘要 JSON 执行过滤规则 4. `sink` - 先落 Markdown,再做 webhook 推送 5. `MCP server` - 暴露 `summarize_url`、`filter_summary`、`store_note` 等工具 6. `OpenClaw Skill` - 让 OpenClaw 负责编排、人工确认或附加动作 7. `OpenClaw 集成` - 最后再接入完整自动化流程 这样每一层都可以独立测试,不会过早被某个平台或代理框架绑定。 --- ## 11. 当前阶段的明确判断 ### 不建议的方向 - 一开始只做 Skill - 一开始把 OpenClaw 当成底层依赖 - 一开始就直接绑死 Notion 一类单一知识库 - 让过滤完全依赖 LLM 自由发挥 ### 建议优先做的方向 - 先定义 `summary-core` 的输入输出 - 摘要结果必须结构化 - 过滤规则优先基于确定性逻辑 - 入库优先选择 Markdown - 对外优先暴露成 MCP,而不是先做纯 Skill --- ## 12. 后续讨论建议 后面可以基于这份文档继续讨论以下问题: 1. `summary-core` 的最小可用接口如何定义 2. `MCP` 版和 `Skill` 版分别暴露哪些能力 3. 正文抽取链路是否需要分层回退 4. 规则引擎使用配置文件还是代码实现 5. Markdown sink 的目录结构怎么设计 6. Webhook / 推送层先接哪一个目标 7. OpenClaw 在整条链路里承担“调度器”还是“人工审核入口” --- ## 13. 当前阶段的一句话结论 当前阶段最合理的方向是:先把“页面摘要”做成一个独立、结构化、可复用的能力内核,再优先封装为 `MCP`,最后再用 `Skill` 和 OpenClaw 做编排与集成。