Chapter 2 ยท Section 2

What Are Signatures?

Signatures are declarative specifications that define what a language model task doesโ€”without specifying how.

~15 min read

Signature: A Task Contract

A Signature in DSPy is a specification that defines the inputs and outputs of a language model task, similar to a function signature in programming.

๐Ÿ’ก Think of It Like a Function Signature

In Python, a function signature tells you what goes in and what comes out:

# Python function signature
def add_numbers(a: int, b: int) -> int:
    """Add two numbers and return the result."""
    return a + b

Similarly, a DSPy signature defines the contract for an LM task:

# DSPy signature
class QuestionAnswer(dspy.Signature):
    """Answer questions accurately."""
    question: str = dspy.InputField()   # What goes in
    answer: str = dspy.OutputField()    # What comes out
๐Ÿ’ก

Key Insight: You don't write the implementation (the prompt)โ€”DSPy generates it for you based on your signature!

๐Ÿงฉ Components of a Signature

Every signature has three essential parts:

๐Ÿ“ƒ

Docstring (Task Description)

Describes what the task does. This becomes part of the prompt that DSPy generates.

class Summarize(dspy.Signature):
    """Summarize the given text in 2-3 sentences."""  # โ† Docstring
    ...
๐Ÿ“ฅ

Input Fields

Define what data the task receives. Use dspy.InputField().

class Summarize(dspy.Signature):
    """Summarize the given text."""
    text: str = dspy.InputField()       # โ† Input field
    ...
๐Ÿ“ค

Output Fields

Define what the task produces. Use dspy.OutputField().

class Summarize(dspy.Signature):
    """Summarize the given text."""
    text: str = dspy.InputField()
    summary: str = dspy.OutputField()   # โ† Output field

๐Ÿ“ A Complete Example

Here's a signature for sentiment analysis with all components:

import dspy

class SentimentAnalysis(dspy.Signature):
    """Analyze the sentiment of the given text and classify it."""
    
    # Input: The text to analyze
    text: str = dspy.InputField(
        desc="The text to analyze for sentiment"
    )
    
    # Outputs: Classification and confidence
    sentiment: str = dspy.OutputField(
        desc="The sentiment: 'positive', 'negative', or 'neutral'"
    )
    confidence: str = dspy.OutputField(
        desc="Confidence level: 'high', 'medium', or 'low'"
    )

Using this signature:

# Create a predictor from the signature
analyzer = dspy.Predict(SentimentAnalysis)

# Use it
result = analyzer(text="I absolutely love this product!")

print(f"Sentiment: {result.sentiment}")      # positive
print(f"Confidence: {result.confidence}")    # high

๐Ÿ”ฎ Why Signatures Work

When you use a signature, DSPy automatically:

1๏ธโƒฃ

Generates a Prompt

DSPy creates an optimized prompt from your docstring, field names, and descriptions.

2๏ธโƒฃ

Formats Your Input

Your input data is properly formatted and inserted into the prompt.

3๏ธโƒฃ

Calls the LM

The formatted prompt is sent to your configured language model.

4๏ธโƒฃ

Parses the Output

The LM's response is parsed and returned as a structured object with your named output fields.

๐ŸŽฏ

The magic: You focus on what you want, and DSPy handles how to get it!

๐Ÿ“ Two Ways to Define Signatures

DSPy offers two syntax options:

Inline Signatures

# Quick, simple syntax
qa = dspy.Predict("question -> answer")

# With multiple fields
summarize = dspy.Predict(
    "document, max_length -> summary"
)
โœ… Quick prototyping โœ… Simple tasks โš ๏ธ Limited control

Class-Based Signatures

# Full-featured syntax
class QA(dspy.Signature):
    """Answer questions accurately."""
    question: str = dspy.InputField()
    answer: str = dspy.OutputField(
        desc="concise answer"
    )
โœ… Full documentation โœ… Type hints โœ… Production-ready

We'll cover both in detail in the following sections.

๐ŸŽจ Common Signature Patterns

Here are signatures for common NLP tasks:

# Question Answering
class QA(dspy.Signature):
    """Answer the question based on the context."""
    context: str = dspy.InputField()
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()

# Summarization
class Summarize(dspy.Signature):
    """Create a concise summary."""
    document: str = dspy.InputField()
    summary: str = dspy.OutputField()

# Classification
class Classify(dspy.Signature):
    """Classify the text into a category."""
    text: str = dspy.InputField()
    category: str = dspy.OutputField()

# Translation
class Translate(dspy.Signature):
    """Translate text to the target language."""
    text: str = dspy.InputField()
    target_language: str = dspy.InputField()
    translation: str = dspy.OutputField()

# Entity Extraction
class ExtractEntities(dspy.Signature):
    """Extract named entities from text."""
    text: str = dspy.InputField()
    entities: list[str] = dspy.OutputField()

๐Ÿ“ Key Takeaways

Signatures are contracts that define task inputs and outputs

Three components: docstring, input fields, output fields

DSPy generates prompts automatically from your signature

Two syntax options: inline (quick) and class-based (full-featured)

Signatures enable optimization because they're declarative