fix(speech): use the provider api key get_llm_provider resolves

speech() called get_llm_provider and then dropped its dynamic_api_key
everywhere except the logging params, so a TTS deployment whose credential
lives in a provider-specific env var fell through to OPENAI_API_KEY on the
openai-compatible branch and to AZURE_OPENAI_API_KEY / AZURE_API_KEY on the
azure branch, failing with a missing-credentials error naming variables the
admin never configured.

Fold dynamic_api_key into both branch key chains, right after an explicitly
passed api_key, so a provider-scoped key is used while an explicit one stays
authoritative.
This commit is contained in:
mateo-berri 2026-09-03 01:33:18 -07:00
parent 658f50663d
commit 3ceaf793ac
2 changed files with 76 additions and 1 deletions

View file

@ -8073,7 +8073,8 @@ def speech(
# set API KEY
api_key = (
api_key
or litellm.api_key # for deepinfra/perplexity/anyscale we check in get_llm_provider and pass in the api key from there
or dynamic_api_key # for deepinfra/perplexity/anyscale we check in get_llm_provider and pass in the api key from there
or litellm.api_key
or litellm.openai_key
or get_secret("OPENAI_API_KEY")
)
@ -8157,6 +8158,7 @@ def speech(
api_key = (
api_key
or dynamic_api_key
or litellm.api_key
or litellm.azure_key
or get_secret("AZURE_OPENAI_API_KEY")

View file

@ -1,6 +1,8 @@
import asyncio
import base64
import threading
from datetime import datetime
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import contextlib
import copy
import json
@ -3259,3 +3261,74 @@ def test_stream_chunk_builder_leaves_xai_reported_cost_to_the_calculator(monkeyp
assert getattr(response.usage, "cost", None) == pytest.approx(0.42)
assert response._hidden_params.get("response_cost") is None
assert logging_obj._response_cost_calculator(result=response) == pytest.approx(0.63)
@contextlib.contextmanager
def _recording_tts_server():
received: Final[list[Mapping[str, str]]] = []
class _Handler(BaseHTTPRequestHandler):
def do_POST(self):
received.append({key.lower(): value for key, value in self.headers.items()})
self.rfile.read(int(self.headers.get("Content-Length") or 0))
body = b"ID3\x04\x00\x00\x00fake-mp3-payload"
self.send_response(200)
self.send_header("Content-Type", "audio/mpeg")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def log_message(self, format, *args):
return
server: Final = ThreadingHTTPServer(("127.0.0.1", 0), _Handler)
thread: Final = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
try:
yield f"http://127.0.0.1:{server.server_port}", received
finally:
server.shutdown()
server.server_close()
thread.join(timeout=5)
def test_speech_openai_compatible_sends_the_provider_scoped_key(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr(litellm, "api_key", None)
monkeypatch.setattr(litellm, "openai_key", None)
monkeypatch.setattr(litellm, "api_base", None)
monkeypatch.setenv("HOSTED_VLLM_API_KEY", "hosted-vllm-scoped-key")
monkeypatch.setenv("OPENAI_API_KEY", "generic-openai-key")
with _recording_tts_server() as (api_base, received):
response: Final = litellm.speech(
model="hosted_vllm/tts-1",
input="which key goes out",
voice="alloy",
api_base=api_base,
)
assert response.content == b"ID3\x04\x00\x00\x00fake-mp3-payload"
assert len(received) == 1
assert received[0]["authorization"] == "Bearer hosted-vllm-scoped-key"
def test_speech_azure_sends_the_provider_scoped_key(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr(litellm, "api_key", None)
monkeypatch.setattr(litellm, "azure_key", None)
monkeypatch.setattr(litellm, "api_base", None)
monkeypatch.setenv("AZURE_AI_API_KEY", "azure-ai-scoped-key")
monkeypatch.setenv("AZURE_OPENAI_API_KEY", "legacy-azure-openai-key")
monkeypatch.setenv("AZURE_API_KEY", "legacy-azure-key")
with _recording_tts_server() as (api_base, received):
response: Final = litellm.speech(
model="azure_ai/tts-1",
input="which key goes out",
voice="alloy",
api_base=api_base,
api_version="2024-05-01-preview",
)
assert response.content == b"ID3\x04\x00\x00\x00fake-mp3-payload"
assert len(received) == 1
assert received[0]["api-key"] == "azure-ai-scoped-key"