LLM 安全的 AI Guardrails

TrustyAI Guardrails Orchestrator 会对 LLM 的输入和输出运行检测器,以过滤或标记内容。它基于开源项目 FMS-Guardrails。TrustyAI Operator 提供了 GuardrailsOrchestrator CRD 用于部署和管理该组件。

本文档仅涵盖 AutoConfig 部署和 内置正则检测器

前提条件

  • 已安装 TrustyAI Operator(参见 安装 TrustyAI)。
  • 在目标命名空间中部署了作为 InferenceService 的 LLM。

使用 AutoConfig 部署

通过 AutoConfig,operator 会根据命名空间中的资源生成 orchestrator 和 gateway 配置;基础设置无需手动创建 ConfigMap。

创建一个启用 autoConfig、内置检测器和网关的 GuardrailsOrchestrator 自定义资源:

apiVersion: trustyai.opendatahub.io/v1alpha1
kind: GuardrailsOrchestrator
metadata:
  name: guardrails-orchestrator
  namespace: <your-namespace>
  # 可选:为路由启用认证(需要 Bearer 令牌)
  annotations:
    security.opendatahub.io/enable-auth: "false"
spec:
  autoConfig:
    inferenceServiceToGuardrail: <inference-service-name>
  enableBuiltInDetectors: true
  enableGuardrailsGateway: true
  replicas: 1
  • inferenceServiceToGuardrail:要保护的 InferenceService(LLM)名称,必须与同一命名空间中部署的模型匹配。
  • enableBuiltInDetectors:设置为 true 时,会添加内置的正则检测器 sidecar。
  • enableGuardrailsGateway:设置为 true 时,网关会暴露预设路由(例如 /all/v1/chat/completions)。

资源状态

该资源具有 status 子资源。status.phase 可为 ProgressingReadyError。使用 AutoConfig 时,status.autoConfigState 包含生成的 ConfigMap 名称(generatedConfigMapgeneratedGatewayConfigMap)、检测到的服务及一条 message。只有当 status.phase == Ready 且对应的 Deployment 就绪后,才应发送流量。

operator 会创建一个 orchestrator ConfigMap 和一个名为 <orchestrator-name>-gateway-auto-config 的 gateway ConfigMap。内置检测器注册名为 built-in-detector

内置正则检测器

内置检测器提供基于正则表达式的算法。支持的算法包括:

类别算法
regexemailus-social-security-numbercredit-cardipv4ipv6us-phone-numberuk-post-code 或自定义正则表达式

默认的网关配置使用占位符正则表达式 ($^)。要启用特定算法(例如 email),请修改 ConfigMap,将 detector_params.regex 设置为算法名称(例如 - email)。

网关 ConfigMap 结构

ConfigMap 名称:<orchestrator-name>-gateway-auto-config。示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: guardrails-orchestrator-gateway-auto-config
  namespace: <your-namespace>
data:
  config.yaml: |
    orchestrator:
      host: "localhost"
      port: 8032
    detectors:
      - name: built-in-detector
        input: true
        output: true
        detector_params:
          regex:
            - $^                          # 修改此占位符,例如 email
    routes:
      - name: all
        detectors:
          - built-in-detector
      - name: passthrough
        detectors:

built-in-detector 下的 regex 修改为所需算法(例如 - email)。更新后,等待 Deployment 就绪。

服务端口和 API 参考

Guardrails Orchestrator 通过名为 <orchestrator-name>-service 的 Service 暴露。端口号取决于是否启用认证(GuardrailsOrchestrator 上的注解 security.opendatahub.io/enable-auth: "true")。

端口和角色

端口名称认证禁用认证启用角色
gateway80908490Guardrails Gateway:预设检测器管道和 OpenAI 风格的聊天完成端点。用于发送经过内置(或配置)检测器检查的聊天请求,检测器在调用 LLM 之前和之后运行。
built-in-detector80808480内置正则检测器 API。独立内容检测(不调用 LLM)。请求体包含 contents(字符串列表)和 detector_params(例如 regex: ["email"])。
https (orchestrator)80328432Orchestrator API:直接访问 orchestrator 端点(例如自定义检测流程、健康检查)。
health80348034健康检查端点。

启用认证时,gateway 和 built-in-detector 端口需要 Bearer 令牌。

认证(启用认证时)

对 gateway 或 built-in-detector 端口的请求必须包含:

Authorization: Bearer <token>

该令牌必须是有效的 Kubernetes ServiceAccount 令牌(或集群认证代理接受的其他令牌),对应的主体需有访问该服务的权限(例如 services/proxy)。未授权请求将返回 401/403。

如何获取令牌

在与 Guardrails Orchestrator 相同的命名空间中,创建 ServiceAccount、Role(对 services/proxy 具有 getcreate 权限)和 RoleBinding,然后为 ServiceAccount 创建令牌:

# 替换 <your-namespace>,可选替换 ServiceAccount 名称(例如 guardrails-client)
kubectl create serviceaccount guardrails-client -n <your-namespace>
kubectl create role -n <your-namespace> guardrails-client --verb=get,create --resource=services/proxy
kubectl create rolebinding -n <your-namespace> guardrails-client --role=guardrails-client --serviceaccount=<your-namespace>:guardrails-client
kubectl create token guardrails-client -n <your-namespace>

可选设置令牌有效期,例如 --duration=8760h 表示一年。最后一条命令会输出令牌;将其设置为 Authorization: Bearer <token> 请求头的值。

集群内的客户端可以使用投影的 ServiceAccount 令牌卷作为 Bearer 令牌。

请求路径参考

路径端口说明
POST /all/v1/chat/completionsgateway (8090 或 8490)通过 guardrails 的聊天完成:请求在输入检查后发送给 LLM,响应由检测器检查。请求体包含 modelmessages(OpenAI 风格)。检测器管道由网关配置固定。
POST /api/v2/chat/completions-detectionorchestrator (8032 或 8432)支持每次请求选择检测器的聊天完成。请求体包含 modelmessages,可选 detectors(例如 {"input": {"built-in-detector": {"regex": ["email"]}}, "output": {...}})。当指定检测器时,返回模型回复及 detectionswarnings。适用于调用方需要为每次请求选择检测器,而非使用预设网关路由的场景。
POST /api/v1/text/contentsbuilt-in-detector (8080 或 8480)独立内容检测。对给定文本运行内置正则(或配置的)检测器,不调用 LLM。请求体包含 contentsdetector_params
GET /healthorchestrator (8032 或 8432)orchestrator 的健康检查。

其他网关路由(例如 /<preset-name>/v1/chat/completions)定义在网关 ConfigMap 的 routes 中。

API 使用及示例

独立检测(/api/v1/text/contents

在不调用 LLM 的情况下运行内置正则检测器。使用 built-in-detector 端口(8080 或 8480)。请求体包含 contents(字符串列表)、detector_params(例如 regex: ["email"])。

使用服务地址(集群内为 <orchestrator-name>-service.<your-namespace>.svc.cluster.local;集群外为暴露的 Ingress 主机)和 built-in-detector 端口(参见端口和角色)。

# 如果启用认证,设置 TOKEN。使用端口 8480(认证)或 8080(无认证)。
curl -k -s -X POST "https://<service-address>:8480/api/v1/text/contents" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"contents":["hello, my email is test@example.com"],"detector_params":{"regex":["email"]}}'

响应: 返回数组(对应每个 contents 条目),每个条目是检测对象数组。每个对象包含 startendtextdetection(例如 EmailAddress)、detection_type(例如 pii)和 score

响应示例(独立检测,检测到邮箱)
[
  [
    {
      "detection": "EmailAddress",
      "detection_type": "pii",
      "end": 35,
      "score": 1.0,
      "start": 19,
      "text": "test@example.com"
    }
  ]
]

Orchestrator API:每次请求选择检测器(/api/v2/chat/completions-detection

当调用方需要为每次请求选择检测器时,使用 orchestrator 端口(8032 或 8432)。请求体包含 modelmessages,可选 detectors(例如输入/输出的检测器参数)。

示例:对输入和输出运行内置检测器,使用正则 email

# 使用 orchestrator 端口 8432(认证)或 8032(无认证)。
curl -k -s -X POST "https://<service-address>:8432/api/v2/chat/completions-detection" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "model": "<inference-service-name>",
    "messages": [{"content": "my email is test@example.com", "role": "user"}],
    "detectors": {
      "input":  { "built-in-detector": { "regex": ["email"] } },
      "output": { "built-in-detector": { "regex": ["email"] } }
    }
  }'

当检测器在输入中发现匹配(例如邮箱)时,响应包含 detectionswarnings,且 choices 为空:

响应示例(输入触发检测)
{
  "id": "0c339dbab9ab45f59e6bf052d4fd78c6",
  "object": "",
  "created": 1773118440,
  "model": "......",
  "choices": [],
  "usage": {
    "prompt_tokens": 0,
    "total_tokens": 0,
    "completion_tokens": 0
  },
  "detections": {
    "input": [
      {
        "message_index": 0,
        "results": [
          {
            "start": 12,
            "end": 28,
            "text": "test@example.com",
            "detection": "EmailAddress",
            "detection_type": "pii",
            "detector_id": "built-in-detector",
            "score": 1.0
          }
        ]
      }
    ]
  },
  "warnings": [
    {
      "type": "UNSUITABLE_INPUT",
      "message": "Unsuitable input detected. Please check the detected entities on your input and try again with the unsuitable input removed."
    }
  ]
}

响应结构与网关聊天相同:包含 choicesdetectionswarnings。不传 detectors 时为普通聊天完成,无检测。

网关 API:预设管道(/all/v1/chat/completions

使用 gateway 端口(8090 或 8490)进行聊天,使用固定检测器管道(由网关 ConfigMap 定义)。请求体包含 modelmessages(OpenAI 风格)。如需每次请求选择检测器,请使用Orchestrator API

使用服务地址和 gateway 端口(参见端口和角色)。

# 使用端口 8490(认证)或 8090(无认证)。
curl -k -s -X POST "https://<service-address>:8490/all/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"model":"<inference-service-name>","messages":[{"content":"my email is test@example.com","role":"user"}]}'

输入/输出通过检测时: detectionswarnings 为 null,choices 包含模型回复:

响应示例(输入/输出通过检测)
{
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "logprobs": null,
      "message": {
        "content": "......",
        "role": "assistant"
      }
    }
  ],
  "created": 1773109415,
  "detections": null,
  "id": "chatcmpl-6d190200e68646bba140fa584ce5c301",
  "model": "......",
  "object": "chat.completion",
  "usage": {
    "completion_tokens": 28,
    "prompt_tokens": 30,
    "total_tokens": 58
  },
  "warnings": null
}

输入触发检测(例如 PII)时: detectionswarnings 有值,choices 为空:

响应示例(输入触发检测)
{
  "choices": [],
  "created": 1773109609,
  "detections": {
    "input": [
      {
        "message_index": 0,
        "results": [
          {
            "detection": "EmailAddress",
            "detection_type": "pii",
            "detector_id": "built-in-detector",
            "end": 28,
            "score": 1.0,
            "start": 12,
            "text": "test@example.com"
          }
        ]
      }
    ],
    "output": null
  },
  "id": "24dcf55e14344b4bbc760944eb6c1630",
  "model": "......",
  "object": "",
  "usage": {
    "completion_tokens": 0,
    "prompt_tokens": 0,
    "total_tokens": 0
  },
  "warnings": [
    {
      "type": "UNSUITABLE_INPUT",
      "message": "Unsuitable input detected. Please check the detected entities on your input and try again with the unsuitable input removed."
    }
  ]
}