Minimal DSPy Foundational Layer
Core Principle
The smallest reusable unit that enables building any prompt engineering system
Foundation Components (4 Core Abstractions)
1. Execution Primitive (primitives/module.py
)
class BaseModule:
"""The fundamental execution unit - anything that can process inputs"""
def forward(self, **kwargs) -> dict
def __call__(self, **kwargs) -> dict # handles tracing, callbacks
def named_parameters(self) -> Iterator[Tuple[str, Any]]
def dump_state(self) -> dict
def load_state(self, state: dict) -> None
Why Essential: Every prompt engineering system needs composable execution units. This is the PyTorch.nn.Module equivalent.
2. Interface Contract (signatures/signature.py
)
class Signature:
"""Declarative I/O specification for any AI interaction"""
input_fields: Dict[str, FieldInfo]
output_fields: Dict[str, FieldInfo]
instructions: str
@classmethod
def from_string(cls, signature_str: str) -> 'Signature'
Why Essential: Every AI system needs to specify what goes in and what comes out. This is reusable across any AI modality.
3. Backend Interface (clients/base_lm.py
)
class BaseBackend:
"""Abstract interface to any AI service (LM, Vision, Audio, etc.)"""
def __call__(self, prompt=None, messages=None, **kwargs) -> Any
async def acall(self, prompt=None, messages=None, **kwargs) -> Any
Why Essential: Any prompt engineering system needs to talk to AI services. This abstraction works for LLMs, vision models, audio models, etc.
4. Format Bridge (adapters/base.py
)
class Adapter:
"""Converts between structured contracts and raw backend formats"""
def format(self, signature: Signature, inputs: dict, **kwargs) -> Any
def parse(self, signature: Signature, response: Any) -> dict
Why Essential: The gap between “what you want” (Signature) and “what the service expects” (strings/JSON/etc.) always exists.
Data Containers (2 Essential Types)
5. Data Primitive (primitives/example.py
)
class Example:
"""Universal data container for AI interactions"""
def __init__(self, **kwargs)
def inputs(self) -> dict
def labels(self) -> dict
def with_inputs(self, *keys) -> 'Example'
6. Configuration Context (utils/settings.py
)
class Settings:
"""Thread-safe global configuration"""
def configure(self, **kwargs)
def context(self, **kwargs) -> ContextManager
What’s NOT Included (Deliberately)
- No specific modules (ChainOfThought, ReAct) - these are implementations
- No specific adapters (ChatAdapter, JSONAdapter) - these are implementations
- No specific backends (OpenAI, Anthropic) - these are implementations
- No optimization (Teleprompters) - this is a higher-level concern
- No evaluation - this is application-level
- No retrieval - this is domain-specific
Size and Dependencies
Lines of Code: ~2,000 lines (vs. 50,000+ in full DSPy)
Dependencies:
pydantic
(for Signature field validation)typing_extensions
(for Python <3.9 compatibility)- That’s it.
Reusability Validation Test
This foundation enables building:
- Traditional prompt engineering:
Signature
+Adapter
+Backend
- Agent frameworks:
BaseModule
composition + tool integration viaAdapter
- Multi-modal systems: Same abstractions work for vision, audio, etc.
- Different paradigms: Function calling, structured output, reasoning chains
- Any language: These abstractions translate to Go, Rust, Elixir, etc.
Decoupling Achievement
✅ Zero knowledge of: Specific LLM providers, prompt formats, optimization strategies ✅ Zero dependencies on: Heavy ML libraries, specific service SDKs, optimization frameworks ✅ Maximum reuse: Same foundation works for chatbots, agents, analysis tools, creative apps
Example Usage
# This foundation enables any prompt engineering pattern:
# Simple completion
signature = Signature.from_string("question -> answer")
result = backend(adapter.format(signature, {"question": "What is AI?"}))
output = adapter.parse(signature, result)
# Complex multi-step reasoning
class ReasoningModule(BaseModule):
def forward(self, **kwargs):
# Any reasoning pattern can be built
pass
# Tool-using agent
class AgentModule(BaseModule):
def forward(self, **kwargs):
# Any agent pattern can be built
pass
Why This is the Right Boundary
- Maximum Reusability: These 6 components appear in every prompt engineering system
- Achievable Decoupling: No circular dependencies, clean interfaces
- Minimal Size: Small enough to understand, maintain, and trust
- Complete Foundation: Sufficient to build any higher-level pattern
- Future-Proof: Abstractions that won’t change as AI evolves
This is the Linux kernel of prompt engineering - minimal, stable, and universally useful.