Skip to main content

Scoring

A training loop that cannot tell improvement from damage is not worth running. miForge scores two held-out sets on a cadence and records every score with enough detail to reproduce it.

Test and retention​

SetThe questionScored every
Test setIs the domain getting better?test_every steps (default 1)
Retention setIs general ability being spent to buy that?retention_every steps (default 1)

The test set holds domain prompts with an expectation: a selector verdict, a grader score, or a reference answer matched exactly or loosely. The retention set holds general prompts outside the domain, scored the same way, and carries a floor.

Both scores are on a 0 to 1 scale, written to the run log at every scoring point, and copied into each checkpoint's manifest when it is saved. So a checkpoint found months later still says how it scored.

The floor​

A model pushed hard at one domain answers that domain better and everything else worse. Loss falls, the test score rises, nothing errors. The retention set is the only instrument that sees it. If a retention score falls below the floor (equal is not a breach), miForge records a breach, and a run with the retention_floor stop condition stops there and saves a final checkpoint, so you have the model at the point it went too far.

The floor comes from the pack's retention slot, or from the run's retention_floor_override. The run records which one it used.

A set used for scoring is never also training material in the same run: held-out data stays held out.

Providers: who answers​

To score a model, miForge has to ask it questions. It does that through a provider:

ProviderWhat it isNeeds
in_process (default)The model miForge is holding, asked directly.Nothing else running.
An OpenAI-compatible endpointAny server that speaks the OpenAI-compatible API: miLLM, vLLM, Ollama, a llama.cpp server, or a hosted service.Configuration (below).

Configure an endpoint with environment variables, one set per provider name you choose:

PROVIDER_LOCALVLLM_BASE_URL=http://vllm.example.com:8000/v1
PROVIDER_LOCALVLLM_MODEL=my-served-model
PROVIDER_LOCALVLLM_API_KEY= # optional; a local server usually needs none

A base address without a model (or the reverse) is refused, and a base address containing a user name and password is refused: put credentials in _API_KEY, never in the address. GET /api/v1/providers lists the providers and whether each is reachable, and POST /api/v1/providers/{name}/check sends one prompt and shows the answer.

Why every score names its provider​

A number from a greedy pass on the in-process model and a number from a sampled request to a different server are two different measurements. Plot them on one curve and the curve is a fiction. So every score records the provider, the decoding parameters, the aggregation method and the sample size, and the run view marks any point where the provider changed.

The scoring block​

A run definition's scoring block chooses how scores are taken. Everything is optional:

"scoring": {
"provider": "in_process",
"aggregation": "mean",
"decode": {"max_tokens": 128, "temperature": 0.0}
}

Decoding is greedy by default (temperature 0), which makes a score repeatable: load the checkpoint at step N into any OpenAI-compatible server, score the same set the same way, and you should get the score miForge recorded at step N.

Scoring outside the cadence​

POST /api/v1/runs/{run_id}/evaluate scores a run's model now, against its pinned provider (the forge_evaluate_now MCP tool). Because it uses the graphics card, an AI agent's request waits for your approval.

Reading scores​

RouteMCP toolReturns
GET /api/v1/runs/{run_id}/scoresforge_list_scoresEvery test and retention score, with sample size and provider.
GET /api/v1/runs/{run_id}/scores/{step}forge_get_scores_at_stepThe scores at one step, with per-item detail.