AI思考5月
分享5月AI使用的四个要点。本文古法手搓,非遗传承。
AI信任问题,容易影响判断,容易被AI说服
最近发现一个很有意思的问题,之前文章说过一个风险,就是AI回答总是给你很完备的错觉,其实可能是胡诌,但这种胡说八道,只要不是无脑同意,涉及到自己专业领域,其实基本都能发觉。然而,最近随着AI系统的逐步优化,产出的质量会越来越高,回答的也会更加有理有据,导致问题更隐蔽了,例如前面说的UAV一做,事实断言基本不会有什么问题。但是,事实和事实组合起来,可不一定是正确的答案!
总结一下最近几次擦屁股的典型场景:
1信息不全,尤其是子agent传递到父agent时,会遗漏信息,我做了专门传递的格式,但格式是死的,还是没法完全避免压缩信息的时候,丢失的“不重要”的信息。目前只能是重要决策,都去子agent扫一眼,来尽量避免。
2都是真相,但是遗漏了方案,导致只是次优解,这个也比较隐蔽,要么有前置知识和判断力,细细审查,判断出AI遗漏,要么粗暴点,让AI多次迭代,用token来大力出奇迹。
3单纯逻辑判断有问题,偶尔AI是会出现事实正确,但推断出问题的情况,这种情况不多,但我严重怀疑跟AI的倾向有关系,倾向附和用户因此可能会受我们发的提示词误导,倾向快速解决问题因而喜欢打补丁,走捷径等等。
其实现实中也是如此,综合上面说的,其实重点就是,随着AI系统越来越强,放手全部同意AI方案的诱惑也越来越大,同时,AI能捅的篓子也越来越大!
人:能力越大,责任越大
AI:能力越大,权限越大,删C盘越溜
UAV(事实断言验证器)
这个是一个很重要的改进,解决的痛点就是AI胡诌怎么办,一本正经的胡说八道,幻觉,推测代替证据等等”事实漂移”(factual drift),于是就做了这个UAV。
一句话解释就是,以插件的形式,代码直接检测,当AI 回复”事实断言”时(如”已配置 X / 版本是 vY / 创建了 Z 文件”)用真实证据(fs/env/exec/工具调用 trace)实时校验,验不过就拦截工具调用或注入警告。
具体实现,需要覆盖各种情况,比较复杂,就不赘述了,说一下比较有意思的数据,上了这个系统之后,某种程度上就可以量化地知道AI胡说八道的频率了:
拿最近一个版本后的数据来举例,总共识别到5831条断言,其中有213条是有事实错误但不阻断,有68条严重错误需要阻断,可能有一些假阳,也有一些遗漏,但大体数量应该差不多,也就是说AI说的事实里面大约有3.65%是有问题的,其中1.16%是严重错误。这个比例看似不高,但其实体感完全不同,因为AI断言的频率很高,而只要有幻觉出现而没发现,都会给后面擦屁股埋下伏笔。
另外,做得过程中拉数据发现,有非常多难以检验的部分,于是再次思考了一下,发现绝大多数情况下,AI只要查询了是不会乱说的,大多数情况是AI没查自信回答,于是换了个思路,从验真,改为验据。也就是从查证是否是事实这个高难度动作,改为相对简单很多的AI断言是否有证据。我的想法是,如果AI专门查了资料,还给了错误答案,那我能接受去优化调研流程,但不能接受未经查证的幻想结论。
Gate优化历程
一路harness,我觉得gate的优化变迁是非常有代表性的,值得记录一下。gate是指我们的主分发agent,平时所有对话都跟gate进行,gate来判断怎么调度分发给其他子agent进行处理,不用输入斜杠命令也不用管并行怎么分发,都交给这个主agent。一路的历程如下:
第一阶段,刚开始做的时候还很早,路由规则是直接写在md文件里,显然这种方式是不稳定的。
第二阶段,做了专门脚本来控制,检测gate自己调工具而不分发,就注入警告,并且将子agent知识的注入,一部分代码化,自动进行,不依赖llm自觉。
第三阶段,发现还不够,只是警告还不够强制,于是开发了票据系统,加上改注入警告为REPLACE直接替换输出+throw直接打断+abort直接物理中断,后来发现REPLACE容易污染上下文,abort是session级别会影响多票据并行分发,就都改为throw来实现。
第四阶段,发票据系统完善后,虽然确实基本不会出现不分发问题,但偶尔会出现分发错误问题,思考了一下,发现很多分发其实非常明确,于是将路由决策直接从gate的LLM 推理外置到 plugin 代码,做了一个可以实时增删查改的路由编辑器,并且将代码路由后的结果直接注入提示词,大大减少了分发错误问题。其中分为三层,L1代码确定性路由,直接注入强制命令,L2建议路由,由关键词命中,也是注入提示词,但让gate可以自己判断,L3物理兜底,如果仍走偏,会直接中断且自动重试。
目前用下来,终于是比较满意了,这里有几点经验总结:
非强制让控制AI行为的手段,最优先用户消息的提示词注入+清理其他上下文,首先直接的用户命令在LLM那边优先级更高,然后尽量减少输入的上下文,例如opencode会自己所有skill的description都拼接到每次输入的上下文,但是deny的skill就不会,所以就可以把skill和agent划分极致一些。
强制部分,hook配上throw中断是比较好的,自动发消息重试这个,在omo里大量使用,算是非常强制了,但是我试了之后降级为保底手段,一是随着正确率上升,触发频次低,二是触发了之后可能出现无限循环,所以做了次数限制,很呆。(以上都是基于opencode,其他工具可以看看有没有替代手段)
结构化是一个利器,定好标准的格式,让AI照着来,不管是输入还是输出,都能明显提升LLM稳定性,也方便自动校验结果。本质其实是用结构化来对抗模糊不确定性,当然额外好处就是也很方便人看。
思路的改变,之前是思考大模型语义来语义去的流程里,有没有可以代码化结构化的,现在应该反过来,整体确定性设计中,哪些是必须灵活处理,必须漏出给大模型来做语义分析的。
shadow思路
最近两个月,有大量对AI系统本身的优化,其中有个技巧我觉得很实用,就是shadow思路,一句话解释就是所有”会干预 AI 行为”的新规则/拦截器,默认先做shadow模式,也就是跟新功能一模一样的实现,但在具体修改的地方用环境变量来切换,默认先shadow模式不实际改,只收集数据。当运行一段时间,收集一段时间数据,验证完全没问题之后再直接切环境变量打开。
这个是一种非常适合AI时代自我优化的思路,其本质就是防止破坏性改动搞挂自己,由于很多时候bug也需要AI系统自己来修,容易陷入死循环只能找cursor,但cursor没有记忆和上下文。
这种数据驱动的方式,也很适合AI自动化,如果想精细点,可以额外分多档风控逐步放开。万一中的万一shadow改real挂了,也可以只修改一个环境变量回滚。
我从票据系统踩坑开始,后面大功能都是用这个思路来做,包括票据系统,上面提到的UAV系统,gate系统。
实战中只能说,上面那些稍微复杂一点的系统制作过程中,这个shadow模式多次救我狗命,强力推荐。
最后分享一个opencode的隐藏小坑:
opencode归档会话后,里面的子agent的会话是不会归档的,一直激活着,会对性能有影响,如果用了类似我这边自动归档的脚本扫描激活会话,就会很卡