Skip to main content

参考

以下是 promptfoo 配置文件的主要结构:

配置

属性类型必填描述
descriptionstring可选的描述,说明你的 LLM 正在尝试做什么
tagsRecord<string, string>可选的标签,用于描述测试套件(例如 env: production, application: chatbot
providersstring | string[] | Record<string, ProviderOptions> | ProviderOptions[]要使用的一个或多个 LLM API
promptsstring | string[]要加载的一个或多个提示
testsstring | Test Case[]测试文件的路径,或 LLM 提示变体列表(即“测试用例”)
defaultTestPartial Test Case为每个测试用例设置默认属性。例如,可以为所有测试用例设置断言。
outputPathstring输出写入位置。如果未设置,则写入控制台/网页查看器。
evaluateOptions.maxConcurrencynumber最大并发请求数。默认为 4
evaluateOptions.repeatnumber每个测试用例的运行次数。默认为 1
evaluateOptions.delaynumber强制测试运行器在每次 API 调用后等待(毫秒)
evaluateOptions.showProgressBarboolean是否显示进度条
扩展名字符串数组要加载的扩展文件列表。每个扩展是一个带有函数名的文件路径。可以是 Python (.py) 或 JavaScript (.js) 文件。支持的钩子有 'beforeAll', 'afterAll', 'beforeEach', 'afterEach'。

测试用例

测试用例代表一个单一的示例输入,该输入被提供给所有提示和提供者。

属性类型是否必需描述
描述字符串你要测试的内容的描述
变量Record<string, string | string[] | any> | string用于替换提示中的键值对。如果 vars 是一个普通字符串,它将被视为一个 YAML 文件路径,从中加载变量映射。
提供者字符串 | ProviderOptions | ApiProvider覆盖此特定测试用例的默认提供者
断言断言[]对 LLM 输出运行的一系列自动检查
阈值数字如果断言的组合分数低于此数字,测试将失败
元数据Record<string, string | string[] | any>包含在测试用例中的附加元数据,对过滤或分组结果很有用
选项对象测试用例的附加配置设置
选项.transformVars字符串在变量被替换到提示中之前运行的文件路径(js 或 py)或 JavaScript 代码片段
选项.transform字符串在任何断言之前对 LLM 输出运行的文件路径(js 或 py)或 JavaScript 代码片段
选项.prefix字符串要添加到提示前的文本
选项.suffix字符串要添加到提示后的文本
选项.provider字符串用于 LLM 评分标准的 API 提供者
选项.runSerially布尔值如果为 true,则无论全局设置如何,都按顺序运行此测试用例
选项.storeOutputAs字符串此测试的输出将存储为一个变量,可在后续测试中使用
选项.rubricPrompt字符串 | 字符串数组模型评分的 LLM 提示

断言

有关使用断言的更多详细信息,包括示例,请参见此处

属性类型是否必需描述
typestring断言类型
valuestring预期值(如果适用)
thresholdnumber阈值,仅适用于某些类型,如 similarcostjavascriptpython
providerstring某些断言(类型 = similar、llm-rubric、model-graded-*)需要一个 LLM 提供者
metricstring此结果的标签。具有相同 metric 的断言将被聚合在一起
note

promptfoo 除了支持 .yaml 文件扩展名外,还支持 .js.json 文件扩展名。

它会自动加载 promptfooconfig.*,但你可以使用 promptfoo eval -c path/to/config 指定自定义配置文件。

扩展钩子

promptfoo 支持扩展钩子,允许你在评估生命周期的特定点运行自定义代码。这些钩子在配置的 extensions 属性中指定的扩展文件中定义。

可用的钩子

钩子名称描述参数
beforeAll在整个测试套件开始之前运行{ suite: TestSuite }
afterAll在整个测试套件完成后运行{ results: EvaluateResult[], suite: TestSuite }
beforeEach在每个单独的测试之前运行{ test: TestCase }
afterEach在每个单独的测试之后运行{ test: TestCase, result: EvaluateResult }

实现钩子

要实现这些钩子,请创建一个 JavaScript 或 Python 文件,其中包含处理你想要使用的钩子的函数。然后,在你的配置中的 extensions 数组中指定此文件的路径和函数名称。

note

所有扩展都接收所有事件类型(beforeAll、afterAll、beforeEach、afterEach)。扩展函数根据 hookName 参数决定处理哪些事件。

示例配置:

extensions:
- file://path/to/your/extension.js:extensionHook
- file://path/to/your/extension.py:extension_hook
important

在配置中指定扩展时,必须在文件路径后包含函数名称,并用冒号 (:) 分隔。这告诉 promptfoo 在扩展文件中调用哪个函数。

示例扩展文件(Python):

def extension_hook(hook_name, context):
if hook_name == 'beforeAll':
print(f"Setting up test suite: {context['suite'].get('description', '')}")
# Perform any necessary setup
elif hook_name == 'afterAll':
print(f"Test suite completed: {context['suite'].get('description', '')}")
print(f"Total tests: {len(context['results'])}")
# Perform any necessary teardown or reporting
elif hook_name == 'beforeEach':
print(f"Running test: {context['test'].get('description', '')}")
# Prepare for individual test
elif hook_name == 'afterEach':
print(f"Test completed: {context['test'].get('description', '')}. Pass: {context['result'].get('success', False)}")
# Clean up after individual test or log results

示例扩展文件(JavaScript):

async function extensionHook(hookName, context) {
if (hookName === 'beforeAll') {
console.log(`Setting up test suite: ${context.suite.description || ''}`);
// Perform any necessary setup
} else if (hookName === 'afterAll') {
console.log(`Test suite completed: ${context.suite.description || ''}`);
console.log(`Total tests: ${context.results.length}`);
// Perform any necessary teardown or reporting
} else if (hookName === 'beforeEach') {
console.log(`Running test: ${context.test.description || ''}`);
// Prepare for individual test
} else if (hookName === 'afterEach') {
console.log(
`Test completed: ${context.test.description || ''}. Pass: ${context.result.success || false}`,
);
// Clean up after individual test or log results
}
}

module.exports = extensionHook;

这些钩子为你的 promptfoo 评估提供了强大的扩展性,允许你为设置、拆卸、日志记录或与其他系统的集成实现自定义逻辑。扩展函数接收 hookName 和一个 context 对象,其中包含每个钩子类型的相关数据。你可以使用此信息来执行特定于评估过程每个阶段的操作。

与提供者相关的类型

ProviderFunction

ProviderFunction 是一个函数,它接受一个提示作为参数,并返回一个解析为 ProviderResponse 的 Promise。它允许你为调用 API 定义自定义逻辑。

type ProviderFunction = (
prompt: string,
context: { vars: Record<string, string | object> },
) => Promise<ProviderResponse>;

ProviderOptions

ProviderOptions 是一个对象,包含提供者的 id 和一个可选的 config 对象,用于传递提供者特定的配置。

interface ProviderOptions {
id?: ProviderId;
config?: any;

// 提示显示字符串列表
prompts?: string[];

// 转换输出,可以使用内联 JavaScript 或外部 py/js 脚本(参见 `Transforms`)
transform?: string;

// 在每次请求前休眠一段时间
delay?: number;
}

ProviderResponse

ProviderResponse 是一个对象,表示来自提供者的响应。它包括提供者的输出、发生的任何错误、关于令牌使用情况的信息以及一个指示响应是否被缓存的标志。

interface ProviderResponse {
error?: string;
output?: string | object;
tokenUsage?: Partial<{
total: number;
prompt: number;
completion: number;
cached?: number;
}>;
cached?: boolean;
cost?: number; // 成本断言所需
logProbs?: number[]; // 困惑度断言所需
}

ProviderEmbeddingResponse

ProviderEmbeddingResponse 是一个对象,表示来自提供者嵌入 API 的响应。它包括来自提供者的嵌入、发生的任何错误以及关于令牌使用情况的信息。

interface ProviderEmbeddingResponse {
error?: string;
embedding?: number[];
tokenUsage?: Partial<TokenUsage>;
}

评估输入

TestSuiteConfiguration

interface TestSuiteConfig {
// 可选的测试描述
description?: string;

// 要使用的一个或多个 LLM API,例如:openai:gpt-4o-mini, openai:gpt-4o, localai:chat:vicuna
providers: ProviderId | ProviderFunction | (ProviderId | ProviderOptionsMap | ProviderOptions)[];

// 一个或多个提示
prompts: (FilePath | Prompt | PromptFunction)[];

// 测试文件的路径,或 LLM 提示变体列表(即“测试用例”)
tests: FilePath | (FilePath | TestCase)[];

// 场景,评估的数据和测试的分组
scenarios?: Scenario[];

// 为每个测试用例设置默认属性。例如,可以为所有测试用例设置断言。
defaultTest?: Omit<TestCase, 'description'>;

// 写入输出的路径。如果未设置,则写入控制台/网页查看器。
outputPath?: FilePath | FilePath[];

// 确定是否启用共享。
sharing?:
| boolean
| {
apiBaseUrl?: string;
appBaseUrl?: string;
};

// Nunjucks 过滤器
nunjucksFilters?: Record<string, FilePath>;

// 环境变量覆盖
env?: EnvOverrides;

// 是否将最新结果写入 promptfoo 存储。这使您可以使用网页查看器。
writeLatestResults?: boolean;
}

UnifiedConfig

UnifiedConfig 是一个对象,包含测试套件配置、评估选项和命令行选项。它用于保存评估的完整配置。

interface UnifiedConfig extends TestSuiteConfiguration {
evaluateOptions: EvaluateOptions;
commandLineOptions: Partial<CommandLineOptions>;
}

Scenario

Scenario 是一个对象,表示要评估的一组测试用例。它包括描述、默认测试用例配置和测试用例列表。

interface Scenario {
description?: string;
config: Partial<TestCase>[];
tests: TestCase[];
}

另请参见此表中的描述。

Prompt

Prompt 就是它听起来像的那样。在静态配置中指定提示对象时,它应该如下所示:

interface Prompt {
id: string; // 路径,通常以 file:// 为前缀
label: string; // 在输出和网页 UI 中显示的方式
}

当直接将 Prompt 对象传递给 JavaScript 库时:

interface Prompt {
// 实际的提示
raw: string;
// 在 UI 中显示的方式
label: string;
// 一个函数,用于在每个输入基础上生成提示。覆盖原始提示。
function?: (context: {
vars: Record<string, string | object>;
provider?: ApiProvider;
}) => Promise<string | object>;
}

EvaluateOptions

EvaluateOptions 是一个对象,包含如何执行评估的选项。它包括 API 调用的最大并发数、是否显示进度条、进度更新的回调、每个测试重复的次数以及测试之间的延迟。

interface EvaluateOptions {
maxConcurrency?: number;
showProgressBar?: boolean;
onProgress?: (progress: number) => void;
repeat?: number;
delay?: number;
}
interface EvaluateOptions {
最大并发数?: number;
显示进度条?: boolean;
进度回调函数?: (进度: number, 总数: number) => void;
生成建议?: boolean;
重复次数?: number;
延迟?: number;
}

评估输出

评估表格

EvaluateTable 是一个对象,表示以表格格式呈现的评估结果。它包括一个带有提示和变量的表头,以及一个包含每个测试用例的输出和变量的表体。

interface EvaluateTable {
head: {
prompts: Prompt[];
vars: string[];
};
body: {
outputs: EvaluateTableOutput[];
vars: string[];
}[];
}

评估表格输出

EvaluateTableOutput 是一个对象,表示以表格格式呈现的单次评估输出。它包括通过/失败结果、分数、输出文本、提示、延迟、令牌使用情况和评分结果。

interface EvaluateTableOutput {
pass: boolean;
score: number;
text: string;
prompt: string;
latencyMs: number;
tokenUsage?: Partial<TokenUsage>;
gradingResult?: GradingResult;
}

评估摘要

EvaluateSummary 是一个对象,表示评估结果的摘要。它包括评估器的版本、每次评估的结果、结果表格以及评估的统计信息。最新版本是 3。它移除了表格,并添加了一个新的 prompts 属性。

interface EvaluateSummaryV3 {
version: 3;
timestamp: string; // ISO 8601 日期时间
results: EvaluateResult[];
prompts: CompletedPrompt[];
stats: EvaluateStats;
}
interface EvaluateSummaryV2 {
version: 2;
timestamp: string; // ISO 8601 日期时间
results: EvaluateResult[];
table: EvaluateTable;
stats: EvaluateStats;
}

评估统计

EvaluateStats 是一个对象,包含有关评估的统计信息。它包括成功和失败的测试数量以及总的令牌使用情况。

interface EvaluateStats {
successes: number;
failures: number;
tokenUsage: Required<TokenUsage>;
}

评估结果

EvaluateResult 大致对应于网格比较视图中的单个“单元格”。它包括提供者、提示和其他输入的信息,以及输出。

interface EvaluateResult {
provider: Pick<ProviderOptions, 'id'>;
prompt: Prompt;
vars: Record<string, string | object>;
response?: ProviderResponse;
error?: string;
success: boolean;
score: number;
latencyMs: number;
gradingResult?: GradingResult;
}

评分结果

GradingResult 是一个对象,表示对测试用例评分的结果。它包括测试用例是否通过、分数、结果的原因、使用的令牌以及任何组件断言的结果。

interface GradingResult {
pass: boolean; # 测试是否通过?
score: number; # 分数在 01 之间
reason: string; # 结果的纯文本原因
tokensUsed?: TokenUsage; # 测试消耗的令牌
componentResults?: GradingResult[]; # 如果这是一个复合分数,它可以有嵌套的结果
assertion: Assertion | null; # 断言的来源
latencyMs?: number; # LLM 调用的延迟
}

已完成提示

CompletedPrompt 是一个对象,表示已评估的提示。它包括原始提示、提供者、指标和其他信息。

interface CompletedPrompt {
id?: string;
raw: string;
label: string;
function?: PromptFunction;

// 这些配置选项合并到提供者配置中。
config?: any;
provider: string;
metrics?: {
score: number;
testPassCount: number;
testFailCount: number;
assertPassCount: number;
assertFailCount: number;
totalLatencyMs: number;
tokenUsage: TokenUsage;
namedScores: Record<string, number>;
namedScoresCount: Record<string, number>;
redteam?: {
pluginPassCount: Record<string, number>;
pluginFailCount: Record<string, number>;
strategyPassCount: Record<string, number>;
strategyFailCount: Record<string, number>;
};
cost: number;
};
}