Originally published at olund.dev.
我的工具链中有一部分会按照已配置的声音生成长篇文章:一个描述受众、语域、词汇和作者语感的编辑身份。该身份是一段散文式的配置。而语气散文配置有一个令人头疼的特性:它们是只写模式。你描述想要的声音(“不慌不忙、充满好奇、从第一性原理出发、绝不夸张”),生成器使用它,而你只能在支付完整生成费用并阅读结果后才能知道描述是否生效。如果语域不对,你再修改形容词并再次付费。
反馈回路就是问题所在。通过完整生成来调整人设,就像每次通过承办婚礼来调整菜谱。我想要的只是一个试听:给定这个身份,立即用这种声音说两句话,花的钱接近于零。
最小的智能体
解决方案是一个预览智能体,设计目标是让它尽可能接近免费——因为你犹豫是否运行的预览就不会被运行。它的所有设计都是在做减法:
- 无工具。 智能体不能读取文件、浏览或搜索。它需要的一切——身份文本和可选主题——都直接内联传入调度。这不只是为了控制成本:一个没有工具且上下文完全内联的智能体是可复现的。相同输入、相同输出类别,没有任何环境因素会发生漂移。
- 快速本地模型。 试听语域是狭窄的工作,它需要对风格描述的忠实度,而非推理深度。调用会被路由到我工作运行时中最便宜的层级——一台运行在我自己机器上的小型模型。一次测量的试听端到端大约消耗 500 个 token,在本地硬件上成本接近于零。
- 硬性输出模式。 智能体必须返回两到六行示例,每行都是一两句该声音会实际说出的句子,且仅此而已——没有标题、没有舞台指示、没有关于声音的评论。模式在调用层被强制执行,因此格式错误的响应会重试,而不是到达 UI。预览是一份契约,而非聊天。
- 构造上的临时性。 提供该服务的路由不写入任何内容:没有数据库行、没有产物、没有历史。持久化的预览输出会变成状态——需要列出、迁移和清理的东西。预览的全部价值在于它会蒸发。
- 超时与一次重试。 九十秒,一次恢复尝试,然后可见地失败。挂起的预览比报错的预览更糟。
提示侧是一条规则以三种方式重复:精确匹配身份的语气、语域和词汇;每行必须是可独立说出的散文;不要进行元评论。用描述声音的示例行代替体现声音的示例行是失败模式,而指令直接针对这一点。
它创建的循环
在设置 UI 中,身份编辑器旁边有一个示例按钮。输入可选主题,点击,片刻后:几行配置声音的文本。编辑身份,再次采样。调优循环从“生成完整作品、阅读、皱眉”缩短到每次迭代几秒。
两个 UI 决定比表面看起来更重要:
预览不使任何内容失效。 它是一个普通的即发即回调用,没有缓存更新,因为它不改变状态。将预览像变更一样接入应用的数据层是一个类别错误,会让每次预览都触发一次重新获取。
空状态进行教学。 当没有配置身份时,按钮不会静默禁用;端点会拒绝并返回“身份未设置”,UI 也会如此说明。一个前置条件不可见的预览功能会被读作损坏。
底层还有一个接口决策:该路由会同步等待工作线程,限制在两分钟内,而不是返回一个由客户端轮询的作业 ID。预览是交互式的——人在现场。当预览需要进度条时,它就不再是预览了,因此 API 形状编码了延迟预算:如果这不能在用户观看时回答,它应该报错,而不是流式传输状态更新。
为什么这是一种模式而非功能
通用形态是:当一个系统消费人类编写的描述并产生昂贵结果时,在两者之间插入尽可能便宜的采样器。 描述到输出的差距是信心悄然消亡的地方——你编写了配置,你认为它表达了你的意思,而唯一可用的验证方式却需要一次完整运行。
采样器在以下情况值得采用:
- 足够即时以成为反射。 几秒,而非几分钟。当采样需要决定是否值得时,迭代就会停止。
- 足够免费以消除负罪感。 本地模型或最便宜的 API 层级。任务天生狭窄;使用最狭窄的能完成工作的线程。
- 足够受限以保持诚实。 在目标格式中强制输出的模式。返回一篇关于它将如何做的文章的采样器只是表演。
- 足够无状态以被忽略。 无持久化、无历史、无清理。运行四十次;没有任何累积。
我现在在散文配置驱动生成时都会采用这种形态:在作品前采样人设,在批处理前采样摘要风格,在评审运行前采样评审者的严厉程度。每个采样器都是一下午的工作,因为减法构建起来很快——整个智能体定义只需一屏,而它所依托的工作运行时已经存在。
其下安静的教训与模型路由有关。本能是将每个任务发送到可用的最强模型。但预览的工作是代表性与即时性,而非最大化——一个带紧凑模式和内联上下文的小型本地模型比一个用更多自由度即兴发挥的前沿模型更能代表“配置的声音会是什么样子”。将线程匹配到任务的狭窄性,有些任务结果证明几乎是免费的。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.