Skip to main content

确定性指标

这些指标是通过对LLM输出运行的逻辑测试创建的。

断言类型返回true如果...
包含输出包含子字符串
包含所有输出包含所有列表中的子字符串
包含任意输出包含列表中的任意子字符串
包含JSON输出包含有效JSON(可选的JSON模式验证)
包含SQL输出包含有效SQL
包含XML输出包含有效XML
成本推理成本低于阈值
等于输出完全匹配
不区分大小写包含输出包含子字符串,不区分大小写
不区分大小写包含所有输出包含所有列表中的子字符串,不区分大小写
不区分大小写包含任意输出包含列表中的任意子字符串,不区分大小写
是JSON输出是有效JSON(可选的JSON模式验证)
是SQL输出是有效SQL语句(可选的权限列表验证)
是有效的OpenAI函数调用确保函数调用匹配函数的JSON模式
是有效的OpenAI工具调用确保所有工具调用匹配工具的JSON模式
是XML输出是有效XML
JavaScript提供的JavaScript函数验证输出
延迟延迟低于阈值(毫秒)
LevenshteinLevenshtein距离低于阈值
困惑度得分归一化困惑度
困惑度困惑度低于阈值
Python提供的Python函数验证输出
正则表达式输出匹配正则表达式
rouge-nRouge-N得分高于给定阈值
以...开头输出以字符串开头
Webhook提供的Webhook返回{pass: true}
tip

每种测试类型都可以通过在前面加上not-来取反。例如,not-equalsnot-regex

断言类型

包含

contains断言检查LLM输出是否包含预期值。

示例:

assert:
- type: contains
value: '预期的子字符串'

icontains与之相同,只是它忽略大小写:

assert:
- type: icontains
value: '预期的子字符串'

包含所有

contains-all断言检查LLM输出是否包含所有指定值。

示例:

assert:
- type: contains-all
value:
- '值1'
- '值2'
- '值3'

包含任意

contains-any断言检查LLM输出是否包含至少一个指定值。

示例:

assert:
- type: contains-any
value:
- '值1'
- '值2'
- '值3'

对于不区分大小写的匹配,使用icontains-any

对于不区分大小写的匹配,使用icontains-all

正则表达式

regex 断言检查 LLM 输出是否与提供的正则表达式匹配。

示例:

assert:
- type: regex
value: "\\d{4}" # 匹配一个四位数字

Contains-JSON

contains-json 断言检查 LLM 输出是否包含有效的 JSON 结构。

示例:

assert:
- type: contains-json

你可以选择设置一个 value 作为 JSON 模式,以便验证 JSON 内容:

assert:
- type: contains-json
value:
required:
- latitude
- longitude
type: object
properties:
latitude:
minimum: -90
type: number
maximum: 90
longitude:
minimum: -180
type: number
maximum: 180

JSON 是有效的 YAML,因此你也可以直接复制任何 JSON 模式:

assert:
- type: contains-json
value:
{
'required': ['latitude', 'longitude'],
'type': 'object',
'properties':
{
'latitude': { 'type': 'number', 'minimum': -90, 'maximum': 90 },
'longitude': { 'type': 'number', 'minimum': -180, 'maximum': 180 },
},
}

如果你的 JSON 模式很大,可以从文件中导入:

assert:
- type: contains-json
value: file://./path/to/schema.json

另见:is-json

Contains-Sql

此断言确保输出是有效的 SQL,或者包含带有有效 SQL 的代码块。

assert:
- type: contains-sql

有关高级用法,包括特定数据库类型和表与列的允许列表,请参见 is-sql

Cost

cost 断言检查 LLM 调用的成本是否低于指定阈值。

这需要 LLM 提供者返回成本信息。目前仅支持 OpenAI GPT 模型和自定义提供者。

示例:

providers:
- openai:gpt-4o-mini
- openai:gpt-4
assert:
# 如果 LLM 调用成本低于 $0.001,则通过
- type: cost
threshold: 0.001

Equality

equals 断言检查 LLM 输出是否等于预期值。

示例:

assert:
- type: equals
value: 'The expected output'

你也可以检查它是否匹配预期的 JSON 格式。

assert:
- type: equals
value: { 'key': 'value' }

如果你的预期 JSON 很大,可以从文件中导入:

assert:
- type: equals
value: 'file://path/to/expected.json'

Is-JSON

is-json 断言检查 LLM 输出是否是有效的 JSON 字符串。

示例:

assert:
- type: is-json

你可以选择设置一个 value 作为 JSON 模式。如果设置,输出将根据此模式进行验证:

assert:
- type: is-json
value:
required:
- latitude
- longitude
type: object
properties:
latitude:
minimum: -90
type: number
maximum: 90
longitude:
minimum: -180
type: number
maximum: 180

JSON 是有效的 YAML,因此你也可以直接复制任何 JSON 模式:

assert:
- type: is-json
value:
{
'required': ['latitude', 'longitude'],
'type': 'object',
'properties':
{
'latitude': { 'type': 'number', 'minimum': -90, 'maximum': 90 },
'longitude': { 'type': 'number', 'minimum': -180, 'maximum': 180 },
},
}

如果你的 JSON 模式很大,可以从文件中导入:

assert:
- type: is-json
value: file://./path/to/schema.json

Is-XML

is-xml 断言检查整个 LLM 输出是否是有效的 XML 字符串。它还可以验证 XML 结构中是否存在特定元素。

示例:

assert:
- type: is-xml

此基本用法检查输出是否是有效的 XML。

你也可以指定所需的元素:

assert:
- type: is-xml
value:
requiredElements:
- root.child
- root.sibling

这检查 XML 是否有效并包含指定的元素。元素以点分隔的路径指定,允许嵌套元素检查。

工作原理

  1. 断言首先尝试使用解析器(fast-xml-parser)将整个输出解析为 XML。
  2. 如果解析成功,则视为有效 XML。
  3. 如果指定了 value
    • 它会检查 requiredElements 键,其中包含所需的元素数组。
    • 每个元素路径(例如,"root.child")通过点进行分割。
    • 它沿着这些路径遍历解析的 XML 对象。
    • 如果未找到任何所需元素,断言失败。

示例

基本 XML 验证:

assert:
- type: is-xml

通过:<root><child>Content</child></root> 失败:<root><child>Content</child></root(缺少结束标签)

检查特定元素:

assert:
- type: is-xml
value:
requiredElements:
- analysis.classification
- analysis.color

通过的测试:<analysis><classification>T-shirt</classification><color>Red</color></analysis> 未通过的测试:<analysis><classification>T-shirt</classification></analysis>(缺少颜色元素)

检查嵌套元素:

assert:
- type: is-xml
value:
requiredElements:
- root.parent.child.grandchild

通过的测试:<root><parent><child><grandchild>Content</grandchild></child></parent></root> 未通过的测试:<root><parent><child></child></parent></root>(缺少grandchild元素)

反向断言

你可以使用 not-is-xml 断言来检查输出是否不是有效的XML:

assert:
- type: not-is-xml

这将通过非XML内容,并失败于有效的XML内容。

注意:is-xml 断言要求整个输出为有效的XML。对于检查较大文本中的XML内容,请使用 contains-xml 断言。

包含XML

contains-xmlis-xml 相同,只是它检查LLM输出是否包含有效的XML内容,即使它不是整个输出。例如,以下是有效的。

当然,这是你的xml:
<root><child>Content</child></root>
如果有其他问题,请告诉我!

是SQL

is-sql 断言检查LLM输出是否为有效的SQL语句。

示例:

assert:
- type: is-sql

要使用此断言,你需要安装 node-sql-parser 包。你可以使用npm安装它:

npm install node-sql-parser

你可以选择在 value 中设置 databaseType 以确定LLM输出将针对的特定数据库语法进行验证。默认的数据库语法是MySQL。有关支持的数据库语法的完整和最新列表,请参阅 node-sql-parser文档
支持的数据库语法列表:

  • Athena
  • BigQuery
  • DB2
  • FlinkSQL
  • Hive
  • MariaDB
  • MySQL
  • Noql
  • PostgresQL
  • Redshift
  • Snowflake(alpha)
  • Sqlite
  • TransactSQL

示例:

assert:
- type: is-sql
value:
databaseType: 'MySQL'

你还可以选择在 value 中设置 allowedTables/allowedColumns 以确定LLM输出将针对的SQL权限列表进行验证。
allowedTables的格式:

{type}::{dbName}::{tableName} // type可以是select, update, delete或insert

allowedColumns的格式:

{type}::{tableName}::{columnName} // type可以是select, update, delete或insert

对于 SELECT *DELETEINSERT INTO tableName VALUES() 没有指定列的情况,需要 .* 列权限正则表达式。

示例:

assert:
- type: is-sql
value:
databaseType: 'MySQL'
allowedTables:
- '(select|update|insert|delete)::null::departments'
allowedColumns:
- 'select::null::name'
- 'update::null::id'

是有效的OpenAI函数调用

这确保任何JSON LLM输出都符合提供者在 functions 配置中指定的模式。了解更多关于 OpenAI提供者

是有效的OpenAI工具调用

这确保任何JSON LLM输出都符合提供者在 tools 配置中指定的模式。了解更多关于 OpenAI提供者

Javascript

参见 Javascript断言

延迟

如果LLM调用时间超过指定的阈值,latency 断言将通过。持续时间以毫秒为单位指定。

示例:

assert:
# 如果LLM调用时间超过5秒则失败
- type: latency
threshold: 5000

注意,latency 要求 缓存被禁用,使用 promptfoo eval --no-cache 或等效选项。

Levenshtein距离

levenshtein 断言检查LLM输出是否在给定的编辑距离内与预期值相符。

示例:

assert:
# 确保与 "hello world" 的Levenshtein距离 <= 5
- type: levenshtein
threshold: 5
value: hello world

value 可以使用模板语法引用其他变量。例如:

tests:
- vars:
expected: foobar
assert:
- type: levenshtein
threshold: 2
value: '{{expected}}'

困惑度

困惑度是自然语言处理中用于量化语言模型预测文本样本的好坏的度量。它本质上是模型不确定性的度量。

高困惑度 表明模型对其预测不太确定,通常是因为文本非常多样化或模型没有很好地调整到手头的任务。

低困惑度 意味着模型以更高的信心预测文本,暗示它更擅长理解和生成与其训练数据相似的文本。 要指定困惑度阈值,请使用 perplexity 断言类型:

assert:
# 如果 LLM 低于困惑度阈值则失败
- type: perplexity
threshold: 1.5
warning

困惑度要求 LLM API 输出 logprobs。目前只有较新版本的 OpenAI GPT 和 Azure OpenAI GPT API 支持这一点。

比较同一 LLM 的不同输出

你可以比较同一模型不同输出的困惑度分数,以了解模型认为哪个输出更可能(或更不令人惊讶)。这是一种调整提示和超参数(如温度)以提高准确性的好方法。

比较不同 LLM 的输出

跨模型比较分数可能没有意义,除非这些模型在相似的数据集上进行了训练,模型之间的分词过程一致,并且模型的词汇量大致相同。

perplexity-score

perplexity-score 是一种支持的指标,类似于 perplexity,但它被归一化在 0 和 1 之间并反转,这意味着较大的数字更好。

这使得它更容易包含在聚合的 promptfoo 分数中,因为通常较高的分数更好。在此示例中,我们比较了多个 GPT 的困惑度:

providers:
- openai:gpt-4o-mini
- openai:gpt-4o
tests:
- assert:
- type: perplexity-score
threshold: 0.5 # 可选
# ...

Python

参见 Python 断言

Starts-With

starts-with 断言检查 LLM 输出是否以指定字符串开头。

此示例检查输出是否以 "Yes" 开头:

assert:
- type: starts-with
value: 'Yes'

Webhook

webhook 断言将 LLM 输出发送到指定的 webhook URL 进行自定义验证。webhook 应返回一个 JSON 对象,其中 pass 属性设置为 truefalse

示例:

assert:
- type: webhook
value: 'https://example.com/webhook'

webhook 将收到一个包含 LLM 输出和上下文(测试用例变量)的 JSON 有效负载的 POST 请求。例如,如果 LLM 输出是 "Hello, World!",测试用例有一个变量 example 设置为 "Example text",则有效负载将如下所示:

{
"output": "Hello, World!",
"context": {
"prompt": "Greet the user",
"vars": {
"example": "Example text"
}
}
}

webhook 应处理请求并返回一个 JSON 响应,其中 pass 属性设置为 truefalse,指示 LLM 输出是否符合自定义验证标准。可选地,webhook 还可以提供一个 reason 属性,描述输出通过或未通过断言的原因。

示例响应:

{
"pass": true,
"reason": "The output meets the custom validation criteria"
}

如果 webhook 返回 pass 值为 true,则断言将被视为成功。如果返回 false,则断言将失败,并使用提供的 reason 来描述失败原因。

你也可以返回一个分数:

{
"pass": true,
"score": 0.5,
"reason": "The output meets the custom validation criteria"
}