Skip to content

[Platform] Add ModelCard with pricing, region and extra metadata to model catalog#2130

Draft
wachterjohannes wants to merge 1 commit into
symfony:mainfrom
wachterjohannes:feature/platform-model-card
Draft

[Platform] Add ModelCard with pricing, region and extra metadata to model catalog#2130
wachterjohannes wants to merge 1 commit into
symfony:mainfrom
wachterjohannes:feature/platform-model-card

Conversation

@wachterjohannes

Copy link
Copy Markdown
Contributor
Q A
Bug fix? no
New feature? yes
Docs? no
Issues -
License MIT

Adds an optional, objective metadata layer to model catalog entries so a Model
can answer "what do you cost?" and "where do you run?". This is the data layer that a
cost tracker (token usage → money) and a criteria router (filter by region/tier) build
on; both are out of scope here.

What's added

  • ModelCatalog\ModelPricing — immutable VO with per-1M-token rates, cache-aware
    (cachedInputPerMillion / cacheWritePerMillion, matching TokenUsage's cache
    counters), currency defaulting to USD.
  • ModelCatalog\ModelCard — immutable VO holding platform-blessed facts (pricing,
    region) plus an open, app-owned extra bag (get() / all()). Platform code never
    branches on extra contents.
  • Model::getCard(): ?ModelCard — new optional 4th constructor slot, defaulting to
    null.
  • AbstractModelCatalog parses an optional metadata key per entry and attaches the
    card.

Usage

// In a ModelCatalog's $models array:
'gpt-x' => [
    'class'        => Gpt::class,
    'capabilities' => [Capability::INPUT_TEXT, Capability::TOOL_CALLING],
    'metadata'     => [
        'pricing' => ['input' => 5.0, 'output' => 30.0, 'cachedInput' => 0.5],
        'region'  => 'us',
        'extra'   => ['tier' => 'flagship'],
    ],
],

// Consuming it:
$card = $catalog->getModel('gpt-x')->getCard();
$card?->getPricing()?->getInputPerMillion(); // 5.0
$card?->getRegion();                          // 'us'
$card?->get('tier');                          // 'flagship'

Notes

  • Fully backward compatiblemetadata is optional and getCard() returns null
    when absent; no existing catalog entry needs editing.
  • The getter is named getCard() (not getMetadata()) on purpose: the platform already
    has a generic mutable Metadata\Metadata bag exposed via getMetadata(): Metadata on
    every Result/Message (runtime side-channel data). A ModelCard is a static catalog
    descriptor, so it gets its own name to avoid overloading that convention.
  • Mechanism only — no real bridge pricing data is shipped; apps populate their own
    catalogs. Model subclasses that override __construct (Claude, OpenAi/Gemini/Scaleway
    Embeddings, Scaleway, Voyage) forward the new argument so the card isn't silently
    dropped; a regression test guards this through a subclass.

Possible follow-ups (separate PRs): wiring a pricing source such as ModelsDev,
populating real bridge data, the cost tracker, and the criteria router.

…odel catalog

Introduce an optional, objective metadata layer for model catalog entries:
ModelCard (pricing, region, plus an open app-owned extra bag) and ModelPricing
(cache-aware, per-million-token rates). A catalog entry may declare an optional
'metadata' key; AbstractModelCatalog builds the ModelCard and exposes it via the
new Model::getCard(). Fully backward compatible - the card defaults to null.

Model subclasses that override the constructor forward the new argument so the
card is not silently dropped.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant