跳到主要内容

Guard 流式检测流程

本文描述 chat.completions 流式响应检测场景下,Aidy 与 CyberGuard 的交互流程与异常语义。

适用范围

当同时满足以下条件时,Aidy 会走流式检测:

  • 请求是 chat.completionsstream=true
  • 路由开启 Guard 响应检测
  • 路由检测模式为 block
  • 上游返回的响应码为 200 且以 text/event-stream content-type 响应

总体流程

1) 建立双向流并发送 Init

Aidy 与 CyberGuard 建立 ChatCompletionStream 双向流,先发送 Init

  • policy_chain:当前路由的检测策略
  • request_id:Aidy 请求 ID

2) 上游 Chunk 转发为检测 Chunk

Aidy 从上游 SSE 持续读取 chat.completion.chunk,提取可检测文本后发送给 CyberGuard:

  • 请求类型:ChatCompletionStreamRequest.Chunk
  • 字段:index + content
  • index1 开始递增(注:保证单调递增,但不保证连续)

3) 消费 DetectResult 并放行/拦截

CyberGuard 可按自身窗口策略返回 0/1/N 条 DetectResult
其中 checked_index = N 语义为:<= N 的内容均已检测完成。

  • safe:Aidy 放行并回放 <= checked_index 的缓存响应给用户
  • unsafe + block_action:Aidy 输出 refusal chunk(delta.refusalfinish_reason=refusal
  • unsafe + override_action:Aidy 输出 substitute stream(代答)

4) 命中风险后 block/substitute 的即时动作

一旦触发风险动作,Aidy 立即:

  1. 停止继续向用户透传上游正常内容
  2. 输出 refusal 或 substitute
  3. 取消上游 LLM 请求
  4. 若尚未向 CyberGuard 发送 EOM,则立即发送 EOM

EOM 与收尾

EOM 发送时机

Aidy 会在以下任一时机发送 EOM

  • 上游自然结束(finish / [DONE]
  • 已命中风险并提前终止上游

EOM 会附带当前已聚合的 tool_calls(若存在)。

EOM 后行为

EOM 发出后,Aidy 继续接收 CyberGuard 返回,直到关闭或超时。

  • 正常结束:CyberGuard 在 EOM 后关闭连接(关闭前可返回 0/1/N 条 DetectResult)
  • 异常结束 1(提前关闭):EOM 前就关闭连接
  • 异常结束 2(检测超时):EOM 后超过 guard.timeout_ms 仍未关闭

日志汇总规则

流式检测结束时,Aidy 会写入两类流式检测结果字段:

guard.chat

  • 取整个流期间(含 EOM 后)收到的第一个 unsafe DetectResult
  • 保留该条 DetectResult 对应的 resultaction
  • statuseffect_action 也按这条 guard.chat 计算
  • 若整个流没有 unsafe,则按最后一个 DetectResult 回填(用于 safe / error)
  • 若自始至终没有任何 DetectResult,则记为错误(status=error,并写入 error

guard.chat_stream

  • 记录整个流期间(含 EOM 后)收到的所有 unsafe DetectResult
  • 以数组形式输出
  • 做去重:对 unsafe 结果(含 action)进行内容去重,重复项只保留第一次出现

字段示例

  • guard.chat:首个 unsafe
  • guard.chat_stream:去重后的所有 unsafe 列表