DefangLabs / DefangLabs/defang

Consolidate default LLM model names into a single MIT source of truth

Open
#2,201 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
166
Forks
24
Avg merge
10h 8m
Merged PRs (30d)
33

Description

Problem

Default LLM model names live in two places that rot independently, and a retirement in either silently breaks deploys:

  • AWS/GCP — the CLI resolves the alias → concrete model ID statically in src/pkg/cli/compose/fixup.go configureAccessGateway (chat-defaultus.amazon.nova-2-lite-v1:0 / gemini-2.5-flash).
  • Azurepulumi-defang picks from a hardcoded chatPreference list in provider/defangazure/azure/models.go.

This just bit us: Azure's gpt-4o 2024-11-20 entered Deprecating, and defang up on Azure failed with 400 ServiceModelDeprecating. Fixed in pulumi-defang#376, but the fix only patched the Azure list — the two sources of truth remain separate.

Why the two resolution mechanisms must stay different (don't unify the code)

AWS / GCP Azure
Model hosting Serverless (Bedrock / Vertex) — a model ID is just a string; IAM is model-agnostic Must be provisioned as an ARM cognitiveservices.Deployment
Resolution Compile-time, in the CLI (no cloud creds needed) Deploy-time, in the CD task (queries Accounts_ListModels per account+region)
  • "Do it in the CLI for all providers" regresses Azure: the CLI runs before the CD task with no Azure creds and can't know what's deployable in the user's account/region — exactly the blind spot that caused this incident.
  • "Do it in Pulumi for all providers" over-complicates serverless AWS/GCP (adds needless deploy-time catalog queries) and re-plumbs the LiteLLM --model command path.

Proposal: consolidate the data, not the code

Make a single declarative table the source of truth:

{provider, role} → ordered preferred model name(s) + format
  • CLI (AWS/GCP) reads the single top entry and resolves statically as it does today.
  • pulumi-defang (Azure) reads the ordered list as its chatPreference/embeddingPreference seed and keeps the deploy-time lifecycle filter from #376 as defense-in-depth (availability is per-account/region; a static list can never be sufficient on Azure alone).

One edit updates every cloud; each provider keeps the resolution mechanism it actually needs.

Where it must live (licensing)
  • pulumi-defang = AGPL-3.0 (viral), defang CLI = MIT.
  • AGPL may depend on MIT; MIT may not depend on AGPL (it would relicense the CLI).
  • ∴ the shared table must be hosted in the CLI (MIT) module (github.com/DefangLabs/defang/src/...) and imported by pulumi-defang — never the reverse.

This is a natural home: the alias vocabulary (chat-default, embedding-default) already lives in the CLI, and the CLI already owns AWS/GCP defaults. The CLI becomes the canonical data owner for all providers even though it doesn't itself deploy Azure.

Sketch
  • Add a leaf package, e.g. src/pkg/cli/compose/models (minimal transitive deps, so pulumi-defang doesn't inherit the CLI's dependency graph), exporting the table.
  • fixup.go configureAccessGateway reads AWS/GCP entries from it.
  • pulumi-defang adds require github.com/DefangLabs/defang/src and seeds the Azure selector from the table.
  • Keep the user-facing alias stable so defang up output is unchanged while the concrete model updates underneath.

Optional follow-up (not required for v1)

Promote the table to Fabric so defaults update via control-plane config without a CLI or CD-image release — this incident required a CD-image rollout to fix. Adds a network hop and new Fabric surface; do it only if release-free updates become a priority.

Non-goals

  • Don't unify the resolution code paths.
  • Don't couple defaults to per-model IAM allowlists (BYOC IAM stays model-agnostic; the Playground GCP :predict allowlist in defang-mvp is a cautionary example, not a pattern to copy).

Acceptance criteria

  • Single declarative default-model table in the CLI (MIT) module.
  • CLI AWS/GCP resolution reads from it (behavior unchanged).
  • pulumi-defang Azure selector seeds from it and retains the lifecycle filter.
  • Updating a default model is a one-line change in one place.
  • Dependency direction is pulumi-defang → defang only.

Context captured from the model-consolidation investigation; see pulumi-defang#376 for the Azure lifecycle fix that motivated this.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/pkg/cli/compose/fixup.go and its configureAccessGateway function, then compare the Azure chatPreference and embeddingPreference handling in pulumi-defang's provider/defangazure/azure/models.go and the lifecycle filter from pulumi-defang#376. Done means the MIT CLI module owns one declarative table, AWS/GCP resolution reads it, Azure seeds from it while retaining deploy-time filtering, and dependency direction remains pulumi-defang → defang.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, azure, gcp, go
Domain
cli, cloud, devops, infrastructure
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.