关于 opik-optimize
opik-optimize 是一项使用 Opik 提示词优化器和评估数据改进提示词的 Skill。它通过留出数据比较候选结果、报告运行成本,并将胜出的库提示词另存为新版本,不修改应用代码。
主要功能
- 01优化前测量基线
- 02使用留出验证数据
- 03依据观察到的问题选择优化器
- 04记录运行链接和成本
- 05将库提示词胜者保存为新版本
- 06不修改应用代码
适用场景
- 01针对现有数据集调整提示词
- 02检查提示词提升能否适用于训练项之外
- 03在 Opik 中为改进的库提示词创建版本
MCP 相关
此 Skill 使用 Opik 和 opik-optimizer 优化提示词,并将库提示词保存为新版本。它可优化工具描述,但 README 未说明 MCP 服务连接或管理功能。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ comet-ml/ opik-skills --skill opik-optimize安装后在 Claude Code 中输入/opik-optimize确认已加载。
详细介绍
Optimize — 基于数据改进提示词
完成定义:得到一个优化后的提示词,其指标得分在未用于调优的数据上超过基线;提供 Opik 中的优化运行链接和达到该结果的成本;并将胜出版本保存为新的提示词版本(如果提示词位于库中)——代码中的替换留作下一步。如果优化无法在声明的预算内运行,请停在第一个真实阻碍处,并且只返回一个下一步。提示词只在自身训练样本上得分更高,不算改进。
操作方式:先测量基线,花费预算前先说明预算,留出数据,根据观察到的问题选择算法,将胜出版本保存在可进行版本管理的位置——不更改任何应用代码。 此技能唯一写入的文件是仓库外的运行器;提示词保存到 Opik,而不是代码库中。
输入
入口为 /opik-optimize <prompt-name>(提示词库中的提示词)、/opik-optimize <path or function>(代码中的提示词),或 /opik-optimize(查找此仓库中的系统提示词)。推断其余信息;以下内容均为可选覆盖项:
- 数据集(默认:项目的现有数据集 → 导出回归测试集 → 从跟踪记录构建)· 指标(默认:若存在
expected_output,则使用启发式指标;否则使用一个二元判定器)· 算法(默认:MetaPromptOptimizer)· 预算(默认:n_samples=50、max_trials=10)· 模型· 验证集划分(默认:留出 20%)。
只有遇到真实且无法推断的阻碍时才提问(见阻碍)。
激活 — 唯一范围内的工作
1. 确定提示词
- 库:
client.get_chat_prompt(name)(文本提示词则使用get_prompt)。记录当前version——它就是基线。 - **代码:**搜索系统提示词 /
messages=[...];逐字读取。记录其所在位置;不要编辑它。 - **跟踪记录:**从一个有代表性的跟踪记录中读取
llmspan 的input.messages。
优化器的 opik_optimizer.ChatPrompt 与库中的 opik.ChatPrompt 是不同的类——请根据原始消息自行构建:
from opik_optimizer import ChatPrompt
prompt = ChatPrompt(name="<name>", system="<system text>", user="{question}") # or messages=[...]; {var} names must match dataset keys
2. 确定数据集(并留出一部分数据)
优化器需要一个 opik.Dataset,其中的项目键必须与提示词的 {variables} 相匹配。
import opik
client = opik.Opik()
dataset = client.get_dataset(name="<dataset>", project_name="<project>")
- 只有测试套件 → 将其项目导出到数据集一次:
suite.get_items()→client.get_or_create_dataset("<suite>-optimize", project_name=…)→insert([{**it["data"]} …])。 - 没有任何现成数据 → 从跟踪记录构建(
search_traces→{"question": t.input[...], "expected_output": …}),或先运行/opik-evaluate。 - 留出数据:拆分为训练集和验证集,并传入
validation_dataset=。注意其作用:优化器会在validation_dataset上为每次试验评分,并使用训练集向推理模型提供示例——因此验证集就是用于筛选的集合,且至少需要 10 个项目,否则候选结果都会打平(4 项目的拆分会记录n_samples … larger than evaluation dataset size,无法区分提示词)。若要在优化器从未见过的项目上衡量增益,请保留第三份数据,并用evaluate()对胜出版本重新评分。总项目数少于约 20 个 → 说明结果会有噪声;少于 10 个 → 阻碍。
3. 定义指标
一个函数 (dataset_item, llm_output) -> float,分数越高越好。为它取一个有意义的名称(def refund_answer_similarity(...))——它的 __name__ 会成为 UI 中 Optimization 运行的目标名称和 result.metric_name;如果函数名为 metric,界面中会显示为“metric”。
- 存在
expected_output→ 使用启发式指标(LevenshteinRatio、Equals或特定任务检查)——结果确定且免费。优先使用分级指标,而不是精确匹配:如果基线在每个项目上的分数都是 0.0(严格输出格式下使用Equals时观察到这种情况),那么每个候选项的分数也都是 0.0,优化器便无从提升——连续五次试验都得到 0 分,这是指标问题,而不是提示词问题。 - 否则 → 针对要优化的失败模式使用一个二元判定器(
../opik-evaluate/references/write-judge-prompt.md),并封装为返回其分数.value。多目标 →MultiMetricObjective。 不要针对未经验证的判定器进行优化:未经验证的判定器最容易被过拟合。
4. 选择算法
| 观察到的失败 | 优化器 |
|---|---|
| 指令不清楚/不够具体(通常的默认选择) | MetaPromptOptimizer |
| 模型需要正确答案示例;可以接受少样本 | FewShotBayesianOptimizer |
| 失败集中在少数几种根本原因上 | HierarchicalReflectiveOptimizer(HRPO) |
| 预算较多,希望进行广泛搜索 | EvolutionaryOptimizer 或 GepaOptimizer |
| 提示词没问题,问题出在 temperature/top_p | ParameterOptimizer.optimize_parameter(...) |
| 问题出在工具描述 | optimize_prompt(..., optimize_tools=True)(已弃用 optimize_mcp) |
5. 说明预算,然后运行
在临时环境中执行 uv add opik-optimizer(或 pip install opik-optimizer),不要修改仓库的锁文件,除非用户希望这样做。每次试验都会使用任务模型和推理模型评估 n_samples 个项目——运行前告知用户大致的调用次数。缺少提供方密钥 → 阻塞项。
from opik_optimizer import MetaPromptOptimizer
optimizer = MetaPromptOptimizer(model="<task model>", verbose=1, seed=42)
result = optimizer.optimize_prompt(
prompt=prompt, dataset=train, metric=metric,
validation_dataset=validation,
n_samples=50, max_trials=10,
project_name="<project>",
)
将运行脚本写入仓库外的临时文件。运行结果会作为 Optimization 显示在 Opik 中(result.get_run_link())。
6. 如实解读结果
指标的 result.initial_score → result.score;查看 result.details["stop_reason"] 和 ["trials_completed"];查看 result.llm_calls、result.llm_cost_total(提供方未返回费用时可能为 None——应说明“费用不可用”,不要编造)。报告验证集分数,而不是训练集分数。如果提升幅度处于不同运行间的噪声范围内(有疑问时,重新运行一次基线),则称为“未测得显著改善”——应如实说明,不要发布仅有微小变化的版本,也不要为此保存新版本。结果持平的常见原因是:答案依赖提示词无法包含的上下文(检索、工具、账户数据)——这时瓶颈不在提示词,下一步应针对最差项目使用 /opik-explain,而不是增加试验次数。
7. 保存最佳版本(库中的提示词)并交接
messages = result.prompt.get_messages() # optimizer ChatPrompt -> raw messages
new_version = client.create_chat_prompt(
name="<name>", messages=messages, project_name="<project>",
change_description=f"opik-optimize: {result.optimizer}, {result.metric_name} {result.initial_score:.2f} -> {result.score:.2f} (validation)",
)
对于存放在代码中的提示词,不要编辑文件——应返回优化后的文本和差异,作为下一步。然后给出一个下一步(见输出):通常是“对新版本运行 /opik-compare,并与回归测试集比较”,或“让应用使用版本 vN”。
阻塞项
遇到最早出现的阻塞项时停止,并且只返回一个下一步:
- "运行
opik configure,然后重新运行/opik-optimize。" - "要优化哪个提示词?请提供库中提示词的名称,或指出包含系统提示词的文件/函数。"
- "没有键匹配的数据集——运行
/opik-evaluate来创建一个,或指定现有数据集。" - "优化器需要提供方凭据——设置
OPENAI_API_KEY(或相应的密钥),然后重新运行。" - "只有 6 个项目——样本太少,无法避免过拟合。请添加案例(或回复
synthetic),然后重新运行。"
输出
**面向用户:**简短的人类可读消息——验证集上的基线分数与优化后分数、运行链接、成本、算法、提示词的更改内容(一两行)、新版本(或代码提示词的差异),以及唯一的下一步。不要提供完整的试验历史。
底层(用于组合/评估)统一采用以下结构:
status:improved|no_improvement|blockedprompt:name、source(library|code|trace)、baseline_version、new_version(保存时)dataset:train{name, count}、validation{name, count}metric:name、kind(heuristic|judge)、validated: true|falseoptimizer:algorithm、n_samples、max_trials、stop_reasonscores:initial、optimized、validation、deltacost:llm_calls、llm_cost_totalrun_urlnext_step:只能有一个
不变量:improved 要求 scores.validation > scores.initial 且差值超出噪声范围,并附带 run_url;no_improvement 仍须附带 run_url 和成本;如果 judge 指标的 validated: false,报告中必须标记;绝不修改代码库;库提示词须保存为新版本,绝不能原地覆盖。
示例
库提示词,启发式指标。 /opik-optimize support-system-prompt。数据集 support-qa(120 个条目,含 expected_output),按 96/24 划分,使用 LevenshteinRatio。MetaPromptOptimizer,50 个样本 × 10 次试验,注明预算。验证分数从 0.62 升至 0.79;成本为 $1.40。保存为 v7。→ improved;下一步 = "/opik-compare support-bot-regressions,并让应用指向 v7"。
没有实际提升。 验证分数从 0.71 升至 0.73,基线重新运行时波动 ±0.03。→ no_improvement:「提升在噪声范围内——提示词不是瓶颈;用 /opik-explain 分析最差的条目。」
代码中的提示词。 在 agent.py 中找到系统提示词。返回优化后的文本及差异;文件保持不变。→ improved;下一步 =「应用差异(或将提示词移至库中,以便进行版本管理)」。
受阻。 没有数据集,也没有轨迹。→ blocked:「先运行 /opik-evaluate 来构建数据集。」
反模式
将训练集分数当作提升;针对未经验证的评审器进行优化;预算不设上限(未指定 n_samples/max_trials)或不注明预算;原地覆盖提示词,而不是创建新版本;编辑代码库中的提示词;将 opik.ChatPrompt 和 opik_optimizer.ChatPrompt 视为可互换;使用少于约 20 个条目进行优化,却将其称为结果;根据新颖性而非观察到的失败来选择算法;使用已弃用的 optimize_mcp。
参考资料
数据集和提示词库的详细信息见与本技能一同安装的 opik 技能——以下路径均相对于此文件:../opik/references/evaluation-datasets.md(数据集、insert、版本、指标)、../opik/references/best-practices.md(提示词库、版本管理)、../opik/references/tracing-python.md(SDK 客户端)。评审器设计与验证:../opik-evaluate/references/write-judge-prompt.md、../opik-evaluate/references/validate-evaluator.md。如果宿主环境中的技能目录结构不同,请找到 opik 技能的 references/ 目录。
优化器 API(opik-optimizer):https://www.comet.com/docs/opik/agent_optimization/overview。如果未安装 opik 技能,请在报告中说明,并使用 https://www.comet.com/docs/opik/,不要凭记忆作答。