Guard 流式检测流程
本文描述 chat.completions 流式响应检测场景下,Aidy 与 CyberGuard 的交互流程与异常语义。
适用范围
当同时满足以下条件时,Aidy 会走流式检测:
- 请求是
chat.completions且stream=true - 路由开启 Guard 响应检测
- 路由检测模式为
block - 上游返回的响应码为 200 且以
text/event-streamcontent-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 index从1开始递增(注:保证单调递增,但不保证连续)
3) 消费 DetectResult 并放行/拦截
CyberGuard 可按自身窗口策略返回 0/1/N 条 DetectResult。
其中 checked_index = N 语义为:<= N 的内容均已检测完成。
- safe:Aidy 放行并回放
<= checked_index的缓存响应给用户 - unsafe + block_action:Aidy 输出 refusal chunk(
delta.refusal,finish_reason=refusal) - unsafe + override_action:Aidy 输出 substitute stream(代答)
4) 命中风险后 block/substitute 的即时动作
一旦触发风险动作,Aidy 立即:
- 停止继续向用户透传上游正常内容
- 输出 refusal 或 substitute
- 取消上游 LLM 请求
- 若尚未向 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 对应的
result与action status与effect_action也按这条guard.chat计算- 若整个流没有 unsafe,则按最后一个 DetectResult 回填(用于 safe / error)
- 若自始至终没有任何 DetectResult,则记为错误(
status=error,并写入error)
guard.chat_stream
- 记录整个流期间(含 EOM 后)收到的所有 unsafe DetectResult
- 以数组形式输出
- 做去重:对 unsafe 结果(含 action)进行内容去重,重复项只保留第一次出现
字段示例
guard.chat:首个 unsafeguard.chat_stream:去重后的所有 unsafe 列表