Model Picker — C# source
Filter every major model by context window, price, modality, and tier — sort by cost, context, or tokens-per-dollar to find the right model for the task.
This is the C# implementation — the same logic the interactive tool runs, in a shareable, citable form.
// model-picker — C# port: filter + rank the AI model catalog.
using System;
using System.Collections.Generic;
using System.Linq;
// Pricing projection of the TS AiModel record — nullables play the role of
// TS null (unpriced model / unknown release date).
record Model(string Id, string Tier, long ContextWindow,
double? InputPerM, double? OutputPerM, string? Released);
// Projection of the TS ModelFilter — the three constraints the presets use.
record ModelFilter(string? Tier = null, long? MinContext = null, double? MaxInputPerM = null);
static class ModelPicker
{
// Curated entry points: a filter + the sort that makes that filter useful.
public static readonly Dictionary<string, (ModelFilter Filter, string Sort)> Presets = new()
{
["long-context"] = (new(MinContext: 500_000), "context"),
["cheap-bulk"] = (new(MaxInputPerM: 1), "price"),
["flagship"] = (new(Tier: "flagship"), "tokensPerDollar"),
};
// Output tokens per USD: 1e6 / OutputPerM, or null when unpriced.
static double? TokensPerDollar(Model m) => m.OutputPerM is { } o ? 1e6 / o : null;
// Filter step, inlined from listModels in src/lib/ai/models.ts (the
// pricing snapshot accessor): null prices never satisfy MaxInputPerM.
public static IEnumerable<Model> ListModels(IEnumerable<Model> models, ModelFilter? f = null) =>
models.Where(m =>
(f?.Tier == null || m.Tier == f.Tier) &&
(f?.MinContext == null || m.ContextWindow >= f.MinContext) &&
(f?.MaxInputPerM == null ||
(m.InputPerM != null && m.InputPerM <= f.MaxInputPerM)));
// Sort keys — the TS SortKey union. Nulls always sort last, id asc on
// ties: nullsLast on an ascending key, nullsSmallest inverted by
// OrderByDescending (null/negative infinity sinks to the end naturally).
public static IEnumerable<Model> PickModels(IEnumerable<Model> models,
ModelFilter? f = null, string sort = "price") =>
sort switch
{
"context" => ListModels(models, f)
.OrderByDescending(m => m.ContextWindow).ThenBy(m => m.Id),
"tokensPerDollar" => ListModels(models, f)
.OrderByDescending(m => TokensPerDollar(m) ?? double.NegativeInfinity)
.ThenBy(m => m.Id),
"released" => ListModels(models, f)
.OrderByDescending(m => m.Released).ThenBy(m => m.Id),
_ => ListModels(models, f)
.OrderBy(m => m.InputPerM ?? double.MaxValue).ThenBy(m => m.Id),
};
public static void Main()
{
var models = new[]
{
new Model("atlas-flagship", "flagship", 1_000_000, 3.0, 15.0, "2025-03-01"),
new Model("atlas-mini", "fast", 200_000, 0.5, 2.0, "2025-01-15"),
new Model("nova-open", "balanced", 1_000_000, null, null, null), // unpriced
new Model("zeta-budget", "budget", 128_000, 0.5, 1.0, "2024-12-01"),
};
var (filter, sort) = Presets["long-context"];
Console.WriteLine($"long-context (minContext >= {filter.MinContext}, sort {sort}):");
foreach (var m in PickModels(models, filter, sort))
Console.WriteLine($" {m.Id,-14}ctx {m.ContextWindow}");
Console.WriteLine("price sort (all models, unpriced last, ties by id):");
foreach (var m in PickModels(models))
Console.WriteLine(m.InputPerM is { } p
? $" {m.Id,-14}${p:F2}/M in" : $" {m.Id,-14}unpriced");
}
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →