给大模型输出装上一把量尺:Golden Set 与 CI 评测的工程化实践

简介: 针对大模型概率性输出特点,Golden Set 提供可版本化的业务样本集,结合确定性规则评测契约(如必含/禁含内容、格式等),实现CI质量门禁与变化可追溯,兼顾准确性、安全性与成本可控。(239字)

传统单元测试通常检查确定性的输入输出:给函数一个参数,断言返回值等于预期。但大模型任务具有概率性,答案可能存在多种合理表达,供应商、模型版本、提示词、上下文长度和采样参数的变化,都可能改变结果。

因此,生产系统需要回答的不是“这次调用有没有报错”,而是更具体的三个问题:

  1. 关键任务是否仍然满足业务约束?
  2. 模型升级后,哪些样本变差了?
  3. 质量提升是否以不可接受的延迟、成本或安全风险为代价?

Golden Set 可以理解为一组经过人工确认的代表性样本。它不是“标准答案库”的简单堆积,而是对真实业务分布的可版本化抽样。每条样本至少应包含输入、必须满足的条件、禁止出现的条件,以及必要时的参考答案。

先定义评测契约

评测的第一步不是选择模型,而是把“好结果”写成可检查的契约。例如客服摘要任务可以规定:必须保留用户诉求和处理结论;不能虚构订单状态;输出必须是合法 JSON;摘要长度不能超过指定上限。

建议把样本存为 JSONL,每行一条,便于 Git 追踪、增量评测和失败样本定位:

{
   "id":"refund-001","input":"用户说商品已退回,但七天后仍未收到退款。","must_include":["退款进度"],"must_not_include":["已完成退款"],"format":"json"}
{
   "id":"refund-002","input":"用户询问如何修改收货地址。","must_include":["修改地址"],"must_not_include":["保证可以修改"],"format":"json"}

样本不应只覆盖“正常提问”。至少要加入边界输入、空字段、错别字、长文本、冲突信息和潜在诱导内容。样本数量没有脱离业务的通用标准;在样本很少时,分数波动会很大,评测结果只能作为趋势信号,不能被解释为稳定的总体准确率。

用确定性规则先筛一遍

很多约束不需要另一个模型判断。格式、字段、关键词、长度和敏感操作可以用程序直接检查,结果更容易复现,也不会产生额外模型费用。下面是一个最小评测器:

# evaluate.py
import json
import os
import sys
from pathlib import Path


def check_case(case: dict, output: str) -> list[str]:
    errors = []
    for text in case.get("must_include", []):
        if text not in output:
            errors.append(f"缺少必要内容: {text}")
    for text in case.get("must_not_include", []):
        if text in output:
            errors.append(f"出现禁止内容: {text}")
    if len(output) > int(os.getenv("MAX_OUTPUT_CHARS", "1200")):
        errors.append("输出超过长度限制")
    if case.get("format") == "json":
        try:
            json.loads(output)
        except json.JSONDecodeError:
            errors.append("不是合法 JSON")
    return errors


def main() -> int:
    result_file = Path(sys.argv[1])
    cases = [json.loads(line) for line in Path("golden.jsonl").read_text().splitlines()]
    results = json.loads(result_file.read_text())
    failed = []
    for case in cases:
        errors = check_case(case, results[case["id"]])
        if errors:
            failed.append({
   "id": case["id"], "errors": errors})
    report = {
   "total": len(cases), "failed": len(failed), "failures": failed}
    Path("evaluation-report.json").write_text(json.dumps(report, ensure_ascii=False, indent=2))
    print(json.dumps(report, ensure_ascii=False))
    return 1 if failed else 0


if __name__ == "__main__":
    raise SystemExit(main())

这个脚本假设模型调用阶段已经把结果写入 results.json,格式是 {"样本 id":"模型输出"}。把调用和评分分开,有两个好处:同一批模型结果可以重复评分;规则变更时不必重新消耗 API 配额。

把模型调用封装成可替换端点

模型调用层应只负责请求、超时、重试和结果归档,不应把供应商细节散落到评测逻辑中。下面以常见的 OpenAI 兼容请求形态举例。实际字段、路径和模型名必须以所选服务的当前文档为准,不能因为“兼容”就假设所有参数都可用。

# run_eval.py
import json
import os
from pathlib import Path
import httpx

BASE_URL = os.environ["MODEL_BASE_URL"].rstrip("/")
API_KEY = os.environ["MODEL_API_KEY"]
MODEL = os.environ["MODEL_NAME"]


def ask(text: str) -> str:
    payload = {
   
        "model": MODEL,
        "temperature": 0,
        "messages": [
            {
   "role": "system", "content": "只输出符合要求的结果。"},
            {
   "role": "user", "content": text},
        ],
    }
    with httpx.Client(timeout=45) as client:
        response = client.post(
            f"{BASE_URL}/chat/completions",
            headers={
   "Authorization": f"Bearer {API_KEY}"},
            json=payload,
        )
        response.raise_for_status()
        data = response.json()
    return data["choices"][0]["message"]["content"]


cases = [json.loads(x) for x in Path("golden.jsonl").read_text().splitlines()]
outputs = {
   }
for case in cases:
    outputs[case["id"]] = ask(case["input"])
Path("results.json").write_text(json.dumps(outputs, ensure_ascii=False, indent=2))

例如,若选择 HaerAPI 作为中转或模型接入层,只有在其当前文档明确说明兼容上述请求路径和字段时,才应将 MODEL_BASE_URL 配置为对应地址;模型标识、计费方式、限流策略和数据处理范围都应以实际文档及合同为准。

本地运行时可以这样注入配置,密钥不会进入代码或仓库:

export MODEL_BASE_URL="https://your-endpoint.example/v1"
export MODEL_API_KEY="replace-with-environment-secret"
export MODEL_NAME="your-model-id"
python run_eval.py
python evaluate.py results.json

在 CI 中设置质量门禁

最简单的门禁是“失败样本数不得超过阈值”。对于关键流程,可以要求零失败;对于开放式生成任务,则可设定分层阈值,并把失败明细作为构建产物保存。

# .github/workflows/llm-eval.yml
name: llm-eval
on: [pull_request]

jobs:
  evaluate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install httpx
      - name: Run golden set
        env:
          MODEL_BASE_URL: ${
   {
    secrets.MODEL_BASE_URL }}
          MODEL_API_KEY: ${
   {
    secrets.MODEL_API_KEY }}
          MODEL_NAME: ${
   {
    vars.MODEL_NAME }}
        run: python run_eval.py
      - name: Check contract
        run: python evaluate.py results.json
      - name: Upload report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: llm-evaluation-report
          path: evaluation-report.json

生产中还应记录每次评测的提交号、模型标识、提示词版本、参数、耗时、token 用量和失败原因。若接口返回这些字段,应原样归档;若不返回,就不要自行推断。为了降低成本,可以在拉取请求阶段运行小型冒烟集,合并或定时任务运行完整集,但两者必须使用清晰的样本标签,避免把部分通过误读为整体通过。

评分器和人工复核如何配合

规则评分适合检查硬约束,不适合判断语义是否自然、答案是否真正解决问题。模型评分器可以辅助处理开放式任务,但它本身也会漂移,必须固定评分提示词、输出结构和判定标准,并定期抽样由人工复核。不要把单一模型的自评结果当作客观真值。

更稳妥的流程是:先用规则筛掉格式和安全问题,再对剩余样本做语义评分;当新版本出现“总分上升但关键类别下降”时,按类别查看混淆和失败案例,而不是只看一个平均数。每个修复过的线上问题都应回流 Golden Set,并标注来源和预期行为,这样评测集才会随着真实风险增长。

常见问题

为什么同样输入每次结果仍可能不同?

temperature=0 只能降低一部分随机性,不能保证不同服务、不同模型版本或并发条件下完全一致。评测应关注契约是否满足,并保留模型和配置元数据。

Golden Set 越大越好吗?

不一定。重复、低价值样本会增加成本,却不一定提高覆盖率。应按业务类别、风险等级和历史失败类型分层,优先补充能区分版本质量的样本。

CI 失败是否意味着模型一定变差?

不一定。也可能是接口字段变化、网络超时、样本更新、解析器缺陷或服务限流。报告必须区分业务断言失败、调用失败和评测程序失败。

可以把用户数据直接放进评测集吗?

应先完成脱敏、授权和访问控制,并确认数据处理要求。无法确认合规边界时,使用合成数据或经过审批的最小化样本,不要把生产日志直接上传到第三方接口。

总结

Golden Set + CI 的核心价值,不是给大模型制造一个看似精确的分数,而是建立可追溯的变化检测机制:用版本化样本描述真实风险,用确定性规则守住硬约束,用受控的语义评测覆盖开放问题,再把失败案例持续回流。模型、端点或提示词发生变化时,团队因此能够看到具体受影响的样本和原因,并在质量、成本、延迟与合规之间作出有证据的决策。

相关文章
|
11月前
|
人工智能 API 调度
在 VSCode 中薅大模型羊毛?我用 Kilo Code + AI Ping 实现大模型智能编程
如今,借助开放的大模型调度平台,普通开发者也能灵活接入高性能大模型。 Kilo Code + 兼容 OpenAI 协议平台的组合,体现了技术民主化的趋势——让创新不再被使用门槛阻挡。
4555 1
|
5月前
|
人工智能 IDE 前端开发
9 年 IDEA 老用户,终于把它彻底卸载了!
我卸载了用了 9 年的 IDEA。带你回顾古法编程到 AI 编程的三次变革,给还在用 IDEA 的同学分享通过 ACP 协议一键接入 Claude Code、Codex 等 AI Agent
657 2
|
7月前
|
人工智能 运维 监控
【AI工程化】AI工程化:MLOps、大模型全生命周期管理、大模型安全(幻觉、Prompt注入、数据泄露、合规)
本知识体系构建以LLMOps为底座、大模型全生命周期管理为核心、安全合规为红线的AI工程化系统性框架,覆盖规划选型、数据治理、研发训练、部署运维到迭代退役全流程,解决落地难、风险高、成本大等核心痛点。
|
2月前
|
机器学习/深度学习 人工智能 JSON
什么是 Jev 模型?一个“拒绝生成文字“的 AI,正在接管软件的判断权
Jev是TypeSafe AI推出的首款“系统一模型”,不生成文本,专精于低成本、高置信度的类型化决策:从预设选项中选择、在刻度上打分、输出是非命题概率。它像一个“懂语义的if语句”,以70–500ms延迟、$0.042/百万token成本,赋能软件自动分流、护栏、告警等高频判断场景。(239字)
400 0
|
3月前
|
人工智能 安全 BI
AI Agent量化评估:LLM-as-Judge、人工标注、A/B测试全解,智能体多维评测实践21.0
本文系统阐述AI Agent评估迭代体系,提出“LLM-as-Judge+人工标注+A/B测试”三位一体评测方法,覆盖功能准确性、服务性能、运行安全、成本损耗四大维度,构建数据层—评测层—分析层—迭代层四层架构,实现从离线初筛、精准校准到线上验证的闭环优化,助力Agent从Demo走向企业级稳定落地。
482 3
|
9月前
|
缓存 自然语言处理 搜索推荐
大模型上线前,我们到底该怎么测?一份来自一线的检查清单
本文分享大模型对话功能上线前的实战测试经验,直击“无标准答案、状态无限、结果不可复现、判断主观”四大难点,提炼出覆盖功能、性能、安全、体验的六类测试清单及红黄绿三色上线准入标准,助力同行少踩坑、稳上线。
|
4月前
|
人工智能 运维 API
阿里云千问大模型完整指南:功能、参数与各类订阅方案详解
阿里云千问系列大模型依托百炼MaaS平台提供标准化调用服务,覆盖文本对话、多模态交互、代码开发、自主智能体等全类业务场景,面向个人开发者、小型团队与中大型企业提供分层模型版本、灵活参数配置体系以及多样化付费订阅模式。2026年平台持续更新模型能力与优惠政策,同步适配OpenClaw、Hermes Agent、Qwen Code等主流AI智能体与编程工具,兼顾轻量化日常使用和企业级复杂长周期任务。本文从模型功能划分、核心参数配置、多类订阅方案、选型建议与故障排查五大板块完整拆解,帮助使用者根据自身场景匹配对应模型、合理控制调用成本、规范完成API接入。
1715 4
|
6月前
|
人工智能 缓存 架构师
DeerFlow 2.0 的 lead_agent 任务总调度 架构设计与实现解析
DeerFlow 2.0 的 lead_agent 任务总调度 架构设计与实现解析
DeerFlow 2.0 的 lead_agent 任务总调度 架构设计与实现解析
|
5月前
|
监控 安全 数据挖掘
面试官问:Agent 怎么评测?
Agent评测不能只看准确率!它是多步骤执行系统,需构建覆盖任务完成率、过程质量、工具调用、成本、延迟、稳定性、安全权限及用户反馈的全链路评估体系,并通过离线冒烟/回归测试、在线真实流量监控与失败样本回流,实现持续迭代闭环。
|
7月前
|
存储 缓存 监控
【架构设计】高性能架构设计:QPS/TPS/RT核心指标、性能优化方法论、水平/垂直扩展、缓存、异步、池化
本文系统构建高性能架构知识体系:以QPS/TPS/RT为核心标尺,遵循“空间换时间、分而治之、无状态化”等七大原则;涵盖垂直/水平扩展骨架、缓存/异步/池化三大引擎,并通过全链路监控、压测、限流熔断等保障闭环。

热门文章

最新文章