Excellent question. This gets to the heart of defining a truly minimal and powerful core. By focusing on reusability and decoupling, we can identify the absolute smallest set of components that constitute a “foundational layer.”
The answer is surprisingly small. The most cohesive, reusable, and decoupled foundational layer is what we can call the DSPy Abstract Model. It does not contain any execution logic itself. Instead, it defines the language and contracts for describing an LM program.
Let’s break down what this minimal foundation looks like and why its boundaries are drawn this way.
The Smallest Foundational Layer: The DSPy Abstract Model
Core Principle: This layer contains only the components necessary to describe and structure an LM program and its data, without making any assumptions about how that program will be executed. It is the universal grammar of DSPy.
This layer would correspond to the proposed dspy-core
package, but stripped down even further to its bare essentials.
Components of the “Abstract Model” Layer:
Primitives:
Example
andPrediction
- Why they belong: These are the universal data carriers. Every part of any DSPy system, from training data to final output, uses these structures. They are pure data containers with a simple, reusable interface (
with_inputs
,labels
). - Decoupling: They are completely decoupled from any execution logic, LMs, or optimizers. They are just structured dictionaries.
- Why they belong: These are the universal data carriers. Every part of any DSPy system, from training data to final output, uses these structures. They are pure data containers with a simple, reusable interface (
Signatures:
Signature
,InputField
,OutputField
- Why they belong: The
Signature
is the most fundamental concept in DSPy. It is the declarative contract that separates intent from implementation. It’s a reusable blueprint for a task. The logic for creating aSignature
(e.g., from a string) is self-contained and does not depend on any runtime components. - Decoupling: A
Signature
on its own does nothing. It is a passive description of a program’s I/O. It has no knowledge of LMs, prompts, or adapters. It is the ultimate reusable and decoupled component.
- Why they belong: The
Module Abstraction:
BaseModule
/Program
- Why they belong: This defines the concept of a composable, stateful building block. It establishes the contract that all executable components must follow: they have parameters (
named_parameters
), they can be saved/loaded (dump_state
/load_state
), and they can be composed. It does not include theforward
method’s execution logic, only its abstract definition. - Decoupling:
BaseModule
is an abstract class. It provides the reusable pattern for composition but contains no concrete implementation, making it perfectly decoupled from any specific runtime.
- Why they belong: This defines the concept of a composable, stateful building block. It establishes the contract that all executable components must follow: they have parameters (
What is Explicitly Excluded from this Foundational Layer (and Why):
dspy.Predict
and other Concrete Modules:- Reason for Exclusion:
Predict
is an implementation. It contains the logic for executing a signature, which involves making an LM call. This couples it to an LM client and an adapter. It is not part of the abstract description of a program.
- Reason for Exclusion:
LM
andRM
Clients:- Reason for Exclusion: These are concrete runtime components responsible for I/O. Their existence is an implementation detail. The abstract model only needs to know that something will eventually fulfill the
Signature
’s contract, not what that something is.
- Reason for Exclusion: These are concrete runtime components responsible for I/O. Their existence is an implementation detail. The abstract model only needs to know that something will eventually fulfill the
Adapter
Layer:- Reason for Exclusion: Adapters are the bridge between the abstract model (
Signature
) and a concrete runtime (LM
client). They are an implementation concern, translating the abstract description into a specific format (e.g., a chat prompt). The foundation doesn’t need to know how a signature will be formatted, only what its fields are.
- Reason for Exclusion: Adapters are the bridge between the abstract model (
Optimizers (
Teleprompter
):- Reason for Exclusion: Optimizers are high-level meta-programs that operate on and manipulate other programs. They are consumers of the foundational layer, not part of it. They depend on having a fully executable runtime (modules, clients, metrics) to function.
Evaluate
and Metrics:- Reason for Exclusion: Evaluation is a process that runs an existing program. It requires a concrete, executable program and is therefore part of the runtime, not the abstract descriptive layer.
Visualizing the Smallest Foundational Layer
This layer is purely about defining the structure and contracts.
Why This is the Right Boundary for a Foundational Layer
Maximum Reusability:
- The
Signature
andExample
structs can be used anywhere, even outside of a full DSPy runtime. For instance, a data validation pipeline could useSignatures
to define its schemas. A logging system could useExamples
to structure its logs. - This layer can be a dependency for any DSPy-compliant runtime (
dspy
,dspy-lite
,DSPEx
, etc.) without pulling in any heavy dependencies.
- The
Maximum Decoupling:
- This foundation is completely agnostic to:
- Which LM is used (OpenAI, Anthropic, local).
- How the LM is called (Chat API, text completion, function calling).
- How the program is optimized (Few-shot, finetuning, instruction optimization).
- How the program is executed (Synchronously, asynchronously, in parallel).
- This clean separation is the key to architectural flexibility. It allows for the creation of diverse and competing runtimes that all adhere to the same programming model.
- This foundation is completely agnostic to:
Stability:
- The concepts in this layer are the most stable parts of DSPy. The definition of a
Signature
or anExample
is unlikely to change drastically, even as new LMs and optimization techniques emerge. - By isolating this into a foundational package (
dspy-core
), you create a stable base that other, more rapidly evolving packages (dspy-runtime
) can build upon without introducing breaking changes to the core contract.
- The concepts in this layer are the most stable parts of DSPy. The definition of a
In conclusion, the smallest, most cohesive, and reusable foundational layer is the DSPy Abstract Model. It consists solely of the primitives required to describe a program’s structure and data contracts, intentionally excluding all components related to execution. This provides a stable, dependency-light, and highly decoupled foundation upon which multiple, diverse runtimes can be built.