编译与优化提示词
实际使用 BootstrapFewShot、MIPRO 及其他 DSPy 优化器。
编译与优化提示词 是 CoddyKit 上的免费 AI Prompt Engineering 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Prompt Engineering 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Prompt Engineering 课程共包含 4 节课。
DSPy 中的优化意味着什么
DSPy 的优化(称为编译)会根据训练集和指标,为您的程序找出最佳提示词配置。优化器会在可能的少样本示例、指令和推理示例中进行搜索。
您只需运行一次编译,保存结果,然后部署优化后的程序。推理时只需进行快速的 LLM 调用,不再产生优化开销。
定义指标函数
每个 DSPy 优化器都需要一个指标函数,用于根据预期输出为预测结果评分。它返回一个数值(或布尔值),数值越高越好。
指标是优化器用来判断某个提示词配置是否良好的信号。
# Metric: exact match on answer field
def exact_match_metric(example, prediction, trace=None):
"""
example: a training example with .answer
prediction: the module's output with .answer
Returns 1.0 if correct, 0.0 otherwise
"""
expected = example.answer.strip().lower()
predicted = prediction.answer.strip().lower()
return float(expected == predicted)
# Metric: F1 score for token overlap (common in QA)
def token_f1_metric(example, prediction, trace=None):
gold_tokens = set(example.answer.lower().split())
pred_tokens = set(prediction.answer.lower().split())
if not pred_tokens:
return 0.0
precision = len(gold_tokens & pred_tokens) / len(pred_tokens)
recall = len(gold_tokens & pred_tokens) / len(gold_tokens)
if precision + recall == 0:
return 0.0
return 2 * precision * recall / (precision + recall)准备训练集
DSPy 需要由 dspy.Example 对象组成的训练集。每个示例都会指定输入和预期输出。对于 BootstrapFewShot,通常 20–50 个示例就足够了。
import dspy
# Build training examples
trainset = [
dspy.Example(
question='What is the capital of Germany?',
answer='Berlin'
).with_inputs('question'),
dspy.Example(
question='Who wrote Romeo and Juliet?',
answer='William Shakespeare'
).with_inputs('question'),
dspy.Example(
question='What year did World War II end?',
answer='1945'
).with_inputs('question'),
# ... add more examples
]
print(f'Training set size: {len(trainset)} examples')
print(trainset[0].question, '->', trainset[0].answer)BootstrapFewShot 优化器
BootstrapFewShot 是最常用的 DSPy 优化器。它会在训练集上运行您的程序,收集成功的轨迹(指标判定通过的输入-输出对),并将这些轨迹用作编译后提示词中的少样本示例。
import dspy
from dspy.teleprompt import BootstrapFewShot
# Define your program
class QA(dspy.Signature):
"""Answer factual questions."""
question: str = dspy.InputField()
answer: str = dspy.OutputField()
program = dspy.ChainOfThought(QA)
# Set up the optimizer
optimizer = BootstrapFewShot(
metric=exact_match_metric,
max_bootstrapped_demos=4, # Up to 4 few-shot examples per predictor
max_labeled_demos=4, # Use labeled examples directly if available
)
# Compile!
compiled_program = optimizer.compile(program, trainset=trainset)
print('Compilation complete')MIPRO 优化器
MIPRO(多提示词指令提议与优化)是一种更强大的优化器。它不仅会选择少样本示例,还会搜索要包含在提示词中的更佳指令文本。
MIPRO 在编译期间需要进行更多 LLM 调用,但通常能实现显著更高的准确率。
import dspy
from dspy.teleprompt import MIPROv2
class QA(dspy.Signature):
"""Answer factual questions."""
question: str = dspy.InputField()
answer: str = dspy.OutputField()
program = dspy.ChainOfThought(QA)
# MIPRO: optimizes both instructions AND few-shot examples
optimizer = MIPROv2(
metric=exact_match_metric,
auto='medium', # 'light' / 'medium' / 'heavy' for optimization budget
num_threads=4, # Parallel evaluation threads
)
compiled_program = optimizer.compile(
program,
trainset=trainset,
num_trials=20, # Number of candidate prompts to evaluate
)
print('MIPRO compilation complete')编译后的提示词是什么样的
编译后,DSPy 会将优化后的少样本示例嵌入提示词。您可以检查编译后程序的预测器来查看这些内容。
import dspy
# After compiling, inspect the optimized state
compiled_program = dspy.ChainOfThought('question -> answer')
# (Assume this was returned by optimizer.compile(...))
# Inspect the demos that were found
for demo in compiled_program.demos:
print('Input:', demo.question)
print('Reasoning:', demo.get('reasoning', 'N/A'))
print('Answer:', demo.answer)
print('---')
# Save the compiled state
compiled_program.save('compiled_qa_program.json')
print('Saved compiled program')teleprompter.compile() 接口
所有 DSPy 优化器都共享相同的 compile() 接口。这种一致性意味着您可以更换优化器,而无需修改程序代码。
from dspy.teleprompt import BootstrapFewShot, MIPROv2, COPRO
# All optimizers use the same interface:
# compiled = optimizer.compile(program, trainset=trainset)
# BootstrapFewShot: fast, uses successful traces as demos
opt1 = BootstrapFewShot(metric=exact_match_metric)
# MIPRO: slower, optimizes instructions too
opt2 = MIPROv2(metric=exact_match_metric, auto='light')
# COPRO: coordinate descent over instruction proposals
opt3 = COPRO(metric=exact_match_metric, depth=3)
# Swap between them with one line change:
compiled = opt1.compile(program, trainset=trainset)
# or: compiled = opt2.compile(program, trainset=trainset)BootstrapFewShotWithRandomSearch
BootstrapFewShotWithRandomSearch 会生成多个候选示例集,并在验证集上选择表现最佳的示例集,从而扩展 BootstrapFewShot 的功能。
这是一个很好的折中方案,兼具 BootstrapFewShot 的简单性和 MIPRO 的强大能力。
from dspy.teleprompt import BootstrapFewShotWithRandomSearch
# Split data into train and validation
trainset = examples[:40]
devset = examples[40:60]
optimizer = BootstrapFewShotWithRandomSearch(
metric=exact_match_metric,
max_bootstrapped_demos=4,
num_candidate_programs=8, # Try 8 different demo sets
num_threads=4,
)
compiled_program = optimizer.compile(
program,
trainset=trainset,
valset=devset, # Picks the best program based on validation
)
print('Best program selected from 8 candidates')编译成本注意事项
编译会进行额外的 LLM 调用,以生成和评估候选提示词。请相应地安排预算:
- BootstrapFewShot:LLM 调用次数约为训练集大小的 1–2 倍
- RandomSearch(8 个候选项):约为 8–10 倍
- MIPRO 中等规模:约为 30–50 倍
请离线运行编译,保存结果,然后部署已保存的程序。生产环境中的推理成本不会改变。
验证编译后的程序
编译后,请始终在留出的测试集上进行评估,以确认优化后的程序确实能够泛化。不要只检查训练集上的表现。
import dspy
# Evaluate on test set
evaluate = dspy.Evaluate(
devset=testset,
metric=exact_match_metric,
num_threads=4,
display_progress=True,
)
# Compare uncompiled vs compiled
uncompiled_score = evaluate(uncompiled_program)
compiled_score = evaluate(compiled_program)
print(f'Uncompiled accuracy: {uncompiled_score:.1%}')
print(f'Compiled accuracy: {compiled_score:.1%}')
print(f'Improvement: +{compiled_score - uncompiled_score:.1%}')整合起来
完整的 DSPy 优化流程是:定义 signature → 构建模块 → 准备训练数据 → 选择优化器 → 编译 → 评估 → 保存。这是从构想到可用于生产环境的优化提示词流水线的完整周期。
import dspy
from dspy.teleprompt import BootstrapFewShot
# 1. Configure LM
dspy.configure(lm=dspy.LM('openai/gpt-4o-mini', api_key='sk-...'))
# 2. Define signature and module
class QA(dspy.Signature):
"""Answer questions accurately."""
question: str = dspy.InputField()
answer: str = dspy.OutputField()
program = dspy.ChainOfThought(QA)
# 3. Compile
optimizer = BootstrapFewShot(metric=exact_match_metric)
compiled = optimizer.compile(program, trainset=trainset)
# 4. Save
compiled.save('production_qa.json')
print('Production program ready')知识检查:BootstrapFewShot
BootstrapFewShot 会使用训练集中的什么内容来改进编译后的提示词?
回顾:编译与优化
DSPy 优化使用指标函数和训练集搜索最佳提示词配置。BootstrapFewShot 从成功的轨迹中找出优质的少样本示例。MIPROv2 还会进一步搜索更佳的指令文本。所有优化器都共享 compile(program, trainset=...) 接口。编译是一次性的离线成本,请使用 program.save() 保存结果,然后部署优化后的程序,以便在推理时无需额外的优化开销。
常见问题解答
「编译与优化提示词」课时是免费的吗?
是的 — 「编译与优化提示词」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Prompt Engineering 课程的其余内容,请升级到 CoddyKit PRO。 AI Prompt Engineering 课程共包含 4 节课。
「编译与优化提示词」这节课中我会学到什么?
实际使用 BootstrapFewShot、MIPRO 及其他 DSPy 优化器。 你通过在浏览器中直接运行的动手代码来练习 AI Prompt Engineering,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Prompt Engineering 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Prompt Engineering 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「编译与优化提示词」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Prompt Engineering 课中编写并运行代码吗?
能。每节 AI Prompt Engineering 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- DSPy 框架简介
- 定义签名与模块
- 编译与优化提示词
- 评估 DSPy 流程