jevbooks

← 全部设计模式

预问

投机分支 · Prefetch

每个分支都先问,只读走到的

把每条岔路上会用到的题提前一起问了,走到哪条就只读哪条的答案。

stateoptargettargettarget

问题

你的浏览器 agent(自己在网页上操作的程序)每一步要做两个决定:先定这一步是点击、打字还是滚动,再定点哪个元素、填哪个字段。

最自然的写法是两次调用:先问操作,等 300 毫秒,拿到答案再问目标,又 300 毫秒。一步 600 毫秒,四十步的任务就有半分钟纯粹花在等往返上。决策再多嵌几层,比如五层,一步就是 1.5 秒。

你想过提前把答案缓存起来,可缓存不了:下一道题问什么,取决于上一道的答案。时间不是花在模型思考上,是花在「等着知道该问什么」上。

解决方案

预问模式说:把每条分支之下会用到的题,和分支题一起发出去,不等答案。

一次请求里同时带三道:这一步做哪种操作;如果是点击,点哪个元素;如果是打字,填哪个字段。它们一起答完回来,你看第一道选了什么,只读对应的那一道。

没走到的分支,答案看都不看就扔掉 —— 没什么好校验的,反正不会照它行动。成立的前提只有一条:每条分支的候选表在发问之前就能写出来。页面上能点的元素、能填的字段,本来就是你的代码先枚举好的,谁也不依赖第一道题的答案。

问 · 答 · 拍

  1. 问把目标和页面放进去,一次问三件事:这一步做哪种操作;点击的话点哪个元素;打字的话填哪个字段。
  2. 答点击 0.84;点击的目标选 12 号 0.71;打字的目标也答了,但用不上。
  3. 拍既然是点击,代码就照点击那道题去点,打字那道的答案直接扔掉。

名字从哪来

像装修时预埋进墙里的线。这会儿还不知道这面墙将来挂电视还是挂灯,可墙一封上再开槽就贵了 —— 所以趁开着,把几路线都埋进去,将来用哪路拉哪路。它不是「提前把答案缓存起来」,是把还没定的几条路一次性都问了。

什么时候用

决策至少两层,而且第二层的候选表在第一层答复之前就能列出来。

什么时候别用

第二层的候选要等第一层定了才存在 —— 点进去之后才知道有哪些按钮。或者分支太多,多问的那些字比省下的一次往返还贵。

做这件事的项目

  • jev-ultrafast — 浏览器代理:Jev 决定每个动作和元素,仅在输入文本时调用语言模型。
  • huncho — 在 System One 模型上将决策作为代码:类型化问题、滞回、日志、校准。
  • mobile-jev — Android 智能体,由 Jev 根据实时设备状态选择每个动作。

用这种模式的全部项目 →

看谁的代码
想看代码
const { answers } = await jev(state, {
  operation:      choice("这一步做哪种操作?", ["click", "type", "scroll"]),
  "click.target": choice("如果是点击,点哪个元素?", clickable),
  "type.target":  choice("如果是打字,填哪个字段?", fields),
});
const op = answers.operation.choice;
const head = answers[`${op}.target`];   // 其余分支直接丢掉,不校验
if (!head) return act(op);              // 滚动没有目标
perform(op, head.choice);
jevbooks 怎么认出它

我们怎么知道一个项目用没用这一招?拿它的 README 问 Jev 一句话,Jev 给个百分比,数字越高说明越像。你要抄这道题,记住一点:别问「这个项目好不好」,要问「有没有讲到这一件具体的事」。

questions.json · 每份 README 都发这道题
{
  "speculative-heads": {
    "type": "noul",
    "instructions": {
      "what": "Does the text describe asking questions for every possible branch up front and consuming only the ones matching the chosen branch, such as an operation question sent together with one target question per operation?",
      "not_for": "Asking follow-up questions only after the first answer arrives."
    },
    "criteria": {
      "true": "The text explicitly describes this. One sentence is enough; other content does not cancel it.",
      "false": "The text does not describe this."
    }
  }
}

用 Jev 做一个 →