Doramagic 项目包 · 项目说明书

dspy 项目

生成时间:2026-05-16 04:11:08 UTC

DSPy概述

DSPy(Declarative Self-Improving Python)是一个用于构建和优化基于语言模型(LM)复杂管道的框架。该框架由斯坦福NLP团队开发,旨在通过声明式编程范式简化大型语言模型应用的开发和优化过程。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 整体架构图

继续阅读本节完整说明和来源证据。

章节 核心组件层次

继续阅读本节完整说明和来源证据。

章节 Module基类

继续阅读本节完整说明和来源证据。

核心定位与价值

DSPy的核心价值在于将语言模型调用从硬编码的提示词转变为可声明式定义、可自动优化的程序组件。根据项目文档,DSPy能够"将声明式语言模型调用编译成自我改进的管道",这使得开发者可以专注于程序逻辑而非提示工程细节。

系统架构

整体架构图

graph TD
    A[用户程序] --> B[DSPy Module]
    B --> C[Signature定义]
    B --> D[Predict组件]
    B --> E[ChainOfThought组件]
    C --> F[InputField/OutputField]
    D --> G[语言模型 LM]
    E --> G
    G --> H[优化器 Teleprompter]
    H --> I[训练集 Trainset]
    I --> H
    H --> B
    G --> J[检索模型 RM]
    J --> K[外部知识库]

核心组件层次

层级组件说明
用户层DSPy Module自定义程序模块,继承dspy.Module
定义层Signature声明输入输出字段及其描述
执行层Predict/ChainOfThought执行语言模型调用
优化层Teleprompter自动优化提示和参数
集成层LM/RM Adapter支持多种语言模型和检索器

核心抽象

Module基类

DSPy的Module是所有程序组件的基类,提供了语言模型管理和预测组件发现功能:

class MyProgram(dspy.Module):
    def __init__(self):
        super().__init__()
        self.qa = dspy.Predict("question -> answer")
        self.summarize = dspy.Predict("text -> summary")

Module类提供以下关键方法:

方法功能资料来源
named_predictors()返回所有Predict组件的(名称, 实例)元组列表module.py:92-100
predictors()返回所有Predict实例的列表module.py:103-120
set_lm(lm)为所有Predict设置语言模型module.py:128-143
get_lm()获取当前使用的语言模型module.py:145-152

Signature系统

Signature用于声明模块的输入输出字段语义,是DSPy中连接程序逻辑与语言模型的关键抽象:

class MySignature(dspy.Signature):
    question: str = dspy.InputField(desc="用户问题")
    answer: str = dspy.OutputField(desc="模型回答")

Signature支持动态修改:

  • prepend(): 在输入字段前插入新字段
  • append(): 在输出字段后追加新字段
  • delete(): 删除指定字段

数据模型

Example类

dspy.Example是DSPy中用于表示训练样本和测试样本的核心数据结构:

example = dspy.Example(question="What is 2+2?", answer="4").with_inputs("question")

主要方法:

方法功能示例
with_inputs(*keys)标记输入字段.with_inputs("question")
inputs()获取仅包含输入字段的新Exampleexample.inputs()
labels()获取仅包含标签字段的新Exampleexample.labels()
toDict()递归转换为JSON友好字典example.toDict()
copy(**kwargs)创建副本并覆盖指定字段ex.copy(answer="5")
without(*keys)返回移除指定字段的副本ex.without("source")

资料来源:example.py:1-250

特殊类型

DSPy提供了多种适配不同场景的特殊数据类型:

#### History类型

用于会话历史管理,允许在提示中包含多轮对话上下文:

history = dspy.History(messages=[
    {"question": "法国的首都是什么?", "answer": "巴黎"},
    {"question": "德国的首都是什么?", "answer": "柏林"}
])

资料来源:history.py:1-60

#### Document类型

支持文档格式的数据,可用于检索增强生成(RAG)场景:

doc = Document(
    data="水的沸点是100°C",
    title="物理基础",
    context="标准大气压下"
)

资料来源:document.py:1-100

#### Citation类型

支持引用信息,用于需要标注来源的场景:

class Citations(dspy.Signature):
    documents: list[Document] = dspy.InputField()
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()
    citations: list[Citation] = dspy.OutputField()

资料来源:citation.py:1-80

回调系统

DSPy提供了灵活的回调机制用于监控和调试程序执行:

class LoggingCallback(dspy.Callback):
    def on_module_start(self, call_id, instance, inputs):
        print(f"Module started: {inputs}")
    
    def on_module_end(self, call_id, outputs):
        print(f"Module finished: {outputs}")
回调方法触发时机
on_module_start()Module的forward方法被调用时
on_module_end()Module的forward方法完成时
on_lm_start()语言模型开始生成时
on_lm_end()语言模型生成完成时

资料来源:callback.py:1-100

安装与使用

安装方式

pip install dspy

安装最新开发版本:

pip install git+https://github.com/stanfordnlp/dspy.git

资料来源:README.md:1-20

基础使用流程

graph LR
    A[定义Signature] --> B[创建Module]
    B --> C[配置LM]
    C --> D[准备Trainset]
    D --> E[编译优化]
    E --> F[执行预测]

Teleprompter优化系统

DSPy的优化器(Teleprompter)负责自动优化程序的提示和参数:

优化器用途
BootstrapFewShotWithRandomSearch小样本引导+随机搜索
BootstrapFinetune引导微调
BetterTogether组合优化策略

BetterTogether是一个典型的组合优化器,可同时执行提示优化(p阶段)和权重优化(w阶段):

optimizer = BetterTogether(
    metric=metric,
    p=GEPA(metric=metric, auto="medium"),
    w=BootstrapFinetune(metric=metric)
)

资料来源:bettertogether.py:1-100

嵌入与检索

Embedder组件

支持自定义嵌入函数和批量处理:

def my_embedder(texts):
    return np.random.rand(len(texts), 10)

embedder = dspy.Embedder(my_embedder)
embeddings = embedder(["hello", "world"], batch_size=1)

关键参数:

参数类型默认值说明
modelstr, Callable必填嵌入模型或函数
batch_sizeint200批处理大小
cachingboolTrue是否启用缓存

资料来源:embedding.py:1-100

检索器支持

DSPy支持多种检索器后端,包括Weaviate等向量数据库:

retriever_model = WeaviateRM("my_collection_name", weaviate_client=client)
dspy.configure(lm=llm, rm=retriever_model)

典型应用模式

问答系统

class QAModule(dspy.Module):
    def __init__(self):
        super().__init__()
        self.predict = dspy.Predict("question -> answer")
    
    def forward(self, question):
        return self.predict(question=question)

lm = dspy.LM("openai/gpt-4o-mini")
qa = QAModule()
qa.set_lm(lm)
result = qa(question="什么是DSPy?")

带推理链的问答

cot = dspy.ChainOfThought("question -> answer")
result = cot(question="1+1等于几?")

检索增强生成

retrieve = dspy.Retrieve(k=3)
passages = retrieve("机器学习基础").passages

开发环境配置

DSPy要求Python 3.10或更高版本。使用uv进行环境管理:

uv venv --python 3.10
uv sync --extra dev

运行测试:

uv run pytest tests/predict

资料来源:CONTRIBUTING.md:1-100

相关研究

DSPy基于以下核心研究论文:

  • [2025年7月] GEPA: Reflective Prompt Evolution Can Outperform Reinforcement Learning
  • [2024年6月] Optimizing Instructions and Demonstrations for Multi-Stage Language Model Programs
  • [2023年10月] DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines

总结

DSPy通过声明式编程范式和自动优化机制,大大简化了基于语言模型应用的开发流程。其核心组件包括:

  • Module系统:提供程序结构的统一抽象
  • Signature机制:声明式定义输入输出语义
  • Teleprompter优化器:自动化提示和参数优化
  • Adapter适配层:支持多种语言模型和工具集成

这套架构使得开发者可以专注于业务逻辑,而将提示工程的具体实现交给DSPy的优化系统自动处理。

资料来源:[example.py:1-250]()

安装与快速开始

DSPy(Declarative Self-Improving Language Model Programs)是一个用于编译声明式语言模型调用的框架,使语言模型程序能够自我改进。本节介绍如何安装 DSPy 框架以及如何快速上手使用该框架进行开发。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 使用 pip 安装(推荐)

继续阅读本节完整说明和来源证据。

章节 安装最新开发版本

继续阅读本节完整说明和来源证据。

章节 开发环境安装

继续阅读本节完整说明和来源证据。

概述

DSPy(Declarative Self-Improving Language Model Programs)是一个用于编译声明式语言模型调用的框架,使语言模型程序能够自我改进。本节介绍如何安装 DSPy 框架以及如何快速上手使用该框架进行开发。

DSPy 的设计理念是将语言模型调用声明化,通过优化器和签名系统自动优化提示和演示,从而提升程序性能。

环境要求

要求项最低版本说明
Python3.10+必须使用 Python 3.10 或更高版本
包管理器pip/uv用于安装 DSPy 包

资料来源:CONTRIBUTING.md:1

安装方式

使用 pip 安装(推荐)

通过 pip 直接安装稳定版本:

pip install dspy

资料来源:README.md:7

安装最新开发版本

如需安装最新的开发版本(从 main 分支),可使用以下命令:

pip install git+https://github.com/stanfordnlp/dspy.git

资料来源:README.md:12

开发环境安装

如需参与 DSPy 开发,推荐使用 uv 或 conda 进行环境管理。

#### 使用 uv 设置开发环境

git clone {url-to-your-fork}
cd dspy
uv sync

验证安装是否成功:

uv run pytest tests/predict

资料来源:CONTRIBUTING.md:20-45

#### 使用 conda 设置开发环境

conda create -n dspy-dev python=3.10
conda activate dspy-dev
pip install -e ".[dev]"

验证安装:

pytest tests/predict

资料来源:CONTRIBUTING.md:47-56

快速开始

基本概念

在使用 DSPy 之前,需要了解以下核心概念:

概念类名用途
示例dspy.Example表示训练或评估数据,包含输入字段和标签字段
模块dspy.Module自定义语言模型程序的基类
预测器dspy.Predict执行语言模型调用的核心组件
语言模型dspy.LM与各种语言模型提供商交互的接口

创建 Example 对象

Example 是 DSPy 中表示数据的基本单元。可以通过关键字参数创建:

import dspy

# 创建包含问题答案的示例
example = dspy.Example(question="1+1 等于多少?", answer="2")

资料来源:dspy/primitives/example.py:31-32

标记输入字段

使用 with_inputs() 方法标记哪些字段是输入字段:

example = dspy.Example(
    question="今天天气如何?",
    answer="晴天"
).with_inputs("question")

标记后,可以使用方法分离输入和标签:

example.inputs().toDict()  # {'question': '今天天气如何?'}
example.labels().toDict()  # {'answer': '晴天'}

资料来源:dspy/primitives/example.py:87-97

定义模块和预测器

创建一个简单的问答模块:

class SimpleQA(dspy.Module):
    def __init__(self):
        super().__init__()
        self.predict = dspy.Predict("question -> answer")
    
    def forward(self, question):
        return self.predict(question=question)

资料来源:dspy/primitives/module.py:1-50

设置语言模型

使用 set_lm() 方法为模块设置语言模型:

lm = dspy.LM("openai/gpt-4o-mini")
qa = SimpleQA()
qa.set_lm(lm)

资料来源:dspy/primitives/module.py:67-78

执行推理

设置好语言模型后,可以执行推理:

result = qa(question="法国的首都是什么?")
print(result.answer)

使用回调监控执行

DSPy 支持通过回调函数监控模块和语言模型的调用:

from dspy.utils.callback import BaseCallback

class LoggingCallback(BaseCallback):
    def on_module_start(self, call_id, instance, inputs):
        print(f"模块调用: {inputs}")
    
    def on_module_end(self, call_id, outputs):
        print(f"模块输出: {outputs}")

# 在语言模型中使用回调
lm = dspy.LM("gpt-3.5-turbo", callbacks=[LoggingCallback()])

资料来源:dspy/utils/callback.py:1-60

构建训练集

将多个 Example 组合成训练集用于优化:

trainset = [
    dspy.Example(question="2+2 等于多少?", answer="4").with_inputs("question"),
    dspy.Example(question="3+3 等于多少?", answer="6").with_inputs("question"),
]

资料来源:dspy/primitives/example.py:98-102

工作流程图

graph TD
    A[创建 Example 数据] --> B[定义 Module]
    B --> C[设置 Language Model]
    C --> D[执行推理]
    D --> E{是否需要优化?}
    E -->|是| F[创建训练集和验证集]
    F --> G[选择 Teleprompter 优化器]
    G --> H[编译优化程序]
    H --> I[使用优化后的程序]
    E -->|否| I
    I --> J[最终部署使用]

下一步

  • 了解更多 DSPy 核心概念,请参阅签名(Signature)文档
  • 学习高级优化技术,请参阅 Teleprompter 相关文档
  • 了解支持的语言模型提供商,请参阅 LM 配置文档

相关文档

文档说明
DSPy Docs官方完整文档
GEPA反思式提示进化算法论文
DSPy 论文框架核心论文

资料来源:[CONTRIBUTING.md:1]()

签名(Signatures)

签名(Signature)是 DSPy 框架中定义模块输入输出接口的核心抽象。一个签名描述了语言模型程序的输入字段(InputField)和输出字段(OutputField),以及附加的指令说明。签名作为 DSPy 程序的结构化蓝图,定义了数据如何流入和流出各个模块。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 字段类型

继续阅读本节完整说明和来源证据。

章节 签名结构

继续阅读本节完整说明和来源证据。

章节 主要方法

继续阅读本节完整说明和来源证据。

概述

签名(Signature)是 DSPy 框架中定义模块输入输出接口的核心抽象。一个签名描述了语言模型程序的输入字段(InputField)和输出字段(OutputField),以及附加的指令说明。签名作为 DSPy 程序的结构化蓝图,定义了数据如何流入和流出各个模块。

签名的主要作用包括:

  • 接口定义:明确指定模块的输入和输出字段
  • 提示词构建:自动生成结构化的提示词给语言模型
  • 数据验证:确保输入输出数据的结构正确性
  • 元编程支持:支持签名的动态组合、修改和转换

资料来源:dspy/signatures/signature.py

核心概念

字段类型

DSPy 提供两种基本字段类型来定义签名中的数据:

字段类型用途说明
InputField输入字段描述语言模型需要接收的输入数据
OutputField输出字段描述语言模型需要生成的输出数据

每个字段都可以通过 desc 参数添加描述文本,这些描述会被纳入提示词中,帮助语言模型理解字段的含义。

资料来源:dspy/signatures/field.py

签名结构

graph TD
    A[签名 Signature] --> B[instructions 说明]
    A --> C[fields 字段集合]
    C --> D[InputField 输入字段]
    C --> E[OutputField 输出字段]
    D --> F[field_name 字段名]
    D --> G[annotation 类型注解]
    D --> H[desc 描述文本]
    E --> F2[field_name 字段名]
    E --> G2[annotation 类型注解]
    E --> H2[desc 描述文本]

Signature 类 API

主要方法

方法名用途返回类型
with_instructions(instructions)创建带新指令的签名副本type[Signature]
with_updated_fields(name, **kwargs)更新指定字段的属性type[Signature]
prepend(name, field, type_=None)在签名开头插入新字段type[Signature]
append(name, field, type_=None)在签名末尾追加新字段type[Signature]
insert(pos, name, field, type_=None)在指定位置插入字段type[Signature]
delete(name)删除指定字段type[Signature]

资料来源:dspy/signatures/signature.py:1-200

with_instructions 方法

创建具有新指令文本的签名类副本:

class MySig(dspy.Signature):
    input_text: str = dspy.InputField(desc="Input text")
    output_text: str = dspy.OutputField(desc="Output text")

NewSig = MySig.with_instructions("Translate to French.")
# NewSig.instructions == "Translate to French."

此方法不会修改原签名,而是返回一个新的签名类。

资料来源:dspy/signatures/signature.py

with_updated_fields 方法

更新指定字段的元数据属性:

class MySig(dspy.Signature):
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()

UpdatedSig = MySig.with_updated_fields(
    "answer",
    desc="The final answer",
    prefix="Result: "
)

资料来源:dspy/signatures/signature.py

字段操作方法

graph LR
    A[原 Signature] -->|prepend| B[在开头插入]
    A -->|append| C[在末尾追加]
    A -->|insert| D[在指定位置]
    A -->|delete| E[删除字段]
    B --> F[new Signature]
    C --> F
    D --> F
    E --> F

prepend 方法 - 在输入字段部分的开头插入新字段:

NewSig = MySig.prepend("context", dspy.InputField(desc="Context for translation"))

append 方法 - 在输出字段部分的末尾追加新字段:

NewSig = MySig.append("confidence", dspy.OutputField(desc="Translation confidence"))

delete 方法 - 返回移除指定字段后的新签名:

NewSig = MySig.delete("unnecessary_field")

资料来源:dspy/signatures/signature.py

make_signature 函数

除了使用类语法定义签名外,DSPy 还提供了 make_signature 工具函数,支持多种签名定义格式:

函数签名

def make_signature(
    signature: str | dict,
    *,
    fresh_fields: bool = True,
    check_args: bool = True,
    custom_types: dict[str, type] | None = None,
) -> dict[str, FieldInfo]:

支持的格式

格式类型示例说明
字符串格式"question -> answer"使用 -> 分隔输入输出
字典格式{"question": str, "answer": str}键值对形式
元组格式{"q": (str, InputField())}指定类型和字段
# 字符串格式
sig1 = make_signature("question, context -> answer")

# 字典格式
sig2 = make_signature({
    "question": (str, InputField()),
    "answer": (str, OutputField())
})

# 使用自定义类型
class MyType:
    pass

sig3 = make_signature(
    "input: MyType -> output",
    custom_types={"MyType": MyType}
)

资料来源:dspy/signatures/utils.py

使用示例

基本用法

import dspy

class RAGSignature(dspy.Signature):
    """回答基于给定上下文的问题"""
    context: str = dspy.InputField(desc="用于回答问题的上下文信息")
    question: str = dspy.InputField(desc="需要回答的问题")
    answer: str = dspy.OutputField(desc="基于上下文得出的答案")

# 使用签名创建预测器
predict = dspy.Predict(RAGSignature)
result = predict(context="巴黎是法国的首都。", question="法国的首都是哪里?")
print(result.answer)  # 输出生成的答案

与 Example 类集成

签名与 Example 类紧密配合使用:

import dspy

# 创建带输入标记的示例
example = dspy.Example(
    question="What is 2+2?",
    answer="4"
).with_inputs("question")

# example.inputs() 返回只包含 question 的示例
# example.labels() 返回只包含 answer 的示例

资料来源:dspy/primitives/example.py

在模块中使用

签名可以被 DSPy 模块继承和组合:

import dspy

class MyModule(dspy.Module):
    def __init__(self):
        super().__init__()
        self.qa = dspy.Predict("question -> answer")
        self.summarize = dspy.Predict("text -> summary")
    
    def forward(self, question: str) -> dspy.Prediction:
        return self.qa(question=question)

资料来源:dspy/primitives/module.py

高级用法

动态签名构建

通过组合方法动态构建复杂签名:

base_sig = dspy.make_signature("input_text -> output_text")

# 链式调用添加字段
enhanced_sig = (
    base_sig
    .prepend("system_prompt", dspy.InputField(desc="系统提示词"))
    .append("confidence", dspy.OutputField(desc="置信度"))
)

class EnhancedPredictor(dspy.Signature):
    pass

EnhancedPredictor.__signature__ = enhanced_sig

签名字段更新

修改现有签名的字段描述:

original = dspy.make_signature("query -> result")

# 更新字段描述
refined = original.with_updated_fields(
    "query",
    desc="搜索查询词",
    prefix="查询: "
)
refined = refined.with_updated_fields(
    "result",
    desc="搜索结果",
    prefix="结果: "
)

最佳实践

1. 清晰的字段描述

为每个字段提供准确的 desc 描述,这会直接影响语言模型的理解和输出质量:

class GoodSignature(dspy.Signature):
    email_content: str = dspy.InputField(
        desc="完整的电子邮件内容,包括发件人、主题和正文"
    )
    sentiment: str = dspy.OutputField(
        desc="情感分类结果,必须是 'positive'、'negative' 或 'neutral' 之一"
    )

2. 类型注解

使用适当的类型注解可以增强代码可读性和 IDE 支持:

class TypedSignature(dspy.Signature):
    user_id: int = dspy.InputField(desc="用户唯一标识符")
    query: str = dspy.InputField(desc="用户查询文本")
    response: str = dspy.OutputField(desc="生成的响应文本")
    confidence: float = dspy.OutputField(desc="响应置信度,范围 0-1")

3. 签名组合策略

当构建复杂流水线时,考虑按功能拆分签名:

graph TD
    subgraph 预处理阶段
        A1[TextInput] --> A2[PreprocessedText]
    end
    subgraph 处理阶段
        A2 --> B1[AnalyzeText]
        B1 --> B2[AnalysisResult]
    end
    subgraph 生成阶段
        B2 --> C1[GenerateResponse]
        C1 --> C2[FinalOutput]
    end

相关模块

模块路径用途
signatures/signature.pydspy/signatures/signature.pySignature 类定义
signatures/field.pydspy/signatures/field.pyInputField 和 OutputField
signatures/utils.pydspy/signatures/utils.pymake_signature 工具函数
signatures/\_signature_do_not_use_directly.pydspy/signatures/内部实现

参考链接

资料来源:[dspy/signatures/signature.py](https://github.com/stanfordnlp/dspy/blob/main/dspy/signatures/signature.py)

内置模块参考

DSPy 内置模块是框架提供的核心组件,用于构建和执行语言模型程序。这些模块封装了常见的提示词工程模式,包括思维链推理、工具调用、并行处理等,使开发者能够以声明式的方式组合复杂的 LLM 应用。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 核心方法

继续阅读本节完整说明和来源证据。

章节 设置语言模型

继续阅读本节完整说明和来源证据。

章节 Predict

继续阅读本节完整说明和来源证据。

概述

DSPy 内置模块是框架提供的核心组件,用于构建和执行语言模型程序。这些模块封装了常见的提示词工程模式,包括思维链推理、工具调用、并行处理等,使开发者能够以声明式的方式组合复杂的 LLM 应用。

内置模块均继承自 dspy.Module 基类,提供了统一的接口和行为规范。每个模块都可以通过签名(Signature)定义输入输出字段,并支持与优化器(Teleprompter)配合使用进行自动优化。

资料来源:dspy/primitives/module.py:1-50

模块体系架构

DSPy 的内置模块遵循分层设计架构,核心模块为 Predict,其他高级模块在其基础上组合扩展。

graph TD
    A[dspy.Module 基类] --> B[Predict 基础模块]
    B --> C1[ChainOfThought 思维链]
    B --> C2[Parallel 并行预测]
    B --> C3[Retry 重试机制]
    B --> C4[BestOfN N选一]
    C1 --> D1[ReAct 推理+行动]
    C1 --> D2[ProgramOfThought 程序思维]
    C1 --> D3[MultiChainComparison 多链比较]
    D1 --> E[CodeAct 代码行动]
    B --> F[Refine 细化迭代]
    B --> G[RLM 推理语言模型]

资料来源:dspy/predict/predict.py

模块基类

dspy.Module 是所有内置模块的基类,提供了通用功能支持。

核心方法

方法名说明返回值
named_predictors()返回所有命名预测器元组列表list[tuple[str, Predict]]
predictors()返回所有 Predict 实例list[Predict]
set_lm(lm)为所有预测器设置语言模型None
get_lm()获取模块使用的语言模型LM 实例
map_named_predictors(func)对所有预测器应用转换函数self
inspect_history(n)查看最近 n 次 LM 调用历史None

设置语言模型

import dspy

lm = dspy.LM("openai/gpt-4o-mini")
program = dspy.Predict("question -> answer")
program.set_lm(lm)

资料来源:dspy/primitives/module.py:45-75

基础模块

Predict

Predict 是 DSPy 最核心的模块,用于基于签名执行语言模型调用。

#### 基本用法

import dspy

# 简单签名
predict = dspy.Predict("question -> answer")
result = predict(question="What is 1+1?")

# 使用类签名
class MySignature(dspy.Signature):
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()

predict = dspy.Predict(MySignature)

#### 初始化参数

参数类型说明默认值
signature`str \Signature`输入输出字段定义必填
lm`LM \None`语言模型实例None
remote_cache`dict \None`远程缓存字典None

资料来源:dspy/predict/predict.py

推理模块

ChainOfThought(思维链)

ChainOfThought 在 Predict 基础上自动加入推理步骤,要求模型先输出思考过程再给出最终答案。

#### 工作原理

  1. 修改签名,在输出字段前添加 reasoning 字段
  2. 生成提示词引导模型进行逐步推理
  3. 提取并返回最终答案
import dspy

cot = dspy.ChainOfThought("question -> answer")
result = cot(question="What is the capital of France?")
print(result.reasoning)  # 中间推理过程
print(result.answer)     # 最终答案

#### 继承链

Module -> Predict -> ChainOfThought

资料来源:dspy/predict/chain_of_thought.py

MultiChainComparison(多链比较)

MultiChainComparison 允许多个推理链并行执行,并对结果进行比较以选出最优答案。

#### 工作流程

graph TD
    A[输入问题] --> B1[推理链1]
    A --> B2[推理链2]
    A --> B3[推理链3]
    B1 --> C[比较结果]
    B2 --> C
    B3 --> C
    C --> D[最优答案]
import dspy

mcc = dspy.MultiChainComparison(n=3)
result = mcc(question="Explain quantum entanglement")

资料来源:dspy/predict/multi_chain_comparison.py

工具调用模块

ReAct(推理与行动)

ReAct 结合了推理(Reasoning)和行动(Acting)能力,支持模型使用工具与环境交互。

#### 特性

  • 支持定义自定义工具
  • 自动管理工具调用循环
  • 推理过程透明可见
import dspy

react = dspy.ReAct("question -> answer")
result = react(question="最新科技新闻有哪些?")

资料来源:dspy/predict/react.py

CodeAct(代码行动)

CodeAct 扩展了 ReAct 模式,专门用于生成和执行 Python 代码来解决复杂问题。

import dspy

code_act = dspy.CodeAct("problem -> solution")
result = code_act(problem="计算斐波那契数列前20项的和")

#### 执行流程

graph LR
    A[问题] --> B[生成代码]
    B --> C[执行代码]
    C --> D{结果正确?}
    D -->|是| E[返回结果]
    D -->|否| B

资料来源:dspy/predict/code_act.py

迭代优化模块

Refine(细化迭代)

Refine 通过迭代方式逐步细化答案,每次迭代基于前一次的结果进行调整。

import dspy

refine = dspy.Refine("question -> answer", max_iters=3)
result = refine(question="解释机器学习原理")

#### 迭代过程

  1. 初始化:生成初始答案
  2. 评估:检查当前答案质量
  3. 细化:根据反馈更新答案
  4. 重复:直到满足条件或达到最大迭代次数

资料来源:dspy/predict/refine.py

Retry(重试机制)

Retry 在预测失败时自动重试,并可选择性地向模型提供错误信息以引导修正。

import dspy

retry_predict = dspy.Retry("question -> answer")
result = retry_predict(question="What is 1+1?")

#### 重试策略

参数说明默认值
max_retries最大重试次数3
on_error错误处理回调内置格式化

资料来源:dspy/predict/retry.py

并行与选择模块

Parallel(并行预测)

Parallel 允许同时执行多个预测器,适合需要并行处理多种推理路径的场景。

import dspy

parallel = dspy.Parallel(
    dspy.Predict("input -> output_a"),
    dspy.Predict("input -> output_b"),
    dspy.ChainOfThought("input -> output_c")
)
results = parallel(input="some text")

资料来源:dspy/predict/parallel.py

BestOfN(N选一)

BestOfN 生成 N 个候选答案,并使用指定的选择标准选出最优结果。

import dspy

bon = dspy.BestOfN("question -> answer", n=5)
result = bon(question="最佳编程语言是什么?")

#### 选择机制

graph TD
    A[生成N个候选] --> B[应用评分函数]
    B --> C[排序候选结果]
    C --> D[返回最优答案]

资料来源:dspy/predict/best_of_n.py

Program of Thought

ProgramOfThought 采用代码作为中间推理表示,通过生成和执行 Python 代码片段来解决问题。

import dspy

pot = dspy.ProgramOfThought("problem -> answer")
result = pot(problem="求解微分方程 dy/dx = 2x")

#### 与 CodeAct 的区别

特性ProgramOfThoughtCodeAct
交互方式生成代码片段生成并执行完整代码
执行环境隔离的解释器完整 Python 环境
适用场景数学计算、逻辑推理复杂系统操作

资料来源:dspy/predict/program_of_thought.py

RLM(推理语言模型)

RLM 是底层的语言模型封装模块,提供对各种 LLM 提供商的统一接口。

import dspy

lm = dspy.LM("openai/gpt-4o-mini")
result = lm(question="What is the meaning of life?")

#### 支持的模型格式

资料来源:dspy/predict/rlm.py

模块导出清单

所有内置模块可通过 dspy.predict 命名空间访问:

模块导入路径说明
Predictdspy.Predict基础预测模块
ChainOfThoughtdspy.ChainOfThought思维链推理
CoTdspy.CoTChainOfThought 别名
ReActdspy.ReAct推理+行动
ProgramOfThoughtdspy.ProgramOfThought程序思维
MultiChainComparisondspy.MultiChainComparison多链比较
Paralleldspy.Parallel并行预测
Refinedspy.Refine迭代细化
BestOfNdspy.BestOfNN选一
CodeActdspy.CodeAct代码行动
Retrydspy.Retry重试机制

资料来源:dspy/predict/__init__.py

组合使用示例

构建复杂管道

import dspy

class MyProgram(dspy.Module):
    def __init__(self):
        super().__init__()
        self.cot = dspy.ChainOfThought("question -> reasoning, answer")
        self.refine = dspy.Refine("initial_answer -> refined_answer")
        self.verify = dspy.Predict("question, answer -> is_correct")
    
    def forward(self, question):
        cot_result = self.cot(question=question)
        refined = self.refine(initial_answer=cot_result.answer)
        verification = self.verify(question=question, answer=refined.refined_answer)
        return {
            "reasoning": cot_result.reasoning,
            "answer": refined.refined_answer,
            "verified": verification.is_correct
        }

program = MyProgram()
result = program(question="What is the square root of 144?")

与优化器结合

from dspy.teleprompt import BootstrapFewShot

# 使用内置模块构建程序
student = dspy.ChainOfThought("question -> answer")

# 编译优化
optimizer = BootstrapFewShot(metric=your_metric)
compiled = optimizer.compile(student, trainset=trainset)

最佳实践

1. 选择合适的模块

场景推荐模块
简单问答Predict
需要推理过程ChainOfThought
多角度分析MultiChainComparison
需要工具交互ReAct
代码生成执行CodeAct / ProgramOfThought
提高可靠性Retry / BestOfN

2. 性能考虑

  • Parallel 适用于可并行的独立任务
  • BestOfN 会增加 N 倍的 API 调用,应根据延迟要求选择
  • Refinemax_iters 参数需权衡质量与成本

3. 调试技巧

# 检查模块的 LM 调用历史
program.inspect_history(n=5)

# 查看当前使用的语言模型
lm = program.get_lm()

# 批量替换预测器
program.map_named_predictors(lambda p: dspy.Retry(p.signature))

资料来源:dspy/primitives/module.py:90-120

资料来源:[dspy/primitives/module.py:1-50](https://github.com/stanfordnlp/dspy/blob/main/dspy/primitives/module.py)

原语与数据结构

DSPy 框架的原语(Primitives)与数据结构构成了整个框架的核心抽象层。这些基础组件定义了如何表示数据、执行程序、管理模块间的通信,以及实现代码的沙箱执行能力。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 Example 类

继续阅读本节完整说明和来源证据。

概述

DSPy 框架的原语(Primitives)与数据结构构成了整个框架的核心抽象层。这些基础组件定义了如何表示数据、执行程序、管理模块间的通信,以及实现代码的沙箱执行能力。

DSPy 的原语系统主要包括以下几个核心组件:

组件文件路径职责
Exampledspy/primitives/example.py数据样本表示与输入/输出字段管理
Predictiondspy/primitives/prediction.py程序执行结果的容器
Moduledspy/primitives/module.py所有 DSPy 程序的基类
PythonInterpreterdspy/primitives/python_interpreter.pyPython 代码的安全执行环境
CodeInterpreterdspy/primitives/code_interpreter.py代码解释器与 REPL 支持

资料来源:dspy/primitives/__init__.py

核心数据结构

Example 类

Example 是 DSPy 中用于表示数据样本的基础数据结构,类似于字典但提供了更丰富的语义支持。

#### 基本功能

import dspy

# 创建 Example 实例
example = dspy.Example(question="巴黎是哪国的首都?", answer="法国").with_inputs("question")

# 访问字段
print(example.question)  # 输出: 巴黎是哪国的首都?
print(example.answer)    # 输出: 法国

#### 字段分类系统

Example 类通过 with_inputs() 方法将字段分为两类:

  • 输入字段(Inputs):程序执行时需要提供的外部数据
  • 标签字段(Labels):期望的输出结果,用于评估和训练
# 使用 inputs() 和 labels() 方法分离字段
input_fields = example.inputs()    # 只包含 question
label_fields = example.labels()    # 只包含 answer

资料来源:dspy/primitives/example.py:1-200

#### 常用方法

方法功能返回类型
with_inputs(*keys)标记输入字段Example
inputs()获取输入字段子集Example
labels()获取标签字段子集Example
copy(**kwargs)创建带修改的副本Example
without(*keys)移除指定字段Example
toDict()转换为字典格式dict
get(key, default)安全获取字段值任意类型
keys() / values() / items()字典式访问list

#### 序列化支持

toDict() 方法支持递归序列化,能够处理嵌套的 Example 对象、Pydantic 模型、列表和字典,确保输出为 JSON 友好的格式:

def convert_to_serializable(value):
    if hasattr(value, "toDict"):
        return value.toDict()
    elif isinstance(value, BaseModel):
        return value.model_dump()
    elif isinstance(value, list):
        return [convert_to_serializable(item) for item in value]
    elif isinstance(value, dict):
        return {k: convert_to_serializable(v) for k, v in value.items()}

资料来源:dspy/primitives/example.py:80-120

资料来源:[dspy/primitives/__init__.py]()

优化器详解

DSPy 的优化器(Optimizer,亦称 Teleprompter)是框架的核心组件,负责自动优化程序中的提示词(Prompt)和演示示例(Demos),以提升语言模型在特定任务上的表现。优化器通过编译(Compile)过程,将声明式的 DSPy 程序转换为经过优化的自改进流水线。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 优化器继承体系

继续阅读本节完整说明和来源证据。

章节 核心编译流程

继续阅读本节完整说明和来源证据。

章节 1. BootstrapFewShotWithRandomSearch

继续阅读本节完整说明和来源证据。

概述

DSPy 的优化器(Optimizer,亦称 Teleprompter)是框架的核心组件,负责自动优化程序中的提示词(Prompt)和演示示例(Demos),以提升语言模型在特定任务上的表现。优化器通过编译(Compile)过程,将声明式的 DSPy 程序转换为经过优化的自改进流水线。

DSPy 优化器的工作机制遵循"Bootstrap"范式:先用初始配置运行程序,收集失败的案例,再利用语言模型自动生成改进的提示词或演示示例,如此迭代优化直到达到满意的性能水平。 资料来源:dspy/teleprompt/bettertogether.py

架构设计

优化器继承体系

所有 DSPy 优化器均继承自 dspy.teleprompt.Teleprompter 基类。基类定义了 compile() 接口,各子类实现具体的优化策略。

graph TD
    A[Teleprompter 基类] --> B[BootstrapFewShot]
    A --> C[BootstrapFewShotWithRandomSearch]
    A --> D[BootstrapFinetune]
    A --> E[MIPROv2]
    A --> F[GEPA]
    A --> G[BetterTogether]
    A --> H[Ensemble]
    A --> I[COPRO]
    A --> J[KNNFewShot]
    A --> K[SimBA]
    A --> L[GRPO]
    
    G --> |组合多个优化器| M[元优化器]

核心编译流程

graph LR
    A[Program] --> B[初始化运行]
    B --> C[收集轨迹]
    C --> D{评估指标}
    D --> |未达标| E[生成候选]
    E --> F[评估候选]
    F --> G[选择最优]
    G --> D
    D --> |达标| H[优化后程序]

内置优化器详解

1. BootstrapFewShotWithRandomSearch

这是 DSPy 中最基础的优化器,结合了 Bootstrap 演示生成和随机搜索策略。它会生成多个候选配置(不同的提示词和演示组合),然后在验证集上评估选择最优方案。 资料来源:dspy/teleprompt/random_search.py

#### 核心参数

参数类型说明默认值
metricCallable评估指标函数,签名 metric(example, pred, trace) -> bool必填
max_bootstrapped_demosint每个预测模块最多保留的演示数量4
max_roundsint最大优化轮次1
num_candidatesint随机搜索的候选数量10
num_threadsint并行线程数1

#### 使用示例

import dspy

# 定义评估指标
def metric(example, pred, trace=None):
    return example.answer.lower() == pred.answer.lower()

# 创建优化器
optimizer = BootstrapFewShotWithRandomSearch(
    metric=metric,
    max_bootstrapped_demos=4,
    num_candidates=10
)

# 编译程序
compiled_program = optimizer.compile(
    student=program,
    trainset=trainset,
    valset=valset
)

2. BootstrapFinetune

BootstrapFinetune 是 DSPy 的微调优化器,通过 Bootstrap 生成的优质数据对语言模型进行微调。它先生成高质量的演示示例,然后利用这些数据对轻量级语言模型进行微调。 资料来源:dspy/teleprompt/bootstrap_finetune.py

#### 核心参数

参数类型说明默认值
metricCallable评估指标函数必填
teacher_settingsdict教师模型的设置None
finetune_settingsdict微调设置(如训练轮数、学习率){}
max_bootstrapped_demosintBootstrap 演示数量上限8

3. MIPROv2 (Multi-Instruction Prompt Optimization v2)

MIPROv2 是先进的提示优化器,采用贝叶斯优化策略同时优化指令和演示。它通过考虑指令与演示之间的交互作用,实现更高效的提示词优化。 资料来源:dspy/teleprompt/mipro_optimizer_v2.py

#### 核心参数

参数类型说明默认值
metricCallable评估指标函数必填
num_trialsint贝叶斯优化试验次数20
max_bootstrapped_demosint演示数量上限4
num_examplesint每轮使用的训练样本数200
autostr自动模式级别:"light"、"medium"、"heavy"None
bootstrap_dataset_sizeintBootstrap 数据集大小None

#### 优化策略

MIPROv2 的核心创新在于将指令优化与演示选择联合考虑:

graph TD
    A[贝叶斯优化器] --> B[指令提议器]
    A --> C[演示采样器]
    B --> D[候选指令集合]
    C --> E[候选演示集合]
    D --> F[笛卡尔积组合]
    E --> F
    F --> G[评估函数]
    G --> H[更新贝叶斯模型]
    H --> A

4. GEPA (Generalized Evolved Prompt Agent)

GEPA 是基于进化算法的提示优化器,通过反思性提示进化策略实现自动优化。它在多阶段语言模型程序的优化中表现出色。 资料来源:dspy/teleprompt/gepa/gepa.py

#### 核心参数

参数类型说明默认值
metricCallable评估指标函数必填
autostr自动模式:"light"、"medium"、"full"None
num_prompt_instructionsint基础指令数量10
max_bootstrap两会intBootstrap 演示上限4

5. BetterTogether (元优化器)

BetterTogether 是 DSPy 的元优化器框架,可以将多个优化器组合成流水线。它支持自定义优化器组合策略,实现复杂的优化流程。 资料来源:dspy/teleprompt/bettertogether.py

#### 设计理念

BetterTogether 将优化过程分解为两个阶段:

  1. 提示优化阶段 (Prompt Optimization, p):优化指令和提示词
  2. 权重优化阶段 (Weight Optimization, w):通过 Bootstrap Finetune 优化权重

#### 使用示例

from dspy.teleprompt import BetterTogether, MIPROv2, BootstrapFinetune

# 方式一:使用自定义优化器组合
optimizer = BetterTogether(
    metric=metric,
    p=MIPROv2(metric=metric, auto="medium"),
    w=BootstrapFinetune(metric=metric)
)

# 方式二:使用默认优化器
optimizer = BetterTogether(metric=metric)

# 编译并指定策略
compiled = optimizer.compile(
    student=program,
    trainset=trainset,
    valset=valset,
    strategy="p -> w"  # 提示优化后接权重优化
)

#### 策略配置

策略字符串说明
"p"仅执行提示优化
"w"仅执行权重优化
"p -> w"先提示优化后权重优化
"w -> p"先权重优化后提示优化
"p -> w -> p"交替优化

6. COPRO (Coordinate Prompt Optimization)

COPRO 是一种协同提示优化方法,通过分析程序结构来优化各个模块的提示词。 资料来源:dspy/teleprompt/copro_optimizer.py

7. SimBA (Simple Bootstrap Agent)

SimBA 是轻量级的 Bootstrap 优化器,适用于资源受限场景。它简化了优化流程,同时保持较好的优化效果。 资料来源:dspy/teleprompt/simba.py

8. KNNFewShot (K-Nearest Neighbors Few-Shot)

KNNFewShot 利用 K 近邻算法为每个测试样本选择最相关的演示示例,实现动态演示选择。 资料来源:dspy/teleprompt/knn_fewshot.py

9. Ensemble

Ensemble 优化器通过集成多个不同配置的预测模块来提升整体性能,适用于需要高稳定性的生产环境。 资料来源:dspy/teleprompt/ensemble.py

10. GRPO (Group Relative Policy Optimization)

GRPO 是一种基于强化学习的优化方法,通过组内相对策略优化来提升语言模型程序性能。 资料来源:dspy/teleprompt/grpo.py

优化器选择指南

graph TD
    A[开始选择] --> B{场景类型}
    B -->|快速原型开发| C[BootstrapFewShotWithRandomSearch]
    B -->|高质量演示| D[BootstrapFinetune]
    B -->|联合优化| E[MIPROv2]
    B -->|进化策略| F[GEPA]
    B -->|复杂流水线| G[BetterTogether]
    B -->|动态演示| H[KNNFewShot]
    B -->|集成预测| I[Ensemble]
    
    C --> J[性能基准]
    D --> J
    E --> J
    F --> J
    G --> J
    H --> J
    I --> J

场景推荐

场景推荐优化器理由
快速实验BootstrapFewShotWithRandomSearch配置简单、速度快
资源充足追求最优MIPROv2贝叶斯优化效果好
多阶段流水线GEPA / BetterTogether支持复杂优化策略
边缘部署SimBA轻量级实现
高稳定性需求Ensemble多模型集成

Teleprompter 基类接口

所有优化器都实现以下核心接口:

class Teleprompter:
    def compile(
        self,
        student: Module,
        *,
        trainset: list[Example],
        valset: list[Example] = None,
        **kwargs
    ) -> Module:
        """编译学生程序"""
        raise NotImplementedError

compile 方法参数

参数类型必填说明
studentModule待优化的 DSPy 程序
trainsetlist[Example]训练数据集
valsetlist[Example]验证数据集,部分优化器需要
max_bootstrapped_demosintBootstrap 演示上限
max_roundsint最大优化轮次
num_threadsint并行线程数

评估指标设计

优化器依赖高质量的评估指标函数。指标函数应满足以下签名:

def metric(example: Example, pred: Prediction, trace=None) -> bool | float:
    """
    参数:
        example: 测试样本
        pred: 模型预测结果
        trace: 轨迹信息(可选,用于 Bootstrap 过程
    返回:
        bool 或 float: 评估结果
    """

指标函数示例

# 精确匹配指标
def exact_match(example, pred, trace=None):
    return example.answer.lower().strip() == pred.answer.lower().strip()

# 带权重的复合指标
def weighted_metric(example, pred, trace=None):
    exact = example.answer.lower() == pred.answer.lower()
    confidence = pred.get("confidence", 1.0)
    return exact * confidence

# 使用 trace 信息(用于 Bootstrap)
def bootstrap_metric(example, pred, trace):
    if trace is None:
        return example.answer.lower() == pred.answer.lower()
    # Bootstrap 过程中可使用更多上下文信息
    return int(trace.get("cost", 1)) < 10

最佳实践

1. 数据集划分

# 正确划分数据集
trainset = [example.with_inputs("question") for example in train_examples]
valset = [example.with_inputs("question") for example in val_examples]

# 确保 valset 有足够的样本用于可靠评估
assert len(valset) >= 20, "验证集应至少包含 20 个样本"

2. 指标设计原则

  • 可量化:指标应能客观衡量输出质量
  • 稳定可靠:多次运行应产生一致结果
  • 与任务目标一致:指标应反映实际业务需求

3. 优化器配置建议

配置项建议值说明
max_bootstrapped_demos4-8过多演示可能增加上下文负担
num_trials (MIPROv2)20-50试验次数越多效果越好但耗时增加
num_candidates10-20候选数量影响搜索空间大小

4. 性能调优

# 使用并行化加速
optimizer = BootstrapFewShotWithRandomSearch(
    metric=metric,
    num_threads=8  # 利用多核 CPU
)

# 控制资源使用
optimizer = MIPROv2(
    metric=metric,
    num_trials=20,  # 限制试验次数
    num_examples=100  # 限制样本数
)

常见问题

Q1: 优化器编译失败怎么办?

检查以下几点:

  1. 确认 metric 函数签名正确且可调用
  2. 确保 trainsetvalset 非空且格式正确
  3. 验证 Example 对象已通过 with_inputs() 设置输入字段

Q2: 如何选择合适的优化器?

参考"优化器选择指南"章节,从场景复杂度、可用资源和性能要求三个维度考量。

Q3: 优化后的性能不理想怎么办?

  • 尝试更换优化器类型
  • 调整优化器参数(如增加试验次数)
  • 改进评估指标函数
  • 检查数据集质量和规模

Q4: 如何调试优化过程?

import logging
logging.basicConfig(level=logging.INFO)

# 启用详细输出
optimizer = MIPROv2(metric=metric, verbose=True)

参考链接

来源:https://github.com/stanfordnlp/dspy / 项目说明书

语言模型客户端

DSPy 的语言模型客户端是框架与各种大语言模型(LLM)交互的核心抽象层。它提供了统一的接口,使开发者能够通过简洁的 API 调用不同的语言模型提供商,同时支持缓存、回调、批处理等高级功能。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 模块层次结构

继续阅读本节完整说明和来源证据。

章节 核心组件

继续阅读本节完整说明和来源证据。

章节 基本初始化

继续阅读本节完整说明和来源证据。

概述

DSPy 的语言模型客户端是框架与各种大语言模型(LLM)交互的核心抽象层。它提供了统一的接口,使开发者能够通过简洁的 API 调用不同的语言模型提供商,同时支持缓存、回调、批处理等高级功能。

语言模型客户端在 DSPy 架构中扮演着至关重要的角色:它被 dspy.Module 中的预测器(如 dspy.Predictdspy.ChainOfThought 等)调用,为整个程序提供推理能力。

架构设计

模块层次结构

DSPy 的语言模型客户端采用分层架构设计:

graph TD
    A[dspy.LM 统一入口] --> B[BaseLM 抽象基类]
    B --> C[OpenAI 客户端]
    B --> D[LiteLLM 客户端]
    B --> E[Databricks 客户端]
    B --> F[Local LM 客户端]
    G[Embedding 嵌入客户端] --> H[Embedder 类]
    G --> I[缓存层 Cache]

核心组件

组件文件路径职责
dspy.LMdspy/clients/lm.py统一入口,支持多种模型提供商
BaseLMdspy/clients/base_lm.py抽象基类,定义接口规范
OpenAIdspy/clients/openai.pyOpenAI API 专用客户端
_LiteLLMdspy/clients/_litellm.pyLiteLLM 封装,支持 100+ 模型
Databricksdspy/clients/databricks.pyDatabricks 模型服务
LocalLMdspy/clients/lm_local.py本地部署模型
Embedderdspy/clients/embedding.py文本嵌入模型客户端
Cachedspy/clients/cache.py请求缓存管理
Providerdspy/clients/provider.py模型提供商配置

使用方式

基本初始化

import dspy

# 使用 OpenAI 模型
lm = dspy.LM("openai/gpt-4o-mini")

# 使用本地模型
lm = dspy.LM("ollama/llama3")

# 配置回调函数
from dspy.utils.callback import LoggingCallback
lm = dspy.LM("gpt-3.5-turbo", callbacks=[LoggingCallback()])

在模块中使用

语言模型客户端通过 dspy.Moduleset_lm() 方法与预测器关联:

import dspy

class MyProgram(dspy.Module):
    def __init__(self):
        super().__init__()
        self.predict = dspy.Predict("question -> answer")
    
    def forward(self, question):
        return self.predict(question=question)

# 创建程序并设置语言模型
lm = dspy.LM("openai/gpt-4o-mini")
program = MyProgram()
program.set_lm(lm)

获取模块当前使用的语言模型:

current_lm = program.get_lm()

Embedder 嵌入客户端

Embedder 类是 DSPy 中用于处理文本嵌入的专用客户端,支持自定义嵌入函数和多种模型。

核心参数

参数类型默认值说明
model`str \Callable`-模型名称或自定义嵌入函数
batch_sizeint200批处理大小
cachingboolTrue是否启用缓存
**kwargsdict-传递给模型的额外参数

使用示例

import dspy
import numpy as np

# 示例 1:使用预定义模型
embedder = dspy.Embedder("openai/text-embedding-3-small")
embeddings = embedder(["hello", "world"], batch_size=1)
assert embeddings.shape == (2, 1536)

# 示例 2:使用自定义函数
def my_embedder(texts):
    return np.random.rand(len(texts), 10)

embedder = dspy.Embedder(my_embedder)
embeddings = embedder(["hello", "world"], batch_size=1)
assert embeddings.shape == (2, 10)

内部处理流程

Embedder_preprocess() 方法负责输入预处理:

def _preprocess(self, inputs, batch_size=None, caching=None, **kwargs):
    # 1. 处理单个字符串输入
    if isinstance(inputs, str):
        is_single_input = True
        inputs = [inputs]
    else:
        is_single_input = False
    
    # 2. 验证所有输入为字符串
    if not all(isinstance(inp, str) for inp in inputs):
        raise ValueError("All inputs must be strings.")
    
    # 3. 合并默认参数与自定义参数
    batch_size = batch_size or self.batch_size
    caching = caching if caching is not None else self.caching
    merged_kwargs = self.default_kwargs.copy()
    merged_kwargs.update(kwargs)
    
    # 4. 分批处理
    input_batches = []
    for i in range(0, len(inputs), batch_size):
        input_batches.append(inputs[i : i + batch_size])
    
    return input_batches, caching, merged_kwargs, is_single_input

回调机制

DSPy 提供回调系统用于监控和调试语言模型调用。回调通过 BaseCallback 抽象类定义:

from dspy.utils.callback import BaseCallback

class LoggingCallback(BaseCallback):
    def on_module_start(self, call_id, instance, inputs):
        print(f"LM is called with inputs: {inputs}")
    
    def on_module_end(self, call_id, outputs):
        print(f"LM is finished with outputs: {outputs}")

回调使用方式:

# 方式 1:全局配置
dspy.configure(callbacks=[LoggingCallback()])

# 方式 2:组件级别配置
lm = dspy.LM("gpt-3.5-turbo", callbacks=[LoggingCallback()])

缓存机制

DSPy 的缓存层位于 dspy/clients/cache.py,用于存储和检索已计算的模型响应,避免重复 API 调用。

缓存的主要特性:

  • 基于请求参数的内容寻址
  • 支持配置 TTL(生存时间)
  • 可与各种模型客户端无缝集成

模型提供商

支持的提供商类型

提供商客户端类说明
OpenAIOpenAIOpenAI API 原生支持
Azure通过 OpenAIAzure OpenAI Service
Anthropic通过 _LiteLLMClaude 系列模型
Google通过 _LiteLLMGemini 系列
Meta通过 _LiteLLMLlama 系列
DatabricksDatabricksDatabricks 模型服务
OllamaLocalLM本地部署模型
LM StudioLocalLM本地部署模型

模型标识符格式

# OpenAI 格式
dspy.LM("openai/gpt-4o")
dspy.LM("openai/gpt-4o-mini")

# 自定义格式
dspy.LM("ollama/llama3")
dspy.LM("local/my-model")

最佳实践

1. 全局配置 vs 组件配置

# 全局配置:所有组件共享同一语言模型
dspy.configure(lm=dspy.LM("gpt-4o"))

# 组件配置:特定组件使用特定模型
lm_special = dspy.LM("gpt-4o")
program.set_lm(lm_special)

2. 回调用于调试

class DebugCallback(BaseCallback):
    def on_module_start(self, call_id, instance, inputs):
        logger.debug(f"Calling LM with: {inputs}")
    
    def on_module_end(self, call_id, outputs):
        logger.debug(f"LM returned: {outputs}")

lm = dspy.LM("gpt-4o", callbacks=[DebugCallback()])

3. 嵌入模型批处理优化

# 大批量处理时使用较大 batch_size
embedder = dspy.Embedder("openai/text-embedding-3-small", batch_size=100)

相关文档

源码索引

文件功能描述
dspy/clients/__init__.py客户端模块入口,导出 LMEmbedder
dspy/clients/lm.pyLM 类实现,支持多种提供商
dspy/clients/base_lm.pyBaseLM 抽象基类
dspy/clients/openai.pyOpenAI 专用客户端
dspy/clients/_litellm.pyLiteLLM 封装
dspy/clients/databricks.pyDatabricks 客户端
dspy/clients/lm_local.py本地模型客户端
dspy/clients/embedding.py嵌入模型客户端 Embedder
dspy/clients/cache.py缓存实现
dspy/clients/provider.py提供商配置
dspy/primitives/module.py模块的 set_lm/get_lm 方法
dspy/utils/callback.py回调系统实现

来源:https://github.com/stanfordnlp/dspy / 项目说明书

适配器系统

DSPy 的适配器系统(Adapter System)是框架中负责将程序签名(Signature)转换为语言模型可处理的格式化消息的核心组件。适配器充当 DSPy 程序与底层语言模型 API 之间的桥梁,负责处理输入输出的结构化转换、字段序列化以及响应解析等关键任务。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 核心组件层次

继续阅读本节完整说明和来源证据。

章节 适配器类型对比

继续阅读本节完整说明和来源证据。

章节 BaseAdapter 抽象基类

继续阅读本节完整说明和来源证据。

概述

DSPy 的适配器系统(Adapter System)是框架中负责将程序签名(Signature)转换为语言模型可处理的格式化消息的核心组件。适配器充当 DSPy 程序与底层语言模型 API 之间的桥梁,负责处理输入输出的结构化转换、字段序列化以及响应解析等关键任务。

适配器系统的主要职责包括:

  • 消息格式化:将 DSPy 签名中的输入字段转换为语言模型 API 可接受的格式
  • 响应解析:将语言模型的输出解析回 DSPy 的结构化数据结构
  • 自定义类型支持:处理复杂数据类型(如图像、历史对话等)的序列化与反序列化
  • 多格式支持:支持多种输出格式规范(如 JSON、XML、Chat 格式等)

资料来源:dspy/adapters/base.py

系统架构

核心组件层次

graph TD
    A[DSPy 程序] --> B[签名 Signature]
    B --> C[适配器 Adapter]
    C --> D{适配器类型}
    D --> E[ChatAdapter]
    D --> F[JSONAdapter]
    D --> G[XMLAdapter]
    D --> H[TwoStepAdapter]
    D --> I[BAMLAdapter]
    C --> J[语言模型 LM API]
    J --> K[响应 Response]
    K --> C
    C --> L[Prediction]

适配器类型对比

适配器类型输出格式解析方式使用场景
ChatAdapterChat Messages结构化解析通用对话场景
JSONAdapterJSONJSON 解析结构化数据输出
XMLAdapterXMLXML 解析XML 格式要求
TwoStepAdapter两阶段格式两步解析复杂推理任务
BAMLAdapterBAMLBAML 解析器类型安全生成

资料来源:dspy/adapters/__init__.py

基础适配器接口

BaseAdapter 抽象基类

所有适配器都继承自 BaseAdapter 抽象基类,定义了适配器的核心接口规范:

class BaseAdapter(ABC):
    """适配器基类,定义所有适配器必须实现的接口"""
    
    @abstractmethod
    def format(self, signature, demos, inputs):
        """将签名和输入格式化为模型消息"""
        pass
    
    @abstractmethod
    def parse(self, signature, response):
        """解析模型响应为预测结果"""
        pass

适配器核心方法

方法参数返回值说明
formatsignature, demos, inputslist[dict]格式化输入消息
parsesignature, responsePrediction解析输出响应
format_field_valuevalue, fieldstr格式化单个字段值
post_save_hookoutput, signatureNone保存后钩子

资料来源:dspy/adapters/base.py

Chat 适配器

ChatAdapter 是 DSPy 默认的适配器实现,专门用于处理对话格式的语言模型 API(如 OpenAI ChatGPT、Google Gemini 等)。

消息格式转换

ChatAdapter 将 DSPy 的签名转换为标准的聊天消息格式:

graph LR
    A[Signature<br/>InputFields] --> B[ChatAdapter]
    C[Demos<br/>Few-Shot] --> B
    B --> D[System Message<br/>历史指令]
    B --> E[User Messages<br/>输入+演示]
    B --> F[Assistant Messages<br/>历史响应]

核心实现逻辑

def format(self, signature, demos, inputs):
    # 构建系统消息(包含指令)
    messages = [self._build_system_message(signature)]
    
    # 添加演示示例
    for demo in demos:
        messages.extend(self._format_demo(demo))
    
    # 添加当前输入
    messages.append(self._build_user_message(inputs))
    
    return messages

资料来源:dspy/adapters/chat_adapter.py

JSON 适配器

JSONAdapter 专为需要结构化 JSON 输出的场景设计,适用于需要机器解析输出的应用。

工作流程

graph TD
    A[输入字段] --> B[构建Prompt]
    B --> C[添加JSON Schema说明]
    C --> D[调用LM]
    D --> E{响应格式}
    E -->|有效JSON| F[json.loads解析]
    E -->|无效JSON| G[尝试修复格式]
    F --> H[Prediction]
    G --> H

格式控制机制

JSONAdapter 通过在提示词中嵌入 JSON Schema 来指导模型生成符合规范的输出:

json_schema = {
    "type": "object",
    "properties": {
        "field_name": {"type": "string", "description": "..."}
    },
    "required": ["field_name"]
}

资料来源:dspy/adapters/json_adapter.py

XML 适配器

XMLAdapter 使用 XML 标签格式封装输出字段,适用于需要明确结构化层次的场景。

标签规范

组件标签格式说明
输出块<answer> ... </answer>包含整个输出
字段<field_name></field_name>单个输出字段
嵌套层级嵌套标签复杂数据结构

解析机制

XMLAdapter 使用正则表达式匹配提取字段值:

pattern = rf"<{field_name}>(.*?)</{field_name}>"
match = re.search(pattern, response)

资料来源:dspy/adapters/xml_adapter.py

TwoStep 适配器

TwoStepAdapter 实现两阶段推理模式,适用于需要"思考-回答"分离的复杂任务。

两阶段流程

graph LR
    A[问题] --> B[第一阶段<br/>推理/分析]
    B --> C[中间推理结果]
    C --> D[第二阶段<br/>生成答案]
    D --> E[最终答案]

配置参数

参数类型默认值说明
reasoning_fieldstr"reasoning"推理字段名
answer_fieldstr"answer"答案字段名
reasoning_typestr"chain_of_thought"推理类型

资料来源:dspy/adapters/two_step_adapter.py

自定义类型系统

类型注册机制

DSPy 适配器系统支持自定义复杂类型的处理,通过标识符分割内容:

graph TD
    A[消息内容] --> B{包含自定义类型?}
    B -->|是| C[查找标识符]
    C --> D[<<CUSTOM-TYPE-START-IDENTIFIER>>]
    D --> E[提取JSON内容]
    E --> F[解析自定义类型]
    F --> G[重建消息结构]
    B -->|否| H[纯文本处理]

类型标识符

标识符用途
<<CUSTOM-TYPE-START-IDENTIFIER>>自定义类型内容开始
<<CUSTOM-TYPE-END-IDENTIFIER>>自定义类型内容结束

资料来源:dspy/adapters/types/base_type.py

内置自定义类型

#### History 类型

History 类型用于管理多轮对话历史:

class History(BaseModel):
    """对话历史类"""
    messages: list[dict]  # 消息列表,每条消息包含历史对话内容

使用示例:

class MySignature(dspy.Signature):
    question: str = dspy.InputField()
    history: dspy.History = dspy.InputField()
    answer: str = dspy.OutputField()

history = dspy.History(messages=[
    {"question": "法国的首都是什么?", "answer": "巴黎"},
    {"question": "德国的首都是什么?", "answer": "柏林"},
])

资料来源:dspy/adapters/types/history.py

#### Image 类型

Image 类型支持图像输入处理:

class Image(BaseModel):
    """图像类型,支持URL和本地文件"""
    url: str  # base64数据URI或URL

支持的数据格式:

格式说明适用场景
http://...网络URL公开图像
https://...安全URL公开图像
data:image/...;base64,...Base64编码本地/内联图像
file://...本地文件路径本地图像

图像处理方法:

方法说明
encode_image()编码图像为可传输格式
format()格式化为 API 消息格式
from_url()从URL创建(已废弃)
from_file()从文件创建

资料来源:dspy/adapters/types/image.py

使用指南

选择合适的适配器

graph TD
    A[开始] --> B{输出需求?}
    B -->|通用对话| C[ChatAdapter]
    B -->|结构化数据| D{数据复杂度?}
    D -->|简单| E[JSONAdapter]
    D -->|复杂| F[TwoStepAdapter]
    B -->|XML格式要求| G[XMLAdapter]
    B -->|类型安全| H[BAMLAdapter]

配置默认适配器

import dspy

# 全局配置
dspy.settings.configure(adapter=dspy.ChatAdapter())

# 或在程序中指定
class MyProgram(dspy.Module):
    def __init__(self):
        self.predict = dspy.Predict(
            "question -> answer",
            adapter=dspy.JSONAdapter()
        )

自定义适配器

from dspy.adapters import BaseAdapter

class MyCustomAdapter(BaseAdapter):
    def format(self, signature, demos, inputs):
        # 自定义格式化逻辑
        return messages
    
    def parse(self, signature, response):
        # 自定义解析逻辑
        return dspy.Prediction(...)

最佳实践

1. 适配器选择建议

场景推荐适配器原因
通用应用ChatAdapter灵活、通用
API 数据提取JSONAdapter结构化、机器可读
文档生成XMLAdapter层次清晰
推理任务TwoStepAdapter分离思考与答案
生产系统BAMLAdapter类型安全

2. 性能优化

  • 批处理:使用 batch_size 参数控制批处理大小
  • 缓存:启用缓存机制减少重复计算
  • 类型选择:根据输出复杂度选择最合适的适配器

3. 错误处理

适配器应处理以下常见错误:

错误类型处理策略
解析失败回退到备用解析器或提示重试
格式不匹配尝试自动修复或抛出明确错误
超限截断或分片处理

总结

DSPy 的适配器系统为框架提供了灵活的消息格式化和解析能力,通过统一的接口抽象支持多种输出格式规范。适配器的模块化设计使得开发者可以轻松扩展新的格式支持,同时内置的多种适配器覆盖了大多数常见使用场景。自定义类型系统的支持进一步增强了框架的表达能力,使得复杂的数据结构处理变得简单可控。

资料来源:[dspy/adapters/base.py](https://github.com/stanfordnlp/dspy/blob/main/dspy/adapters/base.py)

检索增强模块

DSPy的检索增强模块(Retrieval Augmentation Module)是框架中负责从外部知识源获取相关文档或段落的核心组件。该模块通过检索模型(Retriever Model)实现语义搜索功能,使语言模型能够在生成回答时利用外部知识库中的相关信息。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 模块层级结构

继续阅读本节完整说明和来源证据。

章节 核心类关系

继续阅读本节完整说明和来源证据。

章节 基本用法

继续阅读本节完整说明和来源证据。

概述

DSPy的检索增强模块(Retrieval Augmentation Module)是框架中负责从外部知识源获取相关文档或段落的核心组件。该模块通过检索模型(Retriever Model)实现语义搜索功能,使语言模型能够在生成回答时利用外部知识库中的相关信息。

检索增强模块的主要职责包括:

  • 与向量数据库或检索服务集成,实现语义相似度搜索
  • 提供统一的检索接口,支持多种后端实现
  • 将检索结果格式化为可被签名(Signature)处理的数据结构
  • 支持自定义嵌入模型和检索策略

架构设计

模块层级结构

DSPy的检索增强系统采用分层架构设计,从底层到顶层依次为:

层级组件职责
嵌入层Embedder将文本转换为向量表示
检索层各类RM实现执行向量相似度搜索
接口层Retrieve提供统一的模块化调用接口
配置层dspy.configure()全局配置检索模型

核心类关系

graph TD
    A[dspy.configure] --> B[RM Retriever Model]
    B --> C[weaviate_rm.WeaviateRM]
    B --> D[databricks_rm.DatabricksRM]
    B --> E[colbertv2.ColBERTv2]
    F[Retrieve模块] --> B
    G[Embedder] --> H[嵌入服务]
    B --> G

Retrieve 模块

Retrieve是DSPy中用于执行检索的核心模块,继承自Module基类。它作为检索系统的统一入口点,将用户的查询转换为检索请求并返回相关文档。

基本用法

import dspy

# 配置语言模型和检索模型
dspy.configure(lm=dspy.LM("openai/gpt-4o-mini"))
dspy.configure(rm=WeaviateRM("my_collection", weaviate_client=client))

# 创建Retrieve模块
retrieve = dspy.Retrieve(k=5)
results = retrieve("什么是机器学习")

API 参数说明

参数类型默认值说明
kint3返回的最相关文档数量
force_by_idboolFalse是否强制按ID检索

工作流程

sequenceDiagram
    用户 ->> Retrieve: 调用retrieve(query)
    Retrieve ->> RM: query(query_str, k)
    RM ->> 向量数据库: 相似度搜索
    向量数据库 ->> RM: 返回Top-K文档
    RM ->> Retrieve: 格式化检索结果
    Retrieve ->> 用户: 返回Passages对象

检索模型(Retriever Model)

检索模型是实际执行向量搜索的后端实现。DSPy支持多种检索后端,每种实现都遵循统一的接口规范。

Retriever 基类接口

所有检索模型都需要实现以下核心方法:

方法返回类型说明
forward(query)list[str]根据查询返回相关文档列表
query(query_str, k)list执行检索并返回k个结果
__call__(*args, **kwargs)list[str]模块调用接口

WeaviateRM 实现

WeaviateRM是与Weaviate向量数据库集成的检索模型实现。

构造函数参数:

参数类型必填说明
weaviate_collection_namestrWeaviate集合名称
weaviate_clientWeaviateClientWeaviate客户端实例
weaviate_collection_text_keystr集合中存储文本的字段名,默认"content"
kint检索结果数量,默认3
tenant_idstr多租户支持

配置示例:

import dspy
import weaviate

llm = dspy.Cohere(model="command-r-plus", api_key=api_key)
weaviate_client = weaviate.connect_to_local("your-path-here")
retriever_model = WeaviateRM("my_collection_name", weaviate_client=weaviate_client)
dspy.configure(lm=llm, rm=retriever_model)

retrieve = dspy.Retrieve(k=1)
topK_passages = retrieve("what are the stages in planning").passages

内部机制:

该实现通过weaviate_client.collections.get()获取集合对象,然后使用集合的查询接口执行向量相似度搜索。文本内容通过weaviate_collection_text_key字段提取。

DatabricksRM 实现

DatabricksRM是专门为Databricks平台设计的检索模型,利用Databricks向量搜索服务进行语义检索。

ColBERTv2 实现

ColBERTv2是基于ColBERT算法的延迟交互式检索实现,适用于需要细粒度语义匹配的场景。

from dspy.dsp.colbertv2 import ColBERTv2

retriever = ColBERTv2()
results = retriever("query text", k=5)

DPR 实现

DSPy还提供了基于Dense Passage Retrieval(DPR)的工具函数,位于dspy/dsp/utils/dpr.py中,用于处理双塔模型的检索逻辑。

嵌入模块

Embedder 类

Embedder是封装嵌入模型的统一接口,支持自定义嵌入函数和批量处理。

构造函数参数:

参数类型默认值说明
modelstr \Callable必填嵌入模型名称或自定义函数
batch_sizeint200批处理大小
cachingboolTrue是否启用结果缓存
kwargsdict{}传递给嵌入服务的额外参数

使用示例:

import dspy
import numpy as np

# 使用自定义嵌入函数
def my_embedder(texts):
    return np.random.rand(len(texts), 10)

embedder = dspy.Embedder(my_embedder)
embeddings = embedder(["hello", "world"], batch_size=1)

预处理与后处理

Embedder类包含两个关键内部方法:

  • _preprocess():处理输入数据,支持单个字符串或字符串列表,自动进行批量分割
  • _postprocess():处理嵌入结果,支持返回原始格式或批量格式

数据结构

Passages 数据结构

检索结果以Passages对象形式返回,包含以下属性:

属性类型说明
passageslist[str]检索到的文档段落列表
result = retrieve("查询内容")
print(result.passages)  # ['文档1内容', '文档2内容', ...]

示例数据结构

Example类用于组织训练数据和评估数据,支持与检索系统配合使用:

example = dspy.Example(
    question="什么是检索增强生成?",
    answer="检索增强生成是一种结合检索系统和语言模型的技术。"
).with_inputs("question")

# 检索相关文档
context = example.inputs().toDict()

配置管理

全局配置

通过dspy.configure()进行全局配置:

import dspy

dspy.configure(
    lm=dspy.LM("openai/gpt-4o-mini"),  # 语言模型
    rm=WeaviateRM(...)                   # 检索模型
)

模块级配置

也可以在模块级别设置语言模型:

class MyRAG(dspy.Module):
    def __init__(self):
        super().__init__()
        self.retrieve = dspy.Retrieve(k=3)
        self.qa = dspy.Predict("context, question -> answer")
    
    def forward(self, question):
        context = self.retrieve(question).passages
        return self.qa(context=context, question=question)

最佳实践

检索参数调优

场景建议配置
快速原型开发k=3, 使用轻量级嵌入模型
生产环境k=5-10, 启用缓存, 使用高精度嵌入
长文档检索设置合适的chunk_size, 使用rerank

性能优化建议

  1. 启用缓存:对于重复查询较多的场景,设置caching=True
  2. 批量处理:合理设置batch_size参数,平衡内存和吞吐量
  3. 连接池复用:在生产环境中复用向量数据库连接

相关模块

模块文件路径用途
Module基类dspy/primitives/module.py所有DSPy模块的基类,包含set_lm()get_lm()方法
Predictdspy/predict/predict.py预测模块,可与Retrieve组合使用
Exampledspy/primitives/example.py数据示例类,用于组织训练和评估数据
Historydspy/adapters/types/history.py对话历史类型,支持多轮检索场景

扩展开发

自定义检索模型

要实现自定义检索模型,需要继承相关基类并实现核心接口:

class MyRetriever(dspy.Module):
    def __init__(self, collection_name, k=3):
        self.collection_name = collection_name
        self.k = k
    
    def forward(self, query):
        # 实现检索逻辑
        results = self._search_vector_db(query, self.k)
        return results
    
    def _search_vector_db(self, query, k):
        # 向量搜索实现
        pass

集成新向量数据库

dspy/retrievers/目录下创建新的RM实现文件,参考weaviate_rm.py的结构,确保实现统一的__call__接口和检索参数规范。

来源:https://github.com/stanfordnlp/dspy / 项目说明书

评估与指标

DSPy 框架的评估与指标系统是验证和优化语言模型程序的核心组件。该系统提供了标准化的评估接口、灵活的指标定义机制,以及与 DSPy 优化器(Teleprompter)深度集成的评估流程。评估系统的设计遵循模块化原则,允许开发者自定义评估逻辑,同时保持与框架其他部分的一致性。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 评估系统组件关系

继续阅读本节完整说明和来源证据。

章节 关键类结构

继续阅读本节完整说明和来源证据。

章节 创建与使用 Example

继续阅读本节完整说明和来源证据。

概述

DSPy 框架的评估与指标系统是验证和优化语言模型程序的核心组件。该系统提供了标准化的评估接口、灵活的指标定义机制,以及与 DSPy 优化器(Teleprompter)深度集成的评估流程。评估系统的设计遵循模块化原则,允许开发者自定义评估逻辑,同时保持与框架其他部分的一致性。

在 DSPy 中,评估主要通过 dspy.Evaluate 类驱动,而指标(Metrics)则是用于衡量预测质量的回调函数。两者结合构成了完整的程序性能评估体系,支持从简单的精确匹配到复杂的语义相似度等多种评估场景。

核心架构

评估系统组件关系

graph TD
    A[用户程序 dspy.Module] --> B[dspy.Evaluate 评估器]
    B --> C[评估指标 Metric 函数]
    C --> D[Example 测试集]
    B --> E[Prediction 预测结果]
    E --> C
    C --> F[评估分数 Score]
    B --> G[Teleprompter 优化器]
    G --> H[BootstrapFewShot / MIPROv2 等]

关键类结构

类名文件位置职责
Evaluatedspy/evaluate/evaluate.py评估引擎,协调评估流程
Metricdspy/evaluate/metrics.py指标基类与预置指标
AutoEvaluationdspy/evaluate/auto_evaluation.py自动评估支持
Exampledspy/primitives/example.py测试样本数据结构
Predictiondspy/primitives/prediction.py预测结果数据结构

Example 数据结构

Example 是 DSPy 中用于表示测试样本的基础数据结构,它将输入字段和标签字段分离,为评估提供标准化的数据格式。 资料来源:dspy/primitives/example.py:1-50

创建与使用 Example

import dspy

# 创建带标签的示例
example = dspy.Example(
    question="What is the capital of France?",
    answer="Paris"
).with_inputs("question")

# 提取输入字段
inputs = example.inputs()
# Example({'question': 'What is the capital of France?'}) (input_keys={'question'})

# 提取标签字段
labels = example.labels()
# Example({'answer': 'Paris'}) (input_keys={'question'})

Example 核心方法

方法说明返回值
with_inputs(*keys)标记输入字段新的 Example 实例
inputs()获取输入部分仅包含输入字段的 Example
labels()获取标签部分仅包含标签字段的 Example
toDict()转换为字典递归可序列化的字典
copy(**kwargs)复制并覆盖字段新的 Example 实例
without(*keys)移除指定字段新的 Example 实例

toDict() 方法支持递归序列化嵌套的 Example 对象、Pydantic 模型、列表和字典,确保评估结果可以JSON化输出。 资料来源:dspy/primitives/example.py:80-120

评估器(Evaluate)

Evaluate 类概述

dspy.Evaluate 是评估系统的核心类,负责执行整个评估流程。它接受待评估的程序、测试集和指标函数,并返回聚合的评估分数。

基本用法

import dspy

# 定义评估指标
def exact_match_metric(example, pred, trace=None):
    return example.answer.lower() == pred.answer.lower()

# 准备测试集
testset = [
    dspy.Example(question="What is 1+1?", answer="2").with_inputs("question"),
    dspy.Example(question="What is 2+2?", answer="4").with_inputs("question"),
]

# 创建评估器
evaluate = dspy.Evaluate(
    dev=testset,
    metric=exact_match_metric,
    num_threads=1,
)

# 执行评估
score = evaluate(your_program)

Evaluate 参数配置

参数类型默认值说明
devlist[Example]必需开发/测试集
metricCallable必需评估指标函数
num_threadsint1并行评估线程数
max_errorsint-1最大允许错误数
return_outputsboolFalse是否返回详细输出
displayboolTrue是否显示进度

评估流程

sequenceDiagram
    participant User as 用户
    participant Eval as Evaluate
    participant Module as dspy.Module
    participant Metric as Metric函数
    participant Example as Example数据
    
    User->>Eval: evaluate(program)
    Loop 遍历测试集
        Eval->>Module: forward(example.inputs())
        Module-->>Eval: Prediction
        Eval->>Metric: metric(example, pred, trace)
        Metric-->>Eval: score (bool/float)
    End
    Eval->>Eval: 聚合分数
    Eval-->>User: 平均分数

指标函数(Metrics)

指标函数签名

指标函数是评估的核心,它们接受三个参数并返回布尔值或浮点数:

def metric(
    example: Example,  # 测试样本,包含输入和标签
    pred: Prediction,  # 模型预测结果
    trace: Trace | None  # 可选的执行轨迹(用于优化器)
) -> bool | float

预置指标

DSPy 在 dspy.evaluate.metrics 模块中提供了一些常用的预置指标。开发者也可以根据需求自定义指标函数。 资料来源:dspy/evaluate/metrics.py:1-50

自定义指标示例

#### 精确匹配指标

def exact_match_metric(example, pred, trace=None):
    """检查预测答案是否与标签完全匹配(忽略大小写)"""
    return example.answer.lower() == pred.answer.lower()

# 使用示例
gold = dspy.Example(question="What is 1+1?", answer="2").with_inputs("question")
pred = dspy.Prediction(answer="2")
exact_match_metric(gold, pred)  # True

#### 包含检查指标

def answer_contains_metric(example, pred, trace=None):
    """检查标签是否被预测答案包含"""
    return example.answer.lower() in pred.answer.lower()

#### 带权重的复合指标

def composite_metric(example, pred, trace=None):
    """组合多个子指标"""
    exact_match = example.answer.lower() == pred.answer.lower()
    length_penalty = len(pred.answer) > 0
    return float(exact_match) * 0.8 + float(length_penalty) * 0.2

自动评估(Auto Evaluation)

DSPy 提供了自动评估功能,支持在没有人工标注标签的情况下进行程序评估。这对于迭代优化过程中的快速反馈特别有用。 资料来源:dspy/evaluate/auto_evaluation.py:1-30

自动评估工作流

graph LR
    A[程序输出] --> B[Auto Evaluator]
    B --> C{是否有参考标签}
    C -->|是| D[使用参考指标]
    C -->|否| E[使用LLM评判]
    D --> F[评估分数]
    E --> F

LLM 作为评估器

当没有预定义标签时,可以使用大语言模型本身来评估输出质量:

import dspy

# 使用LLM进行自动评估
def llm_judge_metric(example, pred, trace=None):
    lm = dspy.LM("openai/gpt-4")
    prompt = f"""评估以下回答的质量:
    
    问题: {example.question}
    回答: {pred.answer}
    
    回答是否准确、完整且相关?只需回答 '是' 或 '否'。"""
    
    response = lm(prompt)
    return "是" in response.lower()

evaluate = dspy.Evaluate(
    dev=testset,
    metric=llm_judge_metric,
)

数据集(datasets)

DSPy 的数据集模块提供了加载和管理评估数据的功能。Dataset 类是数据管理的基础抽象,支持多种数据格式和加载方式。 资料来源:dspy/datasets/__init__.py:1-30

加载内置数据集

import dspy
from dspy.datasets import GSM8K, HotPotQA

# 加载 GSM8K 数学数据集
gsm8k = GSM8K()
trainset = gsm8k.train
devset = gsm8k.dev

# 加载 HotPotQA 问答数据集
hotpot = HotPotQA()
testset = hotpot.dev

DataLoader API

DataLoader 提供了标准化的数据加载接口,支持训练集、验证集和测试集的划分: 资料来源:dspy/datasets/dataloader.py:1-50

方法说明
from Hub从模型Hub加载数据集
from_jsonl从JSONL文件加载
from_dicts从字典列表加载
train_test_split划分训练集和测试集

自定义数据集

from dspy.datasets import Dataset

class MyDataset(Dataset):
    def __init__(self, path):
        super().__init__()
        self._data = self._load_from_file(path)
    
    def _load_from_file(self, path):
        # 自定义加载逻辑
        pass

# 使用自定义数据集
dataset = MyDataset("path/to/data.jsonl")
trainset = dataset.train
devset = dataset.dev

与优化器的集成

评估系统与 DSPy 的 Teleprompter 优化器紧密集成。优化器使用评估指标来引导搜索最优的程序配置(提示词、示例选择等)。

graph LR
    A[BootstrapFewShot] --> B[评估指标]
    C[MIPROv2] --> B
    D[GEPA] --> B
    B --> E[优化搜索]
    E --> F[最优配置]

完整优化流程

import dspy

# 1. 定义程序
program = dspy.ChainOfThought("question -> answer")

# 2. 准备数据集
trainset = [
    dspy.Example(question=q, answer=a).with_inputs("question")
    for q, a in question_answer_pairs
]

# 3. 定义指标
def exact_match(example, pred, trace=None):
    return example.answer.lower() == pred.answer.lower()

# 4. 使用优化器(内部使用评估)
optimizer = dspy.MIPROv2(metric=exact_match)
compiled_program = optimizer.compile(
    program,
    trainset=trainset,
    max_bootstrapped_demos=4,
)

最佳实践

指标设计原则

  1. 确定性:相同输入应产生相同分数,避免随机性
  2. 高效性:指标函数会被频繁调用,应尽量轻量
  3. 可解释性:分数应能清晰反映输出质量
  4. 可组合性:支持复合指标以评估多个维度

评估执行建议

场景建议
快速原型开发使用 num_threads=-1 启用所有CPU核心
调试设置 return_outputs=True 获取详细输出
生产环境设置合理的 max_errors 避免无限等待
大规模评估分批评估并保存中间结果

常见问题处理

处理评估超时

evaluate = dspy.Evaluate(
    dev=testset,
    metric=my_metric,
    max_errors=10,  # 跳过有问题的样本
    num_threads=4,
)

获取详细评估日志

evaluate = dspy.Evaluate(
    dev=testset,
    metric=my_metric,
    return_outputs=True,
    display=True,
)
results = evaluate(program)
for i, (example, pred, score) in enumerate(results.outputs):
    print(f"[{i}] Score: {score}")

相关模块

参考链接

来源:https://github.com/stanfordnlp/dspy / 项目说明书

失败模式与踩坑日记

保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。

high 来源证据:PythonInterpreter: paths containing commas are silently misparsed by Deno's --allow-read

可能影响授权、密钥配置或安全边界。

medium 来源证据:3.0.4b1

可能阻塞安装或首次运行。

medium 来源证据:3.1.2

可能增加新用户试用和生产接入成本。

medium 来源证据:3.1.3

可能增加新用户试用和生产接入成本。

Pitfall Log / 踩坑日志

项目:stanfordnlp/dspy

摘要:发现 19 个潜在踩坑项,其中 1 个为 high/blocking;最高优先级:安全/权限坑 - 来源证据:PythonInterpreter: paths containing commas are silently misparsed by Deno's --allow-read。

1. 安全/权限坑 · 来源证据:PythonInterpreter: paths containing commas are silently misparsed by Deno's --allow-read

  • 严重度:high
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:PythonInterpreter: paths containing commas are silently misparsed by Deno's --allow-read
  • 对用户的影响:可能影响授权、密钥配置或安全边界。
  • 建议检查:来源问题仍为 open,Pack Agent 需要复核是否仍影响当前版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_43291e191b234ac883662982bf693e18 | https://github.com/stanfordnlp/dspy/issues/9749 | 来源讨论提到 python 相关条件,需在安装/试用前复核。

2. 安装坑 · 来源证据:3.0.4b1

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安装相关的待验证问题:3.0.4b1
  • 对用户的影响:可能阻塞安装或首次运行。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_76f47f2d6cbc4f299fe2a852b20617ef | https://github.com/stanfordnlp/dspy/releases/tag/3.0.4b1 | 来源类型 github_release 暴露的待验证使用条件。

3. 安装坑 · 来源证据:3.1.2

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安装相关的待验证问题:3.1.2
  • 对用户的影响:可能增加新用户试用和生产接入成本。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_3733e2d7817440638629959030da2ddb | https://github.com/stanfordnlp/dspy/releases/tag/3.1.2 | 来源类型 github_release 暴露的待验证使用条件。

4. 安装坑 · 来源证据:3.1.3

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安装相关的待验证问题:3.1.3
  • 对用户的影响:可能增加新用户试用和生产接入成本。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_2b7f0c4a046840b4b453167ce581b80a | https://github.com/stanfordnlp/dspy/releases/tag/3.1.3 | 来源讨论提到 python 相关条件,需在安装/试用前复核。

5. 安装坑 · 来源证据:3.2.0

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安装相关的待验证问题:3.2.0
  • 对用户的影响:可能阻塞安装或首次运行。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_976a3edffce44ac3984c9da4a10a2575 | https://github.com/stanfordnlp/dspy/releases/tag/3.2.0 | 来源讨论提到 python 相关条件,需在安装/试用前复核。

6. 安装坑 · 来源证据:Use Tool functions that require external libaries in CodeAct

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安装相关的待验证问题:Use Tool functions that require external libaries in CodeAct
  • 对用户的影响:可能增加新用户试用和生产接入成本。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_3c605227d53e42b69651c46c3e76c162 | https://github.com/stanfordnlp/dspy/issues/8839 | 来源讨论提到 python 相关条件,需在安装/试用前复核。

7. 能力坑 · 能力判断依赖假设

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:README/documentation is current enough for a first validation pass.
  • 对用户的影响:假设不成立时,用户拿不到承诺的能力。
  • 建议检查:将假设转成下游验证清单。
  • 防护动作:假设必须转成验证项;没有验证结果前不能写成事实。
  • 证据:capability.assumptions | github_repo:587050620 | https://github.com/stanfordnlp/dspy | README/documentation is current enough for a first validation pass.

8. 维护坑 · 维护活跃度未知

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:未记录 last_activity_observed。
  • 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
  • 建议检查:补 GitHub 最近 commit、release、issue/PR 响应信号。
  • 防护动作:维护活跃度未知时,推荐强度不能标为高信任。
  • 证据:evidence.maintainer_signals | github_repo:587050620 | https://github.com/stanfordnlp/dspy | last_activity_observed missing

9. 安全/权限坑 · 下游验证发现风险项

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 对用户的影响:下游已经要求复核,不能在页面中弱化。
  • 建议检查:进入安全/权限治理复核队列。
  • 防护动作:下游风险存在时必须保持 review/recommendation 降级。
  • 证据:downstream_validation.risk_items | github_repo:587050620 | https://github.com/stanfordnlp/dspy | no_demo; severity=medium

10. 安全/权限坑 · 存在评分风险

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 对用户的影响:风险会影响是否适合普通用户安装。
  • 建议检查:把风险写入边界卡,并确认是否需要人工复核。
  • 防护动作:评分风险必须进入边界卡,不能只作为内部分数。
  • 证据:risks.scoring_risks | github_repo:587050620 | https://github.com/stanfordnlp/dspy | no_demo; severity=medium

11. 安全/权限坑 · 来源证据:3.0.4

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:3.0.4
  • 对用户的影响:可能阻塞安装或首次运行。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_d192b20b863c476ca31d4ba476cec875 | https://github.com/stanfordnlp/dspy/releases/tag/3.0.4 | 来源讨论提到 api key 相关条件,需在安装/试用前复核。

12. 安全/权限坑 · 来源证据:3.0.4b2

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:3.0.4b2
  • 对用户的影响:可能影响授权、密钥配置或安全边界。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_392f60c647b74a6592f1692bcdc0070f | https://github.com/stanfordnlp/dspy/releases/tag/3.0.4b2 | 来源讨论提到 api key 相关条件,需在安装/试用前复核。

13. 安全/权限坑 · 来源证据:3.1.0

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:3.1.0
  • 对用户的影响:可能增加新用户试用和生产接入成本。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_364bbccd7d4241c9b6841303fefb5a85 | https://github.com/stanfordnlp/dspy/releases/tag/3.1.0 | 来源讨论提到 python 相关条件,需在安装/试用前复核。

14. 安全/权限坑 · 来源证据:3.1.0b1

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:3.1.0b1
  • 对用户的影响:可能增加新用户试用和生产接入成本。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_4599cbf0d1fd41b4b3c47e5c1aae247a | https://github.com/stanfordnlp/dspy/releases/tag/3.1.0b1 | 来源讨论提到 python 相关条件,需在安装/试用前复核。

15. 安全/权限坑 · 来源证据:3.1.1

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:3.1.1
  • 对用户的影响:可能影响授权、密钥配置或安全边界。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_5656ac7c80214b9fb410d129ccec33d2 | https://github.com/stanfordnlp/dspy/releases/tag/3.1.1 | 来源讨论提到 python 相关条件,需在安装/试用前复核。

16. 安全/权限坑 · 来源证据:3.2.1

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:3.2.1
  • 对用户的影响:可能影响授权、密钥配置或安全边界。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_e2250d3118a04c5e8d213eb2fce4e68d | https://github.com/stanfordnlp/dspy/releases/tag/3.2.1 | 来源讨论提到 node 相关条件,需在安装/试用前复核。

17. 安全/权限坑 · 来源证据:[Bug] PythonInterpreter fails with default setup due to missing Deno read permissions for Pyodide

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:[Bug] PythonInterpreter fails with default setup due to missing Deno read permissions for Pyodide
  • 对用户的影响:可能影响授权、密钥配置或安全边界。
  • 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
  • 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
  • 证据:community_evidence:github | cevd_bb4eb14c9ce944f0a7654217c34b1d1d | https://github.com/stanfordnlp/dspy/issues/9501 | 来源讨论提到 python 相关条件,需在安装/试用前复核。

18. 维护坑 · issue/PR 响应质量未知

  • 严重度:low
  • 证据强度:source_linked
  • 发现:issue_or_pr_quality=unknown。
  • 对用户的影响:用户无法判断遇到问题后是否有人维护。
  • 建议检查:抽样最近 issue/PR,判断是否长期无人处理。
  • 防护动作:issue/PR 响应未知时,必须提示维护风险。
  • 证据:evidence.maintainer_signals | github_repo:587050620 | https://github.com/stanfordnlp/dspy | issue_or_pr_quality=unknown

19. 维护坑 · 发布节奏不明确

  • 严重度:low
  • 证据强度:source_linked
  • 发现:release_recency=unknown。
  • 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
  • 建议检查:确认最近 release/tag 和 README 安装命令是否一致。
  • 防护动作:发布节奏未知或过期时,安装说明必须标注可能漂移。
  • 证据:evidence.maintainer_signals | github_repo:587050620 | https://github.com/stanfordnlp/dspy | release_recency=unknown

来源:Doramagic 发现、验证与编译记录