Jev 为什么能提速 AI Agent:把“生成答案”改造成类型安全的判断层

2026-09-21 28 预计阅读时间: 1 分钟
来源: oschina.net AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:12 分钟

Jev 引起关注,不只是因为一个新模型刷屏,而是因为它代表了一条不同于大语言模型的工程路线:不要求模型继续生成一段自然语言,而是让它在候选项、空判断和分数之间快速做决定。 对 BrowserUse、Codex 一类需要频繁调用工具的 Agent 来说,这种变化可能直接减少输出 token、解析失败和无效推理。

不过,社交媒体上的“速度暴涨”截图不能代替生产验证。真正值得讨论的是:判断模型应该放在 Agent 的哪个位置,Choice、Noul、Score 如何进入类型系统,以及怎样证明端到端任务确实变快了。

Agent 的瓶颈经常不是“不会生成”,而是“不会及时决定”

传统 Agent 往往把所有步骤都交给生成模型:

  1. 阅读当前状态;
  2. 用自然语言分析下一步;
  3. 输出工具名称和参数;
  4. 由程序解析文本;
  5. 解析失败后再次提示模型修正。

如果任务需要连续操作网页、搜索代码或调用十几个工具,这条链路会重复很多次。即使每轮只浪费几百毫秒,累计延迟也很明显。更麻烦的是,自然语言输出存在格式漂移:模型可能多写解释、拼错工具名,或者生成一个 schema 之外的动作。

判断模型对应的是另一种接口:调用方先给出有限候选项,模型只返回结构化决策。例如:

{
  "kind": "choice",
  "value": "click_submit",
  "score": 0.93
}

这类输出的价值不在于“文笔更短”,而在于它把开放式生成改造成受约束决策:

  • Choice:从明确的动作集合中选择一个;
  • Score:为候选动作、页面状态或任务完成度打分;
  • Noul:可以在工程上建模为“没有合适答案”或“拒绝决策”的特殊结果。

来源摘要没有给出 Noul 的完整协议定义,因此这里不把上述解释当作官方语义。接入真实项目时,应以 Jev 的实际类型定义和 SDK 文档为准;关键原则是不要把 Noul 偷偷转换为某个默认动作,而要让它触发回退或人工复核。

判断层适合放在哪里

Jev 这类模型并不一定取代负责写代码、生成计划或组织答案的大模型。更稳妥的结构是让生成模型负责“提出可能性”,判断模型负责“收敛选择”。

工具路由

Agent 已经注册了 search_webopen_pagerun_testsfinish,判断层只需要根据当前状态选出下一项。候选集合越明确,越容易校验权限和参数。

动作门控

对于删除文件、发送邮件、执行 shell 命令等高风险动作,可以让判断层输出分数。只有同时满足白名单、分数阈值和权限策略时,执行器才真正运行工具。

需要注意,模型分数不天然等于统计学概率。0.95 不代表错误率一定只有 5%,除非团队已经在自己的数据集上完成校准。

终止判断

不少 Agent 会因为不知道何时停止而反复搜索。判断层可以根据任务目标、已有证据和最新观察,返回 finishcontinue 或 Noul。相比让模型每轮生成一段“我认为任务已经完成”的说明,固定枚举更容易测试。

候选重排

代码搜索、网页元素定位和记忆检索通常会返回多个结果。可以先用传统检索器召回,再让判断模型为候选项评分或选出一个,从而避免主模型逐条阅读大量无关内容。

可运行示例:给 Agent 加一层类型安全决策

下面是一个只使用 Python 标准库的最小示例。为了能够直接运行,示例中的 mock_judge 使用规则模拟判断模型;接入真实 Jev 服务时,只需把这个函数替换为 API 调用,并保留相同的返回类型和校验逻辑。

将代码保存为 agent_judge.py,使用 Python 3.10 及以上版本运行:

from dataclasses import dataclass
from typing import Literal, Optional

Action = Literal["search", "open_page", "run_tests", "finish"]
DecisionKind = Literal["choice", "noul"]
ALLOWED_ACTIONS = {"search", "open_page", "run_tests", "finish"}


@dataclass(frozen=True)
class Decision:
    kind: DecisionKind
    value: Optional[Action]
    score: float

    def validate(self) -> None:
        if not 0.0 <= self.score <= 1.0:
            raise ValueError("score must be between 0 and 1")

        if self.kind == "choice" and self.value not in ALLOWED_ACTIONS:
            raise ValueError(f"unknown action: {self.value}")

        if self.kind == "noul" and self.value is not None:
            raise ValueError("noul decision must not contain an action")


def mock_judge(task: str, observation: str) -> Decision:
    """用确定性规则模拟 Choice/Noul/Score 接口。"""
    text = f"{task} {observation}".lower()

    if "ambiguous" in text or "信息不足" in text:
        return Decision(kind="noul", value=None, score=0.30)
    if "tests passed" in text or "测试通过" in text:
        return Decision(kind="choice", value="finish", score=0.97)
    if "test" in text or "测试" in text:
        return Decision(kind="choice", value="run_tests", score=0.88)
    if "http" in text or "结果页" in text:
        return Decision(kind="choice", value="open_page", score=0.84)
    return Decision(kind="choice", value="search", score=0.72)


def route(task: str, observation: str, threshold: float = 0.70) -> str:
    decision = mock_judge(task, observation)
    decision.validate()

    # Noul 和低分判断都不能直接执行,应进入更强模型或人工确认。
    if decision.kind == "noul" or decision.score < threshold:
        return "fallback_to_general_llm"

    return f"execute:{decision.value}"


if __name__ == "__main__":
    cases = [
        ("修复登录失败问题", "已经定位代码,下一步需要运行测试"),
        ("整理调研报告", "信息不足,需求 ambiguous"),
        ("确认修复是否完成", "all tests passed"),
    ]

    for task, observation in cases:
        print(route(task, observation))

运行命令:

python agent_judge.py

预期输出类似:

execute:run_tests
fallback_to_general_llm
execute:finish

生产环境中的 API 适配器可以维持同样的契约。一个可参考的请求结构如下,但字段名称需要根据实际服务修改:

{
  "task": "修复登录失败问题",
  "observation": "补丁已应用,但尚未验证",
  "choices": ["search", "open_page", "run_tests", "finish"],
  "output": {
    "types": ["choice", "noul", "score"]
  }
}

接入时不要只验证 JSON 是否能解析,还要检查动作是否属于当前步骤允许的集合。例如管理员工具即使存在,也不应该自动出现在普通用户会话的候选列表中。

不要只测模型延迟,要测整条 Agent 链路

判断模型是否值得引入,建议至少进行一次同任务集的 A/B 测试。基线版本继续使用通用生成模型,实验版本只把路由、门控或终止判断替换为 Jev,然后记录:

  • 端到端任务成功率;
  • 每个任务的总耗时以及 P50、P95 延迟;
  • 调用轮数和输出 token 数;
  • 非法动作、JSON 解析失败和重试次数;
  • Noul 比例以及回退到通用模型的比例;
  • 高分错误决策的数量;
  • 单个成功任务的总成本。

只看单次模型响应时间容易得出错误结论。如果判断模型更快,却让 Agent 多走了三个步骤,端到端体验反而可能变差。反过来,即使多增加一次判断调用,只要它能减少昂贵的主模型调用或错误工具执行,总成本仍可能下降。

上线前的边界与检查清单

判断模型最适合边界清晰、候选项有限、反馈快速的环节。开放式规划、复杂代码生成和面向用户的长文本回答,仍然需要生成模型承担。落地时可以按以下顺序推进:

  • 从低风险的工具路由或候选重排开始,不要直接接管删除、支付等动作;
  • 为 Choice 建立服务端白名单,不能只相信模型输出;
  • 为 Score 做业务数据校准,而不是凭感觉设置统一阈值;
  • 明确定义 Noul 的回退路径,避免把“不知道”变成默认执行;
  • 保留输入、候选集合、输出和最终结果,支持离线复盘;
  • 遇到提示注入或不可信网页内容时,将其视为数据,而不是系统指令;
  • 逐步扩大流量,并持续观察高置信度错误。

Jev 真正值得关注的地方,不是它能否替代所有大模型,而是它把 Agent 中大量模糊的自然语言步骤压缩成了可验证的判断接口。对于频繁循环、工具密集的系统,这一层可能比继续堆叠更长的提示词更有效;但提速是否成立,最终仍要由端到端成功率、延迟和风险数据来回答。


相关推荐