Configuring a language model¶
A program needs a language model to run. dspy4s ships one provider,
OpenAiLanguageModel, which speaks the OpenAI /chat/completions shape. That
covers OpenAI and every OpenAI-compatible server (Azure, Ollama, vLLM, SGLang,
LM Studio, OpenRouter).
Constructing a model¶
Pass a model name and an API key:
For a local server that does not check credentials, use local with the
server's base URL:
def ollama(model: String = "llama3.2"): LanguageModel =
OpenAiLanguageModel.local(model, baseUrl = "http://localhost:11434/v1")
OpenAiLanguageModel.fromEnv(model) reads OPENAI_API_KEY from the environment,
which is what the bundled examples use.
Installing it¶
A model becomes active by putting it in the runtime
context. The Quickstart
shows the full wiring with RuntimeEnvironment.withSettings.
Calling a model directly¶
Most of the time a module calls the model for you. When you need the raw call,
use LanguageModel.call, which returns Either[DspyError, LmResponse]:
def callDirect(prompt: String)(using ctx: RuntimeContext): Either[DspyError, String] =
ctx.lm match
case Some(lm: LanguageModel) =>
val request = LmRequest(
model = lm.id,
messages = Vector(Message(role = MessageRole.User, text = Some(prompt)))
)
lm.call(request).map(_.outputs.headOption.map(_.text).getOrElse(""))
case _ => Left(dspy4s.core.contracts.ConfigurationError("no LanguageModel configured"))
Per-call generation settings¶
Generation parameters such as temperature go in a per-call config bag.
rolloutId is a dedicated field used to bust the cache for an otherwise-identical
call:
def askWithConfig(question: String, temperature: Double, rolloutId: Int)(using
RuntimeContext
): Either[DspyError, String] =
qa(ProgramCall(
input = (question = question),
config = DynamicValues.record("temperature" := temperature),
rolloutId = Some(rolloutId)
)).map(_.output.answer)
Errors¶
dspy4s never throws on a model failure. Every call returns an Either, and
DspyError carries a stable code and message:
def askHandlingErrors(question: String)(using RuntimeContext): String =
ask(question) match
case Right(answer) => answer
case Left(err) => s"LM failed: code=${err.code}, message=${err.message}"
Next: Adapters.