RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Fredoline Eruo
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /Courses
  5. /Advanced Prompt Engineering
  6. /Ch. 7
Advanced Prompt Engineering

07. DSPy Introduction

Chapter 7 of 18 · 20 min
KEY INSIGHT

DSPy abstracts prompt behavior into declared signatures and composed modules, compiling prompts from data rather than hand-coding them.

DSPy (Declarative Self-Programming) reframes prompt engineering from writing prompt strings to declaring computational traces that the system compiles into prompts. The motivation: hand-written prompts are brittle, hard to evaluate, and don't transfer well across model changes. DSPy treats prompts as compiled artifacts optimized against data.

The core concept: a "module" wraps language model calls. Rather than writing ollama.generate(prompt), you use dspy.Predict(MySignature). The module has a signature—an abstract specification of what inputs to what outputs. DSPy's compiler determines how to prompt the model to implement that signature for your specific data.

This matters because it separates concerns. The user declares what the module should do (signature). DSPy decides how to make it do that (compiled prompt + chain-of-thought if needed). The user evaluates whether the result is good. If not, DSPy re-optimizes. This is closer to how traditional compiled languages work: you specify behavior; the compiler figures out machine instructions.

import dspy
from dspy.evaluate import Evaluate

# Configure DSPy to use Ollama
llm = dspy.OllamaLocal(
    model='llama3.2',
    base_url='http://localhost:11434'
)
dspy.settings.configure(lm=llm)

# A basic Signature: define input and output fields
class ExtractPersonInfo(dspy.Signature):
    """Extract structured information from unstructured text about a person."""
    text = dspy.InputField()
    name = dspy.OutputField()
    role = dspy.OutputField()
    organization = dspy.OutputField()

# Create a module that implements this signature
extract = dspy.Predict(ExtractPersonInfo)

# Use it like a function
result = extract(text="Dr. Sarah Chen is the Chief Technology Officer at InnovateTech Labs. She previously led engineering at two startups.")

print(f"Name: {result.name}")
print(f"Role: {result.role}")
print(f"Organization: {result.organization}")

The signature declares outputs without specifying format, instructions, or examples. DSPy's default behavior generates a basic prompt that asks the model to produce those fields. The compilation process improves that prompt based on your data and evaluation criteria.

DSPy introduces the concept of programs: sequences of modules combined into larger workflows. A dspy.ChainOfThought module adds reasoning. A dspy.ChainOfThoughtVote votes across multiple responses. Programs compose: you can chain modules, add feedback loops, and create complex behaviors from simple building blocks.

# A more complex program: extract then validate
class ValidateExtraction(dspy.Signature):
    """Verify extracted information against original text."""
    original_text = dspy.InputField()
    extracted_name = dspy.InputField()
    extracted_role = dspy.InputField()
    extracted_org = dspy.InputField()
    is_valid = dspy.OutputField()
    correction_notes = dspy.OutputField()

extract = dspy.Predict(ExtractPersonInfo)
validate = dspy.Predict(ValidateExtraction)

# Simple composition
def extract_and_validate(text: str):
    extraction = extract(text=text)
    validation = validate(
        original_text=text,
        extracted_name=extraction.name,
        extracted_role=extraction.role,
        extracted_org=extraction.organization
    )
    return {
        'extraction': extraction,
        'validation': validation,
        'is_valid': validation.is_valid.lower() == 'true'
    }

result = extract_and_validate("Your meeting with COO Maria Santos is confirmed for 2pm.")
if not result['is_valid']:
    print(f"Notes: {result['validation'].correction_notes}")

The library currently has rough edges. The Ollama local integration works but documentation assumes OpenAI API access. Error messages are cryptic. The optimizer system (discussed in Chapter 9) requires labeled data that takes effort to produce. DSPy is a effective direction but requires tolerance for partial documentation and experimentation.

EXERCISE

Install DSPy and run the basic signature example against your Ollama instance. Identify one discrepancy between the documentation and your actual experience. Document whether DSPy modules improve or complicate your workflow for simple extraction tasks.

← Chapter 6
Dynamic Prompt Construction
Chapter 8 →
DSPy Signatures