本文记录一个面向 AI 测试开发方向的工程项目:如何把“不稳定的大模型回答”转换成可批量执行、可量化比较、可追踪复现的测试结果。

一、为什么要做 AI 评测平台

传统接口测试通常可以直接断言:

assert response.status_code == 200
assert response.json()["code"] == 0

但大模型可能用不同措辞表达同一个意思。例如参考答案是“退款预计 1 至 3 个工作日到账”,模型可能回答“退款通常三个工作日内原路返回”。如果只做字符串相等判断,正确回答也会失败。

这个项目需要解决四个问题:

  1. 如何批量调用被测模型并保存问题、回答、耗时和 Token?

  2. 如何组合确定性规则、语义相似度和 LLM Judge?

  3. 如何评价 RAG 的召回、排序和答案忠实度?

  4. 如何证明 Judge 自己的评分是可信的?

最终技术栈如下:

Python 3.11 + FastAPI + Pydantic + SQLAlchemy
pytest + httpx + SQLite/MySQL
Qwen Target Model + DeepSeek Judge + text-embedding-v4
Docker + Jenkins Pipeline

项目代码仓库地址:发布到 Gitee 后在这里补充链接。

二、系统架构

平台把目标模型和评测模型分开:Qwen 负责生成回答,DeepSeek 负责评分,百炼 Embedding 负责语义相似度和向量检索。

JSON Dataset / FastAPI Request
              |
              v
       EvaluationRunner
              |
       Qwen Target Model
              |
        actual_answer
              |
     +--------+---------+
     |        |         |
   Rule    Semantic   LLM Judge
             |          |
         Embedding    DeepSeek
     +--------+---------+
              |
       SQLAlchemy Store
              |
       JSON / HTML Report

RAG 专项链路如下:

业务文档 -> Chunk -> Embedding -> Vector Index
                                      |
问题 -> Query Embedding -> Top-K ------+
                         -> Rerank
                         -> Qwen Answer
                         -> Recall/MRR/Faithfulness

这种设计有两个好处:

  • 模型厂商不会侵入业务编排,替换 Base URL、模型名和 Key 即可切换模型。

  • 每种 Evaluator 只处理一种指标,新增安全性或指令遵循评测时不需要修改 Runner。

三、统一 OpenAI-compatible Client

Qwen 和 DeepSeek 都可以通过 OpenAI-compatible 接口接入,因此项目没有在业务层写死厂商 SDK。

配置文件只保存模型角色:

TARGET_MODEL=qwen-plus
JUDGE_MODEL=deepseek-v4-flash
EMBEDDING_MODEL=text-embedding-v4

真实 Key 只保存在本地 .env

DASHSCOPE_API_KEY=本地填写
DEEPSEEK_API_KEY=本地填写

.env、SQLite 数据库、虚拟环境和真实报告都通过 .gitignore 排除,避免上传 Gitee 时泄露。

Client 统一返回以下元数据:

@dataclass(frozen=True)
class ModelResponse:
    content: str
    model: str | None
    latency_ms: float
    attempts: int = 1
    prompt_tokens: int | None = None
    completion_tokens: int | None = None
    total_tokens: int | None = None

这样报告不仅展示回答质量,也能分析延迟、重试和 Token 成本。

四、三种 Evaluator 如何组合

1. Rule Evaluator

Rule 适合必须出现的确定性内容,例如退款回答必须包含“退款”和“到账”。它速度快、成本低、解释性强,但无法识别同义表达。

2. Semantic Evaluator

Semantic Evaluator 对参考答案和实际答案分别计算 Embedding,再计算余弦相似度:

reference_answer -> embedding A
actual_answer    -> embedding B
cosine(A, B)     -> similarity score

它能容忍措辞差异,但语义相似不等于事实正确,因此不能单独作为最终结论。

3. LLM-as-a-Judge

项目把问题、参考答案和实际答案交给 DeepSeek,要求只返回结构化 JSON:

{
  "score": 4,
  "passed": true,
  "reason": "核心结论正确,但遗漏退款发起时间"
}

Pydantic 会检查:

  • score 必须在 1 至 5 之间;

  • 只有 4 分和 5 分允许 passed=true

  • Judge 返回 Markdown 或非法 JSON 时不能被当作有效分数。

三种指标组合后,可以同时获得确定性、语义和开放式质量证据。

五、批量执行为什么需要并发、重试和故障隔离

模型请求属于 I/O 密集任务,批量串行执行速度很慢。项目使用受限线程池并发调用模型,并通过 executor.map 保持结果与输入 Case 的顺序一致。

但并发不能无限提高,否则会触发限流或快速消耗额度。因此并发数可以通过环境变量控制:

EVALUATION_MAX_WORKERS=4

重试策略只处理可能恢复的错误:

408 / 429 / 5xx / 网络异常 -> 指数退避重试
400 等参数错误             -> 立即失败

如果目标模型失败,当前 Case 没有答案,任务应失败;如果某个 Evaluator 失败,则只把该指标标为失败,保留其他有效指标。这就是故障隔离。

模型调用记录和 Evaluator 结果也分别存储。一个 Case 虽然产生三条评测结果,但 Qwen 实际只调用一次,延迟和 Token 不能重复累计三次。

六、RAG 质量如何评测

项目构造了 24 篇模拟电商客服规则和 60 条带期望文档 ID 的 Benchmark,覆盖:

  • 订单

  • 支付

  • 退款

  • 物流

  • 发票

  • 账户安全

  • 14 条跨文档问题

主要检索指标如下。

Recall@K

应召回的相关文档中,Top-K 实际找回了多少:

Recall@K = 命中的唯一相关文档数 / 全部期望文档数

Precision@K

Top-K 结果中有多少是相关文档:

Precision@K = 命中的唯一相关文档数 / K

MRR

第一个相关文档排名的倒数:

第1名命中 -> 1.0
第2名命中 -> 0.5
未命中    -> 0

Faithfulness

Faithfulness 判断回答中的事实是否都能从检索上下文中获得支持。它解决的是“模型引用了知识库,但仍然编造额外信息”的问题。

七、一次真实的 400 问题排查

最开始 Demo 只有少量文本,Embedding 调用正常。扩充到 60 条 Query 后,参数实验突然返回:

400 Bad Request
Embedding request failed or returned invalid data

Key 和模型名都没有变化,因此问题更可能与批量规模有关。查询百炼官方文档后确认,text-embedding-v4 同步接口一次最多接受 10 条文本。

修复方式不是重试 400,而是在 Client 内自动分批:

for start in range(0, len(texts), self.batch_size):
    batch = texts[start:start + self.batch_size]
    # 请求当前 batch,并按 index 排序后追加到结果

随后增加 Mock HTTP 测试,验证 5 条输入、批大小为 2 时,请求会被拆成:

[text1, text2]
[text3, text4]
[text5]

这个问题说明:真实 API 约束必须在批量数据下验证,少量 Smoke Case 无法发现所有工程问题。

八、三组真实 RAG 参数实验

使用 text-embedding-v4 对 60 条 Query 运行三套配置,结果如下:

配置Chunk 数Recall@KPrecision@KMRRHit Rate
Chunk40 / Overlap8 / K2480.910.530.991.00
Chunk80 / Overlap16 / K3240.980.410.991.00
Chunk80 / Overlap16 / K3 / Rerank240.980.411.001.00

实验结论:

  1. K 从 2 增加到 3 后,Recall 从 0.91 提升到 0.98,但 Precision 从 0.53 降到 0.41。

  2. 更大的 Chunk 减少了索引数量,并在当前规则文档上取得更高召回。

  3. 轻量 Rerank 保持 Recall 不变,把 MRR 从 0.99 提升到 1.00。

这里不能简单说“Top-K 越大越好”。更高 K 会给生成模型更多上下文,也可能引入噪声并增加 Token 成本。

九、LLM Judge 自己可信吗

如果完全相信 Judge,评测系统可能只是把一个模型的偏差换成另一个模型的偏差。因此项目构造了 20 条覆盖 1 至 5 分的规则金标 Case,再与 DeepSeek Judge 比较。

真实结果:

通过/失败一致率:85%
精确分数一致率:70%
平均绝对误差:0.30

其中 3 条通过边界分歧都是:金标为 4 分,Judge 给出 3 分。共同特点是核心答案正确,但遗漏了时间、限制条件或安全操作。

这说明当前 Judge 对“基本正确但不完整”的回答偏严格。正确做法不是为了让数字好看而修改标签,而是:

  • 保留分歧 Case;

  • 人工复核 3/4 分边界;

  • 在报告中说明 Judge 的偏差;

  • 重要业务不能只依赖一次模型评分。

十、如何运行项目

1. 安装依赖

python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt

2. 无 Key 验收

python -m scripts.run_demo_acceptance
python -m scripts.validate_benchmark

3. 配置真实模型

Copy-Item .env.example .env

在本地 .env 填写 Key,不要提交该文件。

4. 真实模型验收

python -m scripts.run_real_acceptance --check-config
python -m scripts.run_real_acceptance --confirm-cost

5. RAG 参数实验与 Judge 校准

python -m scripts.run_rag_experiment
python -m scripts.run_judge_calibration --check-dataset
python -m scripts.run_judge_calibration --confirm-cost

6. 运行自动化测试

python -m pytest -q

当前共 82 项测试,覆盖 Client、重试、Evaluator、数据库、API、RAG、报告、Benchmark 和 Judge 校准。

十一、项目当前边界

这个项目是校招级工程项目,不是生产级商业平台。当前边界包括:

  • 向量索引保存在进程内,服务重启后需要重建;

  • Rerank 是向量分与词项重合度组合的轻量基线,不是 Cross-Encoder;

  • 批量任务当前同步执行,尚未接入 Celery/Redis;

  • Benchmark 是模拟电商业务规则,不是真实企业生产数据;

  • Dockerfile 和 Jenkinsfile 已提供,但仍应在目标机器完成实际部署验证;

  • Judge 校准数据是基于明确规则构造的项目金标,不应冒充企业人工标注数据。

明确项目边界不是减分项。相比堆叠一串没有验证的技术名词,能够说明“实现了什么、验证了什么、哪里仍有限制”更符合测试开发思维。

十二、总结

这个项目最终形成了以下闭环:

业务规则与测试集
      -> 真实模型批量执行
      -> Rule / Semantic / Judge
      -> RAG Recall / MRR / Faithfulness
      -> 参数对比与 Judge 校准
      -> JSON / HTML Badcase 报告
      -> 自动化回归

最大的收获不是接入了多少模型,而是把原本不确定的自然语言输出转换成了可量化、可复现、可分析的质量证据。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐