Skip to content

Commit f3edfe8

Browse files
committed
Merge master into fix/llma-streaming-providers-with-tool-calls
Resolved conflicts by: - Keeping both StreamingEventData approach and new sanitization imports - Applying sanitization to formatted inputs before passing to StreamingEventData - Ensuring privacy mode and special token fields are handled by capture_streaming_event
2 parents 722eead + 9f37067 commit f3edfe8

File tree

11 files changed

+630
-14
lines changed

11 files changed

+630
-14
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 6.7.1 - 2025-09-01
2+
3+
- fix: Add base64 inline image sanitization
4+
15
# 6.7.0 - 2025-08-26
26

37
- feat: Add support for feature flag dependencies

posthog/ai/anthropic/anthropic.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
handle_anthropic_tool_delta,
2121
finalize_anthropic_tool_input,
2222
)
23+
from posthog.ai.sanitization import sanitize_anthropic
2324
from posthog.client import Client as PostHogClient
2425
from posthog import setup
2526

@@ -219,12 +220,15 @@ def _capture_streaming_event(
219220
from posthog.ai.utils import capture_streaming_event
220221

221222
# Prepare standardized event data
223+
formatted_input = format_anthropic_streaming_input(kwargs)
224+
sanitized_input = sanitize_anthropic(formatted_input)
225+
222226
event_data = StreamingEventData(
223227
provider="anthropic",
224228
model=kwargs.get("model"),
225229
base_url=str(self._client.base_url),
226230
kwargs=kwargs,
227-
formatted_input=format_anthropic_streaming_input(kwargs),
231+
formatted_input=sanitized_input,
228232
formatted_output=format_anthropic_streaming_output_complete(
229233
content_blocks, accumulated_content
230234
),

posthog/ai/anthropic/anthropic_async.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
handle_anthropic_tool_delta,
2727
finalize_anthropic_tool_input,
2828
)
29+
from posthog.ai.sanitization import sanitize_anthropic
2930
from posthog.client import Client as PostHogClient
3031

3132

@@ -240,7 +241,7 @@ async def _capture_streaming_event(
240241
"$ai_input": with_privacy_mode(
241242
self._client._ph_client,
242243
posthog_privacy_mode,
243-
merge_system_prompt(kwargs, "anthropic"),
244+
sanitize_anthropic(merge_system_prompt(kwargs, "anthropic")),
244245
),
245246
"$ai_output_choices": with_privacy_mode(
246247
self._client._ph_client,

posthog/ai/gemini/gemini.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
extract_gemini_content_from_chunk,
2222
format_gemini_streaming_output,
2323
)
24+
from posthog.ai.sanitization import sanitize_gemini
2425
from posthog.client import Client as PostHogClient
2526

2627

@@ -355,12 +356,15 @@ def _capture_streaming_event(
355356
from posthog.ai.gemini.gemini_converter import standardize_gemini_usage
356357

357358
# Prepare standardized event data
359+
formatted_input = self._format_input(contents)
360+
sanitized_input = sanitize_gemini(formatted_input)
361+
358362
event_data = StreamingEventData(
359363
provider="gemini",
360364
model=model,
361365
base_url=self._base_url,
362366
kwargs=kwargs,
363-
formatted_input=self._format_input(contents),
367+
formatted_input=sanitized_input,
364368
formatted_output=format_gemini_streaming_output(output),
365369
usage_stats=standardize_gemini_usage(usage_stats),
366370
latency=latency,

posthog/ai/langchain/callbacks.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
from posthog import setup
3939
from posthog.ai.utils import get_model_params, with_privacy_mode
40+
from posthog.ai.sanitization import sanitize_langchain
4041
from posthog.client import Client
4142

4243
log = logging.getLogger("posthog")
@@ -480,7 +481,7 @@ def _capture_trace_or_span(
480481
event_properties = {
481482
"$ai_trace_id": trace_id,
482483
"$ai_input_state": with_privacy_mode(
483-
self._ph_client, self._privacy_mode, run.input
484+
self._ph_client, self._privacy_mode, sanitize_langchain(run.input)
484485
),
485486
"$ai_latency": run.latency,
486487
"$ai_span_name": run.name,
@@ -550,7 +551,7 @@ def _capture_generation(
550551
"$ai_model": run.model,
551552
"$ai_model_parameters": run.model_params,
552553
"$ai_input": with_privacy_mode(
553-
self._ph_client, self._privacy_mode, run.input
554+
self._ph_client, self._privacy_mode, sanitize_langchain(run.input)
554555
),
555556
"$ai_http_status": 200,
556557
"$ai_latency": run.latency,

posthog/ai/openai/openai.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
extract_openai_tool_calls_from_chunk,
2121
accumulate_openai_tool_calls,
2222
)
23+
from posthog.ai.sanitization import sanitize_openai, sanitize_openai_response
2324
from posthog.client import Client as PostHogClient
2425
from posthog import setup
2526

@@ -183,12 +184,15 @@ def _capture_streaming_event(
183184
from posthog.ai.utils import capture_streaming_event
184185

185186
# Prepare standardized event data
187+
formatted_input = format_openai_streaming_input(kwargs, "responses")
188+
sanitized_input = sanitize_openai_response(formatted_input)
189+
186190
event_data = StreamingEventData(
187191
provider="openai",
188192
model=kwargs.get("model"),
189193
base_url=str(self._client.base_url),
190194
kwargs=kwargs,
191-
formatted_input=format_openai_streaming_input(kwargs, "responses"),
195+
formatted_input=sanitized_input,
192196
formatted_output=format_openai_streaming_output(output, "responses"),
193197
usage_stats=standardize_openai_usage(usage_stats, "responses"),
194198
latency=latency,
@@ -397,12 +401,15 @@ def _capture_streaming_event(
397401
from posthog.ai.utils import capture_streaming_event
398402

399403
# Prepare standardized event data
404+
formatted_input = format_openai_streaming_input(kwargs, "chat")
405+
sanitized_input = sanitize_openai(formatted_input)
406+
400407
event_data = StreamingEventData(
401408
provider="openai",
402409
model=kwargs.get("model"),
403410
base_url=str(self._client.base_url),
404411
kwargs=kwargs,
405-
formatted_input=format_openai_streaming_input(kwargs, "chat"),
412+
formatted_input=sanitized_input,
406413
formatted_output=format_openai_streaming_output(output, "chat", tool_calls),
407414
usage_stats=standardize_openai_usage(usage_stats, "chat"),
408415
latency=latency,
@@ -474,7 +481,9 @@ def create(
474481
"$ai_provider": "openai",
475482
"$ai_model": kwargs.get("model"),
476483
"$ai_input": with_privacy_mode(
477-
self._client._ph_client, posthog_privacy_mode, kwargs.get("input")
484+
self._client._ph_client,
485+
posthog_privacy_mode,
486+
sanitize_openai_response(kwargs.get("input")),
478487
),
479488
"$ai_http_status": 200,
480489
"$ai_input_tokens": usage_stats.get("prompt_tokens", 0),

posthog/ai/openai/openai_async.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
accumulate_openai_tool_calls,
2424
format_openai_streaming_output,
2525
)
26+
from posthog.ai.sanitization import sanitize_openai, sanitize_openai_response
2627
from posthog.client import Client as PostHogClient
2728

2829

@@ -187,7 +188,9 @@ async def _capture_streaming_event(
187188
"$ai_model": kwargs.get("model"),
188189
"$ai_model_parameters": get_model_params(kwargs),
189190
"$ai_input": with_privacy_mode(
190-
self._client._ph_client, posthog_privacy_mode, kwargs.get("input")
191+
self._client._ph_client,
192+
posthog_privacy_mode,
193+
sanitize_openai_response(kwargs.get("input")),
191194
),
192195
"$ai_output_choices": with_privacy_mode(
193196
self._client._ph_client,
@@ -416,7 +419,9 @@ async def _capture_streaming_event(
416419
"$ai_model": kwargs.get("model"),
417420
"$ai_model_parameters": get_model_params(kwargs),
418421
"$ai_input": with_privacy_mode(
419-
self._client._ph_client, posthog_privacy_mode, kwargs.get("messages")
422+
self._client._ph_client,
423+
posthog_privacy_mode,
424+
sanitize_openai(kwargs.get("messages")),
420425
),
421426
"$ai_output_choices": with_privacy_mode(
422427
self._client._ph_client,
@@ -510,7 +515,9 @@ async def create(
510515
"$ai_provider": "openai",
511516
"$ai_model": kwargs.get("model"),
512517
"$ai_input": with_privacy_mode(
513-
self._client._ph_client, posthog_privacy_mode, kwargs.get("input")
518+
self._client._ph_client,
519+
posthog_privacy_mode,
520+
sanitize_openai_response(kwargs.get("input")),
514521
),
515522
"$ai_http_status": 200,
516523
"$ai_input_tokens": usage_stats.get("prompt_tokens", 0),

0 commit comments

Comments
 (0)