Skip to main content

自定义 Python

python 提供程序允许你使用 Python 脚本作为评估提示的 API 提供程序。当你有自定义逻辑或用 Python 实现的模型,并希望将其集成到测试套件中时,这非常有用。

配置

要配置 Python 提供程序,你需要指定 Python 脚本的路径以及要传递给脚本的任何附加选项。以下是一个 YAML 格式的配置示例:

providers:
- id: 'file://my_script.py'
label: '测试脚本 1' # 此提供程序的可选显示标签
config:
additionalOption: 123

Python 脚本

你的 Python 脚本应实现一个函数,该函数接受提示、选项和上下文作为参数。它应返回一个 JSON 编码的 ProviderResponse

  • ProviderResponse 必须包含一个包含 API 调用结果的 output 字段。
  • 可选地,如果出现问题,它可以包含一个 error 字段,以及一个用于报告使用的令牌数量的 tokenUsage 字段。
  • 默认情况下,支持的函数是 call_apicall_embedding_apicall_classification_api。要覆盖函数名称,请按如下方式指定脚本:file://my_script.py:function_name

以下是一个可以与 Python 提供程序一起使用的 Python 脚本示例,其中包括对提示、选项和上下文的处理:

# my_script.py
import json

def call_api(prompt: str, options: Dict[str, Any], context: Dict[str, Any]) -> ProviderResponse:
# 注意:提示可能是 JSON 格式的,因此你可能需要解析它。
# 例如,如果提示是一个表示对话的 JSON 字符串:
# prompt = '[{"role": "user", "content": "Hello, world!"}]'
# 你可以这样解析它:
# prompt = json.loads(prompt)

# 'options' 参数包含 API 调用的附加配置。
config = options.get('config', None)
additional_option = config.get('additionalOption', None)

# 'context' 参数提供有关哪些变量用于创建最终提示的信息。
user_variable = context['vars'].get('userVariable', None)

# 提示是处理完变量后的最终提示字符串。
# 自定义逻辑来处理提示在这里。
# 例如,你可能调用外部 API 或运行一些计算。
# TODO: 替换为实际的 LLM API 实现。
def call_llm(prompt):
return f"Stub response for prompt: {prompt}"
output = call_llm(prompt)

# 结果应是一个至少包含 'output' 字段的字典。
result = {
"output": output,
}

if some_error_condition:
result['error'] = "处理过程中发生错误"

if token_usage_calculated:
# 如果你想报告令牌使用情况,可以设置 'tokenUsage' 字段。
result['tokenUsage'] = {"total": token_count, "prompt": prompt_token_count, "completion": completion_token_count}

return result

def call_embedding_api(prompt: str) -> ProviderEmbeddingResponse:
# 返回 ProviderEmbeddingResponse
pass

def call_classification_api(prompt: str) -> ProviderClassificationResponse:
# 返回 ProviderClassificationResponse
pass

类型

传递给 Python 脚本函数和 ProviderResponse 返回类型的类型定义如下:

class ProviderOptions:
id: Optional[str]
config: Optional[Dict[str, Any]]

class CallApiContextParams:
vars: Dict[str, str]

class TokenUsage:
total: int
prompt: int
completion: int

class ProviderResponse:
output: Optional[Union[str, Dict[str, Any]]]
error: Optional[str]
tokenUsage: Optional[TokenUsage]
cost: Optional[float]
cached: Optional[bool]
logProbs: Optional[List[float]]

class ProviderEmbeddingResponse:
embedding: List[float]
tokenUsage: Optional[TokenUsage]
cached: Optional[bool]

class ProviderClassificationResponse:
classification: Dict[str, Any]
tokenUsage: Optional[TokenUsage]
cached: Optional[bool]

设置 Python 可执行文件

在某些情况下,你可能需要指定自定义的 Python 可执行文件。这在使用虚拟环境或默认 Python 路径未指向所需 Python 解释器时特别有用。

以下是如何使用 pythonExecutable 选项覆盖 Python 可执行文件的示例:

providers:
- id: 'file://my_script.py'
config:
pythonExecutable: /path/to/python3.11

故障排除

查看 Python 输出

如果你在 Python 脚本中使用 print 语句,请设置 LOG_LEVEL=debug 以查看脚本调用和输出:

LOG_LEVEL=debug npx promptfoo@latest eval

设置 Python 二进制路径

如果你使用特定的 Python 二进制文件(例如来自虚拟环境或 poetry),请将 PROMPTFOO_PYTHON 环境变量设置为二进制文件的位置。 还要注意,promptfoo 会尊重 PYTHONPATH。你可以利用这一点来告诉 Python 解释器你的自定义模块所在的位置。

例如:

PROMPTFOO_PYTHON=venv/bin/python3.9 PYTHONPATH=/usr/lib/foo npx promptfoo@latest eval