☰
OpenChamber Text 模块解析:本地文本清洗与摘要回退机制实战指南
2026/9/25 7:25:03 网站建设 项目流程
  • AI Agent
  • 人工智能
  • 代码智能体
  • 交互助手

【免费下载链接】openchamber

Agentic Development Environment based on OpenCode AI agent

项目地址:https://gitcode.com/gh_mirrors/op/openchamber
点击查看免费下载

导读

OpenChamber 的packages/web/server/lib/text模块是服务端共享的文本变换工具箱,为 TTS 朗读、通知正文、项目记忆笔记等多个产品面提供统一的文本清洗与摘要能力。本文将带你完整掌握该模块的公开 API、三种处理模式(tts/notification/note)的差异与底层实现,并结合源码与测试用例,说明摘要服务在模型提供商不可用时的本地回退机制,以及如何通过 HTTP 端点正确调用它。

模块定位:不属于任何单一产品面的共享文本管线

在 OpenChamber 服务端,text模块的设计原则是中立——它不被 TTS、通知或笔记任何一个产品面独占,而是为所有需要"把一段文本变成更干净、更简短、适合特定出口的文本"的场景提供共享能力。

值得特别说明的是该模块的历史沿革:它此前通过 opencode.ai 的 Zen 提供商代理模型驱动的摘要能力;由于该提供商不再适用于此用途,摘要功能现已完全本地化——只返回经过清洗/蒸馏的本地回退文本,不再发起任何外部模型调用。这一点在模块文档的 Purpose 一节中有明确交代,也是理解整个模块设计的关键背景。

模块唯一的入口文件为 summarization.js,它同时包含摘要桩函数与全部清洗辅助函数,文件头部注释即声明了三种模式的语义:

/** * Shared text summarization service. * * Modes: * - tts: concise speakable text * - notification: concise notification text * - note: distilled project note */

公共导出 API

模块对外暴露以下四个函数:

导出函数签名用途
summarizeText({ text, threshold, maxLength, zenModel, mode })摘要入口,API 兼容桩,zenModel被忽略
sanitizeForTTSsanitizeForTTS(text)为语音输出清洗文本
sanitizeForNotificationsanitizeForNotification(text)为紧凑通知正文清洗文本
sanitizeForNotesanitizeForNote(text)为短笔记/蒸馏输出清洗文本

其中summarizeText的完整签名与默认值如下(见 summarization.js#L119):

export async function summarizeText({ text, threshold = 200, maxLength = 500, zenModel, mode = 'tts' })

参数含义:

  • text:待处理的原始文本,必需。
  • threshold:默认200。当text长度不超过该阈值时,直接判定为"无需摘要"并原样返回清洗结果。
  • maxLength:默认500。蒸馏算法尝试将结果控制在的目标长度。
  • zenModel:历史遗留参数,代码中以void zenModel;显式忽略(见 summarization.js#L120)。
  • mode:默认'tts',决定走哪条清洗/蒸馏管线。

三种模式:tts / notification / note

三个模式对应三条不同的文本出口,清洗策略差异显著。从源码的sanitizeByMode分发逻辑(summarization.js#L65-L69)可以看出:

function sanitizeByMode(text, mode) { if (mode === 'note') return sanitizeForNote(text); if (mode === 'notification') return sanitizeForNotification(text); return sanitizeForTTS(text); }

tts:可朗读的语音摘要

sanitizeForTTS是三种清洗器中最激进的一个,目标是让文本读起来自然(见 summarization.js#L10-L26):

  • 代码块(```` ```围栏)与行内代码(` ``)整体替换为空格——避免 TTS 把代码读出来;
  • 删除 Markdown 强调符号* _ ~ #,删除行首的$ # >引用符;
  • 将| & ; < >等符号替换为空格,移除反斜杠、括号、引号;
  • 把 URL 替换为可朗读的占位短语' a link '(例如https://example.com会变成 "a link");
  • 移除路径类片段,最终把连续空白折叠为单个空格并trim()。

典型输入输出对照:

输入输出
Read \const value = 1` aloud|Read aloud`
Before\n```js\nconst value = 1\n```\nAfterBefore After

notification:紧凑的通知正文

sanitizeForNotification(summarization.js#L28-L44)更注重保真度:

  • 行内代码保留内容本身(`code`→code),仅移除反引号;
  • 删除列表符号- * +与标题符号#;
  • 剥离加粗/斜体的 Markdown 包裹符(**、__、*、_);
  • 把 Markdown 链接text收敛为纯文本text;
  • 将换行折叠为单个空格,压缩连续空白。

note:蒸馏后的项目记忆笔记

sanitizeForNote(summarization.js#L46-L63)在 notification 的基础上更近一步:额外移除 URL与引号,适合把一段对话内容沉淀为简短的项目记忆条目。

本地回退:摘要的"蒸馏"实现

由于模型提供商不可用,summarizeText的摘要能力由两个本地蒸馏函数承担(见 summarization.js#L71-L111):

distillNoteFallback(text, maxLength)(note 模式):

  1. 先经sanitizeForNote清洗;
  2. 剥离常见的 AI 风格前缀,如In summary:、Here is a note:;
  3. 按句子切分,取第一句作为候选;
  4. 再按;:()-与逗号逐级截断到更短的片段;
  5. 理想上限取min(maxLength, max(32, 原文长度 × 0.65));若候选超长,则截取到idealLimit - 1并追加省略号…。

distillNotificationFallback(text, maxLength)(notification 模式):

  1. 清洗后按句子切分;
  2. 优先选取长度 ≥ 20 的第一句话(避免选出残缺碎片),否则回退到第一句或全文;
  3. 长度上限为max(20, maxLength)(maxLength非有限数值时取 100);
  4. 超出时截断并追加省略号。

而tts模式走的是纯清洗路径sanitizeByMode,不做句子级蒸馏——因为语音场景优先保证完整性,由上层自行控制篇幅。

响应契约

summarizeText始终返回一个对象(summarization.js#L122-L137):

字段说明
summary本地清洗/蒸馏后的回退文本
summarized恒为false(模型提供商不可用期间)
reason跳过原因;文本超过阈值时通常为Model summarization provider unavailable
originalLength可选,仅文本超阈值时返回的原始长度
summaryLength可选,仅文本超阈值时返回的摘要长度

注意两条边界分支:

  • 文本为空:返回{ summary: '', summarized: false, reason: 'No text provided' };
  • 文本长度 ≤threshold:返回{ summary: 清洗结果, summarized: false, reason: 'Text under threshold' },此时不附带长度字段。

HTTP 集成:POST /api/text/summarize

该模块通过 TTS 路由注册了一个公开端点(tts/routes.js#L108-L131):

app.post('/api/text/summarize', async (req, res) => { const { text, threshold = 200, maxLength = 500, mode } = req.body || {}; if (!text || typeof text !== 'string' || !text.trim()) { return res.status(400).json({ error: 'Text is required' }); } const result = await summarizeText({ text, threshold, maxLength, mode: typeof mode === 'string' ? mode : 'tts', }); return res.json(result); });

实际调用示例(curl):

curl -X POST http://localhost:PORT/api/text/summarize \ -H 'Content-Type: application/json' \ -d '{ "text": "First sentence. Second sentence with the useful insight.", "threshold": 0, "maxLength": 100, "mode": "note" }'

预期响应:

{ "summary": "First sentence.", "summarized": false, "reason": "Model summarization provider unavailable" }

要点:

  • text缺失或非字符串时返回400;
  • mode缺省时回退为tts;
  • 路由的 catch 分支(tts/routes.js#L126-L129)在异常时按mode选用sanitizeForNote或sanitizeForTTS兜底,保证接口始终能返回一个干净的summary字段。

通知模块中的兼容桩

除了 HTTP 端点,通知模块也直接复用了该管线。template-runtime.js 内部定义了一个同名的summarizeText兼容桩:以threshold: 0、mode: 'notification'调用共享的summarizeText,把targetLength映射为maxLength,并在结果为空时回退返回原文,确保通知正文渲染不因摘要失败而中断。这正是模块文档所说"Add new mode semantics here when multiple product surfaces need the same text pipeline"的实例——多个产品面共享同一条文本管线,而不是各自复制实现。

测试验证:回退行为有据可查

模块的行为由 summarization.test.js 覆盖,三组测试直接印证了核心契约:

  1. TTS 清洗:验证代码块在剥离 Markdown 标点前被移除,Read \const value = 1` aloud→Read aloud`;
  2. 不再调用 Zen 提供商:传入zenModel: 'gpt-5-nano'后断言summarized === false且reason === 'Model summarization provider unavailable',同时校验 notification 蒸馏在 80 字符上限下的省略号截断结果;
  3. note 本地回退:两句话的输入在maxLength: 100下仅保留第一句,验证"取首句"的蒸馏策略。

这些测试同时是贡献者的行为规范:任何对清洗规则的调整都应在该测试文件中同步补充用例。

给贡献者的维护约定

模块文档在 Notes for contributors 一节给出了三条边界,源码中也一一对应:

  • 保持模块中立:不要将本模块重新耦合到 TTS 专属的命名或路由(例如不要在清洗器里加入语音相关的分支);
  • 共享模式优先:当多个产品面需要相同的文本管线时,在此处新增模式语义(扩展sanitizeByMode与fallbackByMode的分发),而不是在其他模块里复制粘贴一套新的清洗器;
  • 模式化清洗:倾向于为每个模式提供专属的 prompt 与清洗行为,避免在无关模块中重复实现。

小结

packages/web/server/lib/text是 OpenChamber 服务端一条轻量但职责清晰的共享文本管线:对外提供summarizeText这一 API 兼容的摘要入口,内部以三种模式分别驱动 TTS、通知与笔记三种出口的清洗与蒸馏回退;在模型提供商不可用期间,它以完全本地、可测试、行为明确的方式保证了所有调用方的文本输出质量。理解这个模块,有助于你在接入 TTS、通知或记忆笔记功能时,正确选择清洗模式并准确解读summarized: false与reason字段所表达的回退语义。

  • AI Agent
  • 人工智能
  • 代码智能体
  • 交互助手

【免费下载链接】openchamber

Agentic Development Environment based on OpenCode AI agent

项目地址:https://gitcode.com/gh_mirrors/op/openchamber
点击查看免费下载
上一篇:FSNotes终极指南:简单高效的跨平台笔记管理解决方案
下一篇:如何用Power Apps扩展Tailwind Traders业务流程:零代码开发教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询