Skip to main content
Version: Latest

Custom evaluations

Operator evaluation data has one canonical home:

evaluation:
benchmarks: [] # definitions not built into this release
indices: [] # operator-owned index DAGs
records: [] # measurements linked to Model Card identities

Built-in data uses the same logical model in the generated catalog snapshot: benchmark definitions, index definitions, and model-linked evaluation records are separate collections. Keeping measurements out of Model Cards avoids duplicating identity metadata and lets one model have many benchmark runs, profiles, and reasoning efforts.

The release-owned source is split by responsibility under config/catalog: Model Cards in resources/models/, benchmark contracts in resources/benchmarks.yaml, measurements in resources/evaluations/, and the index DAG in resources/indices.yaml. Generation validates and embeds one immutable snapshot. User evaluation data extends that snapshot for the local deployment; it does not copy or override release-owned records.

Add evidence for a custom model

For a custom model, omit providers.models[].catalog. The provider model name is then its canonical Model Card identity and is also used by evaluation.records[].model:

version: v0.3

providers:
models:
- name: private-chat
provider_model_id: private-chat-awq
api_format: openai
backend_refs:
- name: primary
provider: vllm
endpoint: model-gateway.example:8000
protocol: http

evaluation:
records:
- model: private-chat
benchmark: livecodebench/livecodebench@6.0.0
benchmark_profile: independent-code-generation
reasoning_effort: high
metrics: {pass_at_1: 0.61}
measured_at: 2026-09-09
source: https://benchmarks.example/runs/private-chat-lcb6

routing:
modelCards:
- name: private-chat
display_name: Private Chat
capabilities: [chat, tools, coding]

For an alias backed by a built-in card, set model to the canonical providers.models[].catalog ID, not the request-facing alias. Several aliases for the same checkpoint therefore share the same model evidence.

The Evaluation Plane freezes the effective card behind each provider alias, including built-in metadata and operator overrides. A catalog-backed live target therefore does not require a duplicate routing.modelCards entry.

Define a benchmark and index

Built-in benchmark IDs need no redeclaration. Define semantics only for an operator-owned benchmark:

evaluation:
benchmarks:
- id: acme/clinical-reasoning@1.0.0
display_name: ACME Clinical Reasoning
domain: medical_reasoning
source: https://benchmarks.example/clinical-reasoning/v1
default_profile: heldout
profiles:
- id: heldout
display_name: Held-out set
description: Frozen v1 cases with deterministic scoring.
metrics:
- id: accuracy
unit: proportion
direction: higher_is_better
range: [0, 1]

indices:
- id: acme/clinical-quality@1.0.0
display_name: Clinical Quality
aggregation: weighted_mean
scale: [0, 100]
missing: {policy: require_coverage, minimum: 0.5}
domains: {medical_reasoning: 0.5, scientific_reasoning: 0.5}
components:
- benchmark: acme/clinical-reasoning@1.0.0
benchmark_profile: heldout
metric: accuracy
weight: 0.5
normalization: {type: identity}
- benchmark: idavidrein/gpqa-diamond@1.0.0
benchmark_profiles: [independent-standard, published-standard]
metric: accuracy
weight: 0.5
normalization: {type: identity}

records:
- model: private-chat
benchmark: acme/clinical-reasoning@1.0.0
benchmark_profile: heldout
reasoning_effort: high
metrics: {accuracy: 0.74}

Resource IDs must be lowercase, namespaced, and versioned. An operator definition cannot shadow a built-in benchmark or index. Publish a new ID when the tasks, profile, scorer, metric meaning, normalization, or weights change.

An undeclared namespaced benchmark record is retained and round-trips through canonical export, but cannot enter an index until its metric range, direction, and profiles are defined.

Choose missing-data semantics

PolicyIndex becomes available whenAggregation
require_allCoverage is 1.0All declared component weights
require_coverageCoverage reaches minimumReported component weights
reported_onlyAny component is presentReported component weights

No policy invents a missing score. Partial policies renormalize reported weights only because the index definition explicitly requests it; coverage and missing components remain visible.

Route on the index

algorithm:
type: multi_factor
multi_factor:
quality:
index: acme/clinical-quality@1.0.0
on_missing: exclude
min_coverage: 0.5
min_score: 60
objective:
strategy: lexicographic
priorities:
- {factor: quality, tolerance: 0.03}
- {factor: cost, tolerance: 0.05}

The Router uses an available result for the candidate's exact reasoning effort, then applies route-level coverage and score gates. See Multi Factor for balanced, quality-first, and cost-first objectives.

In the Dashboard, open Build → Models → Evaluation Records to add or edit records. Benchmark and index definitions remain explicit YAML because changing their semantics creates a versioned scoring contract, not ordinary Model Card metadata.