Skip to content

docs: surface per-provider AI model override env vars - #290

Merged
paulocastellano merged 4 commits into
trypostit:mainfrom
HafizMMoaz:docs/issue-225-ai-model-overrides
Aug 26, 2026
Merged

docs: surface per-provider AI model override env vars#290
paulocastellano merged 4 commits into
trypostit:mainfrom
HafizMMoaz:docs/issue-225-ai-model-overrides

Conversation

@HafizMMoaz

Copy link
Copy Markdown
Contributor

Summary

Investigated this expecting to add AI_IMAGE_MODEL/AI_AUDIO_MODEL
config as suggested, but found the underlying premise doesn't hold up
against the actual laravel/ai package behavior - so this PR does
something narrower and, I think, more correct.

What I found

  • config/ai.php already defines a model override per provider, per
    capability
    - OPENAI_IMAGE_MODEL, OPENAI_AUDIO_MODEL,
    GEMINI_IMAGE_MODEL, XAI_IMAGE_MODEL, OPENROUTER_IMAGE_MODEL,
    OPENROUTER_AUDIO_MODEL, ELEVENLABS_AUDIO_MODEL, etc. - and
    app/Services/Ai/AiImageClient.php already calls Image::of()
    through that config.
  • There's no text-model fallback bug: I checked the laravel/ai
    vendor source directly (OpenAiProvider::defaultImageModel(),
    OpenRouterProvider::defaultImageModel(), etc.) and each provider's
    image/audio default falls back to a hardcoded image/audio model
    when unset, never to that provider's text model.
  • A single global AI_IMAGE_MODEL (as suggested) would actually be a
    worse fit than what exists - model IDs aren't portable across
    providers (gpt-image-2 vs. google/gemini-3.1-flash-image-preview
    vs. an Ollama tag), so a per-provider override is the correct shape,
    not a regression to fix.
  • Ollama specifically has no image or audio driver in laravel/ai at
    all (confirmed in vendor - only TextProvider/EmbeddingProvider
    are implemented), so no config change here can make Ollama do image
    or audio generation. OpenRouter, unlike Ollama, already implements
    both.

The actual gap: .env.example only shows AI_TEXT_PROVIDER /
AI_IMAGE_PROVIDER / AI_AUDIO_PROVIDER (which provider to route to)
and never mentions any of the per-provider model overrides that
already exist and work. A self-hoster reading only .env.example
would have no way to discover them without reading config/ai.php
source - which lines up with the issue's report even though the
mechanism it assumed isn't what's actually happening.

Change

Added the per-provider model override variables (commented out, as
optional) right after the existing AI_*_PROVIDER block in
.env.example, with a note on Ollama's text-only support.

Test plan

No code paths changed - this is .env.example documentation only.
Verified config/ai.php's existing wiring and the vendor laravel/ai
provider classes referenced above by reading them directly rather than
assuming.

Addresses #225 - happy to also add AI_IMAGE_MODEL/AI_AUDIO_MODEL globals if you'd still prefer those for convenience, but wanted to flag they'd need to pick a provider's model format, which only works cleanly if there's exactly one image/audio provider configured

.env.example only showed AI_TEXT_PROVIDER/AI_IMAGE_PROVIDER/
AI_AUDIO_PROVIDER (which provider to use), never the per-provider
model overrides (OPENAI_IMAGE_MODEL, GEMINI_AUDIO_MODEL, etc.) that
config/ai.php already wires up for every provider capability. A
self-hoster reading only .env.example had no way to discover these
existed.

These aren't new: laravel/ai already resolves each capability's
model independently per provider (confirmed in vendor - e.g.
OpenAiProvider::defaultImageModel() falls back to a hardcoded image
model, never to the text model), so there was never actually a
text-model fallback bug to fix in code. The gap was purely that the
override knobs were invisible outside of reading config/ai.php's
source directly.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates .env.example to better document existing laravel/ai environment variables by surfacing optional, per-provider model override env vars (rather than introducing global AI_IMAGE_MODEL / AI_AUDIO_MODEL knobs).

Changes:

  • Adds an “AI Model Overrides (optional)” block with commented-out per-provider *_MODEL overrides near the existing AI_*_PROVIDER settings.
  • Documents that model defaults are capability-specific and (per the PR description) do not fall back from image/audio to text models.
  • Notes Ollama’s lack of image/audio support in laravel/ai.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .env.example
The override block landed with bare variable names and only covered the
five providers whose API keys were already in .env.example. Filled in
what a self-hoster still could not discover:

- Example values on every model override, taken from laravel/ai's
  current per-capability defaults, so the ID format is visible (an
  Ollama tag, an OpenRouter vendor/model path and a bare OpenAI ID
  look nothing alike).
- The keys and URLs for the providers .env.example already advertises
  as valid but never documented: XAI, GROQ, MISTRAL, DEEPSEEK,
  OLLAMA_URL and the openai-compatible endpoint. Ollama was the
  scenario in the original report and OLLAMA_URL matters more there
  than OLLAMA_TEXT_MODEL does.
- GROQ/MISTRAL/DEEPSEEK text models, missing while their providers
  were listed as options.
- openai-compatible has no built-in default model and throws without
  OPENAI_COMPATIBLE_TEXT_MODEL, so that one is flagged as required.
- Corrected the audio provider list: gemini and openrouter implement
  AudioProvider too. The image and audio lists are no longer written
  as exhaustive.
- Mirrored all of it into docker/.env.docker.example, which carried the
  same block untouched and is the file Docker self-hosters copy. Its
  OLLAMA_URL points at the host instead of localhost.
@paulocastellano

Copy link
Copy Markdown
Contributor

@HafizMMoaz i have improved your pull requested and merged it, thank you!

@paulocastellano
paulocastellano merged commit 06fd0ba into trypostit:main Aug 26, 2026
6 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.

3 participants