diff --git a/docs/concepts/agent.md b/docs/concepts/agent.md index c2ccfc0..6b47972 100644 --- a/docs/concepts/agent.md +++ b/docs/concepts/agent.md @@ -46,7 +46,7 @@ agent = Agent(client=client).with_llm( | `rtc` | `RtcConfig` | No | RTC media encryption | | `filler_words` | `FillerWordsConfig` | No | Filler words while waiting for LLM | -When `client` is provided, `Agent(client=...)` returns `CNAgent` for `Area.CN` and `GlobalAgent` for global areas. +When `client` is provided, `Agent(client=...)` returns `CNAgent` for `Area.CN` and `GlobalAgent` for global areas. If `with_stt()` is omitted, the bound client also determines the default ASR vendor: `Fengming` for `Area.CN`, otherwise `Ares`. ## Builder Methods diff --git a/docs/concepts/vendors.md b/docs/concepts/vendors.md index 61bfc47..e214b5d 100644 --- a/docs/concepts/vendors.md +++ b/docs/concepts/vendors.md @@ -103,7 +103,7 @@ tts = ElevenLabsTTS( Used with `agent.with_stt()`. -Use `turn_detection.language` for Agora interaction language; it defaults to `en-US`. STT vendor `language` options are serialized under `asr.params` using each provider's own format. Ares does not take a provider language option; AgentKit uses `turn_detection.language` for REST `asr.language`. +Use `turn_detection.language` for Agora interaction language; it defaults to `en-US`. STT vendor `language` options are serialized under `asr.params` using each provider's own format. If `with_stt()` is omitted, AgentKit defaults to `AresSTT` for global clients and `FengmingSTT` for `Area.CN` clients. Ares does not take a provider language option; AgentKit uses `turn_detection.language` for REST `asr.language`. | Class | Provider | Required Parameters | |---|---|---| diff --git a/docs/guides/regional-routing.md b/docs/guides/regional-routing.md index 76c54e2..ab4c2c3 100644 --- a/docs/guides/regional-routing.md +++ b/docs/guides/regional-routing.md @@ -36,6 +36,7 @@ client = Agora( ## Recommended vendors by area Bind `client` into `Agent(client=client, ...)` and construct vendors directly with SDK classes. The bound client selects `CNAgent` or `GlobalAgent` for IDE hints based on `area`, but does not restrict which vendor classes you can configure. +If you omit `with_stt()`, AgentKit uses `FengmingSTT` by default for `Area.CN` clients and `AresSTT` for global clients. | Client area | STT classes | LLM classes | TTS classes | Avatar classes | |---|---|---|---|---| @@ -125,6 +126,7 @@ agent = Agent(client=client, turn_detection={"language": "zh-CN"}) ``` `Agent(client=...)` returns `CNAgent` for `Area.CN` and `GlobalAgent` for global areas. A bound `client` is required. The SDK does not reject mismatched vendor classes at build time or session start. +The same bound client also controls the default ASR vendor when `with_stt()` is omitted. ## How the domain pool works diff --git a/docs/reference/agent.md b/docs/reference/agent.md index c3abe15..f040652 100644 --- a/docs/reference/agent.md +++ b/docs/reference/agent.md @@ -9,6 +9,7 @@ description: Full API reference for the Python Agent builder class. **Import:** `from agora_agent import Agent, CNAgent, GlobalAgent` Bind the client on every `Agent` builder via `Agent(client=client, ...)`, then pass vendor classes directly. The bound client sets the API routing region and provides area-specific IDE hints via `CNAgent` / `GlobalAgent`: +it also selects the default ASR vendor when `with_stt()` is omitted (`Fengming` for `Area.CN`, otherwise `Ares`). > **`client` is required.** `create_session()` and `create_async_session()` raise `ValueError` if no client was bound on the agent. diff --git a/docs/reference/vendors.md b/docs/reference/vendors.md index b5fc6fb..d1d96c2 100644 --- a/docs/reference/vendors.md +++ b/docs/reference/vendors.md @@ -412,7 +412,7 @@ The SDK also includes named helpers for the remaining Agora-supported LLM provid ## STT Vendors -Use `turn_detection.language` for Agora interaction language; it defaults to `en-US`. Provider-specific language values remain under `asr.params` and may use a different format. AgentKit populates REST `asr.language` from `turn_detection.language`. +Use `turn_detection.language` for Agora interaction language; it defaults to `en-US`. Provider-specific language values remain under `asr.params` and may use a different format. If `with_stt()` is omitted, AgentKit defaults to `AresSTT` for global clients and `FengmingSTT` for `Area.CN` clients. AgentKit populates REST `asr.language` from `turn_detection.language`. ### `SpeechmaticsSTT` diff --git a/src/agora_agent/agentkit/agent.py b/src/agora_agent/agentkit/agent.py index 6e9d3ac..9733ebd 100644 --- a/src/agora_agent/agentkit/agent.py +++ b/src/agora_agent/agentkit/agent.py @@ -1078,7 +1078,8 @@ def _resolve_llm_config(self) -> typing.Dict[str, typing.Any]: def _resolve_asr_config(self, turn_detection_config: TurnDetectionInput) -> typing.Dict[str, typing.Any]: asr_config = dict(self._stt or {}) if not asr_config: - asr_config["vendor"] = "ares" + area_scope = getattr(self._client, "area_scope", None) + asr_config["vendor"] = "fengming" if area_scope == "cn" else "ares" asr_config["language"] = self._field_value(turn_detection_config, "language") return asr_config diff --git a/tests/custom/test_regional_vendors.py b/tests/custom/test_regional_vendors.py index 1d41e95..3821040 100644 --- a/tests/custom/test_regional_vendors.py +++ b/tests/custom/test_regional_vendors.py @@ -66,6 +66,28 @@ def test_agent_constructor_auto_selects_area_aware_subclass() -> None: assert global_agent.__class__.__name__ == "GlobalAgent" +def test_default_asr_vendor_is_area_aware_when_with_stt_is_omitted() -> None: + cn_properties = Agent(client=_client(Area.CN)).to_properties( + channel="room", + agent_uid="1", + remote_uids=["100"], + token="rtc-token", + allow_missing_vendor_categories={"llm", "tts"}, + ) + global_properties = Agent(client=_client(Area.US)).to_properties( + channel="room", + agent_uid="1", + remote_uids=["100"], + token="rtc-token", + allow_missing_vendor_categories={"llm", "tts"}, + ) + + assert cn_properties.asr is not None + assert cn_properties.asr.vendor == "fengming" + assert global_properties.asr is not None + assert global_properties.asr.vendor == "ares" + + def test_cn_client_allows_global_only_vendor() -> None: client = _client(Area.CN) agent = Agent(client=client).with_stt( diff --git a/tests/custom/test_stt_language.py b/tests/custom/test_stt_language.py index 83f2834..697d2ca 100644 --- a/tests/custom/test_stt_language.py +++ b/tests/custom/test_stt_language.py @@ -2,6 +2,7 @@ from agora_agent import ( Agent, + Area, AmazonSTT, AssemblyAISTT, DeepgramSTT, @@ -85,6 +86,18 @@ def test_default_turn_detection_language_is_sent_without_stt() -> None: assert props["turn_detection"] == {"language": "en-US"} +def test_default_stt_vendor_depends_on_client_area_when_stt_is_omitted() -> None: + global_props = properties(base_agent()) + cn_props = properties( + Agent(test_client(area=Area.CN)) + .with_llm(OpenAI(api_key="llm-key", model="gpt-4o-mini", base_url="https://api.openai.com/v1/chat/completions")) + .with_tts(ElevenLabsTTS(key="tts-key", voice_id="voice", model_id="eleven_flash_v2_5", base_url="wss://api.elevenlabs.io/v1")) + ) + + assert global_props["asr"] == {"vendor": "ares", "language": "en-US"} + assert cn_props["asr"] == {"vendor": "fengming", "language": "en-US"} + + def test_stt_vendor_params_match_documented_shapes() -> None: deepgram_managed = DeepgramSTT(model="nova-3", language="en-US").to_config() assert "language" not in deepgram_managed