Synaptic.Eval.Integration behaviour (synaptic v0.2.6)
View SourceBehaviour for integrating with 3rd party eval services like Braintrust, LangSmith, etc.
Eval integrations observe LLM calls and scorer results via Telemetry events and can combine them into complete eval records for external services.
Example Implementation
defmodule MyApp.Eval.BraintrustIntegration do
@behaviour Synaptic.Eval.Integration
@impl Synaptic.Eval.Integration
def on_llm_call(_event, measurements, metadata, config) do
# Log LLM call with tokens, input, output
usage = Map.get(metadata, :usage, %{})
Braintrust.log({
run_id: metadata.run_id,
step: metadata.step_name,
input: metadata.input, # You'd need to capture this separately
output: metadata.output, # You'd need to capture this separately
model: metadata.model,
prompt_tokens: Map.get(usage, :prompt_tokens, 0),
completion_tokens: Map.get(usage, :completion_tokens, 0),
total_tokens: Map.get(usage, :total_tokens, 0),
duration_ms: System.convert_time_unit(measurements.duration, :native, :millisecond)
})
end
@impl Synaptic.Eval.Integration
def on_scorer_result(_event, measurements, metadata, config) do
# Log scorer result
Braintrust.log_score({
run_id: metadata.run_id,
step: metadata.step_name,
scorer: metadata.scorer,
score: metadata.score,
reason: metadata.reason
})
end
endAttaching the Integration
Attach your integration in your application startup (e.g., in application.ex):
defmodule MyApp.Application do
def start(_type, _args) do
# ... other setup ...
Synaptic.Eval.Integration.attach(MyApp.Eval.BraintrustIntegration, %{
# Your config here
})
# ... rest of startup ...
end
endCombining LLM Metrics with Scorer Results
To combine LLM metrics with scorer results, you can:
- Store LLM call data in a process dictionary or ETS table keyed by
{run_id, step_name} - When scorer results arrive, look up the corresponding LLM call
- Combine both into a single eval record
See the README for more detailed examples.
Summary
Callbacks
Called when an LLM call completes.
Called when a scorer completes.
Called when a step completes.
Functions
Attaches Telemetry handlers for the given integration module.
Detaches Telemetry handlers for the given integration module.
Callbacks
@callback on_llm_call( event :: [atom()], measurements :: map(), metadata :: map(), config :: term() ) :: :ok
Called when an LLM call completes.
This callback is invoked via a Telemetry handler attached to [:synaptic, :llm, :stop].
Parameters
event- The Telemetry event name (e.g.,[:synaptic, :llm, :stop])measurements- Map containing:durationand optionally token countsmetadata- Map containing::run_id- Workflow run identifier:step_name- Step name (atom):adapter- Adapter module:model- Model name:stream- Boolean indicating if streaming was used:usage- Optional usage map with:prompt_tokens,:completion_tokens,:total_tokens
config- Configuration passed toattach/2
@callback on_scorer_result( event :: [atom()], measurements :: map(), metadata :: map(), config :: term() ) :: :ok
Called when a scorer completes.
This callback is invoked via a Telemetry handler attached to [:synaptic, :scorer, :stop].
Parameters
event- The Telemetry event name (e.g.,[:synaptic, :scorer, :stop])measurements- Map containing:durationmetadata- Map containing::run_id- Workflow run identifier:workflow- Workflow module:step_name- Step name (atom):scorer- Scorer module:status-:okor:error:score- Score value (number, ornilon error):reason- Reason string (or error message)
config- Configuration passed toattach/2
@callback on_step_complete( event :: [atom()], measurements :: map(), metadata :: map(), config :: term() ) :: :ok
Called when a step completes.
This optional callback can be used to combine LLM metrics with scorer results
after a step finishes. It's invoked via a Telemetry handler attached to
[:synaptic, :step, :stop].
Parameters
event- The Telemetry event name (e.g.,[:synaptic, :step, :stop])measurements- Map containing:durationmetadata- Map containing::run_id- Workflow run identifier:workflow- Workflow module:step_name- Step name (atom):type- Step type:status-:ok,:suspend,:error, or:unknown
config- Configuration passed toattach/2
Functions
Attaches Telemetry handlers for the given integration module.
This function sets up Telemetry handlers that call the integration's callbacks when LLM calls, scorer results, or step completions occur.
Parameters
integration_module- Module implementingSynaptic.Eval.Integrationconfig- Configuration map passed to all callbacks
Example
Synaptic.Eval.Integration.attach(MyApp.Eval.BraintrustIntegration, %{
api_key: System.get_env("BRAINTRUST_API_KEY"),
project: "my-project"
})
@spec detach(module()) :: :ok | {:error, :not_found}
Detaches Telemetry handlers for the given integration module.
Parameters
integration_module- Module implementingSynaptic.Eval.Integration