首页 / 资讯中心 / 文章详情

AtomCode 旁路模型缝 `llm-utility` 与会话标题机制:从第一条提问到模型起名的完整设计

AtomCode 旁路模型缝 `llm-utility` 与会话标题机制:从第一条提问到模型起名的完整设计 ★ FEATURED ARTICLE
人工智能AI Agent代码智能体自主智能体MCP ClientsCLI【免费下载链接】atomcodeClaude Code 的开源替代方案。连接任意大模型编辑代码运行命令自动验证 — 全自动执行。用 Rust 构建极致性能。 An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get Started项目地址https://gitcode.com/atomgit_atomcode/atomcode点击查看免费下载本文是 AtomCode 开源项目内部架构决策记录 ADR 0015 的深度解读。它围绕「会话标题怎么起、什么时候起、谁来起」这一具体问题讲述了项目如何抽象出一条全新的旁路模型缝seamllm-utility并据此重做会话自动命名用便宜的模型、和模型回答并行、用户改名永远优先。读完本文你将掌握该决策的完整来龙去脉、session-title与llm-utility两套缝的行row配置方式、默认行为与 2026-09-25 的修订内容以及压缩摘要等后续消费者如何复用同一机制。背景会话标题此前只能按需算算完就丢在 ADR 0015 落地之前AtomCode 的会话标题存在一组结构性缺陷session-title这条缝只有唯一的提供方它不做模型调用只是拿第一条提问截断成标题repl 里的/title命令算完标题后打印即丢不进会话日志因此session/list列表和 ACP 协议的SessionInfoUpdate都拿不到标题。用户真正想要的是三件事的组合用模型按第一个问题起名、用便宜的模型不要和主对话抢贵的额度、和模型回答并行不要等标题算完才开始回答。这份 ADR 承接了 ADR 0014 中没有人提交Titled这一遗留问题于 2026-09-12 实现。值得强调的是这类程序消费结果的旁路调用不止起名一个压缩摘要、/compact focus定向摘要、下一步建议、子 agent 的快档在 coding 侧都有需求缺口清单里统一标注着「缺 tier provider」。它们的共性在 ADR 中写得非常清楚一次性每次调用都是独立的不构成可缓存的连续对话结果由程序消费读它的是日志、列表、状态更新不是人眼没有前缀可缓存模型单价就是全部成本不该和对话抢同一个网关的限速旁路请求失败不应砸坏用户正等着的主回答。决策一一条新缝llm-utility语义是旁路模型第一个决策是抽象出一条新的缝llm-utility。它的接口面face和主对话用的llm一样都是dyn LlmProvider见 seams.rs 中plexus_service!(LlmUtilitySvc dyn LlmProvider, llm-utility, ...)的定义但语义明确为「程序消费结果的旁路模型」——它不是给人看的对话而是给日志、列表、摘要等程序逻辑读的。在 harness 中这条缝有三个提供方见 llm.rs提供方行用途说明llm-utility-openai-compat生产部署自己配modelbase_url和 key 缺省时沿用主行读的环境实现同一网关、更小的模型llm-utility-selected有模型目录的宿主从宿主的models目录按 id 取模型不指定时挑目录里最弱的模型旁路调用天然想要最便宜的llm-utility-replay测试脚本化的旁路模型无网络测试里用它说旁路请求的答案关键约束是BASE 不挂这条缝消费者按需解析。也就是说默认装配下llm-utility是空的只有某个消费者如模型版起名确实需要旁路模型时才由 patch 或宿主把它填上。llm-utility-openai-compat的解析逻辑在源码中很直观llm.rs配置了base_url就走Want::Explicit否则走Want::EnvironmentWithModel最终从与主对话行同一个model_source::ConfigAndEnv解析出端点、key 和模型。这保证了缺省沿用主行读的环境——你不需要为旁路模型重复配置网关。决策二消费者不回退到llm便宜模型要显式配置第二个决策在初版和 2026-09-25 修订之间有演进但有一条底线始终未变llm-utility找不到时绝不静默借用主对话的llm缝。初版的理由有两条都写进了 ADR限速冲突旁路请求和第一回合抢同一个 adapter 的限速429 会砸在用户正等着的那条回答上测试污染测试里如果回退到llm会吃掉 replay 脚本的下一行而且因为起名是并行触发的吃哪一行是不确定的。结论是「便宜模型要显式配置」比「静默用贵的」更好。2026-09-25 的修订对标题放宽了这条规则改为经模型目录借当前对话模型但对没有模型目录的树——驱动脚本化llm的测试夹具——原第 2 条不吃主脚本的保证原样成立。这一约束在测试with_nothing_to_borrow_the_script_is_not_eaten中被单独守护见 session_title.rs 测试它验证了既没有旁路行也没有模型目录时起名器绝不伸手够那条脚本化的llm回合照常拿到自己那一行答案。决策三怎么起名、什么时候起名——两个行各管一问ADR 的第三个决策是职责拆分怎么起名和什么时候起名是两条不同的行分别填不同的缝。这在 session_title.rs 实现 中体现得淋漓尽致。session-title缝回答怎么起这条缝由session-title-first-prompt和session-title-model两个提供方竞争填充seam 定义见 seams.rstrait 只有describe()和title(log)两个方法session-title-first-prompt默认无模型调用直接取日志里第一条UserMessage经tidy函数清洗成标题。tidy的清洗规则源码 session_title.rs包括取第一行非空行去掉首尾的引号“”「」按词数截断默认max_words 8按字节封顶默认max_bytes 80超限按 4 字节一字符截去掉截断后悬在尾部的标点.。 , : ; ! 、。session-title-model模型版用系统提示词约束模型输出源码常量TITLE_SYSTEMYou name conversations. Given the first message a person sent, reply with a short title for the conversation: at most eight words, in the persons own language, no quotes, no trailing period, and nothing but the title.即不超过八个词、用用户的语言、不要引号句号、只输出标题本身。请求参数方面初版设max_tokens 32、超时 15 秒回来后同样经tidy清洗取第一行、去引号、按词数字节封顶、去尾部标点调用慢、失败或答空时回退到第一条提问截断——会话总归会有一个名字。session-title-on-first-prompt策略行回答什么时候起、落在哪这是第三个决策里最精妙的部分。策略行监听SessionEventCommitted看到UserMessage落地且日志还没有标题时就 spawn 一个后台起名任务实现见 session_title.rs。时序上的关键点第一条提问在模型请求发出之前就 commit 进日志agent_loop.rs的既有行为所以标题与回答天然并行——起名任务在后台跑不阻塞主对话任务回来后 commit 一条Titled事件事件里user_set: false标记这是自动起的名字驱动driver据此不把它显示成用户命名每个会话同时只有一个起名任务在飞实现用一个HashSet记录 in-flight 的会话 idin_flight重复触发直接丢弃。由此日志、session/list、/resume列表和屏上的标题读到的是同一个名字——因为它是作为一条Titled事实提交进日志的而不是存在某个旁路变量里。决策四用户改名永远赢第四条规则是优先级用户自己改的名字谁也动不了。策略行只在日志没有标题时动手且commit 之前再查一次——如果模型思考期间用户手动起了名自动名字直接放弃。repl 的/title 名字以及/rename直接 commitTitled事件里最新的一条生效。ADR 明确不为Titled增加谁起的字段只靠user_set布尔值区分。在 coding 侧这一规则被浓缩成一行逻辑session_title.rspub fn should_accept_ai_name(user_renamed: bool, ai_named: bool) - bool { !user_renamed !ai_named }它的单元测试注释写得很直白人改过的名字不许动自动命名只做一次——第二次自动命名会把人刚刚读熟的名字换掉而他没有做任何事。经典界面--classic与 daemon 的会话目录都读这条规则。决策五默认不开模型起名两行 patch 即可开启第五条决策是默认行为的选择BASE 挂策略行 第一条提问版即默认不需要任何模型调用就有标题要模型起名只需在 patch 层填两行[[patch]] id session-title-first-prompt name session-title-model [[insert]] id llm-utility name llm-utility-openai-compat config { model deepseek-v4-flash }第一段把session-title缝的提供方从第一条提问版换成模型版第二段为llm-utility缝挂上 openai-compat 提供方并指定模型如deepseek-v4-flash。base 层不挂llm-utility的约束在这里体现得很清楚模型版起名行需要旁路模型所以 patch 必须同时把这条缝填上。在 coding 宿主上模型起名的开关由[ui] ai_session_naming控制环境变量ATOMCODE_AI_SESSION_NAMING可覆盖取值为0/false/off时禁用见 config/mod.rs。该配置默认开启default_ai_session_naming() - true见 config/mod.rs。装配时on_harness.rs 里的config_rows会根据names_sessions_with_a_model的结果执行swap(session-title-first-prompt, session-title-model)把默认的截断命名器换成模型命名器。2026-09-25 修订标题借对话模型且不再设输出上限ADR 文末的修订章节2026-09-25揭示了两个真实世界里踩到的坑这也是阅读本文最有价值的部分。坑一llm-utility-selected在没排名的目录上是空的产品里[ui] ai_session_naming默认开on_harness据此把命名器换成session-title-model。但llm-utility由llm-utility-selected填充而它只在模型目录里有capable_model排名时才填源码 llm.rs没有排名时返回None明确留空才是对的——从无序目录里挑大概那个等于从名字推断成本。实测本机没有排名于是llm-utility的位置永远空着开关什么都不做每个会话的名字都是第一条提问原文而且没有任何提示。修复方式是session-title-model找不到llm-utility时向宿主的模型目录要当前对话模型——走ModelsSvc::current()拿到当前模型 id再models.provider(current)取 provider见 session_title.rs。为什么要经目录而不是直接借llm缝ADR 说得明白有目录的宿主才是能把当前模型再交出来的宿主——coding 宿主交出的就是活槽仍是一套凭据没有目录的树脚本化llm的测试夹具无可借原不吃主脚本的保证原样成立。这一层防线有实测为证去掉经目录借这一环时assemble_smoke/verify_cadence/overflow_recovery三组共 8 条判据当场红掉。代价是 ADR 明说的标题与第一回合争同一网关的限速。每会话一次短请求是开关本身要的交换。坑二32 的max_tokens上限把会思考的模型饿死了openai-compat 的思考和回答共用一个max_tokens且思考在前。deepseek-flash 在 32 的上限下思考 106–134 字后finish_reasonlength、正文为空——每次都这样不设上限时 225–260 token 自然结束答出查看工作区状态。同一天的下一步建议也因同一原因去掉了上限commitc1edf150f。修订后的规则是行配置max_tokens默认不设请求由超时15 秒、512 字节读取上限流式读取时超过 512 字节即停止与tidy清洗共同界定。已知不思考的模型仍可在行上显式设max_tokens。这条在测试a_model_that_thinks_first_is_not_starved_by_an_output_cap中被复现一个先吐 120 token 思考再答的模型给定小于思考量的上限就truncated无正文去掉上限后正常输出标题。修订的边界只改标题llm-utility缝本身不因此被填修订明确只改标题。llm-utility缝本身不因此被填team 的 Simple 角色与压缩摘要也读它那两处该不该落到对话模型是各自的决定不能因为标题借了对话模型就默认旁路缝也被填上。权衡过、没做的给人看的回复摘要ADR 记录了一个认真考虑过但明确不做的事用便宜模型把模型的长回复摘成几行覆盖给用户看。三条理由值得一读流式 TUI 里用户已经看完了流摘要来得太晚模型回复里的命令、路径、代码恰恰不能被摘要替掉真正的长输出是工具结果而工具结果已有折叠机制。如果要做形状应是一条Digest { of: seq, text }事件加 TUI 的呈现折叠原文不动、模型可见的消息不动只对工具结果开——等 dogfood 发现折叠不够再说。闸门测试如何钉死这套行为ADR 的闸门章节对应 coding/tests/session_title.rs测试从两个维度守护行为什么时候起默认装配the_first_prompt_names_the_session_once第一条提问后日志里出现一条Titled取前 8 词第二个回合不再加——只起一次名removing_the_policy_row_leaves_sessions_unnamed删掉策略行会话就没有标题。谁来起、谁赢模型版the_utility_model_names_it_when_the_row_says_sopatch 成模型版且挂llm-utility-replay时标题来自旁路脚本Windows build fix.被清洗成Windows build fix主脚本未被消耗without_a_utility_model_the_conversation_model_names_it无旁路模型时经目录借对话模型起名对应修订判据之一with_nothing_to_borrow_the_script_is_not_eaten没有目录可借时不碰主脚本a_namer_that_gets_nothing_back_leaves_the_first_prompt旁路调用失败如网关挂掉时回退到第一条提问a_model_that_thinks_first_is_not_starved_by_an_output_cap会思考的模型不被输出上限饿死对应修订判据a_name_the_person_gave_is_kept用户先起的名字不被覆盖。ADR 记录harness tui 全量 475 条测试全绿差分基线未动。下一个消费者压缩摘要ADR 明确指出的下一个消费者是压缩摘要做一个compaction-summary行填compaction缝把 capabilities 里OverflowCompaction的 stub 模型摘要接到 harness摘要走llm-utility。这在 compaction.rs 中已经落地CompactionSummaryPlugin的uses声明为[compaction, llm, llm-utility]——compaction因为要填那条缝llm用于拿上下文窗口做触发测量摘要本身走llm-utility摘要失败时回退到无模型的事件列表。ADR 在这里留了一条值得传播的提醒摘要模型不能太便宜——标题起坏了只是难看摘要写坏了主对话从此带着错误的记忆。小结llm-utility与session-title这两条缝的设计展示了 AtomCode 在处理程序消费结果的旁路模型调用时的完整方法论缝先行旁路调用是独立的一类需求抽象成一条缝提供方按部署方式自由选择openai-compat / selected / replay默认不给BASE 不挂旁路缝消费者按需解析避免无谓开销职责拆分怎么起session-title缝和什么时候起策略行分开策略行借事件驱动的时机实现并行用户优先自动命名只做一次、只在无标题时做、commit 前复查用户改名永远赢真实世界校准2026-09-25 修订告诉我们——配置的默认值必须经得起模型会思考和目录没有排名这两种现实且旁路缝的默认策略因消费者而异标题可借对话模型摘要未必。如果你要在一个自己的部署里启用模型起名最简路径就是 ADR 里那两行 patch如果你想复用这套旁路模型机制做摘要或建议compaction-summary行和llm-utility-selected行是现成的参考实现。赞分享人工智能AI Agent代码智能体自主智能体MCP ClientsCLI【免费下载链接】atomcodeClaude Code 的开源替代方案。连接任意大模型编辑代码运行命令自动验证 — 全自动执行。用 Rust 构建极致性能。 An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get Started项目地址https://gitcode.com/atomgit_atomcode/atomcode点击查看免费下载相关推荐退役 core::conversation将 AtomCode TUI 会话模型端口至 kernel Message 的设计与实践退役 core::conversation将 AtomCode TUI 会话模型端口至 kernel Message 的设计与实践 这是一份面向架构师与 TU人工智能AI Agent代码智能体自主智能体MCP ClientsCLIDeepSeek Harness 模型目录与 ACP 会话级模型选择从 Provider 路由到逐会话选型的架构实现DeepSeek Harness 模型目录与 ACP 会话级模型选择从 Provider 路由到逐会话选型的架构实现 output /output人工智能AI AgentAgent 框架DeepSeekHermes Desktop 会话级模型覆盖Session Model Override机制解析从聊天内模型选择器到跨 Provider 路由Hermes Desktop 会话级模型覆盖Session Model Override机制解析从聊天内模型选择器到跨 Provider 路由 会话级模型AI 应用交互助手桌面应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站