ChatbotRAG / stream_utils.py
minhvtt's picture
Upload 26 files
75033ed verified
raw
history blame
2.18 kB
"""
SSE (Server-Sent Events) Utilities
Format streaming responses for real-time chat
"""
import json
from typing import Dict, Any, AsyncGenerator
import asyncio
def format_sse(event: str, data: Any) -> str:
"""
Format data as SSE message
Args:
event: Event type (token, status, done, error)
data: Data payload (string or dict)
Returns:
Formatted SSE string
Example:
format_sse("token", "Hello")
# "event: token\ndata: Hello\n\n"
"""
if isinstance(data, dict):
data_str = json.dumps(data, ensure_ascii=False)
else:
data_str = str(data)
return f"event: {event}\ndata: {data_str}\n\n"
async def simulate_typing(
text: str,
chars_per_chunk: int = 3,
delay_ms: float = 20
) -> AsyncGenerator[str, None]:
"""
Simulate typing effect by yielding text in chunks
Args:
text: Full text to stream
chars_per_chunk: Characters per chunk
delay_ms: Milliseconds delay between chunks
Yields:
Text chunks
Example:
async for chunk in simulate_typing("Hello world", chars_per_chunk=2):
yield format_sse("token", chunk)
"""
for i in range(0, len(text), chars_per_chunk):
chunk = text[i:i + chars_per_chunk]
yield chunk
await asyncio.sleep(delay_ms / 1000)
async def stream_text_slowly(
text: str,
event_type: str = "token",
chars_per_chunk: int = 3,
delay_ms: float = 20
) -> AsyncGenerator[str, None]:
"""
Stream text with typing effect in SSE format
Args:
text: Text to stream
event_type: SSE event type
chars_per_chunk: Characters per chunk
delay_ms: Delay between chunks
Yields:
SSE formatted chunks
"""
async for chunk in simulate_typing(text, chars_per_chunk, delay_ms):
yield format_sse(event_type, chunk)
# Event type constants
EVENT_STATUS = "status"
EVENT_TOKEN = "token"
EVENT_DONE = "done"
EVENT_ERROR = "error"
EVENT_METADATA = "metadata"