freellmapi / server /src /services /model-listing.ts
Nryn215's picture
Deploy: Enable and enforce pure ELO-based Intelligence routing strategy
ed57015
Raw
History Blame Contribute Delete
4.23 kB
import type { ModelListRow } from '@freellmapi/shared/types.js';
import { getDb } from '../db/index.js';
import { isUnifyEnabled, getModelGroups } from './model-groups.js';
// Shared catalog-listing logic behind both the OpenAI `GET /v1/models` and the
// Anthropic `GET /v1/models` endpoints, so the two wire formats list the exact
// same models (only the envelope differs). Extracted verbatim from the OpenAI
// proxy route to keep a single source of truth.
export interface NormalizedModel {
id: string;
name: string;
ownedBy: string;
available: number;
enabled: number;
contextWindow: number | null;
intel: number;
}
export interface ModelListing {
// Full catalog, sorted usable-first; callers apply their own `available` filter.
models: NormalizedModel[];
// Honest ceiling for the virtual "auto" model: the largest context window
// among models that can serve a request right now (null when nothing is
// connected). Computed over available models regardless of any caller filter.
autoContextWindow: number | null;
}
export function buildModelListing(): ModelListing {
const availableExpr = `
(CASE WHEN m.enabled = 1 AND EXISTS (
SELECT 1 FROM api_keys k
WHERE k.platform = m.platform
AND k.enabled = 1
AND k.status IN ('healthy', 'unknown', 'error')
AND (m.key_id IS NULL OR k.id = m.key_id)
) THEN 1 ELSE 0 END)`;
const db = getDb();
let allListed: NormalizedModel[];
if (isUnifyEnabled()) {
// Unify ON: one entry per logical model group. Pull per-row availability +
// context keyed by db id, then aggregate over each group's members.
type AvailRow = { id: number; platform: string; intelligence_rank: number; context_window: number | null; enabled: number; available: number };
const rows = db.prepare(`
SELECT m.id, m.platform, m.intelligence_rank, m.context_window,
m.enabled AS enabled, ${availableExpr} AS available
FROM models m
`).all() as AvailRow[];
const byId = new Map(rows.map(r => [r.id, r]));
allListed = getModelGroups().map(g => {
const infos = g.members.map(m => byId.get(m.model_db_id)).filter(Boolean) as AvailRow[];
const ctxs = infos.map(i => i.context_window).filter((c): c is number => c != null);
return {
id: g.canonicalId,
name: g.groupLabel,
ownedBy: 'freellmapi',
available: infos.some(i => i.available === 1) ? 1 : 0,
enabled: infos.some(i => i.enabled === 1) ? 1 : 0,
contextWindow: ctxs.length ? Math.max(...ctxs) : null,
intel: infos.length ? Math.min(...infos.map(i => i.intelligence_rank)) : Number.MAX_SAFE_INTEGER,
};
});
} else {
// Unify OFF: one entry per model_id (dedup picks the available, smartest
// representative row).
const models = db.prepare(`
SELECT platform, model_id, display_name, context_window, enabled, available, intelligence_rank, id
FROM (
SELECT m.platform, m.model_id, m.display_name, m.context_window, m.intelligence_rank, m.id,
m.enabled AS enabled,
${availableExpr} AS available,
ROW_NUMBER() OVER (
PARTITION BY m.model_id
ORDER BY ${availableExpr} DESC, m.intelligence_rank ASC, m.id ASC
) AS rn
FROM models m
)
WHERE rn = 1
`).all() as (ModelListRow & { intelligence_rank: number; id: number })[];
allListed = models.map(m => ({
id: m.model_id, name: m.display_name, ownedBy: m.platform,
available: m.available, enabled: m.enabled, contextWindow: m.context_window,
intel: m.intelligence_rank,
}));
}
// Stable order: usable first, then enabled, then smartest, then name.
allListed.sort((a, b) =>
(b.available - a.available) || (b.enabled - a.enabled) || (a.intel - b.intel) || a.name.localeCompare(b.name));
const availableContextWindows = allListed
.filter(m => m.available === 1 && m.contextWindow != null)
.map(m => m.contextWindow as number);
const autoContextWindow = availableContextWindows.length > 0
? Math.max(...availableContextWindows)
: null;
return { models: allListed, autoContextWindow };
}