chore: merge dev into v2 (#36312)
Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com> Co-authored-by: LukeParkerDev <10430890+Hona@users.noreply.github.com> Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com> Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com> Co-authored-by: Julian Coy <julian@ex-machina.co> Co-authored-by: Brendan Allan <git@brendonovich.dev> Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com> Co-authored-by: opencode <opencode@sst.dev> Co-authored-by: Vladimir Glafirov <vglafirov@gitlab.com> Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com> Co-authored-by: Frank <frank@anoma.ly> Co-authored-by: Jay <53023+jayair@users.noreply.github.com> Co-authored-by: Dustin Deus <deusdustin@gmail.com> Co-authored-by: Kit Langton <kit.langton@gmail.com> Co-authored-by: James Long <longster@gmail.com> Co-authored-by: Simon Klee <hello@simonklee.dk> Co-authored-by: Jay <air@live.ca> Co-authored-by: Jack <jack@anoma.ly> Co-authored-by: David Hill <1879069+iamdavidhill@users.noreply.github.com> Co-authored-by: Aiden Cline <aidenpcline@gmail.com> Co-authored-by: James Long <jlongster@users.noreply.github.com> Co-authored-by: 冯基魁 <56265583+fengjikui@users.noreply.github.com> Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com> Co-authored-by: Victor Navarro <vn4varro@gmail.com>
This commit is contained in:
parent
9028c2d8f8
commit
43ecf3ff1b
82 changed files with 4519 additions and 1231 deletions
286
packages/stats/app/src/lib/comparison-pages.ts
Normal file
286
packages/stats/app/src/lib/comparison-pages.ts
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
import { catalogSlug, findModelCatalogEntry, type ModelCatalog, type ModelCatalogEntry } from "../routes/model-catalog"
|
||||
|
||||
type ComparisonFamilyDefinition = {
|
||||
slug: string
|
||||
name: string
|
||||
lab: string
|
||||
prefixes: string[]
|
||||
aliases?: string[]
|
||||
preferredFamilies?: string[]
|
||||
}
|
||||
|
||||
export type ResolvedComparisonFamily = ComparisonFamilyDefinition & {
|
||||
model: ModelCatalogEntry
|
||||
}
|
||||
|
||||
export const comparisonFamilies: ComparisonFamilyDefinition[] = [
|
||||
{
|
||||
slug: "gpt",
|
||||
name: "GPT",
|
||||
lab: "openai",
|
||||
prefixes: ["gpt", "o"],
|
||||
aliases: ["openai"],
|
||||
preferredFamilies: ["gpt", "o"],
|
||||
},
|
||||
{
|
||||
slug: "claude",
|
||||
name: "Claude",
|
||||
lab: "anthropic",
|
||||
prefixes: ["claude"],
|
||||
aliases: ["anthropic"],
|
||||
preferredFamilies: ["claude-sonnet", "claude-opus"],
|
||||
},
|
||||
{
|
||||
slug: "gemini",
|
||||
name: "Gemini",
|
||||
lab: "google",
|
||||
prefixes: ["gemini"],
|
||||
aliases: ["google"],
|
||||
preferredFamilies: ["gemini-pro", "gemini-flash", "gemini"],
|
||||
},
|
||||
{
|
||||
slug: "deepseek",
|
||||
name: "DeepSeek",
|
||||
lab: "deepseek",
|
||||
prefixes: ["deepseek"],
|
||||
preferredFamilies: ["deepseek-thinking", "deepseek"],
|
||||
},
|
||||
{
|
||||
slug: "qwen",
|
||||
name: "Qwen",
|
||||
lab: "alibaba",
|
||||
prefixes: ["qwen"],
|
||||
aliases: ["alibaba"],
|
||||
preferredFamilies: ["qwen"],
|
||||
},
|
||||
{
|
||||
slug: "glm",
|
||||
name: "GLM",
|
||||
lab: "zhipuai",
|
||||
prefixes: ["glm"],
|
||||
aliases: ["zhipu", "zhipuai", "zai"],
|
||||
preferredFamilies: ["glm"],
|
||||
},
|
||||
{
|
||||
slug: "kimi",
|
||||
name: "Kimi",
|
||||
lab: "moonshotai",
|
||||
prefixes: ["kimi"],
|
||||
aliases: ["moonshot", "moonshotai"],
|
||||
preferredFamilies: ["kimi-k2", "kimi-thinking"],
|
||||
},
|
||||
{
|
||||
slug: "minimax",
|
||||
name: "MiniMax",
|
||||
lab: "minimax",
|
||||
prefixes: ["minimax"],
|
||||
},
|
||||
{
|
||||
slug: "grok",
|
||||
name: "Grok",
|
||||
lab: "xai",
|
||||
prefixes: ["grok"],
|
||||
aliases: ["xai"],
|
||||
preferredFamilies: ["grok"],
|
||||
},
|
||||
{
|
||||
slug: "mistral",
|
||||
name: "Mistral",
|
||||
lab: "mistral",
|
||||
prefixes: ["mistral", "magistral", "devstral", "codestral"],
|
||||
preferredFamilies: ["mistral-large", "mistral-medium", "mistral-small"],
|
||||
},
|
||||
{
|
||||
slug: "llama",
|
||||
name: "Llama",
|
||||
lab: "meta",
|
||||
prefixes: ["llama"],
|
||||
aliases: ["meta"],
|
||||
},
|
||||
{
|
||||
slug: "nemotron",
|
||||
name: "Nemotron",
|
||||
lab: "nvidia",
|
||||
prefixes: ["nemotron", "llama-nemotron"],
|
||||
aliases: ["nvidia"],
|
||||
},
|
||||
{
|
||||
slug: "mimo",
|
||||
name: "MiMo",
|
||||
lab: "xiaomi",
|
||||
prefixes: ["mimo"],
|
||||
aliases: ["xiaomi"],
|
||||
},
|
||||
{
|
||||
slug: "command",
|
||||
name: "Command",
|
||||
lab: "cohere",
|
||||
prefixes: ["command"],
|
||||
aliases: ["cohere"],
|
||||
preferredFamilies: ["command-a", "command-r"],
|
||||
},
|
||||
{
|
||||
slug: "sonar",
|
||||
name: "Sonar",
|
||||
lab: "perplexity",
|
||||
prefixes: ["sonar"],
|
||||
aliases: ["perplexity"],
|
||||
preferredFamilies: ["sonar-pro", "sonar-reasoning", "sonar"],
|
||||
},
|
||||
{
|
||||
slug: "longcat",
|
||||
name: "LongCat",
|
||||
lab: "meituan",
|
||||
prefixes: ["longcat"],
|
||||
aliases: ["meituan"],
|
||||
},
|
||||
{
|
||||
slug: "step",
|
||||
name: "Step",
|
||||
lab: "stepfun",
|
||||
prefixes: ["step"],
|
||||
aliases: ["stepfun"],
|
||||
},
|
||||
{
|
||||
slug: "mai",
|
||||
name: "MAI",
|
||||
lab: "microsoft",
|
||||
prefixes: ["mai"],
|
||||
aliases: ["microsoft"],
|
||||
},
|
||||
]
|
||||
|
||||
export function resolveComparisonFamily(catalog: ModelCatalog, value: string) {
|
||||
const family = findComparisonFamily(value)
|
||||
if (!family) return undefined
|
||||
const model = comparisonFamilyCandidates(catalog, family.slug)[0]
|
||||
if (!model) return undefined
|
||||
return { ...family, model } satisfies ResolvedComparisonFamily
|
||||
}
|
||||
|
||||
export function findComparisonFamily(value: string) {
|
||||
const slug = catalogSlug(value)
|
||||
return comparisonFamilies.find((family) => family.slug === slug || family.aliases?.includes(slug))
|
||||
}
|
||||
|
||||
export function comparisonFamilyCandidates(catalog: ModelCatalog, value: string) {
|
||||
const family = findComparisonFamily(value)
|
||||
if (!family) return []
|
||||
const matches = catalog.models
|
||||
.filter((model) => model.lab === family.lab && isFamilyModel(model, family) && isGeneralComparisonModel(model))
|
||||
.toSorted((a, b) => comparisonFamilyModelSort(a, b, family))
|
||||
return matches.filter((model) => !isDuplicateAliasModel(model, matches))
|
||||
}
|
||||
|
||||
export function comparisonSitemapModels(
|
||||
catalog: ModelCatalog,
|
||||
leaderboard: { model: string; provider: string }[] = [],
|
||||
) {
|
||||
return uniqueModels([
|
||||
...comparisonFamilies.flatMap((family) => comparisonFamilyCandidates(catalog, family.slug).slice(0, 2)),
|
||||
...leaderboard.flatMap((entry) => {
|
||||
const model =
|
||||
findModelCatalogEntry(catalog, entry.model, entry.provider) ?? findModelCatalogEntry(catalog, entry.model)
|
||||
return model && isGeneralComparisonModel(model) ? [model] : []
|
||||
}),
|
||||
]).toSorted((a, b) => a.id.localeCompare(b.id))
|
||||
}
|
||||
|
||||
export function canonicalModelComparisonPath(first: ModelCatalogEntry, second: ModelCatalogEntry) {
|
||||
const models = [first, second].toSorted((a, b) => a.id.localeCompare(b.id))
|
||||
return `/data/compare/${models[0].lab}/${models[0].slug}/${models[1].lab}/${models[1].slug}`
|
||||
}
|
||||
|
||||
export function canonicalFamilyComparisonPath(first: ResolvedComparisonFamily, second: ResolvedComparisonFamily) {
|
||||
const families = [first, second].toSorted((a, b) => a.slug.localeCompare(b.slug))
|
||||
return `/data/compare/${families[0].slug}/${families[1].slug}`
|
||||
}
|
||||
|
||||
export function latestFamilyComparisonPath(catalog: ModelCatalog, first: ModelCatalogEntry, second: ModelCatalogEntry) {
|
||||
const firstFamily = comparisonFamilyForModel(catalog, first)
|
||||
const secondFamily = comparisonFamilyForModel(catalog, second)
|
||||
if (!firstFamily || !secondFamily || firstFamily.slug === secondFamily.slug) return undefined
|
||||
if (firstFamily.model.id !== first.id || secondFamily.model.id !== second.id) return undefined
|
||||
return canonicalFamilyComparisonPath(firstFamily, secondFamily)
|
||||
}
|
||||
|
||||
export function comparisonFamilyForModel(catalog: ModelCatalog, model: ModelCatalogEntry) {
|
||||
const family = comparisonFamilies.find(
|
||||
(candidate) => candidate.lab === model.lab && isFamilyModel(model, candidate) && isGeneralComparisonModel(model),
|
||||
)
|
||||
if (!family) return undefined
|
||||
const latest = comparisonFamilyCandidates(catalog, family.slug)[0]
|
||||
if (!latest) return undefined
|
||||
return { ...family, model: latest } satisfies ResolvedComparisonFamily
|
||||
}
|
||||
|
||||
function isFamilyModel(model: ModelCatalogEntry, family: ComparisonFamilyDefinition) {
|
||||
const values = [model.family, model.slug, model.name]
|
||||
.filter((value): value is string => Boolean(value))
|
||||
.map(catalogSlug)
|
||||
return family.prefixes.some((prefix) => values.some((value) => value === prefix || value.startsWith(`${prefix}-`)))
|
||||
}
|
||||
|
||||
function isGeneralComparisonModel(model: ModelCatalogEntry) {
|
||||
const input = model.modalities.input.map(catalogSlug)
|
||||
const output = model.modalities.output.map(catalogSlug)
|
||||
if (!input.includes("text") || !output.includes("text")) return false
|
||||
return !/(?:^|-)(?:audio|embedding|guard|image|moderation|omni|rerank|safety|speech|transcribe|tts|vision)(?:-|$)/.test(
|
||||
model.slug,
|
||||
)
|
||||
}
|
||||
|
||||
function comparisonFamilyModelSort(
|
||||
first: ModelCatalogEntry,
|
||||
second: ModelCatalogEntry,
|
||||
family: ComparisonFamilyDefinition,
|
||||
) {
|
||||
return (
|
||||
displayDateTime(second.releaseDate ?? second.lastUpdated) -
|
||||
displayDateTime(first.releaseDate ?? first.lastUpdated) ||
|
||||
preferredFamilyIndex(first, family) - preferredFamilyIndex(second, family) ||
|
||||
modelVariantPenalty(first) - modelVariantPenalty(second) ||
|
||||
first.slug.length - second.slug.length ||
|
||||
first.name.localeCompare(second.name)
|
||||
)
|
||||
}
|
||||
|
||||
function preferredFamilyIndex(model: ModelCatalogEntry, family: ComparisonFamilyDefinition) {
|
||||
const index = family.preferredFamilies?.indexOf(catalogSlug(model.family ?? "")) ?? -1
|
||||
return index === -1 ? (family.preferredFamilies?.length ?? 0) : index
|
||||
}
|
||||
|
||||
function modelVariantPenalty(model: ModelCatalogEntry) {
|
||||
return /(?:highspeed|latest|preview|turbo|ultraspeed)/.test(model.slug) ? 1 : 0
|
||||
}
|
||||
|
||||
function isDuplicateAliasModel(model: ModelCatalogEntry, models: ModelCatalogEntry[]) {
|
||||
if (!/(?:-latest|-highspeed|-ultraspeed)$/.test(model.slug)) return false
|
||||
return models.some(
|
||||
(candidate) =>
|
||||
candidate.id !== model.id &&
|
||||
candidate.releaseDate === model.releaseDate &&
|
||||
candidate.family === model.family &&
|
||||
!/(?:-latest|-highspeed|-ultraspeed)$/.test(candidate.slug),
|
||||
)
|
||||
}
|
||||
|
||||
function uniqueModels(models: ModelCatalogEntry[]) {
|
||||
return models.reduce<{ ids: Set<string>; models: ModelCatalogEntry[] }>(
|
||||
(result, model) => {
|
||||
if (result.ids.has(model.id)) return result
|
||||
result.ids.add(model.id)
|
||||
result.models.push(model)
|
||||
return result
|
||||
},
|
||||
{ ids: new Set(), models: [] },
|
||||
).models
|
||||
}
|
||||
|
||||
function displayDateTime(value: string | undefined) {
|
||||
if (!value) return 0
|
||||
const date = new Date(value)
|
||||
if (!Number.isNaN(date.getTime())) return date.getTime()
|
||||
const year = Number(value.match(/\d{4}/)?.[0] ?? 0)
|
||||
return Number.isFinite(year) ? year : 0
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue