跳到主要内容

DSPy:用编译后的 LLM 管道替换脆弱的提示工程

· 阅读需 7 分钟
Mike Thrift
Mike Thrift
Marketing Manager

在思考金融 AI 管道时,我总是遇到同样的问题:你可以构建一个在测试用例上运行良好的系统,但当供应商更改发票格式或出现新的交易类型时,它就会悄无声息地崩溃。这种脆弱性几乎总是存在于提示词中——那些没人想碰的手工编写的字符串。由斯坦福大学的 Khattab 等人引入并发表在 ICLR 2024 上的 DSPy,提出了一种根本不同的构建 LLM 管道的方法,值得任何试图自动化会计工作的人仔细关注。

论文解读

2026-05-11-dspy-compiling-declarative-language-model-calls-self-improving-pipelines

DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines (Khattab, Singhvi, Maheshwari et al., ICLR 2024) 将 LLM 管道构建重新定义为一个编程问题,而不是提示工程问题。其核心观察是,现代 LLM 应用通常被构建为硬编码提示字符串(作者称之为“提示模板”)的集合,并由 Python 控制流粘合在一起。当模型改变或任务分布发生偏移时,必须有人手动重写这些字符串。

DSPy 用两种抽象替换了提示模板:签名 (signatures)模块 (modules)。签名是对 LM 调用应执行操作的类型化声明式规范,可以简练地写成 question -> answer,或者在 Python 类中带有明确的字段描述。模块使用推理策略包装签名——如 ChainOfThoughtReActProgramOfThoughtMultiChainComparison 等。关键的补充是 编译器 (compiler)(论文中称为 teleprompter),它接收一个 DSPy 程序、一个小规模的标记数据集和一个验证指标,然后自动生成少样本示例,从中进行选择,并生成针对该指标优化的提示词。编译器不需要在每个中间步骤都有标签——它可以通过在未标记输入上运行教师程序并过滤产生正确最终输出的轨迹来引导 (bootstrap) 示例。

核心观点

  • 签名将意图与实现解耦。 编写 question, context -> answer 就足以让 DSPy 知道如何构造、调用和优化底层的 LM 调用。开发者无需编写提示字符串。
  • 编译是指标驱动的引导。 BootstrapFewShot 优化器在训练输入上运行程序,收集管道成功的输入输出轨迹,并将这些轨迹用作示例——无需人工标注中间推理步骤。
  • 编译器释放了小模型的能力。 在 GSM8K(数学应用题)上,原生 Llama2-13b 在零样本提示下的得分仅为 9.4%。经过带有反思和集成模块的 DSPy 编译后,得分达到了 46.9%。T5-Large(7.7 亿参数)是一个大多数人认为无法进行复杂推理的模型,在仅使用 200 个标记示例的情况下,在 HotPotQA 上实现了 39.3% 的答案完全匹配率。
  • 专家提示词不是上限。 在 GSM8K 上,GPT-3.5 使用原生的少样本提示达到 25.2%。专家精心编写的思维链将其提升至约 72–73%。而 DSPy 编译后的反思和集成管道将其推高至 81.6%——且无需人工编写任何提示词。
  • 程序化组合。 DSPy 中的多跳检索问答管道仅需约 12 行 Python 代码。作者指出,LangChain 中的等效实现包含 50 个超过 1000 字符的手工提示字符串。
  • 三个编译阶段。 优化器的运作流程为:候选生成(引导轨迹)、参数优化(通过随机搜索或 Optuna 调整超参数)和高阶优化(集成、动态控制流)。

哪些行得通——哪些行不通

实验结果是真实且显著的。使用 Llama2-13b 在 GSM8K 上从 9.4% 提升到 46.9%,同时仅使用少量的标记训练示例,这并非微小的改进——这种差距使得以前需要 GPT-4 的任务,现在用廉价的小模型也变得可行。该架构也非常优雅:签名易于阅读,模块可组合,且这种抽象在所演示的任务中并没有让人感到存在漏洞。

然而局限性也是真实的,尽管论文没有在专门的章节中讨论。最重要的一点是:编译器的好坏取决于你的指标。如果你的验证指标不精确或与实际任务质量不一致(这在实践中极其常见),优化器会找到各种巧妙的方法来最大化指标,但在你真正关心的事情上却失败了。在会计等结构化领域,你可能会定义一个诸如“分录平衡”之类的指标,但一个平衡的分录仍然可能使用了完全错误的账户代码。作者知道这个问题存在,但将其留给了开发者。

第二个局限性:编译仍然需要一些标记数据。论文声称你可以使用 BootstrapFewShot 配合少至 10 个示例,并且只需要输入值(不需要中间标签)。这在理想情况下是正确的,但在实践中,当初始程序无法解决任何训练示例时,引导的可靠性就会下降。如果你的金融智能体管道的基准准确率接近于零(这在你构建新系统时很常见),编译可能会原地打转。

第三,也是更微妙的一点:DSPy 优化了提示词和示例,但它并不优化 程序结构 本身。如果你以一种对于任务来说根本错误的方式将模块连接在一起,编译器也帮不了你。程序设计仍然由开发者负责。

为什么这对金融 AI 很重要

提示词的脆弱性可能是将金融 AI 智能体部署到生产环境中的最大实际障碍。一个通过将描述与账户代码匹配来对交易进行分类的管道,每当商家数据更改格式、每当出现新的支出类别、或每当会计科目表更新时,都会发生降级。使用 DSPy,你可以抽象地定义任务(transaction_description, chart_of_accounts -> account_code, confidence),并让编译器在每次分布偏移时计算出最优示例。

专门针对 Beancount,我可以预见一个由三个链式 DSPy 模块组成的管道:一个从原始银行导出数据中提取结构化交易数据,一个在账本现有的会计科目表中查找最佳匹配账户,还有一个根据复式记账约束验证生成的日记账分录。每个模块都有自己的签名;整个程序根据一个同时检查会计正确性和格式合规性的指标进行编译。指标质量问题在这里最为棘手——你需要一个能捕捉错误账户代码而不仅仅是不平衡分录的指标——但这是一个可以解决的工程问题。

更深层的含义是:DSPy 将工作重点从“编写更好的提示词”转向了“编写更好的指标和收集小型标记数据集”。对于一个需要随着法规、科目表结构和交易格式变化而演进的生产级金融系统来说,这是一种更具可持续性的工程实践。

延伸阅读

  • OPRO: Large Language Models as Optimizers (Yang et al., arXiv:2309.03409) —— Google DeepMind 通过迭代 LM 生成改进来优化提示的方法;是 DSPy 引导方法的一个有用对照。
  • TextGrad: Automatic "Differentiation" via Text (Yuksekgonul et al., arXiv:2406.07496) —— 将优化框架化为通过文本反馈进行的反向传播,而不是指标驱动的引导;在 DSPy 表现较弱的代码和科学任务上显示出强大的结果。
  • DSPy Assertions: Computational Constraints for Self-Refining Language Model Pipelines (Singhvi et al., arXiv:2312.13382) —— 为 DSPy 程序添加硬约束和软约束,允许管道在输出违反领域规则时进行自我纠正;与强制执行会计不变性直接相关。