TrustyAI Service (TAS)

Overview

TrustyAI Service (TAS) 收集模型推理数据(请求输入和响应输出),进行持久化,并将其组织成数据集以供分析,包括针对参考数据和实时流量的漂移检测和偏差评估。

主要功能:

  • 捕获并存储推理记录。
  • model_namedata_tag 组织记录。
  • 提供元数据 API 以检查已收集的数据。
  • 配置记录字段的人类可读列名,方便下游分析。
  • 针对参考子集和当前生产数据运行漂移检测(例如 KS 检验、均值漂移)。
  • 针对受保护属性和结果运行偏差指标(例如 SPD 和 DIR)。

本页涵盖部署 TrustyAIService、通过 POST /data/upload 导入参考数据和通过 POST /consumer/kserve/v2 导入实时推理数据、通过 HTTP API 注册漂移和偏差指标,以及向 Prometheus 暴露时间序列以供监控仪表盘使用。

Prerequisites

  • 已安装 TrustyAI Operator(参见 Install TrustyAI)。
  • 如果使用 storage.format: DATABASE,则需要 MySQL 8.x 数据库。
  • 如果使用 storage.format: PVC,确保集群有可用的默认 StorageClass(由 CSI 驱动支持)以实现动态卷供应,从而使 operator 创建的 PVC 能够绑定。

Deploy TrustyAIService

选择 一种 存储方案:DATABASE(MySQL)或 PVC(卷上的本地文件存储)。以下两个小节是 互斥方案,不是单个流程中的步骤。

DATABASE 模式

MySQL 凭据 Secret

当使用 storage.format: DATABASE 时,创建包含 TAS 部署所需密钥的 Secret:

apiVersion: v1
kind: Secret
metadata:
  name: <tas-name>-db-credentials
  namespace: <your-namespace>
type: Opaque
stringData:
  databaseKind: mysql
  databaseUsername: <username>
  databasePassword: <password>
  databaseService: <mysql-service-name>
  databasePort: "3306"
  databaseName: <db-name>
  # TrustyAI 连接数据库时使用的数据库模式生成策略。
  # 控制 TAS 启动时对数据库模式(表)的操作:
  # - none: 不管理模式
  # - create: 从头创建模式
  # - drop-and-create: 删除现有模式后创建
  # - drop: 删除现有模式
  # - update: 更新模式以匹配预期模型
  # - validate: 仅验证模式是否匹配预期模型
  #
  # 默认:update
  databaseGeneration: update

注意:

  • databaseName 指定的 MySQL 模式(数据库)必须预先创建,TAS 不会自行创建数据库。
  • 数据库必须能从 TAS Pod 访问。
  • databaseGeneration 控制 TAS 启动时如何处理模式变更。

TrustyAIService CR

示例:

apiVersion: trustyai.opendatahub.io/v1
kind: TrustyAIService
metadata:
  name: <tas-name>
  namespace: <your-namespace>
  annotations:
    trustyai.cpaas.io/monitor-enable: "true"
    trustyai.cpaas.io/monitor-interval: "30s"
    trustyai.cpaas.io/monitor-metric-regex: "^trustyai_.*"
spec:
  storage:
    format: DATABASE
    databaseConfigurations: <tas-name>-db-credentials
  metrics:
    schedule: "5s"
    batchSize: 5000
  replicas: 1

DATABASE 模式下,storage.databaseConfigurations 必须设置为上面创建的 MySQL 凭据 Secret 名称,且与 TrustyAIService 位于同一命名空间。

metadata.annotations 为可选,用于让 operator 创建 Prometheus 抓取的 ServiceMonitor(平台可自动收集监控数据)。

  • 设置 trustyai.cpaas.io/monitor-enable: "true" 时,operator 会生成 ServiceMonitor
  • trustyai.cpaas.io/monitor-intervaltrustyai.cpaas.io/monitor-metric-regex 为可选,未提供时 operator 使用默认值。

trustyai.cpaas.io/monitor-interval 控制 Prometheus 抓取 TAS 指标的频率(默认:30s)。 trustyai.cpaas.io/monitor-metric-regex 控制抓取后保留的指标名称(默认:^trustyai_.*)。

spec.metrics 字段:

  • schedule(必填):TAS 运行指标计算的频率(例如每 5s),值为持续时间字符串。
  • batchSize(可选):每次指标计算包含的推理记录数(值越大每次使用的数据越多)。未设置时默认 5000

PVC 模式

storage.formatPVC(无 MySQL Secret)时使用此方案。示例:

apiVersion: trustyai.opendatahub.io/v1
kind: TrustyAIService
metadata:
  name: <tas-name>
  namespace: <your-namespace>
spec:
  storage:
    format: PVC
    folder: /inputs
    size: 1Gi
  data:
    filename: data.csv
    format: CSV
  metrics:
    schedule: "5s"
    batchSize: 5000
  replicas: 1

PVC 模式下:

  • storage.folder:挂载的 PVC 内 TAS 存储和读取数据的路径。
  • storage.size:请求的 PVC 容量(例如 1Gi)。
  • operator 会自动在与 TrustyAIService 同一命名空间创建名为 <tas-name>-pvc 的 PVC。由于 PVC 使用集群默认 StorageClass(未显式设置 storageClassName),集群应提供可用的默认 StorageClass,否则 PVC 可能处于 Pending 状态。

当所选模式的 TrustyAIService 清单准备好后,应用它(DATABASEPVC YAML 均适用):

kubectl apply -f <trustyai-service>.yaml -n <your-namespace>

Verify deployment readiness

kubectl get trustyaiservices -n <your-namespace> <tas-name>

期望的 status.phase 应为 Ready

同时检查 Pod:

kubectl get pods -n <your-namespace> -l app.kubernetes.io/instance=<tas-name>

Access the TAS API

Service overview and authentication

在 TAS 部署中,kube-rbac-proxy 作为 sidecar 运行以提供认证。 operator 在同一命名空间创建两个 Service:

  • <tas-name>:直接路由到 TAS 容器(原始服务)。
  • <tas-name>-tls:路由到 kube-rbac-proxy sidecar;这是需要 Authorization: Bearer <token> 的认证端点。

Obtain a token

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

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

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

Bearer token and base URL

使用上一节获取的令牌作为每个请求的 Authorization: Bearer <token> 头,访问受保护的 TAS API。

选择调用的 基础 URL(主机)

  • 直接服务(无代理认证):https://<tas-name>.<your-namespace>.svc.cluster.local
  • 认证端点(kube-rbac-proxy):https://<tas-name>-tls.<your-namespace>.svc.cluster.local — 当 API 需要 Authorization: Bearer <token> 时使用此主机(通常是 -tls 服务)。

例如,发送 GET /info 请求:

curl -k -H "Authorization: Bearer $TOKEN" \
  "https://<tas-host>/info"

当需要认证头时,将 <tas-host> 替换为认证主机(通常是 -tls URL)。

Data ingestion

Training and reference data (POST /data/upload)

POST /data/upload 是训练和参考批次的 JSON 上传路径:每次调用携带一个记录的合并请求和响应,使用如 TRAININGdata_tag 作为参考子集。实时生产推理通过 POST /consumer/kserve/v2 单独导入(见下文)。

TAS 可以存储模型运行产生的推理记录。记录包含:

  • request:发送给模型的输入特征
  • response:模型返回的输出

数据集由 model_namedata_tag 定义。

准备数据集子集

  1. 选择一个 model_name 用于分组上传的记录。
  2. 选择一个 data_tag 作为参考子集。训练/参考数据使用 data_tag: TRAINING
  3. 每条推理上传一个合并的 request + response 负载。

请求体字段

请求体必须包含:

  • model_name:用于分组收集记录的模型标识符
  • data_tag:数据集子集标签
  • is_ground_truth:上传的输出是否为真实标签(当负载记录模型输出而非验证标签时设为 false
  • request
    • id:该记录的推理 ID
    • inputs:输入张量列表
  • response
    • model_name:必须与 model_name 匹配
    • id:必须与 request.id 匹配
    • outputs:输出张量列表

单条记录语义: TAS 不训练模型;它存储用于监控的行。对于 data_tag: TRAINING,每次上传是一条 参考 样本。request 携带发送给模型的输入特征(相同的 id 关联请求和响应)。response 携带该推理观察到的输出——通常是模型预测张量和用于公平性的结果字段(例如批准分数和决策)。漂移和公平性指标将此参考子集与通过 /consumer/kserve/v2 收集的实时数据进行比较。

下面示例使用小型信用风格特征集:数值输入和一个分组字段(gender),加上名为 predict-0approved 的输出。

{
  "model_name": "demo-model",
  "data_tag": "TRAINING",
  "is_ground_truth": false,
  "request": {
    "id": "training-1",
    "inputs": [
      { "name": "credit_inputs-0", "shape": [1, 1], "datatype": "FP32", "data": [21.0] },
      { "name": "credit_inputs-1", "shape": [1, 1], "datatype": "FP32", "data": [605.0] },
      { "name": "credit_inputs-2", "shape": [1, 1], "datatype": "FP32", "data": [12.0] },
      { "name": "credit_inputs-3", "shape": [1, 1], "datatype": "FP32", "data": [5.0] },
      { "name": "gender", "shape": [1, 1], "datatype": "INT64", "data": [0] }
    ]
  },
  "response": {
    "model_name": "demo-model",
    "id": "training-1",
    "outputs": [
      { "name": "predict-0", "shape": [1, 1], "datatype": "FP32", "data": [0.301] },
      { "name": "approved", "shape": [1, 1], "datatype": "INT64", "data": [0] }
    ]
  }
}

使用 curl 上传

curl -k -X POST "https://<tas-host>/data/upload" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d @<training-data.json>

Live inference data (POST /consumer/kserve/v2)

推理时数据通过 KServe v2 consumer 端点发送到 TAS。每个逻辑推理使用 两次 POST 调用,带相同关联 id:先是模型输入(kind: "request"),然后是模型输出(kind: "response")。请求体为 JSON;张量负载是 Base64 编码ModelInferRequest / ModelInferResponse protobuf 消息,定义见 KServe prediction API v2 (grpc_predict_v2.proto),而非 /data/upload 使用的扁平张量 JSON。

JSON 字段:

字段说明
id关联请求/响应对(例如预测 ID)。
kind"request""response"
modelid用于分组存储行的模型标识符;指标请求使用相同的 modelId。protobuf 负载可能省略 model_name,TrustyAI 使用此 JSON modelid 持久化。
datakind 的 protobuf 消息的 Base64 编码。

示例序列(Base64 负载为占位符):

# 推理请求半部分
curl -k -X POST "https://<tas-host>/consumer/kserve/v2" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"<prediction-id>","kind":"request","modelid":"<modelId>","data":"<base64-ModelInferRequest>"}'

# 推理响应半部分(相同 id)
curl -k -X POST "https://<tas-host>/consumer/kserve/v2" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"<prediction-id>","kind":"response","modelid":"<modelId>","data":"<base64-ModelInferResponse>"}'

设置 referenceTagTRAINING 的漂移指标将该参考子集(来自 /data/upload)与通过此 consumer 路径收集的有机行进行比较。GET /info/tags 可列出如 TRAINING 及实时流的无标签/有机侧标签。

Column name mapping (POST /info/names)

在通过 /data/upload 导入训练/参考数据和通过 /consumer/kserve/v2 导入实时推理后,TAS 可报告已记录的内容,并通过 POST /info/names 将记录的输入/输出列名映射为人类可读名称。

示例:

curl -k -X POST "https://<tas-host>/info/names" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "modelId": "demo-model",
  "inputMapping": {
    "credit_inputs-0": "Age",
    "credit_inputs-1": "Credit Score",
    "credit_inputs-2": "Education",
    "credit_inputs-3": "Employment",
    "gender": "Gender"
  },
  "outputMapping": {
    "predict-0-0": "Acceptance Probability",
    "approved-0": "Approved"
  }
}'

Data drift metrics

数据漂移指标将 参考 子集(例如来自 POST /data/uploadTRAINING 标签行)与 当前 生产数据(通常通过 POST /consumer/kserve/v2 导入)进行比较。注册、列出和删除与其他定时指标请求相同。

漂移指标类型

指标作用
KSTestKolmogorov–Smirnov 风格的经验分布比较,针对参考和当前数据的选定列。
MeanShift比较参考和当前数据选定列的均值(及相关统计量)。
ApproxKSTest具有可调精度参数(epsilonthresholdDelta)的近似 KS 风格漂移检测。
FourierMMD通过随机傅里叶特征的最大均值差异检测漂移(参数包括 gamma 等)。

GET /metrics/drift/<name>/definition 返回每个指标的人类可读文档。

注册定时漂移指标

使用 POST /metrics/drift/<metricName>/request 并带 JSON 体。常用字段:

  • modelId:数据集 ID(必须与上传/consumer 的 modelid 匹配)。
  • requestName:该定时任务的唯一名称。
  • metricName:必须匹配路径段(kstestmeanshiftapproxkstestfouriermmd)。
  • batchSize:每次计算包含的推理行数。
  • referenceTag:参考子集标签(通常为 TRAINING)。
  • fitColumns:待评估的输入列名(记录字段名,例如 POST /info/names 映射前的张量名)。

KSTest 示例:

curl -k -X POST "https://<tas-host>/metrics/drift/kstest/request" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "modelId": "<modelId>",
  "requestName": "<requestName>",
  "metricName": "kstest",
  "batchSize": 20,
  "referenceTag": "TRAINING",
  "fitColumns": ["credit_inputs-0", "credit_inputs-1"]
}'

MeanShift 示例:

curl -k -X POST "https://<tas-host>/metrics/drift/meanshift/request" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "modelId": "<modelId>",
  "requestName": "<requestName>",
  "metricName": "meanshift",
  "batchSize": 20,
  "referenceTag": "TRAINING",
  "fitColumns": ["credit_inputs-0", "credit_inputs-1", "credit_inputs-2", "credit_inputs-3"]
}'

ApproxKSTest — 添加 thresholdDeltaepsilon(语义见 GET /metrics/drift/approxkstest/definition):

curl -k -X POST "https://<tas-host>/metrics/drift/approxkstest/request" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "modelId": "<modelId>",
  "requestName": "<requestName>",
  "metricName": "approxkstest",
  "batchSize": 20,
  "thresholdDelta": 0.05,
  "referenceTag": "TRAINING",
  "fitColumns": ["credit_inputs-0", "credit_inputs-1"],
  "epsilon": 0.01
}'

FourierMMD — 添加 thresholdDeltagammaparameters 对象(见 GET /metrics/drift/fouriermmd/definition):

curl -k -X POST "https://<tas-host>/metrics/drift/fouriermmd/request" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "modelId": "<modelId>",
  "requestName": "<requestName>",
  "metricName": "fouriermmd",
  "batchSize": 20,
  "thresholdDelta": 0.05,
  "referenceTag": "TRAINING",
  "fitColumns": ["credit_inputs-0", "credit_inputs-1"],
  "gamma": 1.0,
  "parameters": { "nWindow": 10, "nTest": 10, "nMode": 50, "randomSeed": 0, "sig": 1.0, "deltaStat": false, "epsilon": 0.01 }
}'

一次性漂移请求

单次按需运行(非定时),POST /metrics/drift/kstestPOST /metrics/drift/meanshift 接受与定时注册相同的 JSON 体,但无 /request 路径后缀。

列出和删除定时漂移任务

列出定时任务:

curl -k -H "Authorization: Bearer $TOKEN" \
  "https://<tas-host>/metrics/drift/kstest/requests"

通过列表响应中的 requestId 停止任务:

curl -k -X DELETE "https://<tas-host>/metrics/drift/kstest/request" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "requestId": "<requestId-uuid>"
}'

路径中的 kstest 可替换为 meanshiftapproxkstestfouriermmd 以管理其他漂移类型。GET /metrics/all/requests 列出所有类别的定时指标。

Prometheus 指标(漂移)

定时漂移结果作为 Micrometer gauge 发布于 GET /q/metrics,例如:

  • KSTest: trustyai_kstest
  • MeanShift: trustyai_meanshift
  • ApproxKSTest: trustyai_approxkstest
  • FourierMMD: trustyai_fouriermmd

每个漂移序列带有标识定时任务和测量内容的标签。trustyai_kstest / trustyai_meanshift / trustyai_approxkstest / trustyai_fouriermmd 上典型的 语义 标签包括:

标签作用
model模型数据集 ID(匹配上传/指标请求中的 modelId)。
requestName定时漂移请求名称(来自 POST .../kstest/request 等)。
metricName序列暴露的指标类型(例如 KSTESTMEANSHIFT;具体大小写取决于 TAS 构建)。
batch_size定时请求配置的批量大小。
subcategory样本对应的特征或列(例如映射后的名称如 Acceptance Probability,取决于指标和 fitColumns)。
request指标请求实例的内部 ID(UUID),如果存在。
endpointMicrometer 的传输或抓取路径提示(例如 http)。

抓取 / 目标 标签(名称依集群和 ServiceMonitor 配置而异)通常包括 namespacepodservicejobinstance。部署的实际值应从 Prometheus 读取(例如指标 UI 中 trustyai_kstest 的标签名或通过 label_values()),而非文档复制——环境特定的 ID 和地址随集群变化。

PromQL 示例(限定单个模型和请求名):

trustyai_kstest{model="<modelId>", requestName="<requestName>"}

若要筛选单个列或特征,可在存在时对 subcategory 添加匹配条件。

Bias metrics

本节介绍通过 TAS HTTP API(POST / GET / DELETE /metrics/group/fairness/...)进行偏差监控(群体公平性指标,如 SPD 和 DIR)。

SPD 和 DIR

TAS 在同一受保护属性和结果上暴露两种相关的 群体公平性 指标:

缩写全称含义(典型用途)
SPDStatistical Parity Difference未特权组与特权组获得有利结果的比率差异。值越接近 0 表示群体间越接近平等。
DIRDisparate Impact Ratio未特权组有利结果比率与特权组比率的比值。值越接近 1 表示平衡越好(传统“四分之三法则”通常比较此比值与阈值)。

两者使用相同的请求字段(protectedAttributeoutcomeNamefavorableOutcome 等)。HTTP 路径和 metricName 区分 SPDspd)和 DIRdir)。

注册定时偏差指标

通过调用以下接口为已部署模型数据集创建定时偏差指标请求:

  • POST /metrics/group/fairness/spd/request(统计公平差异,SPD)
  • POST /metrics/group/fairness/dir/request(差异影响比率,DIR)

示例(SPD):

curl -k -X POST "https://<tas-host>/metrics/group/fairness/spd/request" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "modelId": "<modelId>",
    "requestName": "<requestName>",
    "metricName": "spd",
    "batchSize": 20,
    "protectedAttribute": "<protectedAttribute>",
    "privilegedAttribute": <privilegedValue>,
    "unprivilegedAttribute": <unprivilegedValue>,
    "outcomeName": "<outcomeName>",
    "favorableOutcome": <favorableOutcome>
  }'

SPD 请求字段:

  • modelId:计算指标的模型数据集 ID(必须与上传使用的数据集/模型匹配)。
  • requestName:定时指标请求的唯一名称(用于区分周期任务)。
  • metricName:指标类型名称;此接口使用 spd
  • batchSize:计算定时指标时包含的推理记录数。
  • protectedAttribute:定义比较群体的特征(映射后名称,如使用了映射)。
  • privilegedAttribute:代表特权组的 protectedAttribute 值。
  • unprivilegedAttribute:代表非特权组的 protectedAttribute 值。
  • outcomeName:评估公平性的输出字段(例如分类结果)。
  • favorableOutcome:被视为有利结果的 outcomeName 值。

对于 DIR,使用相同 JSON 体但 "metricName": "dir",调用 POST /metrics/group/fairness/dir/requestGET /metrics/group/fairness/dir/definition 提供指标文本描述。

列出和删除定时偏差任务

停止定时计算,先列出任务,再将响应中的 requestId 发送到对应删除端点:

指标列表接口删除接口
SPDGET /metrics/group/fairness/spd/requestsDELETE /metrics/group/fairness/spd/request
DIRGET /metrics/group/fairness/dir/requestsDELETE /metrics/group/fairness/dir/request

示例(SPD):

curl -k -H "Authorization: Bearer $TOKEN" \
  "https://<tas-host>/metrics/group/fairness/spd/requests"
curl -k -X DELETE "https://<tas-host>/metrics/group/fairness/spd/request" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "requestId": "<requestId-uuid>"
  }'

DIR 任务删除使用相同 requestId JSON 体,调用 .../dir/request 删除 URL。

Prometheus 指标(偏差)

TAS 在 /q/metrics 上暴露 Prometheus 指标。TrustyAI Operator 创建 ServiceMonitor,默认保留偏差相关指标(匹配 trustyai_(spd|dir).* 的序列)。

基础指标名:

  • SPD(统计公平差异):trustyai_spd
  • DIR(差异影响比率):trustyai_dir

每个序列带有标识定时计算及其公平性配置的标签。trustyai_spd / trustyai_dir 上典型的 语义 标签包括:

标签作用
model模型数据集 ID(匹配上传/指标请求中的 modelId)。
requestName定时指标请求名称(来自 POST .../spd/requestPOST .../dir/request)。
metricName序列暴露的指标类型(例如 SPDDIR)。
protected受保护属性列(例如 Gender)。
outcome结果列(例如 Approved)。
favorable_value被视为有利结果的值。
privileged / unprivileged受保护属性上的特权组和非特权组值。
batch_size定时请求配置的批量大小。
request指标请求实例的内部 ID(UUID),如果存在。

抓取 / 目标 标签(名称依集群和 ServiceMonitor 配置而异)通常包括 namespacepodservicejobinstance

示例:选择单个模型和定时请求名的 SPD:

trustyai_spd{model="demo-credit-model-1774142686-91294", requestName="demo-spd-1774142686-91294"}

示例:窗口内的最新值(范围与抓取间隔对齐):

max_over_time(trustyai_spd{model="<modelId>", requestName="<requestName>"}[15m])

当注册了 DIR 定时任务时,对 trustyai_dir 也适用相同的标签过滤。