Guides / 视频转图文攻略

Pi Agent 防跑偏插件实战:让 Jev 出概率,让代码做决定

pi-jev-router 0.3.0 全流程实战:把 Jev 挂进 Pi Agent 的输入事件、把会话压成约 800 token 的 state、用四选一 Choice 加概率门禁给每条消息做跑偏分诊——以及 52 场景标注测试抓出的「选项语义重叠、概率分摊」坑与代码求和修法(14/14 捕获、0/38 误打断、平均 277ms)。

速览结论

会话会跑偏:你正在排查 checkout 服务 OOM 的第十二 条消息里,顺口问了一句扫地机器人怎么换——这个问题从此留在上下文里,跟着后面每一轮。本期(站内首支中文频道来源)把一个类型化的 Jev 决策挂在了 Pi Agent 的输入事件上——回车之后、消息进入 agent 之前。本地过滤器先免费放行斜杠命令、shell 命令、文件路径、15 字以下短指令、图片、排队中消息和会话首条输入;真正含糊的消息才送去 Jev,state 是约 800 token 的压缩视图(标题、最近三问、回复尾、新输入),问题是一个四路 Choice——continue、side_chat、fork、new session。策略只有三行:无关概率低于 0.6 放行、on_topic 高于 0.6 放行、其余触发提醒——「模型出概率,代码做决定」。最有含金量的是评估故事:52 个人工标注场景对着 OpenRouter 上的 Jev 1.13 跑两轮,发现最差版本(0.2.0)漏掉 14 个跑偏里的 2~3 个、还误打断 38 个正常输入里的 1 个——根因是一个「随手问」案例的概率被分摊到两个「无关」选项上(0.45 + 0.47,谁都不过 0.6)。在代码里把同类选项概率求和(0.92 ≥ 0.6 → 提醒)之后,修到 14/14 捕获、0/38 误打断,平均 277ms、P95 0.35 秒以内。错误处理一律 fail-open:没有 key 插件不启用、API 报错与超 2.5 秒放行、移动失败消息回编辑器——最坏结果只是少提醒一次,永远不会丢消息。

视频来源

01Coder

14:19WrJAkrfWuS8

分步图文攻略

  1. 1

    痛点:会话会跑偏,跑偏会污染之后的每一轮

    你正在排查——checkout pod 反复 OOMKilled,已经把内存峰值定位到图片处理环节——这时突然想起该换扫地机器人了,就在这里问了。Agent 欣然作答。但这个问题从此成了永久的会话历史:之后的每一轮都背着它,上下文离你真正要解决的问题越来越远。长会话、随手一问、上下文被污染——作者用这三个词概括了为什么这件事要在消息进入 agent 之前处理。

    黄色卡片点出日常使用智能体的痛点:聊着聊着就跑偏了——长会话、随手一问、上下文被污染三个标签
    聊着聊着,就跑偏了——跑偏发生在会话中途,不是开头。跳转至 1:07
  2. 2

    为什么决策模型合适:一段文字 vs 带概率的固定答案

    整个设计 hangs 在这张对照表上。让大模型判断:输出是一段文字、每次延迟秒级、每条意图成本高。让 Jev 判断:输出是带概率的固定答案、每次延迟约 0.3 秒、30 万条约 0.001 美元。这个判断要在每条消息之前跑、必须便宜、还必须返回程序能直接用的结果——「答案范围固定、一次前向计算给出每个选项的概率」正是这个形状。

    让大模型判断与让 Jev 判断的对照表:一段文字 vs 带概率的固定答案、秒级 vs 约 0.3 秒、成本高 vs 30 万条约 0.001 美元
    答案范围固定,一次前向——正好是输入钩子要的形状。跳转至 2:40
  3. 3

    钩住输入事件——然后先在本地放行,别急着花钱

    Pi Agent(也叫 PIagent 或 Pi 编码智能体)给插件开了一个输入事件:回车之后、消息抵达 agent 之前。钩在这里,跑偏检查就能赶在上下文被污染之前跑。但 Jev 不是免费的,所以插件把不可能跑偏的东西全部本地放行:斜杠命令、shell 命令、文件路径、15 字以下短指令、图片、agent 运行中排队的消息、会话的第一条输入。会话空闲超 12 小时或上下文已用 85% 时,代码直接续接不发问。真正含糊的消息才会送到模型面前。

    用户、Pi TUI、pi-jev-router、Jev API 与当前会话的时序图:Input 事件钩子加本地放行卡(斜杠命令、shell 命令、文件路径、15 字以下短指令等直接放行)
    回车 → Input 事件 → 本地过滤 → 只有含糊的才见到 Jev。跳转至 3:32
  4. 4

    给 Jev 一个压缩视图,不是整条会话

    RouterState 类型刻意很小:session_title(300 字)、最近 3 条用户消息(每条 300 字)、上一条助手回复的结尾(末尾 1500 字)、新输入(最多 2000 字)。一次调用约 800 个输入 token——因为判断跑偏只需要知道「当前会话在做什么」,不需要每个细节。state 越小越快、越便宜、也越不容易被无关噪声稀释判断。生产环境的终端实测里能看到真实预算分布:问题约 14%、摘要约 55%、其余是实时尾部。

    RouterState 类型卡:session_title 300 字、recent_user_messages 最近 3 条 × 300 字、last_assistant_reply_tail 末尾 1500 字、new_input 2000 字
    不发整条会话——发压缩视图(约 800 token)。跳转至 4:17
  5. 5

    问题怎么问:一个四路 Choice 加 Noul 问题

    route 问题是一个四选一的 Choice:continue(本会话继续)、side_chat(随手问一句无关的)、fork(基于当前内容另开一版)、new_session(开一个无关的新任务)。旁边还配有 Noul 问题,比如「这条输入还在当前主题上吗?」——每个答案都带概率。一次请求就把整个路由判断做完;答案是值,不是要解析的散文。

    route·choice 卡片:continue 相续、side_chat 随手问一句无关的、fork 基于当前内容另开一版、new_session 一段无关的新任务
    四个固定选项,每个都带概率——问题就这一个。跳转至 5:02
  6. 6

    策略只有三行:模型出概率,代码做决定

    Jev 只输出概率;要不要提醒用户,写死在代码里。第一行:无关概率 = P(side_chat) + P(new_session) < 0.6 → 放行。第二行:on_topic ≥ 0.6 → 放行。第三行:其余 → 提醒。「模型给出概率、普通代码做决定」的分工让策略可测试、可版本化、不随模型更新而失效。提醒触发后由用户选:留在这里、fork、开新会话、或本会话不再询问。

    三行策略表:无关概率小于 0.6 放行、on_topic 不低于 0.6 放行、其余提醒——放行、放行、提醒
    让模型出概率,让代码做决定——整个门禁就三行。跳转至 5:32
  7. 7

    看懂原始回包:fork 案例为什么正确放行

    正在写一条 8 分钟的视频脚本,作者顺口问 60 秒竖屏版怎么排结构。/route:status 显示原始答案:on_topic 0.85——还在主题上;continue 0.47,其余大部分给了 fork;「无关」接近 0,远在 0.6 阈值之下。fork 不在「无关」集合里,所以代码放行,主题模型直接作答。要不要另开分支的判断留给用户——设计如此。

    route:status 原始答案:on_topic 0.85 还在主题上、「无关 < 0.6 → 放行(fork 不在『无关』里)」、概率柱 continue 0.47、fork 约 0.5、无关约等于 0
    on_topic 0.85、fork ≈ 0.5——代码放行,分支由用户决定。跳转至 8:46
  8. 8

    测试抓出的坑:选项语义重叠,概率被分摊

    标注评估——52 个场景、人工标注、对 OpenRouter 上的 Jev 1.13 每组跑两轮——发现最差版本(0.2.0)漏掉 14 个真实跑偏里的 2~3 个,还误打断 38 个正常输入里的 1 个。漏掉的那条就是教训:「另一个项目突然报错:ECONNREFUSED 127.0.0.1:16379,帮我排查」。Jev 的判断是对的——和当前会话无关——但「无关」被拆成了两个选项:side_chat 0.45、new_session 0.47。谁都不过 0.6 的阈值,于是都没触发,消息放行。

    漏掉案例卡:ECONNREFUSED 排查问题被判与会话无关,但概率拆成 side_chat 0.45 与 new_session 0.47 两个选项、都低于 0.6 阈值
    0.45 + 0.47,谁都不过 0.6——Choice 类问题的经典坑。跳转至 9:47
  9. 9

    两种修法:选项互斥,或在代码里求和

    卡片给了两个办法。办法一:把选项设计得互不重叠,概率就不会分摊。办法二——他实际用的:在代码里把同一类选项的概率加起来。无论「随手问」还是「别的项目的核心任务」,对「要不要提醒」来说是同一件事,所以 0.45 + 0.47 = 0.92 ≥ 0.6 → 提醒。留下还是 fork 还是开新会话,选择权仍在用户;求和只修提醒闸门——这正是它安全的原因。

    修复卡:办法一将选项设计得互不重叠、办法二在代码里把同类选项概率加起来——0.45 + 0.47 = 0.92 ≥ 0.6 → 提醒
    0.45 + 0.47 = 0.92 ≥ 0.6 → 提醒。求和在代码,决定也在代码。跳转至 10:32
  10. 10

    修复之后:14/14 捕获、0/38 误打断、平均 277ms

    修正后的混淆矩阵(随 0.3.0 发布)很干净:14 个跑偏场景全部提醒,38 个正常输入零误打断。延迟:平均 277 毫秒、P95 0.35 秒以内——挂在每条消息上也不心疼。作者的免责声明本身就是功课的一部分:52 个自写自标的场景不是公开基准,结果不代表实用中不会误判;压缩后的会话片段会发给第三方 API(OpenRouter),指向敏感代码之前要想清楚。

    修复后的混淆矩阵:跑偏 14 全部提醒、其他 38 零打断,附平均延迟 277 毫秒、p95 0.35 秒以内
    14/14 提醒、0/38 误打断——平均 277ms、P95 < 0.35s。跳转至 10:57
  11. 11

    失败处理:一律 fail-open

    挂在每条消息关键路径上的检查,必须先回答「它挂了怎么办」。这张表就是答案:没有 API key——不启用,无影响;API 报错、限流——放行,代价是少提醒一次;响应超过 2.5 秒——放行;无 UI 模式——不弹窗;移动失败——消息回到编辑器,不丢。Jev 负责判断,但最终决定永远在用户手里;任何失败模式都不能挡住输入、更不能弄丢消息。正是这种容错立场,让「把模型挂上热路径」这件事变得可行。

    失败处理表:没有 API key 不启用、API 报错限流放行、响应超 2.5 秒放行、无 UI 模式不弹窗、移动失败消息回到编辑器不丢消息
    每一行的最坏结果都是「少提醒一次」——永远不会丢消息。跳转至 11:22

常见问题(FAQ)

什么是会话跑偏(session drift),为什么对 Agent 很重要?

会话跑偏是指在任务进行到一半时插入无关问题——排查 checkout 服务的第十二 条消息里问扫地机器人。Agent 会作答,但这个问题从此留在上下文里:之后的每一轮都背着它,会话对原始问题的专注度持续下降。在输入事件处——消息进入 agent 之前——拦住跑偏,既保住了上下文整洁,也不用限制用户能问什么。

pi-jev-router 是什么,怎么装?

一个 Pi Agent 扩展(Pi 官方对插件的叫法):钩住输入事件——回车后、消息抵达 agent 前——用类型化的 Jev 决策在消息疑似与会话无关时提醒你。视频实测的是 0.3.0 版;插件源码、测试场景和数据都在视频描述里。需要一个 Jev API key(视频用的是 OpenRouter 上的 Jev 1.13);没有 key 插件会保持停用。

为什么用四路 Choice 而不是 yes/no 问题?

因为「无关」不是一种东西。continue、side_chat、fork、new_session 描述的是四种真实不同的用户意图,四个选项上的概率比单一 yes/no 信号更丰富:fork 案例(在主题上、但要开分支)必须放行,而无关问题必须提醒。要避开的坑——视频用真实数据演示了——是选项之间的语义重叠:side_chat 0.45 和 new_session 0.47 都意味着「无关」,但谁都不单独越过 0.6 的闸门。要么让选项互斥,要么在代码里把同类选项概率求和。

「模型出概率,代码做决定」在这里是什么意思?

Jev 只返回概率,从不执行动作。策略是普通代码:无关概率(P(side_chat) + P(new_session))低于 0.6 放行;on_topic 不低于 0.6 放行;其余触发提醒,由用户选择留下、fork、开新会话或本会话静音。策略放在代码里,就可测试、可版本化——概率求和的修复也住在这里。

准确率如何?修复前漏了什么?

52 个人工标注场景、每组两轮:最差版本(0.2.0)捕获 14 个跑偏中的 11~12 个、漏 2~3 个,并误打断 38 个正常输入中的 1 个。漏判来自概率在重叠选项间分摊。在代码里求和同类选项后,0.3.0 对全部 14 个跑偏提醒、38 个正常输入零打断,平均 277ms、P95 0.35 秒以内。诚实的免责:场景自写自标——不是公开基准——结果不代表实用中的准确率。

Jev API 挂了或者太慢怎么办?

一切 fail-open。没有 API key:插件自行停用。API 报错或限流:消息放行,代价只是少提醒一次。响应超过 2.5 秒:放行。无 UI 模式:不弹窗。会话移动失败:消息原样回到编辑器。设计原则:一个会挡消息或丢消息的跑偏护栏,比一个偶尔沉默的护栏糟糕得多。

相关推荐

更多视频攻略