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