From eddcf18379e32123a1542ea18119ea59a4728287 Mon Sep 17 00:00:00 2001 From: Naomi Carrigan Date: Thu, 12 Jun 2025 18:08:07 -0700 Subject: [PATCH 1/3] fix: handle empty objects for providers --- deepgram/clients/agent/v1/websocket/options.py | 18 +++++++++--------- examples/agent/simple/main.py | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/deepgram/clients/agent/v1/websocket/options.py b/deepgram/clients/agent/v1/websocket/options.py index 9abca2d1..2ab1d693 100644 --- a/deepgram/clients/agent/v1/websocket/options.py +++ b/deepgram/clients/agent/v1/websocket/options.py @@ -140,7 +140,7 @@ class Think(BaseResponse): This class defines any configuration settings for the Think model. """ - provider: Provider = field(default_factory=Provider) + provider: Provider = field(default_factory=Provider, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) functions: Optional[List[Function]] = field( default=None, metadata=dataclass_config(exclude=lambda f: f is None) ) @@ -155,7 +155,7 @@ class Think(BaseResponse): ) def __post_init__(self): - if not isinstance(self.provider, Provider): + if not isinstance(self.provider, Provider) and self.provider is not None and not (isinstance(self.provider, dict) and not self.provider): self.provider = Provider(self.provider) def __getitem__(self, key): @@ -175,10 +175,10 @@ class Listen(BaseResponse): This class defines any configuration settings for the Listen model. """ - provider: Provider = field(default_factory=Provider) + provider: Provider = field(default_factory=Provider, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) def __post_init__(self): - if not isinstance(self.provider, Provider): + if not isinstance(self.provider, Provider) and self.provider is not None and not (isinstance(self.provider, dict) and not self.provider): self.provider = Provider(self.provider) def __getitem__(self, key): @@ -192,13 +192,13 @@ class Speak(BaseResponse): This class defines any configuration settings for the Speak model. """ - provider: Provider = field(default_factory=Provider) + provider: Provider = field(default_factory=Provider, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) endpoint: Optional[Endpoint] = field( default=None, metadata=dataclass_config(exclude=lambda f: f is None) ) def __post_init__(self): - if not isinstance(self.provider, Provider): + if not isinstance(self.provider, Provider) and self.provider is not None and not (isinstance(self.provider, dict) and not self.provider): self.provider = Provider(self.provider) def __getitem__(self, key): @@ -215,9 +215,9 @@ class Agent(BaseResponse): """ language: str = field(default="en") - listen: Listen = field(default_factory=Listen) - think: Think = field(default_factory=Think) - speak: Speak = field(default_factory=Speak) + listen: Listen = field(default_factory=Listen, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) + think: Think = field(default_factory=Think, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) + speak: Speak = field(default_factory=Speak, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) greeting: Optional[str] = field( default=None, metadata=dataclass_config(exclude=lambda f: f is None) ) diff --git a/examples/agent/simple/main.py b/examples/agent/simple/main.py index 92d9a585..5a7bb3ae 100644 --- a/examples/agent/simple/main.py +++ b/examples/agent/simple/main.py @@ -42,7 +42,7 @@ def main(): "microphone_record": "true", "speaker_playback": "true", }, - # verbose=verboselogs.DEBUG, + verbose=verboselogs.SPAM, ) print("Created DeepgramClientOptions...") From d062cafd6695b96032ccda1f0e45275f255943b1 Mon Sep 17 00:00:00 2001 From: Naomi Carrigan Date: Thu, 12 Jun 2025 19:42:18 -0700 Subject: [PATCH 2/3] fix: do coderabbit's stuff --- .../clients/agent/v1/websocket/options.py | 84 +++++++++++++++++-- 1 file changed, 75 insertions(+), 9 deletions(-) diff --git a/deepgram/clients/agent/v1/websocket/options.py b/deepgram/clients/agent/v1/websocket/options.py index 2ab1d693..4ef46ce9 100644 --- a/deepgram/clients/agent/v1/websocket/options.py +++ b/deepgram/clients/agent/v1/websocket/options.py @@ -68,16 +68,19 @@ def __getitem__(self, key): _dict["properties"] = _dict["properties"].copy() return _dict[key] + class Provider(dict): """ Generic attribute class for provider objects. """ + def __getattr__(self, name): try: return self[name] except KeyError: # pylint: disable=raise-missing-from raise AttributeError(name) + def __setattr__(self, name, value): self[name] = value @@ -140,7 +143,16 @@ class Think(BaseResponse): This class defines any configuration settings for the Think model. """ - provider: Provider = field(default_factory=Provider, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) + provider: Provider = field( + default_factory=Provider, + metadata=dataclass_config( + exclude=lambda f: ( + f is None + or (isinstance(f, dict) and not f) + or (isinstance(f, Provider) and not f) + ) + ), + ) functions: Optional[List[Function]] = field( default=None, metadata=dataclass_config(exclude=lambda f: f is None) ) @@ -155,7 +167,11 @@ class Think(BaseResponse): ) def __post_init__(self): - if not isinstance(self.provider, Provider) and self.provider is not None and not (isinstance(self.provider, dict) and not self.provider): + if ( + not isinstance(self.provider, Provider) + and self.provider is not None + and not (isinstance(self.provider, dict) and not self.provider) + ): self.provider = Provider(self.provider) def __getitem__(self, key): @@ -175,10 +191,23 @@ class Listen(BaseResponse): This class defines any configuration settings for the Listen model. """ - provider: Provider = field(default_factory=Provider, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) + provider: Provider = field( + default_factory=Provider, + metadata=dataclass_config( + exclude=lambda f: ( + f is None + or (isinstance(f, dict) and not f) + or (isinstance(f, Provider) and not f) + ) + ), + ) def __post_init__(self): - if not isinstance(self.provider, Provider) and self.provider is not None and not (isinstance(self.provider, dict) and not self.provider): + if ( + not isinstance(self.provider, Provider) + and self.provider is not None + and not (isinstance(self.provider, dict) and not self.provider) + ): self.provider = Provider(self.provider) def __getitem__(self, key): @@ -192,13 +221,26 @@ class Speak(BaseResponse): This class defines any configuration settings for the Speak model. """ - provider: Provider = field(default_factory=Provider, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) + provider: Provider = field( + default_factory=Provider, + metadata=dataclass_config( + exclude=lambda f: ( + f is None + or (isinstance(f, dict) and not f) + or (isinstance(f, Provider) and not f) + ) + ), + ) endpoint: Optional[Endpoint] = field( default=None, metadata=dataclass_config(exclude=lambda f: f is None) ) def __post_init__(self): - if not isinstance(self.provider, Provider) and self.provider is not None and not (isinstance(self.provider, dict) and not self.provider): + if ( + not isinstance(self.provider, Provider) + and self.provider is not None + and not (isinstance(self.provider, dict) and not self.provider) + ): self.provider = Provider(self.provider) def __getitem__(self, key): @@ -215,9 +257,30 @@ class Agent(BaseResponse): """ language: str = field(default="en") - listen: Listen = field(default_factory=Listen, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) - think: Think = field(default_factory=Think, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) - speak: Speak = field(default_factory=Speak, metadata=dataclass_config(exclude=lambda f: f is None or (isinstance(f, dict) and not f))) + listen: Listen = field( + default_factory=Listen, + metadata=dataclass_config( + exclude=lambda f: f is None + or (isinstance(f, dict) and not f) + or (isinstance(f, Listen) and not f) + ), + ) + think: Think = field( + default_factory=Think, + metadata=dataclass_config( + exclude=lambda f: f is None + or (isinstance(f, dict) and not f) + or (isinstance(f, Think) and not f) + ), + ) + speak: Speak = field( + default_factory=Speak, + metadata=dataclass_config( + exclude=lambda f: f is None + or (isinstance(f, dict) and not f) + or (isinstance(f, Speak) and not f) + ), + ) greeting: Optional[str] = field( default=None, metadata=dataclass_config(exclude=lambda f: f is None) ) @@ -231,6 +294,8 @@ def __getitem__(self, key): if "speak" in _dict and isinstance(_dict["speak"], dict): _dict["speak"] = Speak.from_dict(_dict["speak"]) return _dict[key] + + @dataclass class Input(BaseResponse): """ @@ -272,6 +337,7 @@ def __getitem__(self, key): _dict["output"] = Output.from_dict(_dict["output"]) return _dict[key] + @dataclass class SettingsOptions(BaseResponse): """ From 9880f832259f56b38e5daa4132ea1636688efbc4 Mon Sep 17 00:00:00 2001 From: John Vajda Date: Fri, 13 Jun 2025 08:48:21 -0600 Subject: [PATCH 3/3] chore: fixes no_mic example --- examples/agent/no_mic/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/agent/no_mic/main.py b/examples/agent/no_mic/main.py index 5d0c3fdf..1fc2f6ed 100644 --- a/examples/agent/no_mic/main.py +++ b/examples/agent/no_mic/main.py @@ -56,7 +56,7 @@ def main(): options.agent.think.provider.model = "gpt-4o-mini" options.agent.think.prompt = "You are a friendly AI assistant." options.agent.speak.provider.type = "deepgram" - options.agent.speak.model = "aura-2-thalia-en" + options.agent.speak.provider.model = "aura-2-thalia-en" options.agent.greeting = "Hello! How can I help you today?" # Send Keep Alive messages