应用场景

上下文压缩

当 Agent 对话被压缩时,判断哪些事实仍然算数。

问题

朴素的截断会把引出这段对话的那个 bug 丢掉。

代码拿到答案后怎么做

只有 `still_relevant` 高的事实时才保留。

留住那个卡上线的事实的压缩

state 带着目前的对话和一个待定事实(保留还是丢弃)。两个问题:still_relevant(该候选项是否应留在压缩后的上下文里)与 topic(对话实际在推进哪条线 — 原本的故障、新功能,还是两者都活跃)。示例里,“500 由 null guest carts 导致”这个事实评出 still-relevant,topic 读出两者都活跃 — 会把 bug 摘要挤出去的朴素截断器输了,这次调用把事实留下了。

逐事实决策,而不是逐轮

当对话必须变短时,在一个请求里评估候选事实 — 每次调用最多 8 个,通常仍是一积分。高于你的相关性线的事实在预算填满之前都保留;topic 说两条线都活跃时就都保留。压缩在轮与轮之间周期性运行,不在热路径上,所以那个 400–600 ms 的往返从不占用用户的时间。

压缩专属的坑

候选事实需要带着出处进 state(“由日志搜索工具发现”),否则相关性分数会偏袒生动的单行事实,而不是 Agent 步步推出来的推理链。不要在轮次中段压缩 — 在轮次之间、没有任何东西在途时运行。还要显式为“两条线都活跃”的案例留预算:只会保住一条线预算的压缩器,在对话真有两条活跃线时会饿死。

请求结构

这是 playground 为该预设发送的完整请求 — 与你的服务器带 Bearer key 发往 /v1/systemone 的 JSON 相同。

curl
curl https://jevai.website/api/v1/systemone \
  -H "Authorization: Bearer $JEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "state": {
    "conversation_so_far": "User asked to debug a 500 on /checkout. We found a null customer_id. User then asked about adding Apple Pay.",
    "candidate_to_keep": "The /checkout 500 is caused by a null customer_id on guest carts."
  },
  "questions": {
    "still_relevant": {
      "type": "noul",
      "instructions": "Should `candidate_to_keep` stay in the compressed context?"
    },
    "topic": {
      "type": "choice",
      "instructions": "Which topic is the conversation on now?",
      "criteria": {
        "debug": "The original outage",
        "feature": "A new feature request",
        "both": "Both are still active"
      }
    }
  }
}'

关于此用例的常见问题

压缩之后能留下多少上下文?
预算允许多少就留多少,按相关性排序。如果 topic 说“都活跃”,就为两条线各留预算 — 为腾地方丢掉最初那个 bug,正是 Agent “忘了自己当初在干嘛”的原因。
可以按整轮而不是按事实打分吗?
事实级候选让决策更锋利:一轮对话常常引出两个前途截然不同的事实。如果你只有轮次边界,由你的包装层提出候选事实。
如果每个事实都排得很靠前怎么办?
压缩变不出空间 — 就摘要最低的一档。类型化调用会在你摘要任何东西之前先告诉你哪个事实是承重的。
在测试台里运行