Skip to content

Commit d77fa9a

Browse files
committed
Merge branch 'master' of github.com:PostHog/posthog-python into feat/langchain-spans
2 parents fc2f96a + 0f8b10b commit d77fa9a

File tree

4 files changed

+45
-1
lines changed

4 files changed

+45
-1
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
## 3.10.0 - 2025-01-27
1+
## 3.11.0 - 2025-01-27
22

33
1. Add the `$ai_span` event to the LangChain callback handler to capture the input and output of intermediary chains.
44

5+
## 3.10.0 - 2025-01-24
6+
7+
1. Add `$ai_error` and `$ai_is_error` properties to LangChain callback handler, OpenAI, and Anthropic.
8+
59
## 3.9.3 - 2025-01-23
610

711
1. Fix capturing of multiple traces in the LangChain callback handler.

posthog/ai/utils.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,17 @@ def call_llm_and_track_usage(
116116
error = None
117117
http_status = 200
118118
usage: Dict[str, Any] = {}
119+
error_params: Dict[str, any] = {}
119120

120121
try:
121122
response = call_method(**kwargs)
122123
except Exception as exc:
123124
error = exc
124125
http_status = getattr(exc, "status_code", 0) # default to 0 becuase its likely an SDK error
126+
error_params = {
127+
"$ai_is_error": True,
128+
"$ai_error": exc.__str__(),
129+
}
125130
finally:
126131
end_time = time.time()
127132
latency = end_time - start_time
@@ -149,6 +154,7 @@ def call_llm_and_track_usage(
149154
"$ai_trace_id": posthog_trace_id,
150155
"$ai_base_url": str(base_url),
151156
**(posthog_properties or {}),
157+
**(error_params or {}),
152158
}
153159

154160
if posthog_distinct_id is None:
@@ -186,12 +192,17 @@ async def call_llm_and_track_usage_async(
186192
error = None
187193
http_status = 200
188194
usage: Dict[str, Any] = {}
195+
error_params: Dict[str, any] = {}
189196

190197
try:
191198
response = await call_async_method(**kwargs)
192199
except Exception as exc:
193200
error = exc
194201
http_status = getattr(exc, "status_code", 0) # default to 0 because its likely an SDK error
202+
error_params = {
203+
"$ai_is_error": True,
204+
"$ai_error": exc.__str__(),
205+
}
195206
finally:
196207
end_time = time.time()
197208
latency = end_time - start_time
@@ -219,6 +230,7 @@ async def call_llm_and_track_usage_async(
219230
"$ai_trace_id": posthog_trace_id,
220231
"$ai_base_url": str(base_url),
221232
**(posthog_properties or {}),
233+
**(error_params or {}),
222234
}
223235

224236
if posthog_distinct_id is None:

posthog/test/ai/anthropic/test_anthropic.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,17 @@ async def test_async_streaming_system_prompt(mock_client, mock_anthropic_stream)
325325
{"role": "system", "content": "You must always answer with 'Bar'."},
326326
{"role": "user", "content": "Foo"},
327327
]
328+
329+
330+
def test_error(mock_client, mock_anthropic_response):
331+
with patch("anthropic.resources.Messages.create", side_effect=Exception("Test error")):
332+
client = Anthropic(api_key="test-key", posthog_client=mock_client)
333+
with pytest.raises(Exception):
334+
client.messages.create(model="claude-3-opus-20240229", messages=[{"role": "user", "content": "Hello"}])
335+
336+
assert mock_client.capture.call_count == 1
337+
338+
call_args = mock_client.capture.call_args[1]
339+
props = call_args["properties"]
340+
assert props["$ai_is_error"] is True
341+
assert props["$ai_error"] == "Test error"

posthog/test/ai/openai/test_openai.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,17 @@ def test_privacy_mode_global(mock_client, mock_openai_response):
173173
props = call_args["properties"]
174174
assert props["$ai_input"] is None
175175
assert props["$ai_output_choices"] is None
176+
177+
178+
def test_error(mock_client, mock_openai_response):
179+
with patch("openai.resources.chat.completions.Completions.create", side_effect=Exception("Test error")):
180+
client = OpenAI(api_key="test-key", posthog_client=mock_client)
181+
with pytest.raises(Exception):
182+
client.chat.completions.create(model="gpt-4", messages=[{"role": "user", "content": "Hello"}])
183+
184+
assert mock_client.capture.call_count == 1
185+
186+
call_args = mock_client.capture.call_args[1]
187+
props = call_args["properties"]
188+
assert props["$ai_is_error"] is True
189+
assert props["$ai_error"] == "Test error"

0 commit comments

Comments
 (0)