在Pi 5上运行3B量化模型管理邮件、写代码、部署的经验总结,指出小模型在多步骤任务中注意力衰减的具体表现。
自从五月起,我就在树莓派 5 上运行一个 AI Agent。不是聊天机器人,不是演示项目,是一个真正能管理邮件、写代码、部署软件、提交文章的 Agent。跑在本地的是一个 3B 参数的量化 LLM。这篇文章讲的是我在为小模型设计任务时踩过的坑。
具体配置细节在另一篇文章里。这里我想聊的是没人写过的东西:当你把模型跑起来、试图让它做实际工作时会发生什么。"能响应提示词"和"能可靠地完成多步骤任务"之间的鸿沟,正是大多数项目折戟的地方。
3B 模型不是 GPT-4。我知道,这很惊人。但背后的含义远比"它没那么聪明"更深层。失败模式是具体且可预测的,一旦你理解了它们,就能针对大部分问题做预防设计。
以下是小模型做 Agent 任务时真正会出的问题:
它会丢失线索。 在多步骤任务的第 4 或第 5 步左右,模型会忘记自己在做什么。不是那种模糊的遗忘。它输出的响应会与两步前说的话相矛盾,或者重复一个已经完成的步骤。这不是上下文窗口的问题,是注意力的问题。3B 模型在长上下文上的注意力比大模型差,即使上下文完全放得下。
它会幻觉工具调用。 模型会编造不存在的参数,或者用错误的参数类型调用工具。它可能在需要文件路径的地方传入一个 URL,或者为一个不支持该参数的命令编造一个 flag。
它会陷入循环。 某件事失败了,模型试图修复,修复以略微不同的方式又失败了,它再用一个大同小异的变体重试。如果你不设置熔断机制,这会无限进行下去。
它会把简单的事情复杂化。 让它创建一个文件,它会写一个 40 行的脚本,包含错误处理和日志,而不是直接写文件。小模型似乎通过过度冗长来弥补自己的局限,这反而让它变得更糟。
经过三个月的反复试错,以下是适用于小模型 Agent 的任务设计哲学:
这是最重要的一件事。不要说"把应用部署到 VPS",而要说:
SSH 到这个 IP 的服务器
运行 apt install nginx
用这个确切的内容创建这个配置文件
运行 systemctl restart nginx
用 curl localhost 验证
每个步骤都应该产生一个你可以检查的明确结果。模型不需要在脑子里hold住整个部署过程,它只需要执行一条命令,看输出,然后继续。
我把 Agent 的工作结构设计成检查清单。每个条目是一个动作配一个预期结果。如果结果不匹配,Agent 停止并报告。光是这一条,就让我的成功率从大约 40% 提升到了 85%。
我在 Agent 项目中看到的最常见错误是试图通过提示词工程来做所有事情。模型的工作应该是决定做什么,而不是怎么做。给它处理"怎么做"的工具。
我的 Agent 有一个终端工具、一个文件编辑器、一个网页浏览器和一个邮件客户端。当它需要安装东西时,不需要从零生成 apt 命令。它调用终端工具,传入 apt install nginx,然后获得真实的输出。工具处理错误码、超时、重试。模型只需要读取结果,决定下一步做什么。
这对小模型尤为重要,因为它们生成正确语法能力更差。如果工具处理语法,模型只需要正确做出高层决策。
当我的 Agent 说任务完成了,我不会信任那个叙述。我检查产物。文件真的改了吗?进程真的启动了吗?端点真的在响应吗?
我在每个工作流中都内置了验证步骤。Agent 声称完成后,一个独立的检查程序运行,检查真实的系统状态。如果 Agent 说"nginx 在运行"但 systemctl is-active nginx 返回"inactive",任务就被标记为失败。
这听起来很明显,但你猜不到有多少 Agent 项目跳过了这一步。模型说"完成了!"系统就报告成功,而不检查。然后三小时后你才发现什么都没发生。
3B 模型在收到太多上下文时会困惑。我会在工具输出送回对话前裁剪它们。如果一条命令产生了 500 行输出,我就给模型发送最后 20 行加一个摘要。如果一个文件有 2000 行,我只发送相关部分。
这与你在 GPT-4 上做的相反,对 GPT-4 来说更多上下文通常更好。对小模型来说,更少的上下文意味着更好的决策。上下文窗口中的信噪比比完整性更重要。
如果 Agent 尝试同一动作三次都失败了,它就停止。不重试,不说"让我换个方法试试"。它停止并向我报告失败。这防止了循环问题,也防止了 Agent 在困惑时做出破坏性行为。
我是付出了代价才学到这一点的。早期,我的 Agent 卡在试图修复一个 nginx 配置错误上,以越来越有创意(也越来越错)的配置循环了 45 分钟我才注意到。现在熔断器在三次尝试后就会切断它。
我追踪 Agent 尝试的每个任务。以下是三个月的数据:
成功完成的任务:289(84%)
需要人工介入的任务:38(11%)
完全失败的任务:15(4%)
84% 的成功率是应用了上述所有设计改进之后的。在我没有开始将任务拆解为原子步骤并添加验证之前,成功率接近 50%。
作为背景介绍,Agent 负责处理:邮件分类和回复(起草,由我审阅后发送)、代码编写和部署、文件管理、网络研究、文章起草。代码和部署任务成功率最高(90%+),因为它们最结构化。文章起草成功率最低(约 70%),因为写作质量很难程序化验证。
我的 Agent 大约 30% 的工作会发送到云端模型而不是本地树莓派。具体来说:
超过 200 行代码的复杂代码审查
文章写作(3B 模型的文风太重复)
需要跨多个大文件进行推理的任务
需要模型做创意而非程序化工作的任务
本地模型处理程序化工作。云端模型处理创意工作。这种分工让我每月的云端 API 费用保持在 8-10 美元左右,而不是之前的 40-60 美元。树莓派免费处理剩下的 70%。
最让我惊讶的是,如果你正确地结构化任务,一个 3B 模型能做多少有用的工作。我原本以为它会是个玩具。不是的。它是一个能力有限的执行者,作用域很窄。它不会设计你的架构或写你的营销文案,但它能可靠地安装软件、配置服务器、管理文件、执行检查清单。
工程努力在设计任务上,而不是在模型上。一个结构良好的 3 步任务,配上清晰的验证,在 3B 模型上能可靠完成。一个模糊的"想办法部署这个"任务在 3B 模型上会失败,在 70B 模型上也会浪费你的时间。你为小模型建立的任务设计纪律也会让你的大模型 Agent 变得更好。
如果你在小模型上构建 Agent:
把你的任务写成编号的检查清单,再交给模型。如果你不能把它写成检查清单,那任务对小模型来说太模糊了。
把你的任务写成编号的检查清单,再交给模型。如果你不能把它写成检查清单,那任务对小模型来说太模糊了。
每个步骤应该只有一个动作和一个可验证的结果。"安装 nginx 并配置它"是两个步骤,不是一个。
每个步骤应该只有一个动作和一个可验证的结果。"安装 nginx 并配置它"是两个步骤,不是一个。
裁剪工具输出。给模型 20 行,不是 200 行。更少的噪音意味着模型做出更好的决策。
裁剪工具输出。给模型 20 行,不是 200 行。更少的噪音意味着模型做出更好的决策。
在工作流中内置验证。不要信任模型的自述。检查系统状态。
在个工作流中内置验证。不要信任模型的自述。检查系统状态。
设置重试限制。三次尝试,然后停止。循环是小模型 Agent 浪费时间的第一名。
设置重试限制。三次尝试,然后停止。循环是小模型 Agent 浪费时间的第一名。
记录什么有效什么无效。一个月后你会看到规律。某些任务类型有 95% 的成功率,其他只有 50%。加倍投入有效的,把其余的交给更大的模型。
记录什么有效什么无效。一个月后你会看到规律。某些任务类型有 95% 的成功率,其他只有 50%。加倍投入有效的,把其余的交给更大的模型。
在树莓派 5 上跑 3B 模型不会取代你的云端 API。但它能处理很大一部分构成 Agent 日常工作中最无聊的程序化工作。关键是,把任务设计当作真正的工程工作,而不是事后才想到的东西。
这就是教训。模型没问题。你的任务结构可能是问题所在。