OpenAI 评分器

2026-11-06 17:45 更新

评分器(grader)将模型输出与参考答案比较,以评估表现。评分器 API可用于测试评分器、比较结果,改进评测框架。

随着相关评测与微调工作流退出,OpenAI 也在弃用这些评分器。当前过渡时间见弃用说明。

概览

评分器返回评分,常用范围为0至1;相比只给0或1,对部分正确的答案给予部分分数有时更有用。评分器以 JSON 定义,类型包括字符串检查、文本相似度、模型数值评分及Python代码执行。

本文介绍各类评分器与入门示例;开始评测请参阅 Evals 指南。

模板

部分评分器的输入支持模板,让同一配置适用于多个样例。字符串中的{{ }}会替换为变量值。格式必须是{{ namespace.variable }},命名空间只支持item与sample;嵌套变量可用类似 JSON Path 的语法访问。

item 命名空间

评测时来自输入数据源。例如:

来源示例 1(json):

{
  "reference_answer": "..."
}

评分器可用{{ item.reference_answer }}引用。

sample 命名空间

来自评测采样阶段的模型输出,包含:

  • output_text:字符串形式的输出。
  • output_json:JSON对象形式的输出,仅样本包含response_format时填充。
  • output_tools:模型的tool_calls,结构与 Chat Completions API输出工具调用一致。
  • choices:结构与 Chat Completions 输出选项一致。
  • output_audio:包含Base64编码data和transcript的音频对象。

例如,{{ sample.output_text }}引用输出文本。

字符串检查评分器

基本字符串操作返回0或1,适合城市名、是/否、是否包含或以正确内容开头等明确判断。

来源示例 2(json):

格式说明:本块保留来源的模式或片段写法,不是可直接解析的完整严格JSON;代码内容保持原样。

{
    "type": "string_check",
    "name": string,
    "operation": "eq" | "ne" | "like" | "ilike",
    "input": string,
    "reference": string,
}

支持的操作:eq为区分大小写的相等;ne为区分大小写的不等;like为区分大小写的包含;ilike为不区分大小写的包含。满足条件返回1,否则返回0。

原指南正文将不等操作拼为neq,与其示例和评分器接口参考不一致;这里按接口定义使用ne。

文本相似度评分器

用于按不同评估方法衡量模型输出与参考的接近程度,适合开放式回答,例如把模型段落与专家参考答案作数值比较。

来源示例 3(json):

格式说明:本块保留来源的模式或片段写法,不是可直接解析的完整严格JSON;代码内容保持原样。

{
    "type": "text_similarity",
    "name": string,
    "input": string,
    "reference": string,
    "pass_threshold": number,
    "evaluation_metric": "fuzzy_match" | "bleu" | "gleu" | "meteor" | "cosine" | "rouge_1" | "rouge_2" | "rouge_3" | "rouge_4" | "rouge_5" | "rouge_l"
}

支持方法:

  • fuzzy_match:使用rapidfuzz模糊匹配。
  • bleu:BLEU。
  • gleu:Google BLEU。
  • meteor:METEOR。
  • cosine:使用text-embedding-3-large嵌入计算余弦相似度,仅用于评测。
  • rouge-*:ROUGE。

模型评分器

使用模型评分器,就是提示另一个模型,为待评估模型的输出评分。

模型数值评分器

按提示词在指定范围内返回数值。

来源示例 4(json):

格式说明:本块保留来源的模式或片段写法,不是可直接解析的完整严格JSON;代码内容保持原样。

{
    "type": "score_model",
    "name": string,
    "input": Message[],
    "model": string,
    "pass_threshold": number,
    "range": number[],
    "sampling_params": {
        "seed": number,
        "top_p": number,
        "temperature": number,
        "max_completions_tokens": number,
        "reasoning_effort": "minimal" | "low" | "medium" | "high"
    }
}

每条消息的格式:

来源示例 5(json):

格式说明:本块保留来源的模式或片段写法,不是可直接解析的完整严格JSON;代码内容保持原样。

{
    "role": "system" | "developer" | "user" | "assistant",
    "content": str
}

输入为包含role与content的聊天消息列表。输出会限制在给定range内,非数值输出默认记0分。消息可用相同模板语法引用标准答案和模型样本。

来源完整调用示例:

来源示例 6(python):

## [中文] 调用评分器测试接口:完全相同得1分,意思相近得0.5,否则0;密钥来自环境变量。
import os
import requests

## get the API key from environment
api_key = os.environ["OPENAI_API_KEY"]
headers = {"Authorization": f"Bearer {api_key}"}

## Define a score-model grader.
grader = {
    "type": "score_model",
    "name": "my_score_model",
    "input": [
        {
            "role": "system",
            "content": "You are an expert grader. If the reference and model answer are exact matches, output a score of 1. If they are somewhat similar in meaning, output a score in 0.5. Otherwise, give a score of 0.",
        },
        {
            "role": "user",
            "content": "Reference: {{ item.reference_answer }}. Model answer: {{ sample.output_text }}",
        },
    ],
    "pass_threshold": 0.5,
    "model": "gpt-4.1-2025-04-14",
    "range": [0, 1],
    "sampling_params": {
        "max_completions_tokens": 32768,
        "top_p": 1,
    },
}

## validate the grader
payload = {"grader": grader}
response = requests.post(
    "https://api.openai.com/v1/fine_tuning/alpha/graders/validate",
    json=payload,
    headers=headers,
)
print("validate response:", response.text)

## run the grader with a test reference and sample
payload = {"grader": grader, "item": {"reference_answer": 1.0}, "model_sample": "0.9"}
response = requests.post(
    "https://api.openai.com/v1/fine_tuning/alpha/graders/run",
    json=payload,
    headers=headers,
)
print("run response:", response.text)

来源示例 7(ruby):

## [中文] Ruby调用模型评分器测试接口,比较候选回答与参考;需要实际凭证,代码未在本轮执行。
require "openai"

client = OpenAI::Client.new
grader = {
  "type" => "score_model",
  "name" => "my_score_model",
  "input" => [
    {
      "role" => "system",
      "content" => "You are an expert grader. If the reference and model answer are exact matches, output a score of 1. If they are somewhat similar in meaning, output a score in 0.5. Otherwise, give a score of 0."
    }, {
      "role" => "user",
      "content" => "Reference: {{ item.reference_answer }}. Model answer: {{ sample.output_text }}"
    }
  ],
  "pass_threshold" => 0.5,
  "model" => "gpt-4.1-2025-04-14",
  "range" => [0, 1],
  "sampling_params" => {
    "max_completions_tokens" => 32768,
    "top_p" => 1
  }
}
item = { reference_answer: 1.0 }
model_sample = "0.9"

puts(client.fine_tuning.alpha.graders.validate(grader: grader).to_json)
puts(client.fine_tuning.alpha.graders.run(grader: grader, item: item, model_sample: model_sample).to_json)

模型数值评分器的输出

score_model使用指定提示词和采样参数请求模型,并要求特定响应格式:

来源示例 8(json):

格式说明:本块保留来源的模式或片段写法,不是可直接解析的完整严格JSON;代码内容保持原样。

{
  "result": float,
  "steps": ReasoningStep[],
}

其中每个推理步骤的结构:

来源示例 9(json):

格式说明:本块保留来源的模式或片段写法,不是可直接解析的完整严格JSON;代码内容保持原样。

{
    description: string,
    conclusion: string
}

格式既要求数值result(奖励值),也为解释评分保留空间。编写评分提示词时可明确引用字段,例如要求在推理结论分析化学键类型,或在不满足条件X时令result为−1.0。

模型评分器约束

来源列出的model取值为:gpt-4o-2024-08-06、gpt-4o-mini-2024-07-18、gpt-4.1-2025-04-14、gpt-4.1-mini-2025-04-14、gpt-4.1-nano-2025-04-14、o1-2024-12-17、o3-mini-2025-01-31、o3-2025-04-16和o4-mini-2025-04-16。此为来源支持列表,仍受模型生命周期及平台退出限制。

推理模型不支持更改temperature;非推理模型不支持reasoning_effort。

如何编写评分提示词

这是迭代过程。建议为模型评分器本身建立评测,准备:

  1. 极详细的任务提示词,包含分步要求与多个具体上下文示例。
  2. 模型及可信领域专家给出的多种高质量回答。
  3. 对这些回答的标准评分,例如理想专家答案应得1分。

这样可自动检验评分器能否区分质量差异。发现边界案例后,将其加入评分器评测,并修改提示词。

例如,已知专家偏好的答案:

来源示例 10():

answer_1 > answer_2 > answer_3

再检查评分器判断是否一致:

来源示例 11():

model_grader(answer_1, reference_answer) > model_grader(answer_2, reference_answer) > model_grader(answer_3, reference_answer)

Python 评分器

允许执行自定义 Python 评分。代码必须有恰好两个参数的grade函数,并返回浮点数。异常、无效浮点值等均视为无效结果,记0分。

来源示例 12(json):

{
  "type": "python",
  "source": "def grade(sample, item):\n    return 1.0",
  "image_tag": "2025-05-08"
}

来源示例 13(python):

## [中文] grade必须恰有两个参数并返回浮点数;当前恒返回1.0只是占位逻辑,不能作为有效质量评分。
from typing import Any


def grade(sample: dict[str, Any], item: dict[str, Any]) -> float:
    # your logic here
    return 1.0

第一个参数是模型输出字典;只有输出使用response_format时,output_json才填充。

来源示例 14(json):

格式说明:本块保留来源的模式或片段写法,不是可直接解析的完整严格JSON;代码内容保持原样。

{
    "choices": [...],
    "output_text": "...",
    "output_json": {},
    "output_tools": [...],
    "output_audio": {}
}

第二个参数是评分上下文字典;评测时包含来自数据源的键。

来源示例 15(json):

格式说明:本块保留来源的模式或片段写法,不是可直接解析的完整严格JSON;代码内容保持原样。

{
    "reference_answer": "...",
    "my_key": {...}
}

以下为来源调用示例。Ruby示例要求把前述grade函数及导入保存为运行目录下的grader.py。示意函数只返回1.0,需替换为真正评分逻辑。

来源示例 16(python):

## [中文] 将Python评分源码作为字符串提交,使用RapidFuzz归一化相似度,除以100得到0到1。
import os
import requests

## get the API key from environment
api_key = os.environ["OPENAI_API_KEY"]
headers = {"Authorization": f"Bearer {api_key}"}

grading_function = """
from rapidfuzz import fuzz, utils

def grade(sample, item) -> float:
    output_text = sample["output_text"]
    reference_answer = item["reference_answer"]
    return fuzz.WRatio(output_text, reference_answer, processor=utils.default_process) / 100.0
"""

## Define a Python grader.
grader = {"type": "python", "source": grading_function}

## validate the grader
payload = {"grader": grader}
response = requests.post(
    "https://api.openai.com/v1/fine_tuning/alpha/graders/validate",
    json=payload,
    headers=headers,
)
print("validate request_id:", response.headers["x-request-id"])
print("validate response:", response.text)

## run the grader with a test reference and sample
payload = {
    "grader": grader,
    "item": {"reference_answer": "fuzzy wuzzy had no hair"},
    "model_sample": "fuzzy wuzzy was a bear",
}
response = requests.post(
    "https://api.openai.com/v1/fine_tuning/alpha/graders/run",
    json=payload,
    headers=headers,
)
print("run request_id:", response.headers["x-request-id"])
print("run response:", response.text)

来源示例 17(ruby):

## [中文] Ruby读取当前目录grader.py并提交Python评分配置;须先保存函数和依赖导入。
require "openai"

client = OpenAI::Client.new
## Save your Python grading function as grader.py before running this example.
grading_function = File.read("grader.py")
grader = {
  type: :python,
  source: grading_function
}
item = { reference_answer: "fuzzy wuzzy had no hair" }
model_sample = "fuzzy wuzzy was a bear"

puts(client.fine_tuning.alpha.graders.validate(grader: grader).to_json)
puts(client.fine_tuning.alpha.graders.run(grader: grader, item: item, model_sample: model_sample).to_json)

不想手动将函数写成字符串时,可用importlib和inspect从Python文件加载。例如grader.py:

来源示例 18(python):

## [中文] 加载grader模块并取得整个文件源码,组成type=python的评分器配置。
import importlib
import inspect

grader_module = importlib.import_module("grader")
grader = {"type": "python", "source": inspect.getsource(grader_module)}

这会自动使用整个文件源码,适合较长评分器。

技术约束

  • 上传代码小于256kB,执行环境无网络。
  • 单次评分最多2分钟。
  • 内存2Gb、磁盘1Gb。
  • 最多2个CPU核,超出会被限流。

镜像标签2025-05-08提供以下第三方包,版本列表保留原样:

来源示例 19():

numpy==2.2.4
scipy==1.15.2
sympy==1.13.3
pandas==2.2.3
rapidfuzz==3.10.1
scikit-learn==1.6.1
rouge-score==0.1.2
deepdiff==8.4.2
jsonschema==4.23.0
pydantic==2.10.6
pyyaml==6.0.2
nltk==3.9.1
sqlparse==0.5.3
rdkit==2024.9.6
scikit-bio==0.6.3
ast-grep-py==0.36.2

另有以下 NLTK 语料:

来源示例 20():

punkt
stopwords
wordnet
omw-1.4
names

限制与建议

评分器设计需要从小规模开始试验,持续改进。

设计建议

  • 避免标签严重失衡;平衡数据或提高罕见样例权重,防止猜多数类。
  • 代码难以判断丰富、开放的答案时,用LLM裁判;用多个候选答案和标准答案校准稳定性与偏好一致性,并在提示词中提供优秀、一般、较差的少样本示例。
以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号