fix(proxy): classify Azure Speech short audio behind a prefixed api base - #41882
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
|
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
bugbot run |
|
@veria-ai please review f1b9642: Azure Speech billing classification now keys on the last path family marker |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit f1b9642. Configure here.
TLDR
Problem this solves:
AZURE_SPEECH_API_BASEwas billed as batch at $0How it solves it:
/speech/vs/speechtotext/segment in the pathUser Flow
Before: a proxy admin fronts Azure Speech with an API gateway at
AZURE_SPEECH_API_BASE=https://apim.example.com/speech-proxy. Short audio calls succeed but never count against key budgetsmax_budget: 0.001via POST https://litellm-domain/key/generateazure_speech/batch-transcriptionat spend 0, and the key's spend stays 0After: the same calls are billed as short audio and the budget trips
max_budget: 0.001via POST https://litellm-domain/key/generateBudget has been exceededazure_speech/short-audiowith non-zero spend, and the key's spend matches itRelevant issues
Follow-up to #41557 (Bugbot finding on the merged PR)
Affected release
Linear ticket
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@greptileaito re-request a review after pushing changes)Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
Setup shared by both runs: a real Azure Speech subscription key in
AZURE_SPEECH_API_KEY, region swedencentral, Postgres attached,master_key: sk-1234. To stand in for an operator's API gateway, a 40 line forwarder listens on127.0.0.1:8089, strips the/speech-proxyprefix, and forwards the request unchanged over TLS to the realswedencentral.stt.speech.microsoft.comorswedencentral.api.cognitive.microsoft.comhost. Both proxies run withAZURE_SPEECH_API_BASE=http://127.0.0.1:8089/speech-proxy. Every Azure call below hit Azure and was billed there. The wav istests/proxy_unit_tests/eagle.wav(5.06 s). Before ran on port 4011, After on 4012;$Hishttp://localhost:<port>Before (6759f28)
VKEY=$(curl -s -X POST $H/key/generate -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{"max_budget":0.001}' | jq -r .key)curl -s -w "\nHTTP %{http_code}\n" "$H/azure_speech/speech/recognition/conversation/cognitiveservices/v1?language=en-US" -H "Authorization: Bearer $VKEY" -H "Content-Type: audio/wav" --data-binary @tests/proxy_unit_tests/eagle.wavcurl -s -w "\nHTTP %{http_code}\n" "$H/azure_speech/speechtotext/transcriptions:transcribe?api-version=2024-11-15" -H "Authorization: Bearer $VKEY" -F "audio=@tests/proxy_unit_tests/eagle.wav" -F 'definition={"locales":["en-US"]}'curl -s "$H/spend/logs?api_key=$VKEY" -H "Authorization: Bearer sk-1234" | jq -r '.[] | select(.model != "") | [.model, .spend, .api_base] | @tsv'curl -s "$H/key/info?key=$VKEY" -H "Authorization: Bearer sk-1234" | jq .info.spendAfter (f1b9642)
VKEY=$(curl -s -X POST $H/key/generate -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{"max_budget":0.001}' | jq -r .key)curl -s -w "\nHTTP %{http_code}\n" "$H/azure_speech/speech/recognition/conversation/cognitiveservices/v1?language=en-US" -H "Authorization: Bearer $VKEY" -H "Content-Type: audio/wav" --data-binary @tests/proxy_unit_tests/eagle.wavcurl -s -w "\nHTTP %{http_code}\n" "$H/azure_speech/speechtotext/transcriptions:transcribe?api-version=2024-11-15" -H "Authorization: Bearer $VKEY" -F "audio=@tests/proxy_unit_tests/eagle.wav" -F 'definition={"locales":["en-US"]}'curl -s "$H/spend/logs?api_key=$VKEY" -H "Authorization: Bearer sk-1234" | jq -r '.[] | select(.model != "") | [.model, .spend, .api_base] | @tsv'curl -s "$H/key/info?key=$VKEY" -H "Authorization: Bearer sk-1234" | jq .info.spendGateway log for the whole run, showing the prefix stripped and the real Azure hosts hit:
Type
🐛 Bug Fix
Caveats (if any)
Low
/speechtotext/is not distinguishable from batch; unlikely in practiceproxy-infra / Run tests, failing ontest_login_throttle_settings_are_not_hot_applied_from_the_database, which fails the same way onmainand touches nothing in this diffReview gate at f1b9642
Greptile 5/5, Bugbot found no new issues, Veria found no security issues, codecov patch 100%, every required check green
Final Attestation
Note
Medium Risk
Changes spend logging and budget enforcement for Azure Speech behind path-prefixed API bases; misclassification could under- or over-charge keys.
Overview
Fixes Azure Speech passthrough logging when
AZURE_SPEECH_API_BASEadds a gateway prefix so the upstream path no longer starts with/speech/.Short-audio route detection no longer uses
path.startswith("/speech/"). It compares the last occurrence of/speech/vs/speechtotext/in the URL path, so prefixed bases (e.g.…/speech-proxy/speech/recognition/…) are classified as short audio with metered spend instead of batch at $0. Fast transcription (suffix match) and batch behavior are unchanged.Tests cover prefixed short-audio, fast-transcription, and batch URLs through an APIM-style base.
Reviewed by Cursor Bugbot for commit f1b9642. Bugbot is set up for automated code reviews on this repo. Configure here.
Link to Devin session: https://app.devin.ai/sessions/2c12f8499dd642e188af5d3e207590d6
Open in Devin Desktop: https://app.devin.ai/desktop/session/2c12f8499dd642e188af5d3e207590d6?variant=devin
Requested by: @yassin-berriai