dspy-signature-designer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDSPy Signature Designer
DSPy Signature 设计器
Goal
目标
Design clear, type-safe signatures that define what your DSPy modules should do.
设计清晰、类型安全的signature,定义你的DSPy模块应实现的功能。
When to Use
适用场景
- Defining new DSPy modules
- Need structured/validated outputs
- Complex input/output relationships
- Multi-field responses
- 定义新的DSPy模块
- 需要结构化/经过验证的输出
- 复杂的输入/输出关系
- 多字段响应
Inputs
输入
| Input | Type | Description |
|---|---|---|
| | What the module should do |
| | Required inputs |
| | Expected outputs |
| | Type hints for fields |
| 输入项 | 类型 | 描述 |
|---|---|---|
| | 模块应实现的功能 |
| | 必填输入项 |
| | 预期输出项 |
| | 字段的类型提示 |
Outputs
输出
| Output | Type | Description |
|---|---|---|
| | Type-safe signature class |
| 输出项 | 类型 | 描述 |
|---|---|---|
| | 类型安全的signature类 |
Workflow
工作流程
Inline Signatures (Simple)
内联Signature(简单场景)
python
import dspypython
import dspyBasic
Basic
qa = dspy.Predict("question -> answer")
qa = dspy.Predict("question -> answer")
With types
With types
classify = dspy.Predict("sentence -> sentiment: bool")
classify = dspy.Predict("sentence -> sentiment: bool")
Multiple fields
Multiple fields
rag = dspy.ChainOfThought("context: list[str], question: str -> answer: str")
undefinedrag = dspy.ChainOfThought("context: list[str], question: str -> answer: str")
undefinedClass-based Signatures (Complex)
基于类的Signature(复杂场景)
python
from typing import Literal, Optional
import dspy
class EmotionClassifier(dspy.Signature):
"""Classify the emotion expressed in the text."""
text: str = dspy.InputField(desc="The text to analyze")
emotion: Literal['joy', 'sadness', 'anger', 'fear', 'surprise'] = dspy.OutputField()
confidence: float = dspy.OutputField(desc="Confidence score 0-1")python
from typing import Literal, Optional
import dspy
class EmotionClassifier(dspy.Signature):
"""Classify the emotion expressed in the text."""
text: str = dspy.InputField(desc="The text to analyze")
emotion: Literal['joy', 'sadness', 'anger', 'fear', 'surprise'] = dspy.OutputField()
confidence: float = dspy.OutputField(desc="Confidence score 0-1")Type Hints Reference
类型提示参考
python
from typing import Literal, Optional, List
from pydantic import BaseModelpython
from typing import Literal, Optional, List
from pydantic import BaseModelBasic types
Basic types
field: str = dspy.InputField()
field: int = dspy.OutputField()
field: float = dspy.OutputField()
field: bool = dspy.OutputField()
field: str = dspy.InputField()
field: int = dspy.OutputField()
field: float = dspy.OutputField()
field: bool = dspy.OutputField()
Collections
Collections
field: list[str] = dspy.InputField()
field: List[int] = dspy.OutputField()
field: list[str] = dspy.InputField()
field: List[int] = dspy.OutputField()
Optional
Optional
field: Optional[str] = dspy.OutputField()
field: Optional[str] = dspy.OutputField()
Constrained
Constrained
field: Literal['a', 'b', 'c'] = dspy.OutputField()
field: Literal['a', 'b', 'c'] = dspy.OutputField()
Pydantic models
Pydantic models
class Person(BaseModel):
name: str
age: int
field: Person = dspy.OutputField()
undefinedclass Person(BaseModel):
name: str
age: int
field: Person = dspy.OutputField()
undefinedProduction Examples
生产环境示例
Summarization
文本摘要
python
class Summarize(dspy.Signature):
"""Summarize the document into key points."""
document: str = dspy.InputField(desc="Full document text")
max_points: int = dspy.InputField(desc="Maximum bullet points", default=5)
summary: list[str] = dspy.OutputField(desc="Key points as bullet list")
word_count: int = dspy.OutputField(desc="Total words in summary")python
class Summarize(dspy.Signature):
"""Summarize the document into key points."""
document: str = dspy.InputField(desc="Full document text")
max_points: int = dspy.InputField(desc="Maximum bullet points", default=5)
summary: list[str] = dspy.OutputField(desc="Key points as bullet list")
word_count: int = dspy.OutputField(desc="Total words in summary")Entity Extraction
实体抽取
python
from pydantic import BaseModel
from typing import List
class Entity(BaseModel):
text: str
type: str
start: int
end: int
class ExtractEntities(dspy.Signature):
"""Extract named entities from text."""
text: str = dspy.InputField()
entity_types: list[str] = dspy.InputField(
desc="Types to extract: PERSON, ORG, LOC, DATE",
default=["PERSON", "ORG", "LOC"]
)
entities: List[Entity] = dspy.OutputField()python
from pydantic import BaseModel
from typing import List
class Entity(BaseModel):
text: str
type: str
start: int
end: int
class ExtractEntities(dspy.Signature):
"""Extract named entities from text."""
text: str = dspy.InputField()
entity_types: list[str] = dspy.InputField(
desc="Types to extract: PERSON, ORG, LOC, DATE",
default=["PERSON", "ORG", "LOC"]
)
entities: List[Entity] = dspy.OutputField()Multi-Label Classification
多标签分类
python
class MultiLabelClassify(dspy.Signature):
"""Classify text into multiple categories."""
text: str = dspy.InputField()
categories: list[str] = dspy.OutputField(
desc="Applicable categories from: tech, business, sports, entertainment"
)
primary_category: str = dspy.OutputField(desc="Most relevant category")
reasoning: str = dspy.OutputField(desc="Explanation for classification")python
class MultiLabelClassify(dspy.Signature):
"""Classify text into multiple categories."""
text: str = dspy.InputField()
categories: list[str] = dspy.OutputField(
desc="Applicable categories from: tech, business, sports, entertainment"
)
primary_category: str = dspy.OutputField(desc="Most relevant category")
reasoning: str = dspy.OutputField(desc="Explanation for classification")RAG with Confidence
带置信度的RAG
python
class GroundedAnswer(dspy.Signature):
"""Answer questions using retrieved context with confidence."""
context: list[str] = dspy.InputField(desc="Retrieved passages")
question: str = dspy.InputField()
answer: str = dspy.OutputField(desc="Factual answer from context")
confidence: Literal['high', 'medium', 'low'] = dspy.OutputField(
desc="Confidence based on context support"
)
source_passage: int = dspy.OutputField(
desc="Index of most relevant passage (0-based)"
)python
class GroundedAnswer(dspy.Signature):
"""Answer questions using retrieved context with confidence."""
context: list[str] = dspy.InputField(desc="Retrieved passages")
question: str = dspy.InputField()
answer: str = dspy.OutputField(desc="Factual answer from context")
confidence: Literal['high', 'medium', 'low'] = dspy.OutputField(
desc="Confidence based on context support"
)
source_passage: int = dspy.OutputField(
desc="Index of most relevant passage (0-based)"
)Complete Module with Signature
带Signature的完整模块
python
import dspy
from typing import Literal, Optional
import logging
logger = logging.getLogger(__name__)
class AnalyzeSentiment(dspy.Signature):
"""Analyze sentiment with detailed breakdown."""
text: str = dspy.InputField(desc="Text to analyze")
sentiment: Literal['positive', 'negative', 'neutral', 'mixed'] = dspy.OutputField()
score: float = dspy.OutputField(desc="Sentiment score from -1 to 1")
aspects: list[str] = dspy.OutputField(desc="Key aspects mentioned")
reasoning: str = dspy.OutputField(desc="Explanation of sentiment")
class SentimentAnalyzer(dspy.Module):
def __init__(self):
self.analyze = dspy.ChainOfThought(AnalyzeSentiment)
def forward(self, text: str):
try:
result = self.analyze(text=text)
# Validate score range
if hasattr(result, 'score'):
result.score = max(-1, min(1, float(result.score)))
return result
except Exception as e:
logger.error(f"Analysis failed: {e}")
return dspy.Prediction(
sentiment='neutral',
score=0.0,
aspects=[],
reasoning="Analysis failed"
)python
import dspy
from typing import Literal, Optional
import logging
logger = logging.getLogger(__name__)
class AnalyzeSentiment(dspy.Signature):
"""Analyze sentiment with detailed breakdown."""
text: str = dspy.InputField(desc="Text to analyze")
sentiment: Literal['positive', 'negative', 'neutral', 'mixed'] = dspy.OutputField()
score: float = dspy.OutputField(desc="Sentiment score from -1 to 1")
aspects: list[str] = dspy.OutputField(desc="Key aspects mentioned")
reasoning: str = dspy.OutputField(desc="Explanation of sentiment")
class SentimentAnalyzer(dspy.Module):
def __init__(self):
self.analyze = dspy.ChainOfThought(AnalyzeSentiment)
def forward(self, text: str):
try:
result = self.analyze(text=text)
# Validate score range
if hasattr(result, 'score'):
result.score = max(-1, min(1, float(result.score)))
return result
except Exception as e:
logger.error(f"Analysis failed: {e}")
return dspy.Prediction(
sentiment='neutral',
score=0.0,
aspects=[],
reasoning="Analysis failed"
)Usage
Usage
analyzer = SentimentAnalyzer()
result = analyzer(text="The product quality is great but shipping was slow.")
print(f"Sentiment: {result.sentiment} ({result.score})")
print(f"Aspects: {result.aspects}")
undefinedanalyzer = SentimentAnalyzer()
result = analyzer(text="The product quality is great but shipping was slow.")
print(f"Sentiment: {result.sentiment} ({result.score})")
print(f"Aspects: {result.aspects}")
undefinedBest Practices
最佳实践
- Descriptive docstrings - The class docstring becomes the task instruction
- Field descriptions - Guide the model with parameter
desc - Constrain outputs - Use for categorical outputs
Literal - Default values - Provide sensible defaults for optional inputs
- Validate types - Pydantic models ensure structured output
- 描述性文档字符串 - 类的文档字符串将作为任务指令
- 字段描述 - 使用参数引导模型
desc - 约束输出 - 对分类输出使用
Literal - 默认值 - 为可选输入提供合理的默认值
- 类型验证 - Pydantic模型确保输出结构化
Advanced Field Options
高级字段选项
python
undefinedpython
undefinedConstraints (available in 3.1.2+)
Constraints (available in 3.1.2+)
class ConstrainedSignature(dspy.Signature):
"""Example with validation constraints."""
text: str = dspy.InputField(
min_length=5,
max_length=100,
desc="Input text between 5-100 chars"
)
number: int = dspy.InputField(
gt=0,
lt=10,
desc="Number between 0 and 10"
)
score: float = dspy.OutputField(
ge=0.0,
le=1.0,
desc="Score between 0 and 1"
)
count: int = dspy.OutputField(
multiple_of=2,
desc="Even number count"
)class ConstrainedSignature(dspy.Signature):
"""Example with validation constraints."""
text: str = dspy.InputField(
min_length=5,
max_length=100,
desc="Input text between 5-100 chars"
)
number: int = dspy.InputField(
gt=0,
lt=10,
desc="Number between 0 and 10"
)
score: float = dspy.OutputField(
ge=0.0,
le=1.0,
desc="Score between 0 and 1"
)
count: int = dspy.OutputField(
multiple_of=2,
desc="Even number count"
)Prefix and format
Prefix and format
class FormattedSignature(dspy.Signature):
"""Example with custom prefix and format."""
goal: str = dspy.InputField(prefix="Goal:")
text: str = dspy.InputField(format=lambda x: x.upper())
action: str = dspy.OutputField(prefix="Action:")undefinedclass FormattedSignature(dspy.Signature):
"""Example with custom prefix and format."""
goal: str = dspy.InputField(prefix="Goal:")
text: str = dspy.InputField(format=lambda x: x.upper())
action: str = dspy.OutputField(prefix="Action:")undefinedLimitations
局限性
- Complex nested types require Pydantic models
- Some LLMs struggle with strict type constraints
- Field descriptions and constraints add to prompt length
- Default values only work for InputField, not OutputField
- 复杂嵌套类型需要使用Pydantic模型
- 部分大语言模型难以处理严格的类型约束
- 字段描述和约束会增加提示词长度
- 默认值仅适用于InputField,不适用于OutputField
Official Documentation
官方文档
- DSPy Documentation: https://dspy.ai/
- DSPy GitHub: https://github.com/stanfordnlp/dspy
- Signatures API: https://dspy.ai/api/signatures/
- Signatures Guide: https://dspy.ai/learn/programming/signatures/
- DSPy Documentation: https://dspy.ai/
- DSPy GitHub: https://github.com/stanfordnlp/dspy
- Signatures API: https://dspy.ai/api/signatures/
- Signatures Guide: https://dspy.ai/learn/programming/signatures/