Skip to content

feat(chat): multi-model /tasks/chat/completions (sunflower-14b + sunflower-9b)#239

Merged
PatrickCmd merged 21 commits into
mainfrom
sunflower-multi-models
Jul 21, 2026
Merged

feat(chat): multi-model /tasks/chat/completions (sunflower-14b + sunflower-9b)#239
PatrickCmd merged 21 commits into
mainfrom
sunflower-multi-models

Conversation

@PatrickCmd

@PatrickCmd PatrickCmd commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Extends the OpenAI-compatible POST /tasks/chat/completions endpoint from a single hardcoded model to two Sunflower text models, each on its own RunPod serverless endpoint. Backward compatible with existing string-content clients; also documents the endpoint across the API docs, tutorial, and frontend, and wires the new config into the Cloud Run deploy.

model Endpoint env var Coverage
sunflower-14b (default) SUNFLOWER_14B_ENDPOINT_ID (falls back to SUNFLOWER_ENDPOINT_ID / QWEN_ENDPOINT_ID) English + 31 Ugandan/regional languages (32 total)
sunflower-9b SUNFLOWER_9B_ENDPOINT_ID 67 African languages (good/moderate/basic tiers)

Behavior

  • Model selection via the model field; sunflower-14b is the default when omitted. Unknown model → 400 listing supported models.
  • No alias. The old Sunbird/Sunflower-14B identifier is not accepted — it returns 400 telling the client to use sunflower-14b.
  • Text only. Message content is a plain string; non-string content → 422.
  • Upstream served name. The model= forwarded to each RunPod/vLLM endpoint defaults to the short name (sunflower-14b / sunflower-9b) to match each endpoint's --served-model-name; overridable via SUNFLOWER_14B_MODEL_NAME / SUNFLOWER_9B_MODEL_NAME.
  • Quota/billing unchanged. Legacy internal qwen/sunflower keys are preserved and now also send the short upstream name (the translation service routes through them to the same 14B endpoint).

Scope note: An earlier revision of this branch added Sunflower Gemma 2B with base64 audio input. That was removed before deployment by product decision — the endpoint serves only the two text models above. Branch history preserves it; the design spec carries an amendment note.

Changes

Backend

  • app/schemas/chat.pySUPPORTED_MODELS = ("sunflower-14b", "sunflower-9b"), DEFAULT_MODEL, RENAMED_MODELS (drives the deprecated-identifier error), resolve_model (no aliases), string-only content.
  • app/services/inference_service.py — env-driven multi-endpoint routing map for both models plus legacy qwen/sunflower keys; short upstream served names.
  • app/routers/chat.py — per-model routing (no hardcoded model constant); _validate_model returns the targeted rename error or the generic unsupported-model error.

Docs

  • app/docs.py, docs/tutorial.md, frontend/src/pages/Tutorial.tsx — model selection, per-model language coverage (sourced from the SALT model pages / HuggingFace), removed-alias behavior, and updated code samples. Rebuilt SPA assets committed.

Deployment / config

  • .github/workflows/deploy-api.yml — adds SUNFLOWER_14B_ENDPOINT_ID / SUNFLOWER_9B_ENDPOINT_ID to the Cloud Run deploy via env_vars_update_strategy: merge (preserves the service's existing env). Azure/Heroku untouched.
  • .env.example — documents the new endpoint vars, the 14B fallback chain, and the optional model-name overrides.

Testing

  • Full suite green apart from 4 pre-existing Google-Analytics-config failures (present at the base commit, unrelated). New coverage: per-model routing, default model, deprecated-alias rejection (400), unknown model (400), non-string content (422), upstream served-name defaults, and legacy-key regression; existing string-content/streaming tests still pass.
  • app/ is black/isort/flake8-clean; frontend npm run build (tsc + vite) passes.

Ops before / after deploy

  • Set the GitHub Actions secrets SUNFLOWER_14B_ENDPOINT_ID and SUNFLOWER_9B_ENDPOINT_ID before the next Cloud Run deploy. (14B still falls back to the existing SUNFLOWER_ENDPOINT_ID/QWEN_ENDPOINT_ID on the service; 9B needs its secret to function.)
  • If any endpoint is redeployed under a different --served-model-name, set SUNFLOWER_14B_MODEL_NAME / SUNFLOWER_9B_MODEL_NAME on the service to match.

Known, out of scope

  • npm run lint fails due to a pre-existing ESLint v10 / flat-config toolchain mismatch (fails identically without this branch's changes); the npm run build type-check gate passes.

🤖 Generated with Claude Code

PatrickCmd and others added 13 commits July 21, 2026 07:52
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- docs/sunflower-multi-models.md: add a "Using via the Sunbird API"
  section covering model selection on /tasks/chat/completions, the
  legacy Sunbird/Sunflower-14B alias, and the Gemma-only <=30s audio
  clip limit with no server-side chunking.
- app/tests/test_routers/test_translation.py: update
  test_feedback_logged_with_sunflower_model to expect the resolved
  canonical model key "sunflower-14b" as model_type, since DEFAULT_MODEL
  now holds the new short key rather than the old upstream model name
  string "Sunbird/Sunflower-14B" (per design spec: feedback model_type
  is the resolved canonical model name).
… base64-only audio

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remove the multimodal Gemma model and all audio machinery (input_audio
content parts, audio-capability check, feedback audio-sanitization),
returning /tasks/chat/completions to text-only string content. Multi-model
routing across sunflower-14b (default) and sunflower-9b, the
Sunbird/Sunflower-14B alias, and the legacy qwen/sunflower keys remain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@PatrickCmd PatrickCmd changed the title feat(chat): multi-model support for /tasks/chat/completions (14B, 9B, Gemma 2B + audio) feat(chat): multi-model support for /tasks/chat/completions (sunflower-14b + sunflower-9b) Jul 21, 2026
github-actions Bot and others added 8 commits July 21, 2026 16:53
Document the /tasks/chat/completions endpoint across app/docs.py, docs/tutorial.md,
and the frontend Tutorial page: model selection (sunflower-14b default, sunflower-9b),
the Sunbird/Sunflower-14B alias, and per-model language coverage sourced from the SALT
model pages (14B: English + 31 Ugandan/regional; 9B: 67 African languages by tier).

Deployment: add SUNFLOWER_14B_ENDPOINT_ID / SUNFLOWER_9B_ENDPOINT_ID to the Cloud Run
deploy workflow using env_vars_update_strategy: merge (preserves existing service env),
and document the new endpoint vars + optional model-name overrides in .env.example.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The old 'Sunbird/Sunflower-14B' identifier is no longer accepted. resolve_model
applies no aliases; the router returns a 400 with a message telling the client
to use 'sunflower-14b' instead (RENAMED_MODELS drives the targeted hint). Docs
(docs.py, tutorial.md, frontend Tutorial page) and the design-spec amendment
note updated accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The upstream `model=` forwarded to the vLLM/RunPod endpoint defaulted to
`Sunbird/Sunflower-14B`, which the deployed endpoint rejects with
404 'The model ... does not exist' — it serves under `--served-model-name
sunflower-14b`. Default the 14B upstream served name to `sunflower-14b`
(9B already `sunflower-9b`); still overridable via SUNFLOWER_14B_MODEL_NAME.
Legacy qwen/sunflower keys (translation service) now send the short name too,
matching the same endpoint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@PatrickCmd PatrickCmd changed the title feat(chat): multi-model support for /tasks/chat/completions (sunflower-14b + sunflower-9b) feat(chat): multi-model /tasks/chat/completions (sunflower-14b + sunflower-9b) Jul 21, 2026
@PatrickCmd
PatrickCmd merged commit dd8170c into main Jul 21, 2026
2 checks passed
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