评估(通常称为 evals)用于测试模型输出,以确保它们符合您指定的风格和内容标准。编写评估以了解您的 LLM 应用程序在面对您的预期时的表现(尤其是在升级或尝试新模型时),是构建可靠应用程序的重要组成部分。
在本指南中,我们将重点介绍使用 Evals API 以编程方式配置评估。如果您愿意,也可以在 OpenAI 控制台中配置评估。
如果您是评估领域的新手,或者希望在构建评估时拥有一个更具迭代性的实验环境,请考虑改用数据集 (Datasets)。
大体上,为您的 LLM 应用程序构建和运行评估分为三个步骤。
- 将要完成的任务描述为评估
- 使用测试输入(提示词和输入数据)运行评估
- 分析结果,然后进行迭代并改进您的提示词
此过程在某种程度上类似于行为驱动开发 (BDD),即在实现和测试系统之前,先指定系统应如何表现。让我们看看如何使用 Evals API 完成上述每个步骤。
为任务创建评估
创建评估始于描述模型要执行的任务。假设我们想要使用一个模型将 IT 支持工单的内容分类为以下三类之一:Hardware(硬件)、Software(软件)或 Other(其他)。
要实现此用例,您可以使用 Chat Completions API 或 Responses API。下方的两个示例都结合了开发者消息和包含支持工单文本的用户消息。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from openai import OpenAI
client = OpenAI()
instructions = """
You are an expert in categorizing IT support tickets. Given the support
ticket below, categorize the request into one of "Hardware", "Software",
or "Other". Respond with only one of those words.
"""
ticket = "My monitor won't turn on - help!"
response = client.responses.create(
model="gpt-4.1",
input=[
{"role": "developer", "content": instructions},
{"role": "user", "content": ticket},
],
)
print(response.output_text)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from openai import OpenAI
client = OpenAI()
instructions = """
You are an expert in categorizing IT support tickets. Given the support
ticket below, categorize the request into one of "Hardware", "Software",
or "Other". Respond with only one of those words.
"""
ticket = "My monitor won't turn on - help!"
completion = client.chat.completions.create(
model="gpt-4.1",
messages=[
{"role": "developer", "content": instructions},
{"role": "user", "content": ticket}
]
)
print(completion.choices[0].message.content)让我们通过 API 设置一个评估来测试这种行为。评估需要两个关键要素
data_source_config:您将与评估一起使用的测试数据的架构。testing_criteria:决定模型输出是否正确的评分器 (graders)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
curl https://api.openai.com/v1/evals \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "IT Ticket Categorization",
"data_source_config": {
"type": "custom",
"item_schema": {
"type": "object",
"properties": {
"ticket_text": { "type": "string" },
"correct_label": { "type": "string" }
},
"required": ["ticket_text", "correct_label"]
},
"include_sample_schema": true
},
"testing_criteria": [
{
"type": "string_check",
"name": "Match output to human label",
"input": "{{ sample.output_text }}",
"operation": "eq",
"reference": "{{ item.correct_label }}"
}
]
}'创建评估后,它将被分配一个 UUID,您稍后启动运行时需要用到它。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"object": "eval",
"id": "eval_67e321d23b54819096e6bfe140161184",
"data_source_config": {
"type": "custom",
"schema": { ... omitted for brevity... }
},
"testing_criteria": [
{
"name": "Match output to human label",
"id": "Match output to human label-c4fdf789-2fa5-407f-8a41-a6f4f9afd482",
"type": "string_check",
"input": "{{ sample.output_text }}",
"reference": "{{ item.correct_label }}",
"operation": "eq"
}
],
"name": "IT Ticket Categorization",
"created_at": 1742938578,
"metadata": {}
}既然我们已经创建了一个描述应用程序所需行为的评估,让我们使用一组测试数据来测试一下提示词。
用评估测试提示词
现在我们已经在评估中定义了我们希望应用程序如何表现,让我们构建一个提示词,使其能够为具有代表性的测试样本可靠地生成正确的输出。
上传测试数据
提供评估运行测试数据的方法有很多种,但上传一个包含我们在创建评估时指定架构数据的 JSONL 文件可能比较方便。下方是一个符合我们设置架构的示例 JSONL 文件
1
2
3
{ "item": { "ticket_text": "My monitor won't turn on!", "correct_label": "Hardware" } }
{ "item": { "ticket_text": "I'm in vim and I can't quit!", "correct_label": "Software" } }
{ "item": { "ticket_text": "Best restaurants in Cleveland?", "correct_label": "Other" } }此数据集包含用于与模型输出进行比较的测试输入和基准事实标签。
接下来,让我们将测试数据文件上传到 OpenAI 平台,以便稍后引用它。您可以在 控制台此处上传文件,也可以通过 API 上传文件。以下示例假设您在保存了上述 JSON 示例数据且名为 tickets.jsonl 的目录中运行命令。
1
2
3
4
curl https://api.openai.com/v1/files \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F purpose="evals" \
-F file="@tickets.jsonl"上传文件时,请记录响应负载中唯一的 id 属性(如果通过浏览器上传,也可以在界面中找到)——稍后我们需要引用该值。
1
2
3
4
5
6
7
8
9
10
11
{
"object": "file",
"id": "file-CwHg45Fo7YXwkWRPUkLNHW",
"purpose": "evals",
"filename": "tickets.jsonl",
"bytes": 208,
"created_at": 1742834798,
"expires_at": null,
"status": "processed",
"status_details": null
}创建评估运行
有了测试数据,让我们评估一个提示词,看看它在测试标准下的表现。通过 API,我们可以通过创建评估运行来完成此操作。
请确保将 YOUR_EVAL_ID 和 YOUR_FILE_ID 替换为您在上述步骤中创建的评估配置和测试数据文件的唯一 ID。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
curl https://api.openai.com/v1/evals/YOUR_EVAL_ID/runs \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Categorization text run",
"data_source": {
"type": "responses",
"model": "gpt-4.1",
"input_messages": {
"type": "template",
"template": [
{"role": "developer", "content": "You are an expert in categorizing IT support tickets. Given the support ticket below, categorize the request into one of Hardware, Software, or Other. Respond with only one of those words."},
{"role": "user", "content": "{{ item.ticket_text }}"}
]
},
"source": { "type": "file_id", "id": "YOUR_FILE_ID" }
}
}'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
curl https://api.openai.com/v1/evals/YOUR_EVAL_ID/runs \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Categorization text run",
"data_source": {
"type": "completions",
"model": "gpt-4.1",
"input_messages": {
"type": "template",
"template": [
{"role": "developer", "content": "You are an expert in categorizing IT support tickets. Given the support ticket below, categorize the request into one of Hardware, Software, or Other. Respond with only one of those words."},
{"role": "user", "content": "{{ item.ticket_text }}"}
]
},
"source": { "type": "file_id", "id": "YOUR_FILE_ID" }
}
}'创建运行时,我们使用 Chat Completions 消息数组或 Responses 输入来设置提示词。此提示词用于为数据集中的每一行测试数据生成模型响应。我们可以使用双花括号语法将动态变量 item.ticket_text 模板化,该变量取自当前的测试数据项。
如果成功创建了评估运行,您将收到如下的 API 响应
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
"object": "eval.run",
"id": "evalrun_67e44c73eb6481909f79a457749222c7",
"eval_id": "eval_67e44c5becec81909704be0318146157",
"report_url": "https://platform.openai.com/evaluation/evals/abc123",
"status": "queued",
"model": "gpt-4.1",
"name": "Categorization text run",
"created_at": 1743015028,
"result_counts": { ... },
"per_model_usage": null,
"per_testing_criteria_results": null,
"data_source": {
"type": "responses",
"source": {
"type": "file_id",
"id": "file-J7MoX9ToHXp2TutMEeYnwj"
},
"input_messages": {
"type": "template",
"template": [
{
"type": "message",
"role": "developer",
"content": {
"type": "input_text",
"text": "You are an expert in...."
}
},
{
"type": "message",
"role": "user",
"content": {
"type": "input_text",
"text": "{{item.ticket_text}}"
}
}
]
},
"model": "gpt-4.1",
"sampling_params": null
},
"error": null,
"metadata": {}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
"object": "eval.run",
"id": "evalrun_67e44c73eb6481909f79a457749222c7",
"eval_id": "eval_67e44c5becec81909704be0318146157",
"report_url": "https://platform.openai.com/evaluation/evals/abc123",
"status": "queued",
"model": "gpt-4.1",
"name": "Categorization text run",
"created_at": 1743015028,
"result_counts": { ... },
"per_model_usage": null,
"per_testing_criteria_results": null,
"data_source": {
"type": "completions",
"source": {
"type": "file_id",
"id": "file-J7MoX9ToHXp2TutMEeYnwj"
},
"input_messages": {
"type": "template",
"template": [
{
"type": "message",
"role": "developer",
"content": {
"type": "input_text",
"text": "You are an expert in...."
}
},
{
"type": "message",
"role": "user",
"content": {
"type": "input_text",
"text": "{{item.ticket_text}}"
}
}
]
},
"model": "gpt-4.1",
"sampling_params": null
},
"error": null,
"metadata": {}
}您的评估运行现已进入队列,它将在处理数据集的每一行时异步执行,为我们指定的提示词和模型生成测试响应。
分析结果
要接收运行成功、失败或取消的更新,请创建一个 webhook 端点并订阅 eval.run.succeeded、eval.run.failed 和 eval.run.canceled 事件。有关详细信息,请参阅 webhooks 指南。
根据数据集的大小,评估运行可能需要一些时间才能完成。您可以在控制台中查看当前状态,也可以通过 API 获取评估运行的当前状态。
1
2
3
curl https://api.openai.com/v1/evals/YOUR_EVAL_ID/runs/YOUR_RUN_ID \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json"您需要同时提供评估和评估运行的 UUID 来获取其状态。获取后,您将看到如下的评估运行数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
{
"object": "eval.run",
"id": "evalrun_67e44c73eb6481909f79a457749222c7",
"eval_id": "eval_67e44c5becec81909704be0318146157",
"report_url": "https://platform.openai.com/evaluation/evals/xxx",
"status": "completed",
"model": "gpt-4.1",
"name": "Categorization text run",
"created_at": 1743015028,
"result_counts": {
"total": 3,
"errored": 0,
"failed": 0,
"passed": 3
},
"per_model_usage": [
{
"model_name": "gpt-4o-2024-08-06",
"invocation_count": 3,
"prompt_tokens": 166,
"completion_tokens": 6,
"total_tokens": 172,
"cached_tokens": 0
}
],
"per_testing_criteria_results": [
{
"testing_criteria": "Match output to human label-40d67441-5000-4754-ab8c-181c125803ce",
"passed": 3,
"failed": 0
}
],
"data_source": {
"type": "responses",
"source": {
"type": "file_id",
"id": "file-J7MoX9ToHXp2TutMEeYnwj"
},
"input_messages": {
"type": "template",
"template": [
{
"type": "message",
"role": "developer",
"content": {
"type": "input_text",
"text": "You are an expert in categorizing IT support tickets. Given the support ticket below, categorize the request into one of Hardware, Software, or Other. Respond with only one of those words."
}
},
{
"type": "message",
"role": "user",
"content": {
"type": "input_text",
"text": "{{item.ticket_text}}"
}
}
]
},
"model": "gpt-4.1",
"sampling_params": null
},
"error": null,
"metadata": {}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
{
"object": "eval.run",
"id": "evalrun_67e44c73eb6481909f79a457749222c7",
"eval_id": "eval_67e44c5becec81909704be0318146157",
"report_url": "https://platform.openai.com/evaluation/evals/xxx",
"status": "completed",
"model": "gpt-4.1",
"name": "Categorization text run",
"created_at": 1743015028,
"result_counts": {
"total": 3,
"errored": 0,
"failed": 0,
"passed": 3
},
"per_model_usage": [
{
"model_name": "gpt-4o-2024-08-06",
"invocation_count": 3,
"prompt_tokens": 166,
"completion_tokens": 6,
"total_tokens": 172,
"cached_tokens": 0
}
],
"per_testing_criteria_results": [
{
"testing_criteria": "Match output to human label-40d67441-5000-4754-ab8c-181c125803ce",
"passed": 3,
"failed": 0
}
],
"data_source": {
"type": "completions",
"source": {
"type": "file_id",
"id": "file-J7MoX9ToHXp2TutMEeYnwj"
},
"input_messages": {
"type": "template",
"template": [
{
"type": "message",
"role": "developer",
"content": {
"type": "input_text",
"text": "You are an expert in categorizing IT support tickets. Given the support ticket below, categorize the request into one of Hardware, Software, or Other. Respond with only one of those words."
}
},
{
"type": "message",
"role": "user",
"content": {
"type": "input_text",
"text": "{{item.ticket_text}}"
}
}
]
},
"model": "gpt-4.1",
"sampling_params": null
},
"error": null,
"metadata": {}
}API 响应包含有关测试标准结果、生成模型响应的 API 使用情况的详细信息,以及一个 report_url 属性,该属性将带您进入控制台中的页面,在那里您可以直观地浏览结果。
在我们的简单测试中,模型可靠地为一小部分测试样本生成了我们想要的内容。实际上,您通常需要使用更多标准、不同的提示词和不同的数据集来运行评估。但上述过程为您提供了构建强大 LLM 应用程序评估所需的所有工具!
后续步骤
现在您已经了解了如何通过 API 和控制台创建并运行评估!以下是一些其他资源,在您继续改进模型结果时可能会有所帮助。
在您迭代提示词时,跟踪其性能表现。
同时比较多种不同提示词和模型的结果。
检查已存储的补全内容以测试提示词回归。
提高模型生成针对您用例的响应的能力。
了解如何将大模型的结果蒸馏到更小、更便宜、更快的模型中。