Skip to content

Commit e6e417c

Browse files
committed
fix(llma): fix OpenAI's Chat Completions streaming
1 parent 5c9b6fb commit e6e417c

2 files changed

Lines changed: 40 additions & 10 deletions

File tree

‎posthog/ai/openai/openai_converter.py‎

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def extract_openai_web_search_count(response: Any) -> int:
263263
1. Priority 1 (exact count): Check for output[].type == "web_search_call" (Responses API)
264264
2. Priority 2 (binary detection): Check for various web search indicators:
265265
- Root-level citations, search_results, or usage.search_context_size (Perplexity)
266-
- Annotations with type "url_citation" in choices/output
266+
- Annotations with type "url_citation" in choices/output (including delta for streaming)
267267
268268
Args:
269269
response: The response from OpenAI API
@@ -275,6 +275,7 @@ def extract_openai_web_search_count(response: Any) -> int:
275275
# Priority 1: Check for exact count in Responses API output
276276
if hasattr(response, "output"):
277277
web_search_count = 0
278+
278279
for item in response.output:
279280
if hasattr(item, "type") and item.type == "web_search_call":
280281
web_search_count += 1
@@ -289,11 +290,13 @@ def extract_openai_web_search_count(response: Any) -> int:
289290
# Check root-level indicators (Perplexity)
290291
if hasattr(response, "citations"):
291292
citations = getattr(response, "citations")
293+
292294
if citations and len(citations) > 0:
293295
return 1
294296

295297
if hasattr(response, "search_results"):
296298
search_results = getattr(response, "search_results")
299+
297300
if search_results and len(search_results) > 0:
298301
return 1
299302

@@ -304,14 +307,36 @@ def extract_openai_web_search_count(response: Any) -> int:
304307
# Check for url_citation annotations in choices (Chat Completions)
305308
if hasattr(response, "choices"):
306309
for choice in response.choices:
310+
# Check message.annotations (non-streaming or final chunk)
307311
if hasattr(choice, "message") and hasattr(choice.message, "annotations"):
308312
annotations = choice.message.annotations
313+
309314
if annotations:
310315
for annotation in annotations:
311-
if (
312-
hasattr(annotation, "type")
313-
and annotation.type == "url_citation"
314-
):
316+
# Support both dict and object formats
317+
annotation_type = (
318+
annotation.get("type")
319+
if isinstance(annotation, dict)
320+
else getattr(annotation, "type", None)
321+
)
322+
323+
if annotation_type == "url_citation":
324+
return 1
325+
326+
# Check delta.annotations (streaming chunks)
327+
if hasattr(choice, "delta") and hasattr(choice.delta, "annotations"):
328+
annotations = choice.delta.annotations
329+
330+
if annotations:
331+
for annotation in annotations:
332+
# Support both dict and object formats
333+
annotation_type = (
334+
annotation.get("type")
335+
if isinstance(annotation, dict)
336+
else getattr(annotation, "type", None)
337+
)
338+
339+
if annotation_type == "url_citation":
315340
return 1
316341

317342
# Check for url_citation annotations in output (Responses API)
@@ -321,12 +346,17 @@ def extract_openai_web_search_count(response: Any) -> int:
321346
for content_item in item.content:
322347
if hasattr(content_item, "annotations"):
323348
annotations = content_item.annotations
349+
324350
if annotations:
325351
for annotation in annotations:
326-
if (
327-
hasattr(annotation, "type")
328-
and annotation.type == "url_citation"
329-
):
352+
# Support both dict and object formats
353+
annotation_type = (
354+
annotation.get("type")
355+
if isinstance(annotation, dict)
356+
else getattr(annotation, "type", None)
357+
)
358+
359+
if annotation_type == "url_citation":
330360
return 1
331361

332362
return 0

‎posthog/ai/utils.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def merge_usage_stats(
5757
source_web_search = source.get("web_search_count")
5858
if source_web_search is not None:
5959
current = target.get("web_search_count") or 0
60-
target["web_search_count"] = current + source_web_search
60+
target["web_search_count"] = max(current, source_web_search)
6161

6262
elif mode == "cumulative":
6363
# Replace with latest values (already cumulative)

0 commit comments

Comments
 (0)