feat(deepgram): add STT/TTS with_cloudflare() for Cloudflare AI Gateway#6133
feat(deepgram): add STT/TTS with_cloudflare() for Cloudflare AI Gateway#6133mcdgavin wants to merge 9 commits into
Conversation
| @staticmethod | ||
| def with_cloudflare( | ||
| *, | ||
| model: str = "@cf/deepgram/nova-3", |
There was a problem hiding this comment.
is it possible to construct "@cf/deepgram" part internally? Then we can reuse the same DeepgramModels | str type
There was a problem hiding this comment.
Thank you for the feedback @chenghao-mou, this is done.
with_cloudflare now takes a bare Deepgram model name typed DeepgramModels | str (default nova-3 for STT, aura-1 for TTS) and prepends @cf/deepgram/ internally.
A value already prefixed with @cf/ is passed through unchanged, so the full form still works.
| numerals: bool = False, | ||
| mip_opt_out: bool = False, | ||
| vad_events: bool = True, | ||
| _connect_headers: NotGivenOr[dict[str, str]] = NOT_GIVEN, |
There was a problem hiding this comment.
We can just call it extra_headers: NotGivenOr[dict[str, str]] = NOT_GIVEN. We use similar parameters in other plugins as well, it could also be useful for self-hosted DG instances too.
There was a problem hiding this comment.
Switched _connect_headers to a public extra_headers, additive, matching the other plugins and supporting self hosting.
One note, a purely additive extra_headers merges on top of the default Authorization: Token <key>, so the Cloudflare path would send both Authorization and cf-aig-authorization which requires a Deepgram key it doesn't need and risks the gateway rejecting the stray header. To keep it additive without that, the default Authorization: Token is now built only when a Deepgram key is present, and at least one auth source (key or extra_headers) is required:
headers = ({"Authorization": f"Token {key}"} if key else {}) | extra_headersBehavior:
- Normal Deepgram (key set):
Authorization: Token+ extras — unchanged. - Self-hosted DG with custom auth (no key): just
extra_headers. - Cloudflare via
with_cloudflare(no key): justcf-aig-authorization.
| sample_rate=sample_rate, | ||
| base_url=base_url, | ||
| http_session=http_session, | ||
| _connect_headers={"cf-aig-authorization": cf_aig_token}, |
There was a problem hiding this comment.
double checking here: the code in their doc says "cf-aig-authorization": "Bearer {CF_AIG_TOKEN}": https://developers.cloudflare.com/ai-gateway/usage/providers/deepgram/
There was a problem hiding this comment.
I double-checked against the realtime WebSockets page. The Bearer form is documented on the /deepgram provider-proxy endpoint, but this plugin targets the /workers-ai endpoint, and its Deepgram (Workers AI) examples (both @cf/deepgram/nova-3 and @cf/deepgram/aura-1) use the raw cf-aig-authorization token:
"wss://gateway.ai.cloudflare.com/v1/<account_id>/<gateway>/workers-ai?model=@cf/deepgram/nova-3..."
headers: { "cf-aig-authorization": process.env.CLOUDFLARE_API_KEY }Since it flows through extra_headers, it's still overridable either way.
- public extra_headers (additive, merged over default Token auth; sole auth when no key) replacing the private _connect_headers seam - with_cloudflare accepts bare model names (nova-3/aura-1), prefixes @cf/deepgram/ - cf-aig-authorization sent as 'Bearer <token>' per Cloudflare's Deepgram docs
- public extra_headers (additive, merged over the default Token auth; sole auth when no key is set) replacing the private _connect_headers seam - with_cloudflare accepts bare model names (nova-3 / aura-1) and prepends @cf/deepgram/ internally - cf-aig-authorization sent as the raw token, matching the /workers-ai endpoint examples (the Bearer form documented on Cloudflare's /deepgram provider proxy is a different endpoint)
55c1545 to
21f1d68
Compare
…on for CF models - with_cloudflare passes api_key="" so a DEEPGRAM_API_KEY in the env is no longer picked up and sent to the gateway as a stray Authorization: Token header - TTS only falls back to the env var when api_key is None (explicit "" means no key) - _validate_model/_validate_keyterm strip the @cf/deepgram/ routing prefix so keyterm is correctly allowed for @cf/deepgram/nova-3
_validate_model dropped the routing prefix when downgrading an en-only model to nova-2-general for a non-English language, yielding an invalid gateway model.
There was a problem hiding this comment.
🚩 stt_v2.py still uses the old _api_key pattern and was not updated
The file livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/stt_v2.py still uses the old self._api_key / Authorization: Token {self._api_key} pattern (lines 119, 190, 288, 487). It was not modified in this PR. If Cloudflare AI Gateway support is expected to work with stt_v2 as well, it would need parallel changes. This may be intentional if stt_v2 is legacy/deprecated.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Intentional. STTv2 is the Deepgram v2 / Flux class (different protocol, /v2/listen). This PR scopes Cloudflare support to the stable STT (nova-3) and TTS (Aura).
A STTv2.with_cloudflare for Flux is a sensible follow-up rather than part of this change.
Summary
Adds Cloudflare AI Gateway support to the Deepgram plugin — streaming STT (Nova-3 / Flux)
and TTS (Aura) — via
deepgram.STT.with_cloudflare(...)anddeepgram.TTS.with_cloudflare(...).Addresses the STT/TTS portion of #3163. (The LLM portion shipped separately in #6131 as
openai.LLM.with_cloudflare.)Design notes
WebSocket protocol verbatim (
channel.alternatives[0].transcript+is_finalfor STT;Speak/Flush/Flushedfor TTS), so these reuse the existing DeepgramSTT/TTSstreaming implementations rather than duplicating them. This mirrors the LLM approach, where
Cloudflare-LLM rode on the OpenAI plugin because it's OpenAI-compatible — each Cloudflare
modality lives on the plugin whose protocol it matches.
Authorization: Token <key>) become an overridable_connect_headers, defaulting to theexact prior value. Existing Deepgram usage is unchanged;
with_cloudflareinjectscf-aig-authorization(the raw Cloudflare token — no Deepgram key required).Testing
tests/test_deepgram_with_cloudflare.py— 12 hermetic--unittests covering URL building,CLOUDFLARE_ACCOUNT_IDenv fallback,base_urloverride, thecf-aig-authorizationheader,default models,
streamingcapability, and theValueErrorpaths.make checkpasses (ruff format + lint, strict mypy).