DSPy 签名详解 #

什么是签名? #

签名(Signature)是 DSPy 中定义模块输入输出接口的声明式方式。它类似于函数的类型签名,但更加丰富,包含了语义描述信息。

text
┌─────────────────────────────────────────────────────────────┐
│                    签名的作用                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 接口定义:明确模块需要什么输入,产生什么输出             │
│  2. 语义描述:通过文档字符串和字段描述传达意图               │
│  3. 自动提示:DSPy 根据签名自动生成提示词                   │
│  4. 类型约束:帮助验证和调试                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

签名的定义方式 #

方式一:类定义(推荐) #

python
import dspy

class QuestionAnswer(dspy.Signature):
    """根据问题给出准确的答案"""
    question = dspy.InputField(desc="用户提出的问题")
    answer = dspy.OutputField(desc="问题的答案,简洁准确")

方式二:简写字符串 #

python
import dspy

qa = dspy.Predict("question -> answer")
result = qa(question="什么是 Python?")

方式三:带类型注解 #

python
import dspy

class Translate(dspy.Signature):
    """翻译文本"""
    text: str = dspy.InputField(desc="需要翻译的文本")
    source_lang: str = dspy.InputField(desc="源语言")
    target_lang: str = dspy.InputField(desc="目标语言")
    translation: str = dspy.OutputField(desc="翻译结果")

签名的结构 #

完整结构 #

python
class MySignature(dspy.Signature):
    """
    文档字符串(Docstring)
    
    这是签名的核心描述,DSPy 会将其作为提示词的一部分。
    应该清晰描述签名的目的和功能。
    """
    input1 = dspy.InputField(desc="输入字段1的描述")
    input2 = dspy.InputField(desc="输入字段2的描述")
    output1 = dspy.OutputField(desc="输出字段1的描述")
    output2 = dspy.OutputField(desc="输出字段2的描述")

各部分详解 #

text
┌─────────────────────────────────────────────────────────────┐
│                    签名组成部分                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 类名                                                    │
│     - 应具有描述性                                          │
│     - 遵循 PascalCase 命名规范                              │
│     - 示例:QuestionAnswer, DocumentSummarizer              │
│                                                             │
│  2. 文档字符串                                              │
│     - 描述签名的用途                                        │
│     - 可以包含详细说明                                      │
│     - DSPy 会将其用于生成提示词                             │
│                                                             │
│  3. 输入字段 (InputField)                                   │
│     - 定义模块需要的输入                                    │
│     - 可以有多个输入字段                                    │
│     - 每个字段可以有描述                                    │
│                                                             │
│  4. 输出字段 (OutputField)                                  │
│     - 定义模块产生的输出                                    │
│     - 可以有多个输出字段                                    │
│     - 每个字段可以有描述                                    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

输入字段详解 #

基本输入字段 #

python
class SimpleQA(dspy.Signature):
    """简单问答"""
    question = dspy.InputField()
    answer = dspy.OutputField()

带描述的输入字段 #

python
class DetailedQA(dspy.Signature):
    """详细问答"""
    question = dspy.InputField(desc="用户的问题,应清晰明确")
    context = dspy.InputField(desc="相关背景信息,用于辅助回答")
    answer = dspy.OutputField(desc="基于上下文的准确回答")

多输入字段 #

python
class MultiInput(dspy.Signature):
    """多输入示例"""
    document = dspy.InputField(desc="需要处理的文档")
    question = dspy.InputField(desc="关于文档的问题")
    style = dspy.InputField(desc="回答风格:简洁/详细/学术")
    answer = dspy.OutputField(desc="符合要求的回答")

前缀说明 #

python
class WithPrefix(dspy.Signature):
    """带前缀的字段"""
    question = dspy.InputField(
        prefix="问题:",
        desc="用户提出的问题"
    )
    answer = dspy.OutputField(
        prefix="答案:",
        desc="问题的答案"
    )

输出字段详解 #

基本输出字段 #

python
class SimpleOutput(dspy.Signature):
    """简单输出"""
    text = dspy.InputField()
    summary = dspy.OutputField()

带描述的输出字段 #

python
class DetailedOutput(dspy.Signature):
    """详细输出"""
    document = dspy.InputField(desc="原始文档")
    summary = dspy.OutputField(desc="文档摘要,不超过100字")
    keywords = dspy.OutputField(desc="关键词列表,逗号分隔")
    sentiment = dspy.OutputField(desc="情感倾向:正面/负面/中性")

多输出字段 #

python
class MultiOutput(dspy.Signature):
    """多输出示例"""
    text = dspy.InputField(desc="需要分析的文本")
    summary = dspy.OutputField(desc="文本摘要")
    entities = dspy.OutputField(desc="识别的实体列表")
    categories = dspy.OutputField(desc="分类标签")
    confidence = dspy.OutputField(desc="分类置信度,0-1之间")

字段类型 #

字符串类型(默认) #

python
class StringFields(dspy.Signature):
    """字符串字段"""
    input_text = dspy.InputField()
    output_text = dspy.OutputField()

类型注解 #

python
class TypedFields(dspy.Signature):
    """带类型注解的字段"""
    question: str = dspy.InputField()
    options: list = dspy.InputField(desc="选项列表")
    answer: str = dspy.OutputField()
    confidence: float = dspy.OutputField(desc="置信度")

复杂类型 #

python
from typing import List, Dict, Optional

class ComplexTypes(dspy.Signature):
    """复杂类型字段"""
    documents: List[str] = dspy.InputField(desc="文档列表")
    config: Dict[str, str] = dspy.InputField(desc="配置字典")
    results: List[Dict] = dspy.OutputField(desc="结果列表")
    metadata: Optional[Dict] = dspy.OutputField(desc="元数据")

内联签名 #

基本语法 #

python
import dspy

qa = dspy.Predict("question -> answer")
result = qa(question="测试问题")

多输入多输出 #

python
multi = dspy.Predict("input1, input2 -> output1, output2")
result = multi(input1="a", input2="b")

带描述的内联签名 #

python
detailed = dspy.Predict(
    "document -> summary: str, keywords: list"
)

内联签名的局限性 #

text
┌─────────────────────────────────────────────────────────────┐
│                    内联签名 vs 类签名                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  内联签名适合:                                              │
│  ✅ 简单的测试和原型                                        │
│  ✅ 单输入单输出的场景                                      │
│  ✅ 快速验证想法                                            │
│                                                             │
│  类签名适合:                                                │
│  ✅ 生产环境代码                                            │
│  ✅ 复杂的多输入多输出                                      │
│  ✅ 需要详细描述的场景                                      │
│  ✅ 需要复用的签名                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

签名继承 #

基本继承 #

python
class BaseQA(dspy.Signature):
    """基础问答签名"""
    question = dspy.InputField()
    answer = dspy.OutputField()

class DetailedQA(BaseQA):
    """详细问答签名"""
    context = dspy.InputField()
    reasoning = dspy.OutputField()

扩展签名 #

python
class BaseAnalysis(dspy.Signature):
    """基础分析"""
    text = dspy.InputField()
    analysis = dspy.OutputField()

class SentimentAnalysis(BaseAnalysis):
    """情感分析"""
    sentiment = dspy.OutputField(desc="情感倾向")

class EntityAnalysis(BaseAnalysis):
    """实体分析"""
    entities = dspy.OutputField(desc="识别的实体")

签名与提示词生成 #

DSPy 如何使用签名 #

text
┌─────────────────────────────────────────────────────────────┐
│                    签名到提示词的转换                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  签名定义:                                                  │
│  class QA(dspy.Signature):                                  │
│      """回答问题"""                                         │
│      question = dspy.InputField()                           │
│      answer = dspy.OutputField()                            │
│                                                             │
│  生成的提示词:                                              │
│  ---                                                        │
│  回答问题                                                    │
│                                                             │
│  Follow the following format.                               │
│                                                             │
│  Question: 用户的问题                                       │
│  Answer: 问题的答案                                         │
│  ---                                                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

文档字符串的重要性 #

python
class GoodSignature(dspy.Signature):
    """
    分析产品评论的情感倾向。
    
    请仔细阅读评论内容,考虑以下方面:
    1. 整体情感基调
    2. 具体提到的优点和缺点
    3. 用户的购买意图和满意度
    
    给出准确的情感分类和详细的分析理由。
    """
    review = dspy.InputField(desc="产品评论内容")
    sentiment = dspy.OutputField(desc="情感分类:正面/负面/中性")
    reasoning = dspy.OutputField(desc="分类理由")

签名设计最佳实践 #

1. 清晰的命名 #

python
class GoodNaming(dspy.Signature):
    """分析新闻文章的主题和立场"""
    article_content = dspy.InputField(desc="新闻文章的正文内容")
    main_topic = dspy.OutputField(desc="文章的主要话题")
    stance = dspy.OutputField(desc="文章的立场倾向")

2. 详细的描述 #

python
class GoodDescription(dspy.Signature):
    """生成产品描述"""
    product_name = dspy.InputField(desc="产品名称")
    features = dspy.InputField(desc="产品特性列表,JSON格式")
    target_audience = dspy.InputField(desc="目标受众描述")
    description = dspy.OutputField(
        desc="吸引人的产品描述,150-200字,"
             "突出产品特点和目标受众需求"
    )

3. 合理的字段划分 #

python
class GoodFieldDivision(dspy.Signature):
    """文档问答"""
    document = dspy.InputField(desc="参考文档")
    question = dspy.InputField(desc="用户问题")
    answer = dspy.OutputField(desc="基于文档的回答")
    source = dspy.OutputField(desc="答案在文档中的来源位置")

4. 避免过度复杂 #

python
class TooComplex(dspy.Signature):
    """过于复杂的签名 - 不推荐"""
    doc1 = dspy.InputField()
    doc2 = dspy.InputField()
    doc3 = dspy.InputField()
    question = dspy.InputField()
    context = dspy.InputField()
    style = dspy.InputField()
    length = dspy.InputField()
    answer = dspy.OutputField()
    summary = dspy.OutputField()
    keywords = dspy.OutputField()
    sentiment = dspy.OutputField()
    entities = dspy.OutputField()

class BetterDesign(dspy.Signature):
    """更好的设计"""
    documents = dspy.InputField(desc="相关文档列表")
    question = dspy.InputField(desc="用户问题")
    answer = dspy.OutputField(desc="综合回答")

签名验证 #

检查签名结构 #

python
import dspy

class MySignature(dspy.Signature):
    """测试签名"""
    question = dspy.InputField()
    answer = dspy.OutputField()

print(MySignature.input_fields)
print(MySignature.output_fields)
print(MySignature.instructions)

运行时验证 #

python
def validate_signature_output(signature, output):
    required_fields = signature.output_fields.keys()
    for field in required_fields:
        if field not in output:
            raise ValueError(f"缺少必需的输出字段: {field}")
    return True

常见签名模式 #

问答模式 #

python
class QuestionAnswer(dspy.Signature):
    """根据上下文回答问题"""
    context = dspy.InputField(desc="相关上下文")
    question = dspy.InputField(desc="用户问题")
    answer = dspy.OutputField(desc="基于上下文的回答")

摘要模式 #

python
class Summarize(dspy.Signature):
    """生成文档摘要"""
    document = dspy.InputField(desc="原始文档")
    max_length = dspy.InputField(desc="最大字数")
    summary = dspy.OutputField(desc="文档摘要")

分类模式 #

python
class Classify(dspy.Signature):
    """文本分类"""
    text = dspy.InputField(desc="待分类文本")
    categories = dspy.InputField(desc="可选类别列表")
    category = dspy.OutputField(desc="分类结果")
    confidence = dspy.OutputField(desc="置信度")

生成模式 #

python
class Generate(dspy.Signature):
    """内容生成"""
    topic = dspy.InputField(desc="主题")
    style = dspy.InputField(desc="风格要求")
    length = dspy.InputField(desc="长度要求")
    content = dspy.OutputField(desc="生成的内容")

转换模式 #

python
class Transform(dspy.Signature):
    """文本转换"""
    input_text = dspy.InputField(desc="输入文本")
    transformation = dspy.InputField(desc="转换类型")
    output_text = dspy.OutputField(desc="转换结果")

下一步 #

现在你已经深入了解了签名的各种用法,接下来学习 模块详解,掌握如何使用签名构建功能模块!

最后更新:2026-03-30