Skip to content

Model Picker — Kotlin 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 Kotlin implementation — the same logic the interactive tool runs, in a shareable, citable form.

// model-picker — Kotlin port: filter + rank the AI model catalog.

// Pricing projection of the TS AiModel record; nullables play TS null.
data class Model(
    val id: String,
    val tier: String,
    val contextWindow: Long,   // context window in tokens.
    val inputPerM: Double?,    // USD per 1M input tokens; null = unpriced.
    val outputPerM: Double?,   // USD per 1M output tokens; null = unpriced.
    val released: String?,     // ISO date; null = unknown.
)
// Projection of the TS ModelFilter — the three constraints the presets use.
data class ModelFilter(val tier: String? = null, val minContext: Long? = null, val maxInputPerM: Double? = null)
// Curated entry points: a filter + the sort that makes that filter useful.
val PRESETS = mapOf(
    "long-context" to (ModelFilter(minContext = 500_000) to "context"),
    "cheap-bulk" to (ModelFilter(maxInputPerM = 1.0) to "price"),
    "flagship" to (ModelFilter(tier = "flagship") to "tokensPerDollar"),
)

// Output tokens per USD: 1e6 / outputPerM, or null when unpriced.
fun tokensPerDollar(m: Model): Double? = m.outputPerM?.let { 1_000_000 / it }

// Comparator core: value order (desc when asked), null last, id asc on ties.
fun <T : Comparable<T>> rank(desc: Boolean = false, key: (Model) -> T?): Comparator<Model> =
    Comparator { a, b ->
        val va = key(a)
        val vb = key(b)
        when {
            va == null && vb == null -> a.id.compareTo(b.id)
            va == null -> 1
            vb == null -> -1
            else -> {
                val c = if (desc) vb.compareTo(va) else va.compareTo(vb)
                if (c == 0) a.id.compareTo(b.id) else c
            }
        }
    }

// Sort comparator per key: value order first, null last, id asc on ties —
// every comparator fully orders, so sortedWith stays deterministic.
val COMPARATORS: Map<String, Comparator<Model>> = mapOf(
    "price" to rank { it.inputPerM },
    "context" to rank(desc = true) { it.contextWindow },
    "tokensPerDollar" to rank(desc = true) { tokensPerDollar(it) },
    "released" to rank(desc = true) { it.released },
)

// Filter step, inlined from listModels in src/lib/ai/models.ts: null prices
// never satisfy maxInputPerM.
fun listModels(models: List<Model>, filter: ModelFilter = ModelFilter()): List<Model> =
    models.filter { m ->
        (filter.tier == null || m.tier == filter.tier) &&
            (filter.minContext == null || m.contextWindow >= filter.minContext) &&
            (filter.maxInputPerM == null ||
                (m.inputPerM != null && m.inputPerM <= filter.maxInputPerM))
    }

// Filter the model list, then sort it. See COMPARATORS for the exact order.
fun pickModels(models: List<Model>, filter: ModelFilter = ModelFilter(), sort: String = "price") =
    listModels(models, filter).sortedWith(COMPARATORS.getValue(sort))

fun main() {
    val models = listOf(
        Model("atlas-flagship", "flagship", 1_000_000, 3.0, 15.0, "2025-03-01"),
        Model("atlas-mini", "fast", 200_000, 0.5, 2.0, "2025-01-15"),
        Model("nova-open", "balanced", 1_000_000, null, null, null), // unpriced
        Model("zeta-budget", "budget", 128_000, 0.5, 1.0, "2024-12-01"),
    )

    val (filter, sort) = PRESETS.getValue("long-context")
    println("long-context (minContext >= ${filter.minContext}, sort $sort):")
    pickModels(models, filter, sort).forEach { println("  %-14s ctx %d".format(it.id, it.contextWindow)) }

    println("price sort (all models, unpriced last, ties by id):")
    pickModels(models).forEach {
        if (it.inputPerM != null) println("  %-14s $%.2f/M in".format(it.id, it.inputPerM))
        else println("  %-14s unpriced".format(it.id))
    }
}

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 →