AI 评测最难处理的,往往不是把模型调用起来,而是回答一个更基础的问题:这次结果到底是在什么环境里产生的?依赖版本、提示词、输入数据、运行参数和工具行为只要有一项变化,评测结果就可能失去可比性。
Docker Sandboxes 可以把评测过程放进隔离且可记录的运行环境中,让团队更容易固定执行条件、保存结构化产物,并为每个结果留下运行时证据。它不会自动解决评测设计问题,但能显著减少“同一份代码在不同机器上跑出不同结论”的情况。
把评测拆成可追踪的输入和输出
一个可复现的评测任务,至少应该明确记录以下内容:
- 模型名称和版本
- 系统提示词、用户提示词或提示词模板
- 测试集版本和样本数量
- 依赖文件与基础镜像
- 温度、最大输出长度等推理参数
- 评测脚本的提交哈希
- 原始模型响应
- 聚合后的指标和错误信息
不要只保存一个最终分数。例如 accuracy: 0.82 无法说明哪些样本失败,也无法判断失败来自模型、解析器还是运行环境。更实用的产物通常包含一份逐样本 JSONL、一份汇总 JSON,以及一份描述运行环境的元数据文件。
用容器固定执行环境
可以先用普通 Docker 容器建立评测基线,再把同样的镜像接入 Docker Sandboxes。下面是一个最小示例。假设项目目录包含 evaluate.py 和 requirements.txt。
Dockerfile:
FROM python:3.11-slim
WORKDIR /workspace
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY evaluate.py .
ENTRYPOINT ["python", "evaluate.py"]
evaluate.py:
import json
import os
import platform
from datetime import datetime, timezone
from pathlib import Path
OUTPUT = Path(os.environ.get("OUTPUT_DIR", "/workspace/artifacts"))
OUTPUT.mkdir(parents=True, exist_ok=True)
examples = [
{"id": "case-001", "input": "2 + 2 = ?", "expected": "4"},
{"id": "case-002", "input": "首都是北京的国家是?", "expected": "中国"},
]
# 这里替换成实际的模型 API 调用或本地推理逻辑。
def run_model(text: str) -> str:
return "4" if text == "2 + 2 = ?" else "中国"
results = []
for example in examples:
actual = run_model(example["input"])
results.append({
"id": example["id"],
"input": example["input"],
"expected": example["expected"],
"actual": actual,
"correct": actual == example["expected"],
})
correct = sum(item["correct"] for item in results)
summary = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"python": platform.python_version(),
"platform": platform.platform(),
"total": len(results),
"correct": correct,
"accuracy": correct / len(results),
}
(OUTPUT / "results.jsonl").write_text(
"".join(json.dumps(item, ensure_ascii=False) + "\n" for item in results),
encoding="utf-8",
)
(OUTPUT / "summary.json").write_text(
json.dumps(summary, ensure_ascii=False, indent=2),
encoding="utf-8",
)
print(json.dumps(summary, ensure_ascii=False))
构建并运行:
docker build --tag ai-eval:local .
mkdir -p artifacts
docker run --rm \
--network none \
--read-only \
--tmpfs /tmp \
--mount "type=bind,src=$PWD/artifacts,dst=/workspace/artifacts" \
ai-eval:local
cat artifacts/summary.json
cat artifacts/results.jsonl
这个例子关闭了网络,并把结果目录单独挂载出来。实际评测如果需要访问模型 API,应改为受控网络策略,并通过环境变量或密钥管理系统注入凭据,不要把 API Key 写入镜像或结果文件。
把容器运行升级为 Sandbox 运行
Docker Sandboxes 的价值在于进一步隔离运行过程,尤其适合会执行代码、调用工具或操作工作区的 AI 评测任务。具体命令和参数取决于安装的 Docker 版本及 Sandbox CLI,因此可以先检查本机支持的接口:
docker sandbox --help
docker sandbox run --help
如果当前环境支持从已有镜像启动 Sandbox,可以采用类似下面的流程。命令中的挂载参数需要按照本机 CLI 的帮助信息调整:
docker build --tag ai-eval:local .
mkdir -p artifacts
docker sandbox run \
--network none \
--mount "type=bind,src=$PWD/artifacts,dst=/workspace/artifacts" \
ai-eval:local
可以把每次评测封装成一个脚本,统一生成运行证据:
#!/usr/bin/env bash
set -euo pipefail
RUN_ID="$(date -u +%Y%m%dT%H%M%SZ)"
OUT="artifacts/$RUN_ID"
mkdir -p "$OUT"
printf '{"run_id":"%s","git_commit":"%s","image":"%s"}\n' \
"$RUN_ID" \
"$(git rev-parse HEAD 2>/dev/null || printf unknown)" \
"ai-eval:local" > "$OUT/manifest.json"
# 根据本机 Docker Sandbox CLI 的实际参数运行。
docker sandbox run \
--network none \
--mount "type=bind,src=$PWD/$OUT,dst=/workspace/artifacts" \
ai-eval:local
运行证据不应只包含终端日志。建议至少保存以下文件:
artifacts/<run-id>/
├── manifest.json # 提交哈希、镜像标签、运行 ID
├── summary.json # 汇总指标
├── results.jsonl # 逐样本结果
└── stdout.log # 原始标准输出,按需保存
如果评测依赖外部模型服务,还应记录服务端点的逻辑名称、请求参数、超时和重试策略。涉及隐私数据时,要在写入 results.jsonl 前脱敏,并限制日志中出现完整提示词和模型响应。
可复现不等于结果永远相同
容器能固定 Python 版本和依赖,但不能自动消除所有随机性。模型服务可能发生版本更新,GPU 推理可能存在非确定性,外部搜索或工具调用也会改变返回内容。因此评测系统要区分“环境可复现”和“结果确定性”。
可以采用这些控制手段:
- 固定基础镜像版本,不使用没有版本号的
latest。 - 提交锁定的依赖文件,并在构建阶段记录镜像摘要。
- 固定随机种子;如果底层框架支持,开启确定性算法。
- 对外部 API 使用录制响应、测试替身或固定快照。
- 保存原始响应,而不是只保存解析后的标签。
- 为评测脚本和数据集生成版本号或内容哈希。
- 将失败样本、超时和解析异常单独计数。
落地检查清单
开始使用 Docker Sandboxes 前,可以先验证四件事:
- 同一个镜像在两台机器上能够生成相同格式的产物。
- 评测结果目录不依赖容器内部的临时文件。
- 运行记录包含代码、镜像、数据和参数的版本信息。
- 网络、密钥、数据脱敏和日志保留策略已经明确。
Docker Sandboxes 最适合作为评测执行层,而不是评测方法本身。团队仍然需要定义合理的数据集、指标和失败分类;Sandbox 则负责让每次执行更隔离、更容易审计,也更方便在 CI 或批量实验中重放。先从一个小型基准集和结构化产物开始,再逐步加入网络控制、响应快照和自动化对比,通常比一次性改造整套评测平台更稳妥。