Guard
Aidy 内置了 Guard 检测能力,通过静态配置 plugins.guard.* 与 route 级 plugin_config.guard 配置。
启用条件
Guard 插件只有在同时满足以下条件时,才会被挂进请求链路:
- 静态配置
plugins.guard.enable = true - 当前 route 配置了
plugin_config.guard detect_chat_request、detect_chat_response、detect_embeddings_request中至少有一个mode != disabled
如果以上任一条件不满足,Guard 不会进入当前 route 的请求链路。
另外,Guard 当前只挂在 chat 与 embeddings 的 forward hook 上。因此即使路由启用了 Guard,models、options 与 unknown 请求也不会进入 Guard 插件。
静态配置
check_service_url
用于指定 Guard 检测服务的 URL,例如 http://localhost:8080。对应静态配置 plugins.guard.check_service_url。
检测服务直连检测模型 API,如对应检测 API URL 为 http://localhost:8080/v1/chat/responses,则此处应配置为 http://localhost:8080。
timeout
检测服务请求超时时间,默认 30s。对应静态配置 plugins.guard.timeout_ms。
当检测服务响应超时时,将跳过 guard 检测流程
路由配置
路由配置用于指定特定路由的 Guard 检测配置。请参见 路由配置 的 Guard 节。
需要注意的是,以下情况都属于“Guard 已经进入链路后发生降级或跳过”,不属于“未启用”:
- 某个 detect 的
policy_chain_json非法,导致该 detect 在运行时被降级为 disabled - Guard detect 命中
tenant.detect_rate_limit_cpm限额 - Guard 检测请求超时或检测服务异常,最终走 bypass / skip 逻辑
输出
检测结果将与请求/响应日志一同输出,并汇总到 ext_fields.guard。
请求日志
ext_fields.guard 使用以下 proto:
说明:
request与response按是否执行到对应阶段决定是否出现- 两者的字段语义与之前请求日志中的 guard 字段保持一致,只是存储位置变为
ext_fields.guard
request / response 的常见字段包括:
statusactioneffect_actionerrornot_detect_reasonchat或embeddingschat_stream
当检测到违规请求时,路由级别仍只有 block 与 log_only 两种模式,但 CyberGuard 的 action 会细分为以下行为:
block_action:拦截模式(intercept)override_action:代答模式(substitute)alert_action:仅记录(log_only)pass_action:通过(pass)
其中 block_action 与 override_action 在 Chat / Embeddings 的响应方式不同;log_only 仍保持“仅记录,不改写响应”的原有行为。
行为 - 拦截模式
拦截模式对应 CyberGuard 返回 block_action(且路由 mode=block)。
Chat - 请求风险
当检测到请求存在风险时,直接拦截并返回 HTTP 412 + error JSON(message 来自 CyberGuard,若为空则使用默认提示):
HTTP/1.1 412 Precondition Failed
Content-Type: application/json
{"error":{"code":null,"message":"[来源于 CyberGuard 返回]您的请求包含不安全内容,无法生成回复","param":null,"type":"security_guard_error"}}
Chat - 响应风险
- 非流式:返回 HTTP 512 + error JSON(结构同上)。
- 流式:在触发风险后插入 refusal chunk(
delta.refusal),并以finish_reason=refusal结束,随后输出[DONE];不会继续转发后续上游内容。
示例(两段 refusal chunk + 完成信号):
{"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-4o-mini","system_fingerprint":"fp_44709d6fcb","choices":[{"index":0,"delta":{"refusal":"I'm sorry, I cannot assist with that request."},"logprobs":null,"finish_reason":null}]}
{"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-4o-mini","system_fingerprint":"fp_44709d6fcb","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"refusal"}]}
Embeddings - 请求风险
Embeddings 的拦截逻辑始终返回 HTTP 412 + error JSON(同上)。
行为 - 代答模式
代答模式对应 CyberGuard 返回 override_action(且路由 mode=block)。Chat 将返回模拟输出(from-security-guard),Embeddings 仍按拦截处理。
Chat - 请求风险
当请求触发风险时,返回代答内容(HTTP 200),格式与 OpenAI 兼容:
- 非流式:
object=chat.completion,model=from-security-guard - 流式:输出
chat.completion.chunk,finish_reason=stop,随后[DONE]
Chat - 响应风险
当响应触发风险时,返回代答内容(同上),并终止后续上游内容的转发。
Embeddings - 请求风险
即便 CyberGuard 返回 override_action,Embeddings 仍按拦截处理,返回 HTTP 412 + error JSON。