SPB Git forge

spb/polyllm

Public
15commits 1branches 0releases
2.2 MBsize
maindefault branch
13 days agolast push
TypeScript 97.4% SQL 1% JavaScript 0.9% CSS 0.6%
4.5 KB · 104 lines typescript
Raw Blame History
1import type { CatalogEntry } from "@/lib/ai/registry/catalog";2import type { ModelCapabilities, ModelPricing, ModelStatus } from "@/lib/ai/core/types";3import data from "./catalog-data.json";45/**6 * OpenAI catalog — generated from docs/provider-research/openai.models.json7 * (official models/pricing pages + real probes, audited 2026-09-08).8 * `GET /v1/models` exposes no capability/context/pricing metadata, so this file is9 * the source of truth for everything except existence and `shutdown_date`.10 *11 * Verified rules encoded here:12 *  - sampling params (temperature/top_p/penalties) are accepted only on non-reasoning13 *    models, or on reasoning models when `reasoning.effort === "none"` ("conditional");14 *  - `seed` and `stop` do not exist in the Responses API;15 *  - effort levels are per model (`reasoningEfforts`).16 */17interface Row {18  id: string;19  displayName: string;20  family: string;21  contextTokens: number | null;22  maxOutputTokens: number | null;23  capabilities: ModelCapabilities;24  sampling: "yes" | "no" | "conditional";25  verbosity: boolean;26  reasoningEfforts: string[] | null;27  defaultReasoningEffort: string | null;28  pricing: { inputPerMillion: number | null; cachedInputPerMillion: number | null; outputPerMillion: number | null };29  status: ModelStatus;30  apis: string[] | null;31  shutdownDate: string | null;32}3334function weight(id: string): number {35  if (id.startsWith("gpt-6")) return 100;36  if (id.startsWith("gpt-5.6-sol")) return 96;37  if (id.startsWith("gpt-5.6-terra")) return 94;38  if (id.startsWith("gpt-5.6-luna")) return 92;39  if (id === "gpt-5.6") return 91;40  if (id.startsWith("gpt-5.5-pro")) return 86;41  if (id.startsWith("gpt-5.5")) return 88;42  if (id.startsWith("gpt-5.4-pro")) return 80;43  if (id.startsWith("gpt-5.4-mini")) return 82;44  if (id.startsWith("gpt-5.4-nano")) return 81;45  if (id.startsWith("gpt-5.4")) return 84;46  if (id.startsWith("gpt-5.3")) return 70;47  if (id.startsWith("gpt-5.2")) return 68;48  if (id.startsWith("gpt-5.1")) return 66;49  if (id.startsWith("gpt-5")) return 60;50  if (id === "chat-latest") return 58;51  if (id.startsWith("gpt-4.1")) return 50;52  if (id.startsWith("o3") || id.startsWith("o4")) return 45;53  if (id.startsWith("gpt-4o")) return 40;54  return 10;55}5657export const OPENAI_CATALOG = new Map<string, CatalogEntry>(58  (data as Row[]).map((r) => {59    const isSnapshot = /-\d{4}-\d{2}-\d{2}$|-\d{4}$/.test(r.id);60    const pricing: ModelPricing | null =61      r.pricing.inputPerMillion != null || r.pricing.outputPerMillion != null62        ? { inputPerMillion: r.pricing.inputPerMillion ?? undefined, cachedInputPerMillion: r.pricing.cachedInputPerMillion ?? undefined, outputPerMillion: r.pricing.outputPerMillion ?? undefined, source: "openai-pricing-page", asOf: "2026-09-08" }63        : null;64    const entry: CatalogEntry = {65      displayName: r.displayName,66      family: r.family,67      capabilities: r.capabilities,68      limits: { contextTokens: r.contextTokens ?? undefined, maxOutputTokens: r.maxOutputTokens ?? undefined },69      parameters: {70        temperature: r.sampling !== "no",71        topP: r.sampling !== "no",72        frequencyPenalty: r.sampling !== "no",73        presencePenalty: r.sampling !== "no",74        maxTokens: true,75        stop: false,76        seed: false,77        topK: false,78        verbosity: r.verbosity,79        reasoningEffort: Boolean(r.reasoningEfforts?.length),80        reasoningEffortLevels: r.reasoningEfforts ?? undefined,81        temperatureRange: { min: 0, max: 2 },82      },83      pricing,84      status: r.status,85      sortWeight: weight(r.id) - (isSnapshot ? 5 : 0),86      metadata: {87        samplingMode: r.sampling,88        defaultReasoningEffort: r.defaultReasoningEffort,89        apis: r.apis ?? ["responses"],90        responsesSupported: (r.apis ?? ["responses"]).includes("responses"),91        shutdownDate: r.shutdownDate,92        snapshot: isSnapshot,93      },94    };95    return [r.id, entry];96  }),97);9899/** Ids returned by /v1/models that are not chat models (audio, image, embeddings…). */100export const OPENAI_NON_CHAT = /babbage|davinci|instruct|transcribe|tts|whisper|audio|realtime|image|sora|embedding|moderation|search-preview|search-api|deep-research|computer-use/i;101102/** Listed by /v1/models but return 404 (verified 2026-09-08). */103export const OPENAI_DEAD_IDS = new Set(["gpt-5-chat-latest", "gpt-5.1-chat-latest", "gpt-5.2-chat-latest", "gpt-5.3-chat-latest", "gpt-5-codex", "gpt-5.1-codex", "gpt-5.1-codex-max", "gpt-5.1-codex-mini", "gpt-5.2-codex", "o3-deep-research", "o4-mini-deep-research"]);104