Dsxir.LM behaviour (dsxir v0.1.0)

Copy Markdown

Behaviour for LM providers.

Predictors and adapters issue LM requests through this contract; they never reach into a specific provider SDK directly. The active impl plus its config live in Dsxir.Settings under :lm as a {impl_module, config :: keyword()} tuple. The dispatcher functions on this module read :lm from settings, merge per-call opts on top of the config, and invoke the impl.

The behaviour declares the callbacks predictors and adapters call. New callbacks (structured output for the Json adapter, streaming for the Chat adapter, embeddings for the in-memory retriever) extend the behaviour when their consumers land — old impls keep working while their new-callback path raises until implemented.

In tests, stub impl callbacks with mimic rather than building bespoke fakes.

Summary

Functions

Dispatch an embed call to the impl module currently active in Dsxir.Settings. Per-call opts are merged on top of the config. Raises Dsxir.Errors.Invalid.Configuration when :lm is unset, malformed, or the configured impl does not implement the optional embed/3 callback.

Empty usage map used by impls when the upstream LM did not report token counts or cost. The shape is always present: tokens_in, tokens_out, and cost are all nil.

Dispatch a generate_object call to the impl module currently active in Dsxir.Settings, requesting a structured object validated against schema.

Dispatch a generate_text call to the impl module currently active in Dsxir.Settings. Per-call opts are merged on top of the config from settings. Raises Dsxir.Errors.Invalid.Configuration when :lm is unset or malformed.

Types

config()

@type config() :: keyword()

messages()

@type messages() :: [map()]

opts()

@type opts() :: keyword()

usage()

@type usage() :: %{
  tokens_in: nil | non_neg_integer(),
  tokens_out: nil | non_neg_integer(),
  cost: nil | float()
}

Callbacks

embed(config, list, opts)

(optional)
@callback embed(config(), [String.t()], opts()) ::
  {:ok, [[float()]], usage()} | {:error, term()}

generate_object(config, messages, schema, opts)

(optional)
@callback generate_object(config(), messages(), Zoi.schema(), opts()) ::
  {:ok, map(), usage()} | {:error, term()}

generate_text(config, messages, opts)

@callback generate_text(config(), messages(), opts()) ::
  {:ok, String.t(), usage()} | {:error, term()}

Functions

embed(inputs, opts \\ [])

@spec embed([String.t()], opts()) :: {:ok, [[float()]], usage()} | {:error, term()}

Dispatch an embed call to the impl module currently active in Dsxir.Settings. Per-call opts are merged on top of the config. Raises Dsxir.Errors.Invalid.Configuration when :lm is unset, malformed, or the configured impl does not implement the optional embed/3 callback.

empty_usage()

@spec empty_usage() :: usage()

Empty usage map used by impls when the upstream LM did not report token counts or cost. The shape is always present: tokens_in, tokens_out, and cost are all nil.

generate_object(messages, schema, opts \\ [])

@spec generate_object(messages(), Zoi.schema(), opts()) ::
  {:ok, map(), usage()} | {:error, term()}

Dispatch a generate_object call to the impl module currently active in Dsxir.Settings, requesting a structured object validated against schema.

Per-call opts are merged on top of the config from settings. Raises Dsxir.Errors.Invalid.Configuration when :lm is unset, malformed, or when the configured impl does not implement the optional generate_object/4 callback.

generate_text(messages, opts \\ [])

@spec generate_text(messages(), opts()) ::
  {:ok, String.t(), usage()} | {:error, term()}

Dispatch a generate_text call to the impl module currently active in Dsxir.Settings. Per-call opts are merged on top of the config from settings. Raises Dsxir.Errors.Invalid.Configuration when :lm is unset or malformed.