Skip to content

Composing programs

Programs are ordinary Scala values, so you compose them the way you compose any other code: call one program inside another. To package a multi-step pipeline as a single reusable program, extend DynamicModule and chain predictors in its forward method.

This module answers a question, then rewrites the answer in simpler terms, using two predictors in sequence:

final class SimplifyModule extends DynamicModule:
  override val moduleName: String = "simplify_module"
  private val predict1            = DynamicPredict(Signature.fromString("question -> answer").layout, name = Some("predict1"))
  private val predict2            =
    DynamicPredict(Signature.fromString("answer -> simplified_answer").layout, name = Some("predict2"))

  override protected def forwardDynamic(call: ProgramCall[DynamicValue.Record])(using
      RuntimeContext
  ): Either[DspyError, RawPrediction] =
    for
      step1 <- predict1(call)
      answer = textField(step1.output, "answer")
      step2 <- predict2(ProgramCall(input = DynamicValues.recordFromEntries(Vector("answer" := answer))))
    yield step2.raw

The result is itself a program: you call it with inputs, it returns a prediction, and it can be evaluated, optimized, saved, or nested inside a still larger module, exactly like a single Predict.

What to notice

  • Each step is a named DynamicPredict. Naming matters when you later want to optimize or stream a specific step.
  • forwardDynamic returns Either[DspyError, RawPrediction], so a failure in any step short-circuits the for comprehension. DynamicModule then lifts that value into the uniform Prediction[DynamicValue.Record] boundary.
  • Nothing about composition is special-cased. A composite module is the same kind of value as the modules it contains.

When to use it

You want Approach
A one-off pipeline Call programs in sequence in plain code.
A reusable multi-step program Extend DynamicModule, chain predictors in forward.
The model to choose the steps Use ReAct instead of fixing them.

Next: Language models.