diff --git a/CHANGELOG.md b/CHANGELOG.md index 4030c91b..6044ef4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 6.2.1 - 2025-06-21 + +- feat: make `posthog_client` an optional argument in PostHog AI providers wrappers (`posthog.ai.*`), intuitively using the default client as the default + # 6.1.1 - 2025-07-16 - fix: correctly capture exceptions processed by Django from views or middleware diff --git a/posthog/__init__.py b/posthog/__init__.py index c15aea37..0c81a4e0 100644 --- a/posthog/__init__.py +++ b/posthog/__init__.py @@ -676,7 +676,7 @@ def shutdown(): _proxy("join") -def setup(): +def setup() -> Client: global default_client if not default_client: if not api_key: @@ -706,6 +706,8 @@ def setup(): default_client.disabled = disabled default_client.debug = debug + return default_client + def _proxy(method, *args, **kwargs): """Create an analytics client if one doesn't exist and send to it.""" diff --git a/posthog/ai/anthropic/anthropic.py b/posthog/ai/anthropic/anthropic.py index d80e1b70..6f2461ae 100644 --- a/posthog/ai/anthropic/anthropic.py +++ b/posthog/ai/anthropic/anthropic.py @@ -8,7 +8,7 @@ import time import uuid -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, cast from posthog.ai.utils import ( call_llm_and_track_usage, @@ -17,6 +17,7 @@ with_privacy_mode, ) from posthog.client import Client as PostHogClient +from posthog import setup class Anthropic(anthropic.Anthropic): @@ -26,14 +27,14 @@ class Anthropic(anthropic.Anthropic): _ph_client: PostHogClient - def __init__(self, posthog_client: PostHogClient, **kwargs): + def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs): """ Args: posthog_client: PostHog client for tracking usage **kwargs: Additional arguments passed to the Anthropic client """ super().__init__(**kwargs) - self._ph_client = posthog_client + self._ph_client = posthog_client or setup() self.messages = WrappedMessages(self) diff --git a/posthog/ai/anthropic/anthropic_async.py b/posthog/ai/anthropic/anthropic_async.py index e8c123c7..68f0c7c3 100644 --- a/posthog/ai/anthropic/anthropic_async.py +++ b/posthog/ai/anthropic/anthropic_async.py @@ -10,6 +10,7 @@ import uuid from typing import Any, Dict, Optional +from posthog import setup from posthog.ai.utils import ( call_llm_and_track_usage_async, get_model_params, @@ -26,14 +27,14 @@ class AsyncAnthropic(anthropic.AsyncAnthropic): _ph_client: PostHogClient - def __init__(self, posthog_client: PostHogClient, **kwargs): + def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs): """ Args: posthog_client: PostHog client for tracking usage **kwargs: Additional arguments passed to the Anthropic client """ super().__init__(**kwargs) - self._ph_client = posthog_client + self._ph_client = posthog_client or setup() self.messages = AsyncWrappedMessages(self) diff --git a/posthog/ai/anthropic/anthropic_providers.py b/posthog/ai/anthropic/anthropic_providers.py index 44509820..97bc7656 100644 --- a/posthog/ai/anthropic/anthropic_providers.py +++ b/posthog/ai/anthropic/anthropic_providers.py @@ -5,9 +5,12 @@ "Please install the Anthropic SDK to use this feature: 'pip install anthropic'" ) +from typing import Optional + from posthog.ai.anthropic.anthropic import WrappedMessages from posthog.ai.anthropic.anthropic_async import AsyncWrappedMessages from posthog.client import Client as PostHogClient +from posthog import setup class AnthropicBedrock(anthropic.AnthropicBedrock): @@ -17,9 +20,9 @@ class AnthropicBedrock(anthropic.AnthropicBedrock): _ph_client: PostHogClient - def __init__(self, posthog_client: PostHogClient, **kwargs): + def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs): super().__init__(**kwargs) - self._ph_client = posthog_client + self._ph_client = posthog_client or setup() self.messages = WrappedMessages(self) @@ -30,9 +33,9 @@ class AsyncAnthropicBedrock(anthropic.AsyncAnthropicBedrock): _ph_client: PostHogClient - def __init__(self, posthog_client: PostHogClient, **kwargs): + def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs): super().__init__(**kwargs) - self._ph_client = posthog_client + self._ph_client = posthog_client or setup() self.messages = AsyncWrappedMessages(self) @@ -43,9 +46,9 @@ class AnthropicVertex(anthropic.AnthropicVertex): _ph_client: PostHogClient - def __init__(self, posthog_client: PostHogClient, **kwargs): + def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs): super().__init__(**kwargs) - self._ph_client = posthog_client + self._ph_client = posthog_client or setup() self.messages = WrappedMessages(self) @@ -56,7 +59,7 @@ class AsyncAnthropicVertex(anthropic.AsyncAnthropicVertex): _ph_client: PostHogClient - def __init__(self, posthog_client: PostHogClient, **kwargs): + def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs): super().__init__(**kwargs) - self._ph_client = posthog_client + self._ph_client = posthog_client or setup() self.messages = AsyncWrappedMessages(self) diff --git a/posthog/ai/gemini/gemini.py b/posthog/ai/gemini/gemini.py index 52e80ff5..74ba20db 100644 --- a/posthog/ai/gemini/gemini.py +++ b/posthog/ai/gemini/gemini.py @@ -10,6 +10,7 @@ "Please install the Google Gemini SDK to use this feature: 'pip install google-genai'" ) +from posthog import setup from posthog.ai.utils import ( call_llm_and_track_usage, get_model_params, @@ -36,6 +37,8 @@ class Client: ) """ + _ph_client: PostHogClient + def __init__( self, api_key: Optional[str] = None, @@ -56,12 +59,14 @@ def __init__( posthog_groups: Default groups for all calls (can be overridden per call) **kwargs: Additional arguments (for future compatibility) """ - if posthog_client is None: + self._ph_client = posthog_client or setup() + + if self._ph_client is None: raise ValueError("posthog_client is required for PostHog tracking") self.models = Models( api_key=api_key, - posthog_client=posthog_client, + posthog_client=self._ph_client, posthog_distinct_id=posthog_distinct_id, posthog_properties=posthog_properties, posthog_privacy_mode=posthog_privacy_mode, @@ -97,10 +102,10 @@ def __init__( posthog_groups: Default groups for all calls **kwargs: Additional arguments (for future compatibility) """ - if posthog_client is None: - raise ValueError("posthog_client is required for PostHog tracking") + self._ph_client = posthog_client or setup() - self._ph_client = posthog_client + if self._ph_client is None: + raise ValueError("posthog_client is required for PostHog tracking") # Store default PostHog settings self._default_distinct_id = posthog_distinct_id diff --git a/posthog/ai/openai/openai.py b/posthog/ai/openai/openai.py index d86fecfc..3730050f 100644 --- a/posthog/ai/openai/openai.py +++ b/posthog/ai/openai/openai.py @@ -15,6 +15,7 @@ with_privacy_mode, ) from posthog.client import Client as PostHogClient +from posthog import setup class OpenAI(openai.OpenAI): @@ -24,16 +25,15 @@ class OpenAI(openai.OpenAI): _ph_client: PostHogClient - def __init__(self, posthog_client: PostHogClient, **kwargs): + def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs): """ Args: api_key: OpenAI API key. - posthog_client: If provided, events will be captured via this client instead - of the global posthog. + posthog_client: If provided, events will be captured via this client instead of the global `posthog`. **openai_config: Any additional keyword args to set on openai (e.g. organization="xxx"). """ super().__init__(**kwargs) - self._ph_client = posthog_client + self._ph_client = posthog_client or setup() # Store original objects after parent initialization (only if they exist) self._original_chat = getattr(self, "chat", None) diff --git a/posthog/ai/openai/openai_async.py b/posthog/ai/openai/openai_async.py index 76c32a74..25f9b5ab 100644 --- a/posthog/ai/openai/openai_async.py +++ b/posthog/ai/openai/openai_async.py @@ -1,6 +1,6 @@ import time import uuid -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, cast try: import openai @@ -9,6 +9,7 @@ "Please install the OpenAI SDK to use this feature: 'pip install openai'" ) +from posthog import setup from posthog.ai.utils import ( call_llm_and_track_usage_async, get_model_params, @@ -24,7 +25,7 @@ class AsyncOpenAI(openai.AsyncOpenAI): _ph_client: PostHogClient - def __init__(self, posthog_client: PostHogClient, **kwargs): + def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs): """ Args: api_key: OpenAI API key. @@ -33,7 +34,7 @@ def __init__(self, posthog_client: PostHogClient, **kwargs): **openai_config: Any additional keyword args to set on openai (e.g. organization="xxx"). """ super().__init__(**kwargs) - self._ph_client = posthog_client + self._ph_client = posthog_client or setup() # Store original objects after parent initialization (only if they exist) self._original_chat = getattr(self, "chat", None) diff --git a/posthog/ai/openai/openai_providers.py b/posthog/ai/openai/openai_providers.py index 428022e8..9d1d1a6d 100644 --- a/posthog/ai/openai/openai_providers.py +++ b/posthog/ai/openai/openai_providers.py @@ -15,7 +15,10 @@ from posthog.ai.openai.openai_async import WrappedChat as AsyncWrappedChat from posthog.ai.openai.openai_async import WrappedEmbeddings as AsyncWrappedEmbeddings from posthog.ai.openai.openai_async import WrappedResponses as AsyncWrappedResponses +from typing import Optional + from posthog.client import Client as PostHogClient +from posthog import setup class AzureOpenAI(openai.AzureOpenAI): @@ -25,7 +28,7 @@ class AzureOpenAI(openai.AzureOpenAI): _ph_client: PostHogClient - def __init__(self, posthog_client: PostHogClient, **kwargs): + def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs): """ Args: api_key: Azure OpenAI API key. @@ -34,7 +37,7 @@ def __init__(self, posthog_client: PostHogClient, **kwargs): **openai_config: Any additional keyword args to set on Azure OpenAI (e.g. azure_endpoint="xxx"). """ super().__init__(**kwargs) - self._ph_client = posthog_client + self._ph_client = posthog_client or setup() # Store original objects after parent initialization (only if they exist) self._original_chat = getattr(self, "chat", None) @@ -63,7 +66,7 @@ class AsyncAzureOpenAI(openai.AsyncAzureOpenAI): _ph_client: PostHogClient - def __init__(self, posthog_client: PostHogClient, **kwargs): + def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs): """ Args: api_key: Azure OpenAI API key. @@ -72,7 +75,7 @@ def __init__(self, posthog_client: PostHogClient, **kwargs): **openai_config: Any additional keyword args to set on Azure OpenAI (e.g. azure_endpoint="xxx"). """ super().__init__(**kwargs) - self._ph_client = posthog_client + self._ph_client = posthog_client or setup() # Store original objects after parent initialization (only if they exist) self._original_chat = getattr(self, "chat", None) diff --git a/posthog/version.py b/posthog/version.py index db8806db..3bad59a9 100644 --- a/posthog/version.py +++ b/posthog/version.py @@ -1,4 +1,4 @@ -VERSION = "6.1.1" +VERSION = "6.2.1" if __name__ == "__main__": print(VERSION, end="") # noqa: T201