Skip to content

Commit f891b4c

Browse files
committed
Merge branch 'master' into haacked/case-insensitive-matching
2 parents a70e137 + e480b88 commit f891b4c

File tree

10 files changed

+301
-109
lines changed

10 files changed

+301
-109
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
1+
## 3.12.1 - 2025-02-11
2+
3+
1. Fix mypy support for 3.12.0
4+
2. Deprecate `is_simple_flag`
5+
6+
## 3.12.0 - 2025-02-11
7+
8+
1. Add support for OpenAI beta parse API.
9+
2. Deprecate `context` parameter
10+
111
## 3.11.1 - 2025-02-06
212

313
1. Fix LangChain callback handler to capture parent run ID.
414

515
## 3.11.0 - 2025-01-28
616

717
1. Add the `$ai_span` event to the LangChain callback handler to capture the input and output of intermediary chains.
18+
819
> LLM observability naming change: event property `$ai_trace_name` is now `$ai_span_name`.
920
1021
2. Fix serialiazation of Pydantic models in methods.

llm_observability_examples.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import os
22
import uuid
33

4+
from pydantic import BaseModel
5+
46
import posthog
57
from posthog.ai.openai import AsyncOpenAI, OpenAI
68

79
# Example credentials - replace these with your own or use environment variables
810
posthog.project_api_key = os.getenv("POSTHOG_PROJECT_API_KEY", "your-project-api-key")
9-
posthog.personal_api_key = os.getenv("POSTHOG_PERSONAL_API_KEY", "your-personal-api-key")
1011
posthog.host = os.getenv("POSTHOG_HOST", "http://localhost:8000") # Or https://app.posthog.com
1112
posthog.debug = True
1213
# change this to False to see usage events
@@ -31,10 +32,11 @@ def main_sync():
3132
groups = {"company": "test_company"}
3233

3334
try:
34-
basic_openai_call(distinct_id, trace_id, properties, groups)
35-
streaming_openai_call(distinct_id, trace_id, properties, groups)
36-
embedding_openai_call(distinct_id, trace_id, properties, groups)
37-
image_openai_call()
35+
# basic_openai_call(distinct_id, trace_id, properties, groups)
36+
# streaming_openai_call(distinct_id, trace_id, properties, groups)
37+
# embedding_openai_call(distinct_id, trace_id, properties, groups)
38+
# image_openai_call()
39+
beta_openai_call(distinct_id, trace_id, properties, groups)
3840
except Exception as e:
3941
print("Error during OpenAI call:", str(e))
4042

@@ -187,10 +189,32 @@ async def embedding_async_openai_call(posthog_distinct_id, posthog_trace_id, pos
187189
return response
188190

189191

192+
class CalendarEvent(BaseModel):
193+
name: str
194+
date: str
195+
participants: list[str]
196+
197+
198+
def beta_openai_call(distinct_id, trace_id, properties, groups):
199+
response = openai_client.beta.chat.completions.parse(
200+
model="gpt-4o-mini",
201+
messages=[
202+
{"role": "system", "content": "Extract the event information."},
203+
{"role": "user", "content": "Alice and Bob are going to a science fair on Friday."},
204+
],
205+
response_format=CalendarEvent,
206+
posthog_distinct_id=distinct_id,
207+
posthog_trace_id=trace_id,
208+
posthog_properties=properties,
209+
posthog_groups=groups,
210+
)
211+
print(response)
212+
return response
213+
214+
190215
# HOW TO RUN:
191216
# comment out one of these to run the other
192217

193218
if __name__ == "__main__":
194219
main_sync()
195-
196220
# asyncio.run(main_async())

posthog/__init__.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import datetime # noqa: F401
2+
import warnings
23
from typing import Callable, Dict, List, Optional, Tuple # noqa: F401
34

45
from posthog.client import Client
@@ -64,6 +65,14 @@ def capture(
6465
posthog.capture('distinct id', 'purchase', groups={'company': 'id:5'})
6566
```
6667
"""
68+
69+
if context is not None:
70+
warnings.warn(
71+
"The 'context' parameter is deprecated and will be removed in a future version.",
72+
DeprecationWarning,
73+
stacklevel=2,
74+
)
75+
6776
return _proxy(
6877
"capture",
6978
distinct_id=distinct_id,
@@ -102,6 +111,14 @@ def identify(
102111
})
103112
```
104113
"""
114+
115+
if context is not None:
116+
warnings.warn(
117+
"The 'context' parameter is deprecated and will be removed in a future version.",
118+
DeprecationWarning,
119+
stacklevel=2,
120+
)
121+
105122
return _proxy(
106123
"identify",
107124
distinct_id=distinct_id,
@@ -137,6 +154,14 @@ def set(
137154
})
138155
```
139156
"""
157+
158+
if context is not None:
159+
warnings.warn(
160+
"The 'context' parameter is deprecated and will be removed in a future version.",
161+
DeprecationWarning,
162+
stacklevel=2,
163+
)
164+
140165
return _proxy(
141166
"set",
142167
distinct_id=distinct_id,
@@ -172,6 +197,14 @@ def set_once(
172197
})
173198
```
174199
"""
200+
201+
if context is not None:
202+
warnings.warn(
203+
"The 'context' parameter is deprecated and will be removed in a future version.",
204+
DeprecationWarning,
205+
stacklevel=2,
206+
)
207+
175208
return _proxy(
176209
"set_once",
177210
distinct_id=distinct_id,
@@ -208,6 +241,14 @@ def group_identify(
208241
})
209242
```
210243
"""
244+
245+
if context is not None:
246+
warnings.warn(
247+
"The 'context' parameter is deprecated and will be removed in a future version.",
248+
DeprecationWarning,
249+
stacklevel=2,
250+
)
251+
211252
return _proxy(
212253
"group_identify",
213254
group_type=group_type,
@@ -245,6 +286,14 @@ def alias(
245286
posthog.alias('anonymous session id', 'distinct id')
246287
```
247288
"""
289+
290+
if context is not None:
291+
warnings.warn(
292+
"The 'context' parameter is deprecated and will be removed in a future version.",
293+
DeprecationWarning,
294+
stacklevel=2,
295+
)
296+
248297
return _proxy(
249298
"alias",
250299
previous_id=previous_id,
@@ -288,6 +337,14 @@ def capture_exception(
288337
289338
```
290339
"""
340+
341+
if context is not None:
342+
warnings.warn(
343+
"The 'context' parameter is deprecated and will be removed in a future version.",
344+
DeprecationWarning,
345+
stacklevel=2,
346+
)
347+
291348
return _proxy(
292349
"capture_exception",
293350
exception=exception,

posthog/ai/openai/openai.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def __init__(self, posthog_client: PostHogClient, **kwargs):
3131
self._ph_client = posthog_client
3232
self.chat = WrappedChat(self)
3333
self.embeddings = WrappedEmbeddings(self)
34+
self.beta = WrappedBeta(self)
3435

3536

3637
class WrappedChat(openai.resources.chat.Chat):
@@ -249,3 +250,45 @@ def create(
249250
)
250251

251252
return response
253+
254+
255+
class WrappedBeta(openai.resources.beta.Beta):
256+
_client: OpenAI
257+
258+
@property
259+
def chat(self):
260+
return WrappedBetaChat(self._client)
261+
262+
263+
class WrappedBetaChat(openai.resources.beta.chat.Chat):
264+
_client: OpenAI
265+
266+
@property
267+
def completions(self):
268+
return WrappedBetaCompletions(self._client)
269+
270+
271+
class WrappedBetaCompletions(openai.resources.beta.chat.completions.Completions):
272+
_client: OpenAI
273+
274+
def parse(
275+
self,
276+
posthog_distinct_id: Optional[str] = None,
277+
posthog_trace_id: Optional[str] = None,
278+
posthog_properties: Optional[Dict[str, Any]] = None,
279+
posthog_privacy_mode: bool = False,
280+
posthog_groups: Optional[Dict[str, Any]] = None,
281+
**kwargs: Any,
282+
):
283+
return call_llm_and_track_usage(
284+
posthog_distinct_id,
285+
self._client._ph_client,
286+
"openai",
287+
posthog_trace_id,
288+
posthog_properties,
289+
posthog_privacy_mode,
290+
posthog_groups,
291+
self._client.base_url,
292+
super().parse,
293+
**kwargs,
294+
)

posthog/ai/openai/openai_async.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def __init__(self, posthog_client: PostHogClient, **kwargs):
3030
self._ph_client = posthog_client
3131
self.chat = WrappedChat(self)
3232
self.embeddings = WrappedEmbeddings(self)
33+
self.beta = WrappedBeta(self)
3334

3435

3536
class WrappedChat(openai.resources.chat.AsyncChat):
@@ -248,3 +249,45 @@ async def create(
248249
)
249250

250251
return response
252+
253+
254+
class WrappedBeta(openai.resources.beta.AsyncBeta):
255+
_client: AsyncOpenAI
256+
257+
@property
258+
def chat(self):
259+
return WrappedBetaChat(self._client)
260+
261+
262+
class WrappedBetaChat(openai.resources.beta.chat.AsyncChat):
263+
_client: AsyncOpenAI
264+
265+
@property
266+
def completions(self):
267+
return WrappedBetaCompletions(self._client)
268+
269+
270+
class WrappedBetaCompletions(openai.resources.beta.chat.completions.AsyncCompletions):
271+
_client: AsyncOpenAI
272+
273+
async def parse(
274+
self,
275+
posthog_distinct_id: Optional[str] = None,
276+
posthog_trace_id: Optional[str] = None,
277+
posthog_properties: Optional[Dict[str, Any]] = None,
278+
posthog_privacy_mode: bool = False,
279+
posthog_groups: Optional[Dict[str, Any]] = None,
280+
**kwargs: Any,
281+
):
282+
return await call_llm_and_track_usage_async(
283+
posthog_distinct_id,
284+
self._client._ph_client,
285+
"openai",
286+
posthog_trace_id,
287+
posthog_properties,
288+
posthog_privacy_mode,
289+
posthog_groups,
290+
self._client.base_url,
291+
super().parse,
292+
**kwargs,
293+
)

0 commit comments

Comments
 (0)