面向 LLM 安全的 AI Guardrails

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

本文仅介绍 AutoConfig 部署以及 内置的 regex 检测器

前提条件

  • 已安装 TrustyAI Operator(参见 Install TrustyAI)。
  • 在目标 namespace 中已将 LLM 作为 InferenceService 部署。

使用 AutoConfig 部署

使用 AutoConfig 时,operator 会根据 namespace 中的资源生成 orchestrator 和 gateway 配置;对于基础设置,无需手动创建 ConfigMap。

创建一个带有 autoConfig、并启用内置检测器和 gateway 的 GuardrailsOrchestrator 自定义资源:

apiVersion: trustyai.opendatahub.io/v1alpha1
kind: GuardrailsOrchestrator
metadata:
  name: guardrails-orchestrator
  namespace: <your-namespace>
  # Optional: enable auth for routes (Bearer token required)
  annotations:
    security.opendatahub.io/enable-auth: "false"
spec:
  autoConfig:
    inferenceServiceToGuardrail: <inference-service-name>
  enableBuiltInDetectors: true
  enableGuardrailsGateway: true
  replicas: 1
  • inferenceServiceToGuardrail:要进行 guardrail 的 InferenceService(LLM)名称;必须与同一 namespace 中已部署的模型匹配。
  • enableBuiltInDetectors:当为 true 时,会添加一个内置 regex 检测器 sidecar。
  • enableGuardrailsGateway:当为 true 时,gateway 会暴露预设路由(例如 /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 的名称注册。

内置 regex 检测器

内置检测器提供基于 regex 的算法。支持的算法包括:

类别算法
regexemailus-social-security-numbercredit-cardipv4ipv6us-phone-numberuk-post-code,或自定义 regex

默认的 gateway 配置使用一个占位 regex($^)。要启用某个特定算法(例如 email),请 patch 该 ConfigMap,并将 detector_params.regex 设置为算法名称(例如 - email)。

Gateway 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:
            - $^                          # change this placeholder, e.g. email
    routes:
      - name: all
        detectors:
          - built-in-detector
      - name: passthrough
        detectors:

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

Service 端口和 API 参考

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

端口和 角色

Port nameAuth disabledAuth enabled角色
gateway80908490Guardrails Gateway:预设 detector pipeline 和 OpenAI-style chat completion 端点。用于发送 chat 请求;在调用 LLM 前后,请求会先由内置(或已配置)的检测器进行检查。
built-in-detector80808480内置 regex 检测器 API。独立内容检测(不调用 LLM)。请求体:contents(字符串列表)和 detector_params(例如 regex: ["email"])。
https (orchestrator)80328432Orchestrator API:直接访问 orchestrator 端点(例如自定义检测流程、健康检查)。
health80348034健康检查端点。

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

认证(已启用 auth)

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

Authorization: Bearer <token>

该 token 必须是有效的 Kubernetes ServiceAccount token(或集群 auth proxy 接受的其他 token),且其主体对该服务具有访问权限(例如 services/proxy)。未授权请求会返回 401/403。

如何获取 token

在与 Guardrails Orchestrator 相同的 namespace 中创建一个 ServiceAccount、一个 Role(对 services/proxy 具有 getcreate 权限)以及一个 RoleBinding;然后为该 ServiceAccount 创建 token:

# Replace <your-namespace> and optionally the ServiceAccount name (e.g. 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>

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

集群内的客户端可以使用投影的 ServiceAccount token volume 作为 Bearer token。

请求路径参考

PathPort用途
POST /all/v1/chat/completionsgateway (8090 or 8490)经过 guardrails 的 chat completions:请求在输入检查后发送到 LLM,响应再由检测器检查。请求体:modelmessages(OpenAI-style)。detector pipeline 由 gateway 配置固定。
POST /api/v2/chat/completions-detectionorchestrator (8032 or 8432)支持按请求选择 detector 的 chat completions。请求体:modelmessages,以及可选的 detectors(例如 {"input": {"built-in-detector": {"regex": ["email"]}}, "output": {...}})。当指定了 detector 时,返回模型回复以及 detectionswarnings。当调用方需要为每个请求决定运行哪些 detector,而不是使用预设 gateway 路由时,请使用此接口。
POST /api/v1/text/contentsbuilt-in-detector (8080 or 8480)独立内容检测。对给定文本运行内置 regex(或已配置的)检测器;不调用 LLM。请求体:contentsdetector_params
GET /healthorchestrator (8032 or 8432)orchestrator 的健康检查。

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

API 使用和示例

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

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

使用 Service 地址(集群内:<orchestrator-name>-service.<your-namespace>.svc.cluster.local;集群外:如果已暴露,则使用 Ingress host)以及 built-in-detector 端口(参见 端口和 角色)。

# If auth is enabled, set TOKEN. Use port 8480 (auth) or 8080 (no auth).
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"]}}'

Response: 数组(每个 contents 条目对应一项),其中包含检测对象数组。每个对象具有 startendtextdetection(例如 EmailAddress)、detection_type(例如 pii)以及 score

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

Orchestrator API:按请求选择 detector (/api/v2/chat/completions-detection)

当调用方必须为每个请求选择运行哪些 detector 时,请使用 orchestrator 端口(8032 或 8432)。请求体:modelmessages,以及可选的 detectors(例如带有 detector 参数的 input / output)。

示例:在输入和输出上运行带有 regex email 的内置检测器:

# Use orchestrator port 8432 (auth) or 8032 (no auth).
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"] } }
    }
  }'

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

Response 示例(输入触发检测)
{
  "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."
    }
  ]
}

响应结构与 gateway chat 一致:choicesdetectionswarnings。如果是普通 chat completion 且不进行检测,则省略 detectors

Gateway API:预设 pipeline (/all/v1/chat/completions)

使用 gateway 端口(8090 或 8490)进行 chat,并使用固定的 detector pipeline(在 gateway ConfigMap 中定义)。请求体:modelmessages(OpenAI-style)。如果需要按请求选择 detector,请改用 orchestrator API

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

# Use port 8490 (auth) or 8090 (no auth).
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 中包含模型回复:

Response 示例(输入/输出通过)
{
  "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 为空:

Response 示例(输入触发检测)
{
  "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."
    }
  ]
}