Skip to content

Data Sources

Before you can filter or recommend models, you need a catalog. pickai ships fromModelsDev() to fetch 3,700+ models from models.dev, but find() and recommend() accept any Model[], so you can bring your own data too.

Fetches the full catalog from models.dev/api.json and returns Promise<Model[]>. Uses the platform fetch API (Node 18+, Deno, Bun, browsers).

import { fromModelsDev } from "pickai";
const models = await fromModelsDev();

The full catalog includes many resellers and aggregators. When calling find() or recommend(), you can narrow results to known providers using the Provider Constants.

If you’ve already fetched the models.dev data (for caching, offline use, or testing), pass it directly:

import { fromModelsDev, type ModelsDevData } from "pickai";
import { readFileSync } from "fs";
// Fetch https://models.dev/api.json yourself and cache however you like
const cached: ModelsDevData = JSON.parse(readFileSync("api.json", "utf-8"));
const models = await fromModelsDev(cached);

If you want to use the models.dev parser without the fetch wrapper, parseModelsDevData() is exported directly:

import { parseModelsDevData } from "pickai";
const data = await fetchFromYourCache();
const models = parseModelsDevData(data);

This returns Model[] synchronously. Useful when you manage fetching and caching yourself.

models.dev provides structured capability fields (reasoning, openWeights, structuredOutput, attachment), knowledge cutoff dates, and model status that other catalog sources don’t expose. These fields are what make metadata-only filtering and scoring meaningful: you can score on knowledge freshness, filter by reasoning capability, and exclude deprecated models out of the box.

That said, metadata can only tell you what a model supports, not how well it performs. For actual quality ranking, add benchmark data as a custom scoring criterion.

find() and recommend() accept any Model[], so you can maintain a curated list, load from a database, combine multiple sources, or test with fixed data.

Each model must conform to the Model interface. These fields are required:

FieldTypeExample
idstring"claude-sonnet-4-5"
namestring"Claude Sonnet 4.5"
providerstring"anthropic"
openRouterIdstring"anthropic/claude-sonnet-4.5"
limit{ context, output }{ context: 200000, output: 16384 }
modalities{ input[], output[] }{ input: ["text", "image"], output: ["text"] }

The remaining fields are optional, but specific pickai features depend on them:

FieldUsed by
costcostEfficiency scoring, maxCostInput/maxCostOutput filters, sortByCost
releaseDaterecency scoring, default sort order in find()
knowledgeknowledgeFreshness scoring, minKnowledge filter
familyperFamily() constraint
reasoningreasoning filter, Purpose.Reasoning
toolCalltoolCall filter, Purpose.Coding
structuredOutputstructuredOutput filter
statusexcludeDeprecated filter

Missing optional fields are handled gracefully. Models without cost score 0 on costEfficiency (unknown cost gets no credit for being cheap). Models without releaseDate or knowledge score as oldest in their respective criteria.

custom-source.ts
import { recommend, Purpose, type Model } from "pickai";
// Bring your own model data: useful for testing, offline use,
// or when you maintain your own model catalog
const models: Model[] = [
{
id: "claude-sonnet-4-5",
name: "Claude Sonnet 4.5",
provider: "anthropic",
openRouterId: "anthropic/claude-sonnet-4.5",
cost: { input: 3, output: 15 },
limit: { context: 200_000, output: 16_384 },
modalities: { input: ["text", "image"], output: ["text"] },
reasoning: true,
toolCall: true,
structuredOutput: true,
family: "claude-sonnet",
releaseDate: "2025-02-24",
knowledge: "2025-04",
},
{
id: "gpt-4o",
name: "GPT-4o",
provider: "openai",
openRouterId: "openai/gpt-4o",
cost: { input: 2.5, output: 10 },
limit: { context: 128_000, output: 16_384 },
modalities: { input: ["text", "image", "audio"], output: ["text"] },
toolCall: true,
structuredOutput: true,
family: "gpt",
releaseDate: "2024-05-13",
knowledge: "2024-10",
},
];
const results = recommend(models, Purpose.Coding);
for (const m of results) {
console.log(` ${m.score.toFixed(3)} | ${m.name} (${m.provider})`);
}