跳到正文
返回博客
我给口述 Prompt 加了一道窄门
作者
Zinian
发布时间
2026年8月4日
阅读时间
9 分钟阅读

AI 工程

我给口述 Prompt 加了一道窄门

Local Prompt Refiner 不是把需求写得更漂亮,而是用本地小模型、确定性约束和真实输入测试,尽量不让一句‘不要动后端’消失在整理过程中。

我对 Codex 最常说的,可能不是需求,而是需求后面的补丁。

“对了,不要动后端。”

“等等,先给 plan,别直接改。”

“数据库也别碰。”

一段口述越长,这些边界越容易埋在“然后”“就是”“我感觉”中间。人听得出来哪句只是口头禅,哪句是不能丢的限制;模型却可能把两者一起压平,最后交回一份语法漂亮、权限失控的任务书。

Local Prompt Refiner 就是从这个很窄的问题里长出来的。它有 Web、CLI 和 macOS 菜单栏三个入口,接住粘贴或录下来的中文,再整理成可以交给 Codex、Claude Code、Cursor Agent 的执行指令、计划、/goal 或 JSON。

但我后来给它的定位,反而比“Prompt 优化器”更小:它不是负责把话写聪明,而是负责让明确说过的边界别在改写里丢掉。

模型负责理解,代码负责不许忘

整理口述听起来像一个纯文本任务:删重复、补标点、分章节。只靠模型也确实能做出一个看起来不错的 Demo。

问题在于,“看起来不错”和“可以直接执行”中间隔着权限。

“只改 UI”少一个“只”,范围就变了;“先计划”被整理成“制定并实施计划”,动作就提前了;“别动数据库”如果在摘要里消失,后面的 Coding Agent 不会知道自己刚跨过一条线。它不是总结质量下降一点,而是把用户没有授权的工作伪装成了合理下一步。

所以我没有继续追求一份更会说话的 system prompt,而是把工作拆成两层:模型负责理解和重组,程序负责守住那些可以明确检测的义务。

模型输出回来后,服务端会统一章节、清掉可能泄露的 thinking、压缩 Plan,再从原始输入重新检查“不改后端”“只改 UI”“先给计划”“不动数据库”“不要大改架构”这些硬限制。如果模型没保留,程序会把它补回对应区块。

模糊项没有这么神。当前代码只识别三类模式:范围自相矛盾、既要求先计划又要求立刻执行,以及需要进一步落地的主观 UI 表达。识别到以后,Markdown / Plan 会写进 Ambiguities / Need attention/goal 会落进 Stop if,JSON 则进入 ambiguities 数组。长而乱的样本现在也会对这些已知模式做 fixture 检查,但底层仍然是正则和固定样本。它不是通用语义裁判,也不能保证所有模糊话都会被抓住。

这层 guardrail 不聪明,甚至有点笨。它靠模式和同义表达工作,不理解世界,也不保证整份输出语义完美。但正因为它笨,它不会在第二次生成时又突然改变主意。模型可以负责“这段话大概想做什么”,代码负责“这句话既然说了,就不能当没听见”。

JSON 模式很快又给这套分工补了一刀:真实评估里,模型曾把 schema 要求的数组返回成字符串。内容可能没错,下游拿到的却不是“差一点的 JSON”,而是一份不满足契约的数据。

我的处理很直接。非空字符串落在数组字段时,归一化成单元素数组;空字符串变成空数组。缺字段、非法 JSON、占位值或更严重的 shape mismatch 不猜,只允许一次带严格 schema 的 repair retry。第二次仍失败,就把错误和原始输出交出来,到此为止。能机械确认的轻微偏差可以修,不能确认的内容继续自动脑补,只是在把错误藏深一点。

四种输出模式也只做一件事:把权限写成不同形状。Execute 表示可以动手,Plan 表示先读仓库和给方案,/goal 写清长任务的停止条件,JSON 给程序消费。它们不是四套文案皮肤。

8B 不是将就,是任务终于被收窄

这个项目一开始也走过很自然的弯路:更大的模型应该更稳吧。

实际记录没这么配合。在一次针对 Plan 模式的样本里,qwen3.6:35b-a3b 请求超时;换成 Qwen3-8B-MLX-4bit 后,同一个样本通过,平均耗时约 8.1 秒。后来那轮全量评估跑了 10 条中文口述、3 种输出模式,共 30 个 case,结果是 30/30。

我不把这个数字写成“小模型打败大模型”。它只证明了更有限的一件事:在这台机器、这组 fixture 和这项窄任务里,能稳定返回、再接受确定性修补的 8B 模型,比一次因为延迟超时的 35B 更有用。

后续样本扩到更长、更乱的输入后,问题也马上出现了:三条 fast Plan 虽然都通过硬限制、标题和 thinking 泄露检查,却全部超过 1400 字符的 warning 线;一条矛盾范围样本同样通过检查,但输出明显偏长。也就是说,它会守住测试在看的东西,同时在没被严格约束的维度上继续啰嗦。很模型,也很诚实。

这也是我更愿意继续扩 fixture,而不是先换更大模型的原因。任务越窄,失败越能被命名;失败能被命名,才有机会进入下一轮测试。模型尺寸只是其中一个旋钮,不是结论。

语音入口也是契约的一部分

菜单栏版本加入本地 whisper.cpp 转写后,我本来以为最麻烦的会是中文识别。结果真正卡住的是:它录错了麦克风。我一边认真调转写参数,一边把数字静音喂给 Whisper,多少有点给空气做 NLP 的意思。

这台 Mac 的系统默认输入碰巧是 BlackHole 2ch,一个虚拟音频设备。早期录音链路跟着系统默认走,格式、构建、测试都能过,最后得到的却可能是一段数字静音。后来的修复不是继续调 Whisper prompt,而是枚举输入设备、记住用户选择、优先真实物理输入,并在录音时按 UID 显式绑定;选到 BlackHole、Loopback 一类设备时,界面会直接警告。

代码和 30 个 Swift 测试都通过了,但我不把这段写成“麦克风问题已经解决”。独立声学回环里,内置麦仍然是 peak 0、RMS 0;另一个 Continuity 输入能录到非静音电平,却没有稳定录到播放的句子。Whisper 对直接生成的同一句音频可以正确转写,说明失败点在真实声学输入链路,可完整的端到端硬验收仍然没过。

语音在这里不是一个方便的输入框皮肤,它是契约的来源。如果录音设备根本没接住“不要动后端”,后面的模型再会保留限制也没有用:那句话从未进入系统。于是语音路径的验收必须从“有没有录到正确声音”开始,而不是从转写文案看起来像不像中文开始。

窄门只负责一件事

Local Prompt Refiner 现在没有历史记录,也不替你托管云服务。默认流程是本地前端或菜单栏调用本地 Node 服务,再由它连接你配置的 OpenAI-compatible 端点;如果端点也在本机,整条文本链路可以留在本地,如果你把地址指向远端,它当然就不再是“完全离线”。

我喜欢这个形状,因为它没有假装自己能理解所有需求。它只接住一个反复发生的小动作:把人类口述变成 Agent 可以执行的契约,然后在最容易丢权限的地方多看一眼。

现在我把一段话交给它,最后检查的不是标题够不够像规格文档。我会去找开头那三句:“只改 UI”“先给 plan”“数据库别碰”。

三句都还在,窄门才算工作。少一句,后面多九个漂亮标题也救不回来。

相关文章

和这个主题相邻的更多笔记。

用本地工具和云模型搭建个人 AI 工作台

精选
AI 工程
2026年5月8日8 分钟阅读更新于 2026年5月10日

一个实用的 AI 工作环境:能起草、测试和发布,又不会把流程缠在一起。

ai-agent
automation
codex
阅读全文

做 AI DJ,难的不是选歌

AI 工程
2026年7月6日10 分钟阅读

Claudio FM 是一个 AI 私人电台。做它的过程里我发现,让一个 AI DJ 可信,难点不在选歌,而在教它何时闭嘴、说什么、以及在它必然出错时别把电台拖垮。

claudio-fm
ai-radio
tts
阅读全文

我如何为小型产品团队组织 Agent 工作流

精选
Agent 工作流
2026年4月24日7 分钟阅读更新于 2026年4月28日

小团队的 agent 工作流需要清楚入口、可见检查点和严格的交接路径。

codex
claude
workflow
阅读全文

下一步

继续浏览文章列表,或者把这篇文章里的问题展开成一次具体讨论。