Skip to content

scoreModels

recommend() handles scoring internally, but scoreModels() exposes the scoring engine directly. Use it when you want to score models with custom criteria without the full recommend pipeline, or when building your own selection logic on top of scored results.

function scoreModels<T extends Model>(
models: T[],
criteria: WeightedCriterion[],
): ScoredModel<T>[]
ParameterTypeDescription
modelsT[]Models to score.
criteriaWeightedCriterion[]Criteria paired with weights.

ScoredModel<T>[]: models with added score (0-1) and coverage (0-1) properties, sorted by score descending. coverage is the fraction of criterion weight backed by real data for that model.

  • Normalizes weights to sum to 1 (weight 7 and weight 3 become 0.7 and 0.3).
  • Computes the weighted sum per model. Criteria that return undefined (no data for that model) contribute 0 and reduce the model’s coverage.
  • All-zero weights produce all-zero scores with zero coverage.
  • Empty input returns [].
import { scoreModels, costEfficiency, recency } from "pickai";
const scored = scoreModels(models, [
{ criterion: costEfficiency, weight: 3 },
{ criterion: recency, weight: 1 },
]);
console.log(scored[0].name, scored[0].score);

See Scoring & Ranking for how criteria and weights work together.

All built-in criteria use min-max normalization across the candidate set. Scores are relative to the other candidates.

const costEfficiency: ScoringCriterion

Cheaper models score higher. Based on model.cost.input (USD per 1M tokens). Models without pricing data are uncovered (unknown cost gets no credit for being cheap).

const recency: ScoringCriterion

Newer models score higher. Based on model.releaseDate. Models without a release date are uncovered and excluded from the scale, so one dateless model cannot compress everyone else toward the top.

const contextCapacity: ScoringCriterion

Larger context windows score higher. Based on model.limit.context.

const outputCapacity: ScoringCriterion

Larger output limits score higher. Based on model.limit.output.

const knowledgeFreshness: ScoringCriterion

More recent knowledge cutoffs score higher. Based on model.knowledge (e.g., "2025-03"). Models without a knowledge cutoff are uncovered and excluded from the scale.

Helper for creating custom min-max normalized criteria. Reduces the boilerplate of extracting values, filtering nulls, and normalizing.

function minMaxCriterion(
getValue: (model: Model) => number | undefined,
invert?: boolean,
): ScoringCriterion
ParameterTypeDefaultDescription
getValuefunctionrequiredExtracts a numeric value from a model, or undefined if unavailable.
invertbooleanfalseIf true, lower values score higher (useful for cost).

Models where getValue returns undefined are uncovered: the criterion contributes 0 to their score and lowers their coverage.

For lower-is-better fields like cost, use invert: true rather than negating inside getValue. An expression like 1 - (cost ?? Infinity) turns missing data into a huge negative score; invert keeps undefined as “no data”.

import { minMaxCriterion, matchesModel } from "pickai";
// Score models by external benchmark data
const arenaScore = minMaxCriterion((model) => {
const match = benchmarks.find((b) => matchesModel(b.modelId, model.id));
return match?.score;
});
// Score models by cost (cheaper = higher score)
const cheapest = minMaxCriterion((model) => model.cost?.input, true);

See the benchmark example recipes for working implementations.