← Back to 003 decomposition

003 gemini

Documentation for 003_gemini from the Ds ex repository.

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:

  1. Primitives: Example and Prediction

    • 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.
  2. 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 a Signature (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.
  3. 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 the forward 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.

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.
  • LM and RM 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.
  • 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.
  • 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.

graph TD subgraph "The DSPy Abstract Model (Smallest Foundational Layer)" direction LR subgraph "Data Contracts" A(Example Struct) B(Prediction Struct) end subgraph "I/O Contracts" C(Signature Metaclass) D(InputField) E(OutputField) end subgraph "Composition Contract" F(BaseModule / Program ABC) end end C -- "Creates Signatures with" --> D C -- "Creates Signatures with" --> E note right of A Pure Data. No execution logic. Can be serialized and passed anywhere. end note right of C Pure Description. Defines the 'what', not the 'how'. No knowledge of prompts or LMs. end note right of F Pure Structure. Defines how programs are composed and managed. No `forward` implementation. end

Why This is the Right Boundary for a Foundational Layer

  1. Maximum Reusability:

    • The Signature and Example structs can be used anywhere, even outside of a full DSPy runtime. For instance, a data validation pipeline could use Signatures to define its schemas. A logging system could use Examples 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.
  2. 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.
  3. Stability:

    • The concepts in this layer are the most stable parts of DSPy. The definition of a Signature or an Example 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.

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.