posthoganalytics 6.7.1__tar.gz → 6.7.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {posthoganalytics-6.7.1/posthoganalytics.egg-info → posthoganalytics-6.7.2}/PKG-INFO +1 -1
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/anthropic/__init__.py +10 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/anthropic/anthropic.py +93 -63
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/anthropic/anthropic_async.py +86 -20
- posthoganalytics-6.7.2/posthoganalytics/ai/anthropic/anthropic_converter.py +393 -0
- posthoganalytics-6.7.2/posthoganalytics/ai/gemini/__init__.py +22 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/gemini/gemini.py +60 -67
- posthoganalytics-6.7.2/posthoganalytics/ai/gemini/gemini_converter.py +438 -0
- posthoganalytics-6.7.2/posthoganalytics/ai/openai/__init__.py +20 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/openai/openai.py +110 -151
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/openai/openai_async.py +62 -70
- posthoganalytics-6.7.2/posthoganalytics/ai/openai/openai_converter.py +585 -0
- posthoganalytics-6.7.2/posthoganalytics/ai/types.py +142 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/utils.py +205 -253
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/client.py +7 -7
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_feature_flags.py +2 -2
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/version.py +1 -1
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2/posthoganalytics.egg-info}/PKG-INFO +1 -1
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics.egg-info/SOURCES.txt +4 -0
- posthoganalytics-6.7.1/posthoganalytics/ai/gemini/__init__.py +0 -11
- posthoganalytics-6.7.1/posthoganalytics/ai/openai/__init__.py +0 -5
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/LICENSE +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/MANIFEST.in +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/README.md +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/__init__.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/__init__.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/anthropic/anthropic_providers.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/langchain/__init__.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/langchain/callbacks.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/openai/openai_providers.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/sanitization.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/args.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/consumer.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/contexts.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/exception_capture.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/exception_utils.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/feature_flags.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/integrations/__init__.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/integrations/django.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/poller.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/py.typed +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/request.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/__init__.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_before_send.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_client.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_consumer.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_contexts.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_exception_capture.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_feature_flag.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_feature_flag_result.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_module.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_request.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_size_limited_dict.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_types.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/test/test_utils.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/types.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/utils.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics.egg-info/dependency_links.txt +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics.egg-info/requires.txt +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics.egg-info/top_level.txt +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/pyproject.toml +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/setup.cfg +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/setup.py +0 -0
- {posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/setup_analytics.py +0 -0
|
@@ -6,6 +6,12 @@ from .anthropic_providers import (
|
|
|
6
6
|
AsyncAnthropicBedrock,
|
|
7
7
|
AsyncAnthropicVertex,
|
|
8
8
|
)
|
|
9
|
+
from .anthropic_converter import (
|
|
10
|
+
format_anthropic_response,
|
|
11
|
+
format_anthropic_input,
|
|
12
|
+
extract_anthropic_tools,
|
|
13
|
+
format_anthropic_streaming_content,
|
|
14
|
+
)
|
|
9
15
|
|
|
10
16
|
__all__ = [
|
|
11
17
|
"Anthropic",
|
|
@@ -14,4 +20,8 @@ __all__ = [
|
|
|
14
20
|
"AsyncAnthropicBedrock",
|
|
15
21
|
"AnthropicVertex",
|
|
16
22
|
"AsyncAnthropicVertex",
|
|
23
|
+
"format_anthropic_response",
|
|
24
|
+
"format_anthropic_input",
|
|
25
|
+
"extract_anthropic_tools",
|
|
26
|
+
"format_anthropic_streaming_content",
|
|
17
27
|
]
|
{posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/anthropic/anthropic.py
RENAMED
|
@@ -8,13 +8,19 @@ except ImportError:
|
|
|
8
8
|
|
|
9
9
|
import time
|
|
10
10
|
import uuid
|
|
11
|
-
from typing import Any, Dict, Optional
|
|
11
|
+
from typing import Any, Dict, List, Optional
|
|
12
12
|
|
|
13
|
+
from posthoganalytics.ai.types import StreamingContentBlock, ToolInProgress
|
|
13
14
|
from posthoganalytics.ai.utils import (
|
|
14
15
|
call_llm_and_track_usage,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
merge_usage_stats,
|
|
17
|
+
)
|
|
18
|
+
from posthoganalytics.ai.anthropic.anthropic_converter import (
|
|
19
|
+
extract_anthropic_usage_from_event,
|
|
20
|
+
handle_anthropic_content_block_start,
|
|
21
|
+
handle_anthropic_text_delta,
|
|
22
|
+
handle_anthropic_tool_delta,
|
|
23
|
+
finalize_anthropic_tool_input,
|
|
18
24
|
)
|
|
19
25
|
from posthoganalytics.ai.sanitization import sanitize_anthropic
|
|
20
26
|
from posthoganalytics.client import Client as PostHogClient
|
|
@@ -62,6 +68,7 @@ class WrappedMessages(Messages):
|
|
|
62
68
|
posthog_groups: Optional group analytics properties
|
|
63
69
|
**kwargs: Arguments passed to Anthropic's messages.create
|
|
64
70
|
"""
|
|
71
|
+
|
|
65
72
|
if posthog_trace_id is None:
|
|
66
73
|
posthog_trace_id = str(uuid.uuid4())
|
|
67
74
|
|
|
@@ -120,34 +127,65 @@ class WrappedMessages(Messages):
|
|
|
120
127
|
):
|
|
121
128
|
start_time = time.time()
|
|
122
129
|
usage_stats: Dict[str, int] = {"input_tokens": 0, "output_tokens": 0}
|
|
123
|
-
accumulated_content =
|
|
130
|
+
accumulated_content = ""
|
|
131
|
+
content_blocks: List[StreamingContentBlock] = []
|
|
132
|
+
tools_in_progress: Dict[str, ToolInProgress] = {}
|
|
133
|
+
current_text_block: Optional[StreamingContentBlock] = None
|
|
124
134
|
response = super().create(**kwargs)
|
|
125
135
|
|
|
126
136
|
def generator():
|
|
127
137
|
nonlocal usage_stats
|
|
128
|
-
nonlocal accumulated_content
|
|
138
|
+
nonlocal accumulated_content
|
|
139
|
+
nonlocal content_blocks
|
|
140
|
+
nonlocal tools_in_progress
|
|
141
|
+
nonlocal current_text_block
|
|
142
|
+
|
|
129
143
|
try:
|
|
130
144
|
for event in response:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
# Extract usage stats from event
|
|
146
|
+
event_usage = extract_anthropic_usage_from_event(event)
|
|
147
|
+
merge_usage_stats(usage_stats, event_usage)
|
|
148
|
+
|
|
149
|
+
# Handle content block start events
|
|
150
|
+
if hasattr(event, "type") and event.type == "content_block_start":
|
|
151
|
+
block, tool = handle_anthropic_content_block_start(event)
|
|
152
|
+
|
|
153
|
+
if block:
|
|
154
|
+
content_blocks.append(block)
|
|
155
|
+
|
|
156
|
+
if block.get("type") == "text":
|
|
157
|
+
current_text_block = block
|
|
158
|
+
else:
|
|
159
|
+
current_text_block = None
|
|
160
|
+
|
|
161
|
+
if tool:
|
|
162
|
+
tool_id = tool["block"].get("id")
|
|
163
|
+
if tool_id:
|
|
164
|
+
tools_in_progress[tool_id] = tool
|
|
165
|
+
|
|
166
|
+
# Handle text delta events
|
|
167
|
+
delta_text = handle_anthropic_text_delta(event, current_text_block)
|
|
168
|
+
|
|
169
|
+
if delta_text:
|
|
170
|
+
accumulated_content += delta_text
|
|
171
|
+
|
|
172
|
+
# Handle tool input delta events
|
|
173
|
+
handle_anthropic_tool_delta(
|
|
174
|
+
event, content_blocks, tools_in_progress
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Handle content block stop events
|
|
178
|
+
if hasattr(event, "type") and event.type == "content_block_stop":
|
|
179
|
+
current_text_block = None
|
|
180
|
+
finalize_anthropic_tool_input(
|
|
181
|
+
event, content_blocks, tools_in_progress
|
|
182
|
+
)
|
|
144
183
|
|
|
145
184
|
yield event
|
|
146
185
|
|
|
147
186
|
finally:
|
|
148
187
|
end_time = time.time()
|
|
149
188
|
latency = end_time - start_time
|
|
150
|
-
output = "".join(accumulated_content)
|
|
151
189
|
|
|
152
190
|
self._capture_streaming_event(
|
|
153
191
|
posthog_distinct_id,
|
|
@@ -158,7 +196,8 @@ class WrappedMessages(Messages):
|
|
|
158
196
|
kwargs,
|
|
159
197
|
usage_stats,
|
|
160
198
|
latency,
|
|
161
|
-
|
|
199
|
+
content_blocks,
|
|
200
|
+
accumulated_content,
|
|
162
201
|
)
|
|
163
202
|
|
|
164
203
|
return generator()
|
|
@@ -173,47 +212,38 @@ class WrappedMessages(Messages):
|
|
|
173
212
|
kwargs: Dict[str, Any],
|
|
174
213
|
usage_stats: Dict[str, int],
|
|
175
214
|
latency: float,
|
|
176
|
-
|
|
215
|
+
content_blocks: List[StreamingContentBlock],
|
|
216
|
+
accumulated_content: str,
|
|
177
217
|
):
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
"$ai_cache_read_input_tokens": usage_stats.get(
|
|
199
|
-
"cache_read_input_tokens", 0
|
|
200
|
-
),
|
|
201
|
-
"$ai_cache_creation_input_tokens": usage_stats.get(
|
|
202
|
-
"cache_creation_input_tokens", 0
|
|
218
|
+
from posthoganalytics.ai.types import StreamingEventData
|
|
219
|
+
from posthoganalytics.ai.anthropic.anthropic_converter import (
|
|
220
|
+
standardize_anthropic_usage,
|
|
221
|
+
format_anthropic_streaming_input,
|
|
222
|
+
format_anthropic_streaming_output_complete,
|
|
223
|
+
)
|
|
224
|
+
from posthoganalytics.ai.utils import capture_streaming_event
|
|
225
|
+
|
|
226
|
+
# Prepare standardized event data
|
|
227
|
+
formatted_input = format_anthropic_streaming_input(kwargs)
|
|
228
|
+
sanitized_input = sanitize_anthropic(formatted_input)
|
|
229
|
+
|
|
230
|
+
event_data = StreamingEventData(
|
|
231
|
+
provider="anthropic",
|
|
232
|
+
model=kwargs.get("model", "unknown"),
|
|
233
|
+
base_url=str(self._client.base_url),
|
|
234
|
+
kwargs=kwargs,
|
|
235
|
+
formatted_input=sanitized_input,
|
|
236
|
+
formatted_output=format_anthropic_streaming_output_complete(
|
|
237
|
+
content_blocks, accumulated_content
|
|
203
238
|
),
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
distinct_id=posthog_distinct_id or posthog_trace_id,
|
|
216
|
-
event="$ai_generation",
|
|
217
|
-
properties=event_properties,
|
|
218
|
-
groups=posthog_groups,
|
|
219
|
-
)
|
|
239
|
+
usage_stats=standardize_anthropic_usage(usage_stats),
|
|
240
|
+
latency=latency,
|
|
241
|
+
distinct_id=posthog_distinct_id,
|
|
242
|
+
trace_id=posthog_trace_id,
|
|
243
|
+
properties=posthog_properties,
|
|
244
|
+
privacy_mode=posthog_privacy_mode,
|
|
245
|
+
groups=posthog_groups,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
# Use the common capture function
|
|
249
|
+
capture_streaming_event(self._client._ph_client, event_data)
|
{posthoganalytics-6.7.1 → posthoganalytics-6.7.2}/posthoganalytics/ai/anthropic/anthropic_async.py
RENAMED
|
@@ -8,15 +8,26 @@ except ImportError:
|
|
|
8
8
|
|
|
9
9
|
import time
|
|
10
10
|
import uuid
|
|
11
|
-
from typing import Any, Dict, Optional
|
|
11
|
+
from typing import Any, Dict, List, Optional
|
|
12
12
|
|
|
13
13
|
from posthoganalytics import setup
|
|
14
|
+
from posthoganalytics.ai.types import StreamingContentBlock, ToolInProgress
|
|
14
15
|
from posthoganalytics.ai.utils import (
|
|
15
16
|
call_llm_and_track_usage_async,
|
|
17
|
+
extract_available_tool_calls,
|
|
16
18
|
get_model_params,
|
|
17
19
|
merge_system_prompt,
|
|
20
|
+
merge_usage_stats,
|
|
18
21
|
with_privacy_mode,
|
|
19
22
|
)
|
|
23
|
+
from posthoganalytics.ai.anthropic.anthropic_converter import (
|
|
24
|
+
format_anthropic_streaming_content,
|
|
25
|
+
extract_anthropic_usage_from_event,
|
|
26
|
+
handle_anthropic_content_block_start,
|
|
27
|
+
handle_anthropic_text_delta,
|
|
28
|
+
handle_anthropic_tool_delta,
|
|
29
|
+
finalize_anthropic_tool_input,
|
|
30
|
+
)
|
|
20
31
|
from posthoganalytics.ai.sanitization import sanitize_anthropic
|
|
21
32
|
from posthoganalytics.client import Client as PostHogClient
|
|
22
33
|
|
|
@@ -62,6 +73,7 @@ class AsyncWrappedMessages(AsyncMessages):
|
|
|
62
73
|
posthog_groups: Optional group analytics properties
|
|
63
74
|
**kwargs: Arguments passed to Anthropic's messages.create
|
|
64
75
|
"""
|
|
76
|
+
|
|
65
77
|
if posthog_trace_id is None:
|
|
66
78
|
posthog_trace_id = str(uuid.uuid4())
|
|
67
79
|
|
|
@@ -120,34 +132,65 @@ class AsyncWrappedMessages(AsyncMessages):
|
|
|
120
132
|
):
|
|
121
133
|
start_time = time.time()
|
|
122
134
|
usage_stats: Dict[str, int] = {"input_tokens": 0, "output_tokens": 0}
|
|
123
|
-
accumulated_content =
|
|
135
|
+
accumulated_content = ""
|
|
136
|
+
content_blocks: List[StreamingContentBlock] = []
|
|
137
|
+
tools_in_progress: Dict[str, ToolInProgress] = {}
|
|
138
|
+
current_text_block: Optional[StreamingContentBlock] = None
|
|
124
139
|
response = await super().create(**kwargs)
|
|
125
140
|
|
|
126
141
|
async def generator():
|
|
127
142
|
nonlocal usage_stats
|
|
128
|
-
nonlocal accumulated_content
|
|
143
|
+
nonlocal accumulated_content
|
|
144
|
+
nonlocal content_blocks
|
|
145
|
+
nonlocal tools_in_progress
|
|
146
|
+
nonlocal current_text_block
|
|
147
|
+
|
|
129
148
|
try:
|
|
130
149
|
async for event in response:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
150
|
+
# Extract usage stats from event
|
|
151
|
+
event_usage = extract_anthropic_usage_from_event(event)
|
|
152
|
+
merge_usage_stats(usage_stats, event_usage)
|
|
153
|
+
|
|
154
|
+
# Handle content block start events
|
|
155
|
+
if hasattr(event, "type") and event.type == "content_block_start":
|
|
156
|
+
block, tool = handle_anthropic_content_block_start(event)
|
|
157
|
+
|
|
158
|
+
if block:
|
|
159
|
+
content_blocks.append(block)
|
|
160
|
+
|
|
161
|
+
if block.get("type") == "text":
|
|
162
|
+
current_text_block = block
|
|
163
|
+
else:
|
|
164
|
+
current_text_block = None
|
|
165
|
+
|
|
166
|
+
if tool:
|
|
167
|
+
tool_id = tool["block"].get("id")
|
|
168
|
+
if tool_id:
|
|
169
|
+
tools_in_progress[tool_id] = tool
|
|
170
|
+
|
|
171
|
+
# Handle text delta events
|
|
172
|
+
delta_text = handle_anthropic_text_delta(event, current_text_block)
|
|
173
|
+
|
|
174
|
+
if delta_text:
|
|
175
|
+
accumulated_content += delta_text
|
|
176
|
+
|
|
177
|
+
# Handle tool input delta events
|
|
178
|
+
handle_anthropic_tool_delta(
|
|
179
|
+
event, content_blocks, tools_in_progress
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Handle content block stop events
|
|
183
|
+
if hasattr(event, "type") and event.type == "content_block_stop":
|
|
184
|
+
current_text_block = None
|
|
185
|
+
finalize_anthropic_tool_input(
|
|
186
|
+
event, content_blocks, tools_in_progress
|
|
187
|
+
)
|
|
144
188
|
|
|
145
189
|
yield event
|
|
146
190
|
|
|
147
191
|
finally:
|
|
148
192
|
end_time = time.time()
|
|
149
193
|
latency = end_time - start_time
|
|
150
|
-
output = "".join(accumulated_content)
|
|
151
194
|
|
|
152
195
|
await self._capture_streaming_event(
|
|
153
196
|
posthog_distinct_id,
|
|
@@ -158,7 +201,8 @@ class AsyncWrappedMessages(AsyncMessages):
|
|
|
158
201
|
kwargs,
|
|
159
202
|
usage_stats,
|
|
160
203
|
latency,
|
|
161
|
-
|
|
204
|
+
content_blocks,
|
|
205
|
+
accumulated_content,
|
|
162
206
|
)
|
|
163
207
|
|
|
164
208
|
return generator()
|
|
@@ -173,11 +217,27 @@ class AsyncWrappedMessages(AsyncMessages):
|
|
|
173
217
|
kwargs: Dict[str, Any],
|
|
174
218
|
usage_stats: Dict[str, int],
|
|
175
219
|
latency: float,
|
|
176
|
-
|
|
220
|
+
content_blocks: List[StreamingContentBlock],
|
|
221
|
+
accumulated_content: str,
|
|
177
222
|
):
|
|
178
223
|
if posthog_trace_id is None:
|
|
179
224
|
posthog_trace_id = str(uuid.uuid4())
|
|
180
225
|
|
|
226
|
+
# Format output using converter
|
|
227
|
+
formatted_content = format_anthropic_streaming_content(content_blocks)
|
|
228
|
+
formatted_output = []
|
|
229
|
+
|
|
230
|
+
if formatted_content:
|
|
231
|
+
formatted_output = [{"role": "assistant", "content": formatted_content}]
|
|
232
|
+
else:
|
|
233
|
+
# Fallback to accumulated content if no blocks
|
|
234
|
+
formatted_output = [
|
|
235
|
+
{
|
|
236
|
+
"role": "assistant",
|
|
237
|
+
"content": [{"type": "text", "text": accumulated_content}],
|
|
238
|
+
}
|
|
239
|
+
]
|
|
240
|
+
|
|
181
241
|
event_properties = {
|
|
182
242
|
"$ai_provider": "anthropic",
|
|
183
243
|
"$ai_model": kwargs.get("model"),
|
|
@@ -190,7 +250,7 @@ class AsyncWrappedMessages(AsyncMessages):
|
|
|
190
250
|
"$ai_output_choices": with_privacy_mode(
|
|
191
251
|
self._client._ph_client,
|
|
192
252
|
posthog_privacy_mode,
|
|
193
|
-
|
|
253
|
+
formatted_output,
|
|
194
254
|
),
|
|
195
255
|
"$ai_http_status": 200,
|
|
196
256
|
"$ai_input_tokens": usage_stats.get("input_tokens", 0),
|
|
@@ -207,6 +267,12 @@ class AsyncWrappedMessages(AsyncMessages):
|
|
|
207
267
|
**(posthog_properties or {}),
|
|
208
268
|
}
|
|
209
269
|
|
|
270
|
+
# Add tools if available
|
|
271
|
+
available_tools = extract_available_tool_calls("anthropic", kwargs)
|
|
272
|
+
|
|
273
|
+
if available_tools:
|
|
274
|
+
event_properties["$ai_tools"] = available_tools
|
|
275
|
+
|
|
210
276
|
if posthog_distinct_id is None:
|
|
211
277
|
event_properties["$process_person_profile"] = False
|
|
212
278
|
|