41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
|
|
class OpenAIStreamAccumulator:
|
|
"""Normalize incremental deltas and provider-specific full-message snapshots."""
|
|
|
|
def __init__(self) -> None:
|
|
self.text = ""
|
|
self.saw_delta = False
|
|
|
|
def feed(self, choice: dict[str, Any]) -> str:
|
|
delta = choice.get("delta")
|
|
if isinstance(delta, dict) and delta.get("content") is not None:
|
|
chunk = str(delta.get("content") or "")
|
|
if chunk:
|
|
self.saw_delta = True
|
|
self.text += chunk
|
|
return chunk
|
|
|
|
message = choice.get("message")
|
|
if not isinstance(message, dict) or message.get("content") is None:
|
|
return ""
|
|
snapshot = str(message.get("content") or "")
|
|
if not snapshot:
|
|
return ""
|
|
if not self.text:
|
|
self.text = snapshot
|
|
return snapshot
|
|
if snapshot == self.text or self.text.startswith(snapshot):
|
|
return ""
|
|
if snapshot.startswith(self.text):
|
|
suffix = snapshot[len(self.text):]
|
|
self.text = snapshot
|
|
return suffix
|
|
if self.saw_delta:
|
|
# A final full snapshot cannot safely replace chunks already delivered.
|
|
return ""
|
|
return ""
|