12. DSPy / TextGrad 这类"自动 Prompt 优化"框架是怎么工作的?

整理 DSPy、TextGrad 等自动化 prompt 优化框架的机制与适用场景。

简单回答

DSPy(Stanford)和 TextGrad(Stanford)这类框架的核心思路是把 prompt 工程从"人工调字符串"变成"用算法自动优化字符串"。DSPy 把 LLM 应用抽象成 可微分程序——每个调用是一个 module,整个 pipeline 像神经网络一样能被"训练"。它通过在评估集上反复调用 LLM,自动搜索最优的 instruction 文本和 few-shot 示例组合。TextGrad 更激进——把 LLM 输出的"自然语言反馈"当成梯度,反向传播优化 prompt。两者都试图把 prompt 工程从手艺变成科学,在指标明确的任务(数学、分类、抽取)上效果不错;但开放式任务、复杂多 agent 场景上仍有局限。

详细解释

手工 Prompt 的问题

传统 prompt 工程是手艺活——工程师写一个 prompt,跑测试,看结果,改 prompt,再跑。每次迭代靠直觉和经验。

这个流程的问题是:

主观性强:什么是"好 prompt"没有统一标准,很大程度看工程师感觉。 不可复现:同一个工程师两周后写的 prompt 可能和上次不一样。 搜索空间小:人工只能探索有限的 prompt 变体(一两天能试几十个)。 局部最优:很容易卡在某个版本上不再改进,但客观上有更好的 prompt 没被发现。 多 module 耦合复杂:复杂应用有多个 LLM 调用,每个 module 的 prompt 互相影响,人工调一个会破坏其他。

DSPy、TextGrad 等框架试图把这个流程自动化,让算法去搜索更好的 prompt。

DSPy 的核心抽象

DSPy 的核心理念:把 LLM 应用拆成一系列 Module,每个 module 有清晰的输入输出 Signature。整个程序像 PyTorch 神经网络一样可以被"编译"和"训练"。

例子,一个简单的 RAG 模块:

class RAG(dspy.Module):
    def __init__(self):
        self.retrieve = dspy.Retrieve(k=5)
        self.generate = dspy.ChainOfThought("context, question -> answer")

    def forward(self, question):
        context = self.retrieve(question).passages
        return self.generate(context=context, question=question)

这里 "context, question -> answer" 是 signature,告诉 DSPy 这个模块输入两个字段输出 answer。DSPy 内部会基于 signature 自动生成 prompt 模板。

关键的是 DSPy 的 Optimizer(之前叫 Teleprompter)。给定:

  • 一个 DSPy 程序(你写的 module 组合)
  • 一个评估指标(一个函数 (prediction, ground_truth) → score
  • 一组训练样本

Optimizer 会自动搜索每个 module 的最优 prompt——具体内容包括 instruction 文本、few-shot 示例的选择、推理模板等。

DSPy 内置几种 Optimizer:

BootstrapFewShot:从训练样本中筛出"模型自己解对的"作为 few-shot 示例。比手工选示例更有针对性。

MIPROv2:用 Bayesian optimization 在 instruction text 和 few-shot 示例的组合上搜索。能找出"什么样的 instruction 配什么样的示例最好"。

COPRO:用一个 LLM 生成多个 instruction 候选,在评估集上跑,选最好的。

调用时是这样:

teleprompter = dspy.MIPROv2(metric=my_metric)
optimized_program = teleprompter.compile(student=RAG(), trainset=trainset)

compile 完成后 optimized_program 就是被自动调优过的 RAG 模块——它的内部 prompt 已经被搜索到比初始版本好的形式。

DSPy 的实际效果

公开 benchmark 上 DSPy 优化后的程序通常比手工 prompt 提升 5-15 个百分点。在 HotpotQA、GSM8K、MultiHop QA 等任务上有可复现的提升数据。

更大的价值是 节省工程师时间 —— 工程师只需要写好 module 结构和评估指标,调 prompt 的工作交给 DSPy。一次 compile 可能跑几小时几百次 LLM 调用,但比工程师手工调几天更高效。

TextGrad 的核心思路

TextGrad(Stanford 的 Pranav Rajpurkar 团队)走了一条更激进的路。

它的灵感来自 PyTorch 的自动微分——既然神经网络的梯度可以从 loss 反向传播到参数更新,能不能在自然语言系统里做类似的事?

TextGrad 的回答是:用 LLM 生成的 自然语言反馈 当作"梯度"。

具体做法:

  1. 跑一遍 LLM 程序,得到输出
  2. 用一个 evaluator LLM 评价输出哪里不好("答案错在没考虑边界条件")
  3. 这段评价被当作 "loss"
  4. 用另一个 LLM 反向"求梯度"——分析"prompt 应该怎么改才能避免这个错误"
  5. 用一个 LLM 应用这个"梯度"——直接修改 prompt 的内容
  6. 用新 prompt 再跑一遍,循环几次直到性能达标

整个过程像在做"自然语言的反向传播"。每个 LLM 调用扮演 forward、loss、gradient、update 中的一环。

TextGrad 的优势是非常通用——任何任务只要能给评估反馈都能用。在医学诊断、代码优化、分子设计等领域有不错的实验结果。

两者的差异

DSPy 和 TextGrad 解决的问题相关但角度不同:

DSPy 偏向工程化:模块化设计、明确的 Signature、内置 optimizer。适合有 ground truth 的任务(分类、抽取、QA)。

TextGrad 偏向通用化:把整个 prompt 优化看作可微分流程。适合反馈是自然语言而不是数值指标的任务。

两者并不互斥——DSPy 可以用 TextGrad 风格的 LLM-as-evaluator 作为 metric,反过来 TextGrad 也能基于 DSPy 风格的模块化结构操作。

局限和适用边界

自动化 prompt 优化不是万能的:

需要明确的评估指标。如果你说不清"什么是好的回答",自动优化无从下手。开放式创意任务很难用 DSPy。

评估集质量决定上限。和模型训练一样,评估集烂了优化的方向就错了。需要有代表性的几百到几千条样本。

优化成本高。一次 DSPy compile 可能调用 LLM 几百到几千次,金钱和时间成本不低。中小项目可能算不过账。

优化结果可能 overfit。在评估集上极致优化但泛化差。需要 train/dev/test 分割(和 ML 一样)。

多 agent 复杂场景挑战大。Agent 系统里 module 之间动态决策、长 reasoning 链、tool calling,DSPy 当前对此支持不充分。

效果天花板还是模型本身。再优化的 prompt 也突破不了模型的能力上限。GPT-4 优化得好不会变成 GPT-5。

实际项目里怎么用

适合用自动 prompt 优化的场景:

  • 明确指标的任务:分类、抽取、QA、代码生成、数学。能用代码或 ground truth 自动评估。
  • 稳定的生产 pipeline:上了线持续运行的系统,prompt 优化的成本可以摊销在长期收益上。
  • 多 module 耦合的复杂程序:手工调一个 module 会破坏其他时,自动化优化能找到更好的整体平衡。
  • 工程师时间贵:算下来一次 compile 几百美元 LLM 费用比工程师调一周便宜。

不适合的场景:

  • 快速原型 / 一次性 demo:没几个调用就部署,自动优化的成本回不来。
  • 创意/开放式任务:评估指标不清晰,DSPy 没发挥空间。
  • prompt 频繁手动迭代的早期阶段:还在探索 prompt 长什么样的时候,自动优化可能限制思路。

工业落地案例

公开案例还不多,但已经看到一些:

  • JetBlue(航空公司):用 DSPy 优化客服 RAG,在文档问答上准确率提升 8-12 个点。
  • Databricks Compound AI:把 DSPy 集成到他们的 LLM 评估和优化平台。
  • 学术界用 DSPy 复现各种 SOTA prompt 工程论文,节省手工调参时间。

预计 2025 年会有更多大规模工业落地案例。

面试时可以这样答

DSPy 和 TextGrad 这类框架把 prompt 工程从手工调字符串变成算法自动优化。

DSPy 的核心抽象是把 LLM 应用拆成 module,每个 module 有清晰的 signature 输入输出。给定一个评估指标和训练样本,DSPy 的 optimizer 自动搜索每个 module 的最优 instruction 和 few-shot 示例。常用的 optimizer 包括 BootstrapFewShot(筛模型自己解对的样本作示例)、MIPROv2(Bayesian 搜索 instruction 和示例组合)、COPRO(LLM 生成多个 instruction 候选选最好的)。

TextGrad 更激进——把 LLM 生成的自然语言反馈当作梯度,整个 prompt 优化看作"自然语言的反向传播"。evaluator LLM 给评价当 loss、gradient LLM 分析 prompt 应该怎么改、update LLM 直接修改 prompt 内容、循环优化。优势是通用——任何能给反馈的任务都能用。

公开 benchmark 上 DSPy 优化通常提升 5-15 个百分点,更大价值是节省工程师时间,写好 module 和指标后调 prompt 的工作自动化。

局限明显。需要明确评估指标,开放式创意任务用不了。评估集质量决定上限。优化成本高,一次 compile 几百到几千次 LLM 调用。可能 overfit 到评估集要 train/dev/test 分割。多 agent 复杂场景当前支持不充分。效果天花板还是模型本身。

适合的场景是明确指标任务、稳定生产 pipeline、多 module 耦合复杂程序、工程师时间贵的项目。不适合快速原型、创意任务、还在探索 prompt 长什么样的早期阶段。

工业落地案例 JetBlue 用 DSPy 优化客服 RAG 提升 8-12 个点,Databricks 把 DSPy 集成到 LLM 评估平台。预计 2025 年会有更多大规模落地。

常见追问

  1. DSPy 的 BootstrapFewShot 怎么避免"用模型对的答案做示例"导致过拟合?
  2. TextGrad 的"自然语言梯度"是稳定的吗?同样的 loss 不同的 LLM 会给不同方向的"梯度"吗?
  3. 用 DSPy 优化好的 prompt 换模型后还有效吗?跨模型迁移性如何?