提示、测试和输出
提示
从原始文本生成提示
默认情况下,配置将接受原始文本作为提示:
prompts:
- '将以下文本翻译成法语:"{{name}}: {{text}}"'
- '将以下文本翻译成德语:"{{name}}: {{text}}"'
YAML 也支持多行字符串:
prompts:
- |-
你好 LLM,
请将以下文本翻译成法语:
"{{name}}: {{text}}"
- |-
将以下文本翻译成德语:
"{{name}}: {{text}}"
使用 Nunjucks 模板语法在提示中包含变量,这些变量将在评估期间被测试用例中的实际值替换。
提示作为 JSON
一些 LLM API 接受 JSON 聊天格式的提示,如 [{ "role" : "user", "content": "..."}]
。
默认情况下,纯文本提示会被包装在 user
角色的消息中。如果你提供 JSON,那么 promptfoo 将完全按照提供的 messages
对象发送。
以下是一个聊天格式提示的示例:
prompts:
- file://path/to/personality1.json
在 personality1.json
中:
[
{
"role": "system",
"content": "你是一个有帮助的助手"
},
{
"role": "user",
"content": "告诉我关于 {{topic}}"
}
]
了解更多关于 与 OpenAI 消息格式进行聊天对话。
从文件生成提示
你的提示可能复杂到难以在行内维护。在这种情况下,可以引用一个文件。文件路径相对于配置文件目录:
prompts:
- file://path/to/prompt1.txt
- file://path/to/prompt2.txt
- file://path/to/prompt.json
- file://path/to/prompt.yaml
- file://path/to/prompt.yml
- file://path/to/prompt.md
# 支持通配符
- file://prompts/*.txt
- file://path/**/*
# 提示函数
# 执行整个文件
- file:///root/path/to/prompt.js
- file://./path/to/prompt.py
# 执行单个函数
- file:///root/path/to/prompt.js:prompt1
- file:///root/path/to/prompt.js:prompt2
- file:///root/path/to/prompt.py:prompt1
- file:///root/path/to/prompt.py:prompt2
- file:///root/path/to/prompt.py:PromptClass.prompt1
- file:///root/path/to/prompt.py:PromptClass.prompt2
将它们检入版本控制。这种方法有助于跟踪更改、协作,并确保不同环境之间的一致性。
多个提示文件的示例:
将以下文本翻译成法语:"{{name}}: {{text}}"
将以下文本翻译成德语:"{{name}}: {{text}}"
提示也可以是 JSON。使用此配置多轮提示格式:
[
{
"role": "system",
"content": "你是一个翻译器,可以将输入转换为 {{ language }}。"
},
{
"role": "user",
"content": "{{ text }}"
}
]
单个文本文件中的多个提示
如果你只有一个文本文件,可以在文件中包含多个提示,用分隔符 ---
分隔。如果你有多个文件,每个提示应该在单独的文件中。
单个提示文件包含多个提示的示例 (prompts.txt
):
将以下文本翻译成法语:"{{name}}: {{text}}"
---
将以下文本翻译成德语:"{{name}}: {{text}}"
提示分隔符可以通过 PROMPTFOO_PROMPT_SEPARATOR
环境变量覆盖。
提示作为 Markdown
Markdown 格式的提示与原始文本提示类似。你可以在 Markdown 文件中定义提示:
你是一个有帮助的助手,用于 Promptfoo。请回答以下问题:{{question}}
注意,每个 Markdown 文件只支持一个提示。
针对不同模型的不同提示
要为不同的提供者设置单独的提示,可以在 promptfooconfig.yaml
的 providers
部分指定提示文件。每个提供者可以有自己的一组提示,这些提示根据其特定的要求或输入格式定制。
以下是如何为 llama3.1 和 GPT-4o 模型设置单独提示的示例:
prompts:
- id: file://prompts/gpt_chat_prompt.json
label: gpt_chat_prompt
- id: file://prompts/llama_completion_prompt.txt
label: llama_completion_prompt
providers:
- id: openai:gpt-4o-mini
prompts:
- gpt_chat_prompt
- id: openai:gpt-4o
prompts:
- gpt_chat_prompt
- id: replicate:meta/meta-llama-3.1-405b-instruct
label: llama-3.1-405b-instruct
prompts:
- llama_completion_prompt
在此配置中,gpt_chat_prompt
用于 GPT-4o 和 GPT-4o-mini 模型,而 llama_completion_prompt
用于 llama3.1 模型。提示在 prompts
目录中的单独文件中定义。
确保为每个模型创建相应格式的提示文件。例如,GPT 模型可能期望一个消息的 JSON 数组,而 llama 可能期望带有特定前缀的纯文本格式。
提示函数
提示函数允许你在提示中加入自定义逻辑。这些函数可以用 JavaScript 或 Python 编写,并以 .js
或 .py
扩展名包含在提示文件中。
要在 promptfooconfig.yaml
中指定一个提示函数,直接引用文件即可。例如:
prompts:
- file://prompt.js
- file://prompt.py
在提示函数中,你可以通过上下文访问测试用例变量和提供者信息。函数将能够访问一个 vars
对象和一个 provider
对象。通过访问 provider
对象,你可以为不同格式的不同提供者动态生成提示。
函数应返回一个表示提示的字符串或对象。
示例
一个 JavaScript 提示函数,prompt.js
:
module.exports = async function ({ vars, provider }) {
return [
{
role: 'system',
content: `You're an angry pirate named ${provider.label || provider.id}. Be concise and stay in character.`,
},
{
role: 'user',
content: `Tell me about ${vars.topic}`,
},
];
};
要在提示文件中引用特定函数,使用以下语法:filename.js:functionName
:
module.exports.prompt1 = async function ({ vars, provider }) {
return [
{
role: 'system',
content: `You're an angry pirate named ${provider.label || provider.id}. Be concise and stay in character.`,
},
{
role: 'user',
content: `Tell me about ${vars.topic}`,
},
];
};
一个 Python 提示函数,prompt.py:my_prompt_function
:
import json
import sys
def my_prompt_function(context: dict) -> str:
provider: dict = context['providers']
provider_id: str = provider['id'] # ex. openai:gpt-4o or bedrock:anthropic.claude-3-sonnet-20240229-v1:0
provider_label: str | None = provider.get('label') # exists if set in promptfoo config.
variables: dict = context['vars'] # access the test case variables
return (
f"Describe {variables['topic']} concisely, comparing it to the Python"
" programming language."
)
if __name__ == "__main__":
# If you don't specify a `function_name` in the provider string, it will run the main
print(my_prompt_function(json.loads(sys.argv[1])))
要验证你的函数是否生成了正确的提示:
- 运行
promptfoo view
- 检查表头是否包含你的函数代码。
- 将鼠标悬停在你要调查的特定输出上,点击放大镜(🔎)以在详细信息窗格中查看最终提示。
默认情况下,promptfoo 会在你的 shell 中运行 python
可执行文件。
要覆盖 Python 可执行文件,请将 PROMPTFOO_PYTHON
环境变量设置为可执行文件(例如 /usr/bin/python3.11
或 python3.11
)。
查看最终提示
提示函数在结果表顶部显示源代码,因为它们可以返回在不同测试用例之间不同的动态值。
为了查看每个测试用例的提示,切换 Table Settings
> Show full prompt in output cell
。这将显示每个测试用例/提供者组合的最终提示。
提示配置
提示可以通过 config
对象进行配置。该对象与提供者配置对象合并,合并后的对象用于调用提供者 API。
一个很好的用例是为特定提示设置 response_format
。
示例
prompts:
- label: 'Prompt #1'
raw: 'You are a helpful math tutor. Solve {{problem}}'
config:
response_format:
type: json_schema
json_schema: ...
Nunjucks 过滤器
Nunjucks 是一种模板语言,具有许多内置过滤器,可以应用于变量。例如:{{ varName | capitalize }}
。
Nunjucks 自定义过滤器 是 JavaScript 函数,可以应用于模板中的变量。
要定义一个 Nunjucks 过滤器,创建一个导出函数的 JavaScript 文件。该函数将用作过滤器,它应将输入值作为参数并返回转换后的值。
以下是一个将字符串转换为大写的自定义 Nunjucks 过滤器示例(allcaps.js
):
module.exports = function (str) {
return str.toUpperCase();
};
要在 Promptfoo 中使用自定义的 Nunjucks 过滤器,请将其添加到配置文件(promptfooconfig.yaml
)中。nunjucksFilters
字段应包含过滤器名称到定义它们的 JavaScript 文件路径的映射:
prompts:
- file://prompts.txt
providers:
- openai:gpt-4o-mini
nunjucksFilters:
allcaps: ./allcaps.js
tests:
# ...
然后,通过在变量或表达式后附加管道(|
)符号来在提示中使用该过滤器:
Translate this to {{language}}: {{body | allcaps}}
在这个例子中,body
变量在用于提示之前会通过 allcaps
过滤器进行处理。这意味着文本将被转换为大写。
默认提示
如果在配置中未定义 prompts
,则 Promptfoo 默认会使用一个“直通”提示:{{prompt}}
。这个提示只是简单地传递 prompt
变量的内容。
测试文件
如果你有很多测试,可以选择将它们与主配置文件分开保存。
最简单的方法是创建一个包含测试列表的 tests.yaml
文件,然后在 promptfooconfig.yaml
中像这样包含它:
prompts:
# ...
providers:
# ...
tests: file://path/to/tests.yaml
你甚至可以将其拆分为多个文件或 glob 模式:
tests:
- file://relative/path/to/normal_test.yaml
- file://relative/path/to/special_test.yaml
- file:///absolute/path/to/more_tests/*.yaml
从 CSV 导入
promptfoo 还支持测试 CSV 格式。
CSV 文件的第一行应包含变量名称,每一后续行应包含每个测试用例的相应值。
变量通过 Nunjucks 模板语法替换到提示中。第一行是变量名称。所有其他行是变量值。
测试文件示例(tests.csv
):
language,input
German,"Hello, world!"
Spanish,Where is the library?
测试文件可选支持几个特殊列:
__expected
:包含 测试断言 的列。此列允许你根据质量预期自动标记输出。- 对于多个断言,使用
__expected1
、__expected2
、__expected3
等。
- 对于多个断言,使用
__prefix
:在发送到 API 之前,此字符串会前置到每个提示中__suffix
:在发送到 API 之前,此字符串会附加到每个提示中__description
:测试描述__metric
:分配给测试用例中每个断言的指标__threshold
:分配给测试用例的阈值
你可以从 Google Sheets 加载测试。
输出文件
评估结果会写入此文件。例如:
promptfoo eval --output filepath.json
输出文件也可以通过 promptfoo 配置中的 outputPath
键来设置。
支持多种文件格式,包括 JSON、YAML、CSV 和 HTML。
输出文件中的每个记录对应一个测试用例,并包含原始提示、LLM 生成的输出以及测试用例中使用的变量值。
有关示例输出,请参见 examples/ 目录。
排列输入和断言
一个普通的 prompts.txt
/promptfooconfig.yaml
对支持每个测试将一组变量与一组断言组合。尝试将多组变量与多组 断言组合会导致配置条目呈指数级增长。
场景 使你能够在单个配置条目中使用 1+ 组变量和 1+ 组断言的所有可能组合。