fix(mistral): ensure /v1 on the Voxtral TTS base URL

A host-only api_base or MISTRAL_API_BASE (the documented form, https://api.mistral.ai) built
https://api.mistral.ai/audio/speech and 404ed. Match the chat and OCR configs by appending /v1
when the configured base does not already end with it.
This commit is contained in:
mateo-berri 2026-09-02 13:32:51 -07:00
parent 25bb8c92e3
commit 7c91b0120f
2 changed files with 16 additions and 8 deletions

View file

@ -115,8 +115,9 @@ class MistralTextToSpeechConfig(BaseTextToSpeechConfig):
api_base: str | None,
litellm_params: Mapping[str, object],
) -> str:
base_url: Final = api_base or get_secret_str("MISTRAL_API_BASE") or self.TTS_BASE_URL
return f"{base_url.rstrip('/')}/audio/speech"
configured_base: Final = (api_base or get_secret_str("MISTRAL_API_BASE") or self.TTS_BASE_URL).rstrip("/")
versioned_base: Final = configured_base if configured_base.endswith("/v1") else f"{configured_base}/v1"
return f"{versioned_base}/audio/speech"
def transform_text_to_speech_request(
self,

View file

@ -91,16 +91,23 @@ def test_get_complete_url_default_base(monkeypatch: pytest.MonkeyPatch):
assert url == SPEECH_URL
def test_get_complete_url_custom_base():
@pytest.mark.parametrize(
"api_base",
["https://custom.api.example.com/v1/", "https://custom.api.example.com/v1", "https://custom.api.example.com"],
)
def test_get_complete_url_custom_base_always_versioned(api_base: str):
config: Final = MistralTextToSpeechConfig()
url: Final = config.get_complete_url(
model="voxtral-mini-tts-2603",
api_base="https://custom.api.example.com/v1/",
litellm_params={},
)
url: Final = config.get_complete_url(model="voxtral-mini-tts-2603", api_base=api_base, litellm_params={})
assert url == "https://custom.api.example.com/v1/audio/speech"
def test_get_complete_url_host_only_env_base_gets_v1(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setenv("MISTRAL_API_BASE", "https://api.mistral.ai")
config: Final = MistralTextToSpeechConfig()
url: Final = config.get_complete_url(model="voxtral-mini-tts-2603", api_base=None, litellm_params={})
assert url == SPEECH_URL
def test_validate_environment_sets_bearer_header():
config: Final = MistralTextToSpeechConfig()
headers: Final = config.validate_environment(