资讯动态

深入解析 oh-my-pi 会话标题生成协议:`<title>` 标记指令的设计与实现

发布时间:2026/9/11 5:47:42 来源:尧图企业网站定制
深入解析 oh-my-pi 会话标题生成协议title标记指令的设计与实现【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pititle-marker-instruction.md是 oh-my-pi 编码代理Coding Agent会话标题自动生成管线中的一条核心指令它要求模型把生成的标题以title.../title标签包裹输出并在遇到无实质任务的输入时输出titlenone/title。本文以这条指令为切入点结合 title-generator.ts、title-system.md、text.ts、title-client.ts 等源码完整还原这条标记协议从提示词设计、在线/本地双路径生成、容错解析到大小写归一化的全链路实现帮助你理解如何用一条简单指令约束 LLM 输出固定格式并可靠地解析回结构化数据这一通用工程范式。一、问题背景为什么会话标题需要一条独立的标记指令在 oh-my-pi 中每个会话session都应该有一个简短、可读的名字用于 TUI 会话列表、终端标题π 会话名以及协作者共享视图。但标题生成有一个天然矛盾标题模型大多是小体积模型默认约 350M 的本地 tiny 模型或通过 tiny/smol 角色解析出的在线模型它们能力有限容易在输出里夹带解释文字、引用用户原文、甚至把整段回答当成标题。为此项目把标题生成拆成一个受控的独立子任务并用一条专门的系统指令约束输出格式——这就是 title-marker-instruction.md 的职责。其全文为Output only the title wrapped intitleand/titletags, with nothing before or after. When the message carries no concrete task yet (a bare greeting, acknowledgement, or small talk), output exactlytitlenone/title.这条指令规定了两个关键契约输出格式只允许输出被title与/title包裹的标题标签前后不得有任何其他内容空结果语义当消息只是问候、确认或闲聊等不包含具体任务时必须精确输出titlenone/title而非自行发挥一个标题。后续所有解析逻辑、容错处理和归一化都以这个契约为基准。理解这一点是读懂整套标题管线的钥匙。二、从历史教训看标记方案的选择为什么不用更结构化工的方案例如强制模型调用一个set_title工具源码注释给出了明确答案。在 title-generator.ts 中记录道The model is always asked to wrap the title intitle.../titleand the title is parsed from text. A forcedset_titletool call was the old scheme, but hosts that ignore or reject forcedtool_choicethen echoed the prompts{title: ...}JSON example verbatim as the session title; markers work uniformly everywhere.也就是说旧方案是强制工具调用set_title但部分模型后端会忽略或拒绝强制的tool_choice此时模型会把提示词里 JSON 示例原样吐出来当成会话标题例如字面量{title: ...}。而纯文本标记方案在所有后端上行为一致——不需要依赖工具调用能力只要模型能遵循把答案包进标签这个极简指令即可。顺带一提也正是因为模型偶尔会把提示词中训练时见过的 JSON 结构当作标题输出解析侧专门实现了unwrapJsonTitle兼容函数见下文第六节会在把原始 JSON 作为会话标题之前将其解包成纯文本标题。三、在线路径系统提示词拼接与流式容错解析当用户显式选择在线标题模型providers.tinyModel配置为ONLINE_TINY_TITLE_MODEL_KEY时标题生成走 generateTitleOnline。这一路径的关键细节如下。3.1 系统提示词的两种组装方式title-generator.ts 中默认情况下系统提示词是TITLE_SYSTEM_PROMPT即渲染了示例的 title-system.md如果调用方传入自定义customSystemPrompt例如任务标签场景则用[customSystemPrompt, TITLE_MARKER_INSTRUCTION]拼接——自定义提示词负责内容语义title-marker-instruction.md负责输出格式约束两者解耦。其中TITLE_MARKER_INSTRUCTION正是通过prompt.render(titleMarkerInstruction)渲染 title-marker-instruction.md 得到的。这与 title-system.md 形成互补后者给出完整任务描述和 few-shot 示例如[AI] titleFix login button on mobile/title、问候时输出title/前者则是只输出标签、前后不得有杂音的硬约束。3.2 请求参数把标题当抽取而非生成调用completeSimple时设置的参数同样服务于标记协议title-generator.ts参数值设计意图disableReasoningtrue标题是抽取任务不需要思考链但TITLE_MAX_TOKENS被放宽到 1024以兼容那些无视disableReasoning、仍强制输出思考内容的后端注释关联 issue #4355temperature0贪心解码保证确定性否则如 Ollama 默认 0.8 的高温会把 hashline 这类词生成成 HasHroshi 之类的乱序拼写maxTokens1024硬上限而非目标值正常标题只有 37 个词放高上限是为了给未被抑制的思考内容留出到达title标记的 token 预算3.3 解析正则 思考信封剥离 可见性判断模型返回后extractGeneratedTitletitle-generator.ts按宽容优先的策略解析用TITLE_MARKER_GLOBAL_RE /title([\s\S]*?)\/title|title\s*\/|title\s*$/gi查找第一个可见的闭合标题标记可见性判断isVisibleTitleMarker会先把标记位置之前的文本经StreamMarkupHealing剥离已知的thinking泄漏包裹think.../think、thinking 等确保title不是藏在思考块里的伪标题若存在可见的标记标题则以其为准markedTitle优先级最高否则退化为去掉前导泄漏思考标记后取整句的兜底路径并在无标记路径上拒绝thinking process:这类散文式思考前导最终标题再经unwrapJsonTitle处理兼容{title: ...}形式的 JSON 输出包括被 json 代码围栏包裹、被截断的残缺 JSON——后者会尝试用正则抢救引号内的 title 值。这一层容错直接对应了标记指令中nothing before or after的严格要求正因为模型经常违规解析侧才需要这么多兜底逻辑来宽容地找回合法的title内容。四、本地 tiny 模型路径prefill 与 stop 序列当用户配置本地 tiny 标题模型如lfm2.5-230m时标题生成不经过在线 API而是通过 title-client.ts 与机器上的推理 worker 进程ONNX 或 Apple Silicon 上的 MLX经 Unix socket 通信。标记指令在这里演化成了解码期约束这是整条协议最精巧的地方const TITLE_PREFILL title; // 作为 prefill 预填 const TITLE_CLOSE /title; // 作为 stop 停止序列 const TITLE_MAX_NEW_TOKENS 20; // 标题最多生成 20 个新 token在TinyTitleClient.generate中构造请求时title-client.tsprefill: title让模型在生成前就看到已输出的title从第一个 token 起就进入标题内容stop: /title模型一旦生成闭合标签立即停止天然截断任何多余内容maxNewTokens: 20即使停止序列未被触发也限制标题长度上限。对应的解析函数extractTinyTitletitle-client.ts先取最后一个title前缀再依次剥离闭合标签、残余标签和多余内容最后交给normalizeGeneratedTitle归一化。同时本地 worker 的提示词使用includeExamples: false渲染的title-system.mdTINY_TITLE_SYSTEM_PROMPT因为小模型更容易被示例干扰而标记指令通过 prefill/stop 在解码层面已经保证了格式。这套提示词 prefill stop token 上限的四重保障正是对 title-marker-instruction.md 中只输出标签、无多余内容这一要求从**软约束提示词到硬约束解码参数**的完整落实。五、前置过滤低信号输入不打扰模型标记指令规定没有具体任务时输出titlenone/title但代码选择根本不问模型。原因在 text.ts 的注释中写得很清楚默认 tiny 标题模型约 350M无法可靠遵循请回答 none这类指令容易为琐碎输入幻觉出一个标题。因此generateSessionTitle的第一步是调用isLowSignalTitleInput(firstMessage)title-generator.ts做确定性前置过滤如果首条用户消息全由问候语、客套话、填充词hi、hey、thanks、ok、ping等见FILLER_TITLE_TOKENS集合或纯数字构成直接返回null会话保持未命名等待下一条消息再试。这个设计恰好解释了标记指令中titlenone/title的定位它是有能力的模型在无法判定任务时的兜底哨兵代码中NO_TITLE_SENTINEL none与title-system.md中问候场景输出title/自闭合空标签互相呼应而低信号过滤则是不依赖模型能力的第一道闸门。两道防线共同保证标题永远不会是 hi。六、归一化与大小写校准让解析结果真正可用即便模型严格遵守了title标记输出仍可能带引号、句尾标点或残缺标签。normalizeGeneratedTitletext.ts负责最终清洗只取首行剥离首尾引号与残缺title//title标签去掉末尾的.!?与哨兵值none大小写不敏感比对命中则返回null表示暂无标题施加硬性上限MAX_TITLE_CHARS 80、MAX_TITLE_WORDS 12超出即整体拒绝而不是截断因为那意味着模型没有执行标题任务、而是把回答全文输出了注释关联 issue #7303。进一步地reconcileTitleCasingtext.ts以用户原始消息为大小写事实来源做逐 token 校准用户消息里原样出现过的词保持原样TinyVMM、iOS这类用户刻意区分的混合大小写isDistinctiveCasing在模型压平后恢复CNPG→Cnpg这类被标题化的全大写缩写辅音为主或命中COMMON_TITLE_ACRONYMS白名单恢复为全大写dAemon这类模型拼坏的 camelCase 残留则转小写。同时通过isShoutySource避免把用户全大写强调的句子如FIX the BUG NOW重新吼回去。这一层看似与标记指令无关实则是让title内内容从模型输出变成可用标题的最后一公里——直接决定会话列表和终端标题的观感质量。七、协议复用子代理任务标签标记指令 标题生成管线并不只服务于会话命名。在 label.ts 中generateTaskLabel复用了generateSessionTitle只替换了系统提示词const label await generateSessionTitle( text, registry, settings, sessionId, undefined, undefined, TASK_LABEL_SYSTEM_PROMPT, // 自定义任务标签提示词 signal, );这正是 title-generator.ts 中[customSystemPrompt, TITLE_MARKER_INSTRUCTION]拼接设计的直接受益者内容语义由调用方自定义输出契约由标记指令统一保证。子代理的 UI 标签由此获得与会话标题相同的格式可靠性generateTaskLabel还额外用labelEchoesHandle过滤掉与 spawn handle如Name-2重复的标签。这证明该标记协议是一个可插拔的通用短文本生成 结构化提取基础设施。八、实践要点与设计启示回顾整个标题生成管线title-marker-instruction.md的价值不在于它本身多复杂而在于它被三层机制托举形成了一套可复用的工程模式指令极简、契约明确一条指令只做一件事——规定输出包裹在title标签内、无任务输出titlenone/title不给模型留解释空间解码期硬约束兜底在线路径用temperature: 0 高maxTokens上限保证可达性本地路径用prefill/stop/20 token 上限把只能输出标题变成解码器层面的物理事实解析侧全面容错支持思考信封剥离、可见性判定、JSON 解包、截断抢救、长度/词汇上限与大小写校准使协议在任何模型输出形态下都能收敛到干净标题确定性前置过滤低信号输入根本不发模型请求把模型不可靠的变量挡在协议之外提示词与指令解耦复用title-marker-instruction.md可与其他自定义提示词自由拼接服务于会话标题、子代理标签等多个场景。对于需要在自身 Agent 系统中实现让 LLM 稳定输出结构化字段的开发者oh-my-pi 的这套title标记协议提示词约束 prefill/stop 硬约束 容错解析 确定性过滤四层组合是一个经过生产级打磨的完整范本值得直接借鉴。【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价