Documentation
¶
Overview ¶
Package evaluation provides an evaluation framework for testing agents.
Index ¶
- Constants
- Variables
- func GenerateRunName() string
- func PrintComparison(out io.Writer, c Comparison)
- func Save(sess *session.Session, filename string) (string, error)
- func SaveRunJSON(run *EvalRun, outputDir string) (string, error)
- func SaveRunSessions(ctx context.Context, run *EvalRun, outputDir string) (string, error)
- func SaveRunSessionsJSON(run *EvalRun, outputDir string) (string, error)
- func SessionFromEvents(events []map[string]any, title string, questions []string) *session.Session
- type Baseline
- type Comparison
- type Config
- type EvalChange
- type EvalRun
- type InputSession
- type Judge
- type MetricDelta
- type Metrics
- type RelevanceResult
- type Result
- type RunOutput
- type RunOutputConfig
- type Runner
- type Summary
Constants ¶
const DefaultContainerRuntime = "docker"
DefaultContainerRuntime is the container runtime executable used when Config.ContainerRuntime is empty, keeping the historical Docker behavior.
const MaxTolerance = 1.0
MaxTolerance is the largest accepted --regression-tolerance. A rate cannot move by more than 1.0, so anything above it silently disables the aggregate gate — better rejected at startup than discovered when a regression sails through.
Variables ¶
var ErrNoBaselineEvals = errors.New("baseline contains no evaluations")
ErrNoBaselineEvals reports a baseline carrying no evaluations. A gate built on one would compare against all-zero metrics and pass unconditionally.
var ErrNoCurrentEvals = errors.New("run produced no evaluations to compare")
ErrNoCurrentEvals reports a run that produced no evaluations — an --only pattern that matched nothing, for instance. There is nothing to gate on.
var ErrNothingComparable = errors.New("baseline and run share no metric or evaluation to compare")
ErrNothingComparable reports a baseline and run with no metric and no evaluation in common, so the comparison could only ever pass.
Functions ¶
func GenerateRunName ¶
func GenerateRunName() string
GenerateRunName creates a memorable name for an evaluation run.
func PrintComparison ¶ added in v1.126.0
func PrintComparison(out io.Writer, c Comparison)
PrintComparison writes a human-readable comparison.
func SaveRunJSON ¶
SaveRunJSON saves the eval run results to a JSON file. This is kept for backward compatibility and debugging purposes.
func SaveRunSessions ¶
SaveRunSessions saves all eval sessions to a SQLite database file. The database follows the same schema as the main session store, allowing the sessions to be loaded and inspected using standard session tools.
func SaveRunSessionsJSON ¶
SaveRunSessionsJSON saves the full evaluation run output to a JSON file. The output includes run metadata (config, summary) and all sessions with their eval criteria and scoring results (pass/fail, judge reasoning, errors).
func SessionFromEvents ¶
SessionFromEvents reconstructs a session from raw container output events. This parses the JSON events emitted by docker agent run --exec --json and builds a session with the conversation history.
Types ¶
type Baseline ¶ added in v1.126.0
type Baseline struct {
Name string
Summary Summary
// Passed maps an evaluation's key (see evalKey) to whether it passed.
Passed map[string]bool
}
Baseline is a previously saved run, reduced to what a regression gate needs.
It is loaded from the JSON the eval command actually writes — a RunOutput from SaveRunSessionsJSON — rather than from EvalRun, which has no producer outside tests and whose Duration field is typed incompatibly.
func LoadBaseline ¶ added in v1.126.0
LoadBaseline reads the run JSON the eval command writes.
A file that parses but carries no evaluations is rejected rather than treated as an empty baseline: every rate would be skipped by the has-flag guards and the gate would report success while every evaluation in the current run failed. A gate must fail closed.
type Comparison ¶ added in v1.126.0
type Comparison struct {
Baseline Metrics `json:"baseline"`
Current Metrics `json:"current"`
Tolerance float64 `json:"tolerance"`
Deltas []MetricDelta `json:"deltas"`
Changes []EvalChange `json:"changes"`
// Regressed is true when any gating metric moved beyond the tolerance, or
// an evaluation that passed in the baseline now fails.
Regressed bool `json:"regressed"`
}
Comparison is the result of checking a run against a baseline.
func Compare ¶ added in v1.126.0
func Compare(baseline *Baseline, current *EvalRun, tolerance float64) (Comparison, error)
Compare checks current against baseline.
tolerance is the amount an aggregate quality rate may fall (or the failure rate may climb) before it counts as a regression, so judge variance does not fail a build on noise. A tolerance of 0 means any movement in the wrong direction regresses; a negative value is clamped to 0.
The tolerance governs aggregate rates ONLY. An evaluation that passed in the baseline and now fails gates regardless of tolerance — that transition is the exact signal this check exists to catch, and absorbing it would defeat the point. Consequently a large tolerance still cannot hide an outright breakage.
Note the corollary: adding a new FAILING evaluation lowers the aggregate rate and therefore gates, even though no existing evaluation regressed. That is intended — a suite that got worse should say so — but it means "add a known- failing eval as a TODO" needs an explicit tolerance bump or a fix.
Cost is reported but never gates: a cost increase is not a quality regression, and gating on it would make the check fire on provider price changes.
A metric absent from either run is skipped rather than treated as 0 — adding the first size expectation to a suite must not look like a regression. If that leaves nothing to gate on and no evaluation in common, an error is returned: a comparison that can only ever pass is worse than no comparison.
type Config ¶
type Config struct {
AgentFilename string // Path to the agent configuration file
EvalsDir string // Directory containing evaluation files
JudgeModel string // Model for relevance checking (format: provider/model, optional)
Concurrency int // Number of concurrent runs (0 = number of CPUs)
TTYFd int // File descriptor for terminal size queries (e.g., int(os.Stdout.Fd()))
Only []string // Only run evaluations matching these patterns
BaseImage string // Custom base image for running evaluations
KeepContainers bool // If true, don't remove containers after evaluation (skip --rm)
EnvVars []string // Environment variables to pass: KEY (value from env) or KEY=VALUE (explicit)
Repeat int // Number of times to repeat each evaluation (default 1)
ContainerRuntime string // Docker-compatible container runtime executable (default "docker")
}
Config holds configuration for evaluation runs.
type EvalChange ¶ added in v1.126.0
type EvalChange struct {
Eval string `json:"eval"`
// Was and Now are "pass", "fail", or "absent".
Was string `json:"was"`
Now string `json:"now"`
Regressed bool `json:"regressed"`
}
EvalChange records one evaluation's pass/fail transition between runs.
type EvalRun ¶
type EvalRun struct {
Name string `json:"name"`
Timestamp time.Time `json:"timestamp"`
Duration time.Duration `json:"duration"`
Config Config `json:"-"` // Used to build RunOutput, not serialized directly
Results []Result `json:"results"`
Summary Summary `json:"summary"`
}
EvalRun contains the results and metadata for an evaluation run.
func Evaluate ¶
func Evaluate(ctx context.Context, ttyOut, out io.Writer, isTTY bool, runName string, runConfig *config.RuntimeConfig, cfg Config) (*EvalRun, error)
Evaluate runs evaluations with a specified run name. ttyOut is used for progress bar rendering (should be the console/TTY). out is used for results and status messages (can be tee'd to a log file).
type InputSession ¶
type InputSession struct {
*session.Session
SourcePath string // Path to the source eval file (not serialized)
RepeatIndex int // Repeat iteration (1-based); 0 means no repeat
}
InputSession wraps a session with its source path for evaluation loading.
type Judge ¶
type Judge struct {
// contains filtered or unexported fields
}
Judge runs LLM-as-a-judge relevance checks concurrently.
func NewJudge ¶
NewJudge creates a new Judge that runs relevance checks with the given concurrency. Concurrency defaults to 1 if n < 1.
func (*Judge) CheckRelevance ¶
func (j *Judge) CheckRelevance(ctx context.Context, response string, criteria []string) (results []RelevanceResult, err error)
CheckRelevance runs all relevance checks concurrently with the configured concurrency. It returns a result for every criterion (both passed and failed, each with a reason from the judge model), and an error if any check encountered an error (e.g. judge model misconfiguration). Errors cause a hard failure so that configuration issues are surfaced immediately rather than silently producing zero-relevance results.
func (*Judge) Validate ¶ added in v1.32.4
Validate performs an end-to-end check of the judge model by sending a trivial relevance prompt and verifying the response is valid structured JSON. This catches configuration errors (bad API key, unsupported model, missing structured-output support, etc.) before running any evaluations, allowing the framework to fail fast.
type MetricDelta ¶ added in v1.126.0
type MetricDelta struct {
Name string `json:"name"`
Baseline float64 `json:"baseline"`
Current float64 `json:"current"`
Delta float64 `json:"delta"`
Regressed bool `json:"regressed"`
// Informational marks a metric that is reported but never gates, so a
// reviewer can see it moved without the build failing over it.
Informational bool `json:"informational,omitempty"`
}
MetricDelta is one metric's movement between two runs. Higher is better for quality rates and worse for FailureRate, so Regressed — not the sign of Delta — is what a gate reads.
type Metrics ¶ added in v1.126.0
type Metrics struct {
TotalEvals int `json:"total_evals"`
FailedEvals int `json:"failed_evals"`
FailureRate float64 `json:"failure_rate"`
SizePassRate float64 `json:"size_pass_rate"`
HasSizes bool `json:"has_sizes"`
ToolsF1Mean float64 `json:"tools_f1_mean"`
HasTools bool `json:"has_tools"`
RelevanceRate float64 `json:"relevance_rate"`
HasRelevance bool `json:"has_relevance"`
TotalCost float64 `json:"total_cost"`
}
Metrics is the comparable shape of an evaluation run: the rates a regression gate can be built on, derived from the same Summary the run prints.
Rates are 0 when their denominator is 0, and the corresponding Has… flag says whether the rate means anything. Without that distinction "no size expectations declared" and "every size expectation failed" would both read as 0.0 and a gate could not tell them apart.
type RelevanceResult ¶
type RelevanceResult struct {
Criterion string `json:"criterion"`
Passed bool `json:"passed"`
Reason string `json:"reason"`
}
RelevanceResult contains the result of a single relevance check.
type Result ¶
type Result struct {
InputPath string `json:"input_path"`
Title string `json:"title"`
Question string `json:"question"`
Response string `json:"response"`
Cost float64 `json:"cost"`
OutputTokens int64 `json:"output_tokens"`
Size string `json:"size"`
SizeExpected string `json:"size_expected"`
ToolCallsScore float64 `json:"tool_calls_score"`
ToolCallsExpected float64 `json:"tool_calls_score_expected"`
RelevancePassed float64 `json:"relevance"`
RelevanceExpected float64 `json:"relevance_expected"`
RelevanceResults []RelevanceResult `json:"relevance_results,omitempty"`
Error string `json:"error,omitempty"`
RawOutput []map[string]any `json:"raw_output,omitempty"`
Session *session.Session `json:"-"` // Full session for database storage (not in JSON)
}
Result contains the evaluation results for a single test case.
type RunOutput ¶ added in v1.42.0
type RunOutput struct {
Name string `json:"name"`
Timestamp time.Time `json:"timestamp"`
Duration string `json:"duration"`
Config RunOutputConfig `json:"config"`
Summary Summary `json:"summary"`
Sessions []*session.Session `json:"sessions"`
}
RunOutput is the top-level structure for the evaluation run JSON output.
type RunOutputConfig ¶ added in v1.42.0
type RunOutputConfig struct {
Agent string `json:"agent"`
JudgeModel string `json:"judge_model,omitempty"`
Concurrency int `json:"concurrency"`
EvalsDir string `json:"evals_dir"`
BaseImage string `json:"base_image,omitempty"`
ContainerRuntime string `json:"container_runtime,omitempty"`
}
RunOutputConfig captures the evaluation run configuration.
type Runner ¶
type Runner struct {
Config
// contains filtered or unexported fields
}
Runner runs evaluations against an agent.
type Summary ¶
type Summary struct {
TotalEvals int `json:"total_evals"`
FailedEvals int `json:"failed_evals"`
TotalCost float64 `json:"total_cost"`
SizesPassed int `json:"sizes_passed"`
SizesTotal int `json:"sizes_total"`
ToolsF1Sum float64 `json:"tools_f1_sum"`
ToolsCount int `json:"tools_count"`
RelevancePassed float64 `json:"relevance_passed"`
RelevanceTotal float64 `json:"relevance_total"`
}
Summary contains aggregate statistics across all evaluations.