问题
你在做一个游戏的画面覆盖层:玩家一进入战斗,血条和技能栏放大;战斗结束,再缩回去。这规则根本写不出来——怪物、特效、界面每个游戏都不一样——所以你让 Jev 每帧看一眼画面上的文字,给你一个「正在打架」的概率。
你定了一条线 0.7 就上线了。第一天就有人发了段录屏,配字「这玩意儿抽风了」。你把那几秒的日志拉出来:0.68、0.72、0.69、0.71。没有一次答错。战斗的边缘本来就模棱两可,是你那一条线把「差不多」翻译成了一秒五次的「是、不是、是、不是」。
你把线抬到 0.8:不怎么闪了,但血条晚半秒才放大,玩家先挨一刀才看得清自己的血。你降到 0.6,闪烁挪到了战斗结束的时候。怎么调都不对,因为毛病不在线的高低,在于只有一条线。
解决方案
恒温器模式说:用两条线,并且记住上一次的结论。进入用高线——概率到 0.8 覆盖层才放大,宁可晚半拍,不要误报。
退出用低线。一旦进了战斗,只要还有 0.6 就留在战斗里,跌破 0.6 才算结束。0.6 到 0.8 中间这一段是专门留给「差不多」的:落在这里,什么都不变。
第三样东西是记忆。这一帧要对照上一帧来判。上一帧已经在打,0.71 的意思是「继续」;上一帧没在打,同一个 0.71 的意思是「还没到」。同一个数,两种含义,区别就在那份记忆里。
问 · 答 · 拍
- 问把当前画面上的文字和按钮(发给 Jev 看的那份材料,术语叫 state)放进去,只问一句:现在正在发生战斗吗?
- 答0.71。
- 拍上一帧已经在战斗里,0.71 也没跌破退出线,于是保持在战斗里,覆盖层一动不动。
名字从哪来
家里的恒温器 20 度开暖气、22 度才关。要是开和关都定在 21 度,锅炉会在 20.9 和 21.1 之间开开关关响一整夜。中间那两度,就是它留给「差不多」的地方。
什么时候用
你判的是一个会持续一阵子的状态——在战斗中、这个任务需要人接手、这条链路该走大模型——而且来回切换是有成本的:界面闪、重复通知、缓存重建。
什么时候别用
每次调用判的是彼此独立的东西:一封邮件、一次改动、一条评论。它们之间没有「上一次」,硬塞一份记忆进去,只会把上一封的结论拖到下一封身上。
做这件事的项目
- huncho — 在 System One 模型上将决策作为代码:类型化问题、滞回、日志、校准。
- foreman — 使用决策模型的智能体监督者与软件工厂工头。
- jev-browser — 由 TypeSafe 的 Jev 模型驱动的快速、低成本浏览器自动化。
看谁的代码
- huncho
src/policy.ts:268-276十行代码:一条进入线、一条退出线,加上上一次的结论,三样一起决定这个状态保不保持。
- foreman
src/foreman/policy.py:21-127一个监工在打断下属之前先等三十秒,并把自己上一次的判断回喂进去:同一个想法,量的是时间而不是概率。
- jev-browser
src/navigate.ts:441-458「卡住了」第三步之前不算数;同一个动作连着两次没效果,就换成第二顺位的那个,不再原地重复。
想看代码
function active(p, previous, { enter, exit }) {
if (p >= enter) return true; // 到了高线:进入
return previous === true && p >= exit; // 已经在里面,又没跌破低线:保持
}
const prev = held.get(session.id) ?? false;
const now = active(answers.combat.p, prev, { enter: 0.8, exit: 0.6 });
held.set(session.id, now);jevbooks 怎么认出它
我们怎么知道一个项目用没用这一招?拿它的 README 问 Jev 一句话,Jev 给个百分比,数字越高说明越像。你要抄这道题,记住一点:别问「这个项目好不好」,要问「有没有讲到这一件具体的事」。
{
"hysteresis": {
"type": "noul",
"instructions": {
"what": "Does the text describe different thresholds for entering and leaving a state, or feeding the previous decision back to prevent flip-flopping?",
"not_for": "A single static threshold."
},
"criteria": {
"true": "The text explicitly describes this. One sentence is enough; other content does not cancel it.",
"false": "The text does not describe this."
}
}
}