Doramagic 项目包 · 项目说明书
dspy 项目
DSPy:一个通过编程而非提示词来使用 LLM 的框架。
Core Programming Model: Signatures, Modules & Adapters
DSPy 框架的核心设计理念是"编程而非提示"——开发者通过组合 Python 模块来构建 AI 系统,而不是手工编写脆弱的提示字符串 (README.md)。这一抽象由三个紧密协作的核心概念支撑:Signature(签名)声明输入输出契约、Module(模块)封装可调用的计算单元、Adapter(适配器)负责把签名转换为 LM 实际消费的提示并把输出解析回结构化字段。它们...
继续阅读本节完整说明和来源证据。
概述 (Overview)
DSPy 框架的核心设计理念是"编程而非提示"——开发者通过组合 Python 模块来构建 AI 系统,而不是手工编写脆弱的提示字符串 (README.md)。这一抽象由三个紧密协作的核心概念支撑:Signature(签名)声明输入输出契约、Module(模块)封装可调用的计算单元、Adapter(适配器)负责把签名转换为 LM 实际消费的提示并把输出解析回结构化字段。它们共同把"模型调用"从一次性的字符串拼接,转化为可编译、可优化、可观察的 Python 程序。
Signatures — 声明式输入输出契约
Signature 是 DSPy 声明任务输入输出字段的基础结构。模块内部通过 Signature 类来表达"我需要哪些输入、要得到哪些输出",而字段类型则由 dspy.signatures.field 中的 OutputField 等构造器定义。DummyLM 在模拟 LM 输出时会按字段名格式化响应,例如:
[[## answer ##]]
red
(dspy/utils/dummies.py:40-58)。这种 [[## field_name ##]] 的标题约定与 chat_adapter.py 中的 field_header_pattern 正则共同保证:同一个签名既能被人阅读,也能被确定性解析。当签名字段未被正确定义类型时,会触发 IS_TYPE_UNDEFINED 常量所标记的特殊情形 (dspy/utils/constants.py)。
Modules — 可组合的程序单元
dspy.Module 是所有可执行单元的基类,前向传播通过 forward() 完成。框架通过 BaseCallback 提供对模块生命周期的钩子(on_module_start / on_module_end),从而支持优化器在编译期注入提示或示例 (dspy/utils/callback.py:1-40)。模块可嵌套组合:例如 dspy.Predict 是一个最常见的叶节点模块,其内部持有一个签名与一个适配器;上层模块(如 ReAct、ChainOfThought)则由多个 Predict 节点串联而成。社区对"Chat 模式"和"结构化输出"的支持请求(Issue #662、#1365)正是围绕这些模块的 forward() 路径展开的——当 LM 拒绝或解析失败时,模块需要决定回退策略。
Adapters — 提示格式化与字段解析
Adapter 是签名与具体 LM 调用之间的"翻译层"。基类位于 dspy/adapters/base.py,默认实现 ChatAdapter 在 dspy/adapters/chat_adapter.py 中定义,其核心职责有二:
- 格式化(Format):把签名字段渲染为 LM 可读的
[[## field ##]]标题块。DummyLM 通过_use_example复用已有对话中包含相同字段头的输出 (dspy/utils/dummies.py:88-100)。 - 解析(Parse):把 LM 文本回填到签名定义的字段。解析失败时抛出
AdapterParseError(继承自DSPyError)(dspy/utils/exceptions.py)。
下表汇总了三类组件的职责边界:
| 组件 | 关键文件 | 主要职责 |
|---|---|---|
| Signature | dspy/signatures/signature.py, dspy/signatures/field.py | 声明输入/输出字段及其语义提示 |
| Module | dspy/primitives/module.py, dspy/predict/predict.py | 组合签名与适配器,提供 forward() 调用入口 |
| Adapter | dspy/adapters/base.py, dspy/adapters/chat_adapter.py | 在签名与 LM 之间做格式化/解析 |
调用流程与可观察性
下图描绘了一次典型 DSPy 调用中三类组件的协作关系:
flowchart LR
User[用户输入] --> M[Module.forward]
M --> Sig[Signature: 输入/输出字段]
M --> P[dspy.Predict]
P --> A[Adapter: ChatAdapter]
A -- 格式化提示 --> LM[BaseLM / LiteLLM]
LM -- 原始文本 --> A
A -- 解析回字段或 AdapterParseError --> P
P --> H[dspy.history]
H --> IP[inspect_history.pretty_print_history]
CB[BaseCallback: on_module_start/end] -.-> M
CB2[BaseCallback: on_lm_start/end] -.-> A调用完成后,pretty_print_history 会把最近 n 条历史以人类可读形式渲染(支持 text、image_url、input_audio 等多模态内容),方便开发者调试提示模板 (dspy/utils/inspect_history.py)。框架同时把语言模型层的错误分为 LMProviderError、LMTimeoutError、LMContextWindowExceededError 等子类,并提供 is_retryable_lm_error 帮助上层模块决定是否重试 (dspy/utils/exceptions.py)。这种"分类型异常 + 回调 + 历史可观察"的设计,正是社区 Issue #338(流式输出)、#192(函数调用)等扩展请求能够安全落地的基础。
社区关切与边界
根据社区讨论,核心编程模型在以下方向仍在演进:
- 结构化输出:Issue #1365 推动 OpenAI Structured Outputs 与 Adapter 的深度集成,使得 JSON 解析回退链路更可靠。
- 流式 LM 输出:Issue #338 指出,模块会以任意顺序多次调用 LM,因此流式需要重新设计 Adapter 的增量解析契约。
- Chat 模式与函数调用:Issue #662 与 #192 反映了开发者希望在签名中直接表达"工具/函数"语义,而不是手工把它们塞进提示。
理解 Signatures / Modules / Adapters 的职责边界,是参与上述讨论与编写自定义适配器的前提。
参见 (See Also)
- DSPy 官方文档
- 优化器与 GEPA 提示优化:arxiv:2507.19457
- DSPy Assertions(计算约束自精炼):arxiv:2312.13382
来源:https://github.com/stanfordnlp/dspy / 项目说明书
Language Model Clients & Adapter Variants
DSPy 是一个"以编程代替提示"的基础模型框架,其核心理念是把 LM 调用抽象为可组合的 Python 模块 ([README.md:24-28]())。在这一架构里,语言模型 (LM) 客户端与适配器 (Adapter) 共同承担"用户代码 ↔ 各类 LLM 提供商"之间的桥接职责:客户端负责底层调用、错误分类与重试;适配器负责把声明式 Signature 渲染为不同模...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
DSPy 是一个"以编程代替提示"的基础模型框架,其核心理念是把 LM 调用抽象为可组合的 Python 模块 (README.md:24-28)。在这一架构里,语言模型 (LM) 客户端与适配器 (Adapter) 共同承担"用户代码 ↔ 各类 LLM 提供商"之间的桥接职责:客户端负责底层调用、错误分类与重试;适配器负责把声明式 Signature 渲染为不同模型所需的提示格式,并将模型输出解析回结构化字段。
本文聚焦于 LM 客户端与适配器配套的错误体系、测试替身、历史查看、回调系统以及外部工具互操作这五个支撑性子系统。
架构总览
下图展示了 LM 客户端、适配器、错误体系与回调系统在一次 DSPy 调用中的位置关系。
graph TB
A[用户代码 / dspy.Module] --> B[BaseLM / dspy.LM 客户端]
B --> C[Adapter 渲染与解析]
C --> D[Provider Backend]
D --> E[LiteLLM]
E --> F[OpenAI / Anthropic / 其他]
B -. 异常分类 .-> G[Error 体系]
B -. 生命周期 .-> H[Callback 系统]
C -. 解析失败 .-> I[AdapterParseError]错误处理体系
DSPy 通过 DSPyError 基类提供统一的结构化异常,所有 LM 异常均继承自 LMError,并通过 default_code 暴露稳定的错误码 (dspy/utils/exceptions.py:17-65)。基类还支持 model、provider、provider_code、status、request_id、retry_after 等结构化元数据,便于上层做分类与告警 (dspy/utils/exceptions.py:24-58)。
异常分类
| 异常类 | 语义 | default_code |
|---|---|---|
LMProviderError | 提供商返回错误响应 | provider |
LMAuthError | 身份认证失败 | auth |
LMContextWindowExceededError | 上下文窗口超出 | context_window_exceeded |
LMUnsupportedModelError | 模型不可用 | unsupported_model |
LMTimeoutError | 请求超时 | timeout |
LMServerError | 服务端失败 | server |
LMTransportError | 网络传输失败 | (由子类定义) |
LMUnexpectedError | 兜底未分类异常 | unexpected |
AdapterParseError | 适配器解析失败 | (独立) |
LMUnexpectedError 专门处理"既非已知 provider 错误又带 HTTP 状态码"的边界场景,避免被适配器当成解析错误 (dspy/utils/exceptions.py:67-76)。is_retryable_lm_error() 函数把"速率限制 + 超时 + 服务端 + 传输"四类纳入可重试集合 (dspy/utils/exceptions.py:124-134)。
社区讨论:issue #1365 与 #192 反映用户希望客户端原生支持 OpenAI Structured Outputs 与函数调用错误语义;issue #338 则讨论了 streaming 调用时如何重新分类错误。
测试与开发工具
DummyLM 继承自 BaseLM,提供三种工作模式 (dspy/utils/dummies.py:24-66):
- 字典列表模式:按调用顺序返回列表中的下一项,并用
ChatAdapter渲染字段; - 字典字典模式:以 prompt 末段为键查询对应输出;
- 示例跟随模式:通过
follow_examples与reasoning选项在历史中复用示例或注入推理内容。
默认适配器为 ChatAdapter (dspy/utils/dummies.py:88-95),使 DummyLM 能够如实模拟真实输出格式。pretty_print_history 工具以彩色方式打印最近 n 条 prompt/输出 (dspy/utils/inspect_history.py:25-30),并支持写入文件(自动关闭 ANSI 颜色)以及 tool_calls、image_url、input_audio 等多模态内容 (dspy/utils/inspect_history.py:35-66)。
外部工具互操作
适配器层提供与第三方工具生态的桥接函数,二者都使用 convert_input_schema_to_tool_args 作为统一入口:
- LangChain:
convert_langchain_tool将BaseTool转成 DSPyTool,内部把ainvoke包装为 async 函数 (dspy/utils/langchain_tool.py:18-25),并通过args_schema抽取参数名、类型与描述 (dspy/utils/langchain_tool.py:30-38)。 - MCP:
convert_mcp_tool把ClientSession与Tool包装成 DSPy 工具 (dspy/utils/mcp.py:33-46);_convert_mcp_tool_result规整CallToolResult,区分文本与非文本内容,并在isError=True时抛出RuntimeError(dspy/utils/mcp.py:9-31)。
社区讨论:issue #192 询问如何把 LangChain/LlamaIndex 的 function calling 迁移到 DSPy 工具体系;issue #662 关注 chat 模式下的提示格式兼容问题。
回调与基础设施
BaseCallback 定义了模块级与 LM 级的生命周期钩子:on_module_start/on_module_end 接收 call_id、instance 与 inputs/outputs,异常时携带 exception (dspy/utils/callback.py:13-37);on_lm_start/on_lm_end 在 LM __call__ 前后触发 (dspy/utils/callback.py:39-65),便于上层做日志、追踪或重试。
辅助层还包括:IS_TYPE_UNDEFINED 哨兵常量供适配器识别未声明类型字段 (dspy/utils/constants.py:3);print_message 为带时间戳的日志打印工具 (dspy/dsp/utils/utils.py:7-23);DPR_tokenize/strip_accents 提供检索/分词支持 (dspy/dsp/utils/dpr.py:51-82);_LazyModule 在首次属性访问时才真正 exec_module,避免重量级依赖阻塞导入 (dspy/utils/lazy_import.py:35-58)。
版本与变更
3.3.0b1 引入了 ReActV2 模块与新的 BaseLM 系统,并升级到 GEPA 0.1.1。LM 相关 API 在迭代中总体保持稳定,但异常类型与适配器解析失败语义存在微调,建议升级时关注 issue #390 的重构路线图以及 #338、#662 中提到的流式与 chat 格式问题。
See Also
来源:https://github.com/stanfordnlp/dspy / 项目说明书
Optimization & Compilation (Teleprompters)
在 DSPy 中,"Teleprompter" 是用于自动优化和编译声明式 LM 程序的组件。其核心思想是:开发者编写模块化的 Python 代码(由 dspy.Module 与 dspy.Signature 组成),由 Teleprompter 在小型训练集上自动搜索提示词、示范样例(demos)甚至模型权重,从而把"程序"编译成高质量的 LM pipeline。
继续阅读本节完整说明和来源证据。
一、概述:DSPy 中的"编译"概念
在 DSPy 中,"Teleprompter" 是用于自动优化和编译声明式 LM 程序的组件。其核心思想是:开发者编写模块化的 Python 代码(由 dspy.Module 与 dspy.Signature 组成),由 Teleprompter 在小型训练集上自动搜索提示词、示范样例(demos)甚至模型权重,从而把"程序"编译成高质量的 LM pipeline。
README 将 DSPy 定位为"编程而非提示"框架,并明确指出它提供"优化提示与权重的算法,无论你构建的是简单分类器、复杂 RAG 流水线还是 Agent 循环" README.md。Teleprompter 正是这一能力的承载体。
flowchart LR
A[声明式程序<br/>dspy.Module] --> B[Teleprompter<br/>优化器]
B --> C[训练集<br/>trainset]
B --> D[评估指标<br/>metric]
B --> E[优化后的程序<br/>compiled]
C --> B
D --> B
E --> F[推理部署]二、主流 Teleprompter 一览
DSPy 提供了多代优化器,覆盖从轻量随机搜索到基于反思的提示进化。下表汇总了仓库内置的核心 Teleprompter:
| 优化器 | 主要思路 | 适用场景 | 源码入口 |
|---|---|---|---|
BootstrapFewShot | 用程序自举生成示范,逐步填充 demos | 入门级、最常用 | bootstrap.py |
RandomSearch | 在自举候选池中随机采样多组 demos 并评估 | 轻量稳健基线 | random_search.py |
COPRO | 协作式提示优化,迭代生成候选指令 | 指令敏感任务 | copro_optimizer.py |
MIPROv2 | 多阶段贝叶斯式优化(指令 + 示范联合搜索) | 复杂多步程序 | mipro_optimizer_v2.py |
GEPA | 反思式提示进化,可与 RL 抗衡 | 需深度语义反思的任务 | gepa/gepa.py |
SIMBA | 简化智能体/模块微调与行为对齐 | Agent 风格模块 | simba.py |
社区中长期讨论的 OpenAI 结构化输出支持(Issue #1365)以及函数调用(Issue #192)能力,会通过 Adapter 层与 Teleprompter 协同:优化器评估候选指令时,会经过同一 Adapter 完成解析与校验 dspy/utils/exceptions.py。当底层 LM 不支持某特性时,会抛出 UnsupportedFeatureError,可由优化器捕获并回退到下一候选。
三、典型优化工作流
一次标准的 compile 调用通常包含以下阶段:
- 准备阶段:定义
dspy.Module(如ChainOfThought组合)、训练集(若干dspy.Example)、以及metric(可调用对象,返回分数或bool)。 - 实例化 Teleprompter:选择与任务规模匹配的优化器,例如
MIPROv2(metric=metric, auto="medium")。 - 执行编译:调用
teleprompter.compile(student=program, trainset=trainset),内部循环包含「提案 → LM 调用 → 评分 → 更新」四个动作。 - 回写程序:优化完成后,程序内部的
Signature指令、prompt 模板与 demos 被替换为最优候选;随后可直接用于推理。 - 可观测性:训练与评估期间,LM 历史可通过
pretty_print_history调试,模块与 LM 的生命周期事件由BaseCallback体系暴露 dspy/utils/callback.py,便于构建自定义评估器或早停逻辑。
四、常见使用模式与失败模式
- 从小到大:先以
BootstrapFewShot建立基线,再视需要升级到MIPROv2或GEPA,避免一开始就在小数据集上消耗大量算力。 - 指标设计:
metric是优化的目标函数,过于宽松会导致提示退化,过于严格则在 LLM-as-judge 下成本激增。建议先用DummyLM跑通管道,再切换到真实 LM dspy/utils/dummies.py。 - 多轮对话/Chat 模式:社区 Issue #662 关注 Chat 模型对 DSPy 默认格式的兼容性。在 Chat 场景下,应使用
ChatAdapter并显式声明dspy.configure(adapter=...),确保 Teleprompter 评估时使用一致的解析路径。 - 流式输出:Issue #338 讨论的 stream 能力目前主要影响推理阶段,对 Teleprompter 影响较小,因为优化阶段通常依赖完整响应以进行解析与打分。
- 结构化输出回退:当 Provider 拒绝 JSON schema 时,Teleprompter 抛出的
LMProviderError会携带provider_code、status等元数据,开发者可据此决定重试、降级到文本解析或更换 Adapter dspy/utils/exceptions.py。 - 实验性 API:部分新优化器(如 GEPA 0.1.1)通过
@experimental装饰器标记,使用前应在文档中确认其稳定性 dspy/utils/annotation.py。
五、与"编程式 LM"理念的关系
Teleprompter 是 DSPy"声明式自改进 Python"(Declarative Self-improving Python)这一名称中"自改进"二字的工程实现。它将手工调参迁移到算法搜索,使程序本身成为可被持续优化的对象——这也是 README 中强调"迭代构建模块化 AI 系统"的关键支撑。配合 dspy.Module 的可组合性、Adapter 的统一协议以及 BaseCallback 的可观测性,开发者可以在不重写业务逻辑的前提下,反复运行不同 Teleprompter 来持续提升程序质量。
See Also
- Signatures & Modules — 了解被优化的程序结构
- Adapters — 优化器与推理共用解析协议
- BaseLM & Providers — 优化器调用 LM 的统一入口
- Exception Handling — 处理优化过程中的 Provider 错误
来源:https://github.com/stanfordnlp/dspy / 项目说明书
Tools, Streaming, Retrieval & Utilities
DSPy 作为"声明式自改进 Python"框架,其核心能力不仅来自签名(Signature)和模块(Module),还依赖一套围绕 Tools(工具调用)、Streaming(流式 LM 输出)、Retrieval(检索)以及通用 Utilities(工具函数) 组成的辅助层。本页重点说明这些辅助模块的源码实现、典型使用方式以及与社区关注点的对应关系。
继续阅读本节完整说明和来源证据。
1. 概览与定位
DSPy 作为"声明式自改进 Python"框架,其核心能力不仅来自签名(Signature)和模块(Module),还依赖一套围绕 Tools(工具调用)、Streaming(流式 LM 输出)、Retrieval(检索)以及通用 Utilities(工具函数) 组成的辅助层。本页重点说明这些辅助模块的源码实现、典型使用方式以及与社区关注点的对应关系。
社区中的 #192 function calling 与 #338 Adding stream to DSPy LMs 长期是用户高互动话题;而 3.3.0b1 Release Notes 中提到的"fewer dependencies framework wide"也直接影响本页所讨论的 lazy import 机制。
来源:https://github.com/stanfordnlp/dspy / 项目说明书
失败模式与踩坑日记
保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。
假设不成立时,用户拿不到承诺的能力。
新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
风险会影响是否适合普通用户安装。
可能影响授权、密钥配置或安全边界。
Pitfall Log / 踩坑日志
项目:stanfordnlp/dspy
摘要:发现 9 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:能力坑 - 能力判断依赖假设。
1. 能力坑 · 能力判断依赖假设
- 严重度:medium
- 证据强度:source_linked
- 发现:README/documentation is current enough for a first validation pass.
- 对用户的影响:假设不成立时,用户拿不到承诺的能力。
- 证据:capability.assumptions | https://github.com/stanfordnlp/dspy | README/documentation is current enough for a first validation pass.
2. 维护坑 · 维护活跃度未知
- 严重度:medium
- 证据强度:source_linked
- 发现:未记录 last_activity_observed。
- 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
- 证据:evidence.maintainer_signals | https://github.com/stanfordnlp/dspy | last_activity_observed missing
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 证据:downstream_validation.risk_items | https://github.com/stanfordnlp/dspy | no_demo; severity=medium
4. 安全/权限坑 · 存在评分风险
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:风险会影响是否适合普通用户安装。
- 证据:risks.scoring_risks | https://github.com/stanfordnlp/dspy | no_demo; severity=medium
5. 安全/权限坑 · 来源证据:[Bug] (withdrawn) Module.save() JSON state + Retrieve.dump_state json_mode
- 严重度:medium
- 证据强度:source_linked
- 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:[Bug] (withdrawn) Module.save() JSON state + Retrieve.dump_state json_mode
- 对用户的影响:可能影响授权、密钥配置或安全边界。
- 证据:community_evidence:github | https://github.com/stanfordnlp/dspy/issues/9933 | 来源类型 github_issue 暴露的待验证使用条件。
6. 安全/权限坑 · 来源证据:[Feature] MCP guide — security agent over remote HTTP MCP servers (re #8957)
- 严重度:medium
- 证据强度:source_linked
- 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:[Feature] MCP guide — security agent over remote HTTP MCP servers (re #8957)
- 对用户的影响:可能影响授权、密钥配置或安全边界。
- 证据:community_evidence:github | https://github.com/stanfordnlp/dspy/issues/9922 | 来源类型 github_issue 暴露的待验证使用条件。
7. 安全/权限坑 · 来源证据:[Feature] Memory/retrieval poisoning defense via OWASP Agent Memory Guard
- 严重度:medium
- 证据强度:source_linked
- 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:[Feature] Memory/retrieval poisoning defense via OWASP Agent Memory Guard
- 对用户的影响:可能阻塞安装或首次运行。
- 证据:community_evidence:github | https://github.com/stanfordnlp/dspy/issues/9911 | 来源讨论提到 python 相关条件,需在安装/试用前复核。
8. 维护坑 · issue/PR 响应质量未知
- 严重度:low
- 证据强度:source_linked
- 发现:issue_or_pr_quality=unknown。
- 对用户的影响:用户无法判断遇到问题后是否有人维护。
- 证据:evidence.maintainer_signals | https://github.com/stanfordnlp/dspy | issue_or_pr_quality=unknown
9. 维护坑 · 发布节奏不明确
- 严重度:low
- 证据强度:source_linked
- 发现:release_recency=unknown。
- 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
- 证据:evidence.maintainer_signals | https://github.com/stanfordnlp/dspy | release_recency=unknown
来源:Doramagic 发现、验证与编译记录