FastAPI VAC Routes Implementation - Key Fixes Summary
Overview
This document summarizes the critical fixes applied to make the FastAPI VAC Routes implementation fully functional with proper SSE streaming support.
Critical Fixes Applied
1. Archive QA Function - Async/Sync Mismatch
Problem: archive_qa()
is a synchronous function but was being called with await
Error: TypeError: object NoneType can't be used in 'await' expression
Fix: Removed await
from all archive_qa()
calls
# Before (incorrect)
await archive_qa(chunk, vector_name)
# After (correct)
archive_qa(chunk, vector_name) # This is a sync function, not async
2. Streaming Loop Exit Timing
Problem: The streaming loop exited when stream_finished
was set, before the final result could be yielded
Fix: Modified loop condition to continue until task is complete
# Changed the loop to check task completion status
while not stop_event.is_set():
if chat_callback_handler.stream_finished.is_set() and chat_task.done():
break
3. Empty String Yields
Problem: Empty strings were being yielded, causing issues with SSE format Fix: Added check to not yield empty strings
if final_yield: # Only yield if we have actual content
yield final_yield
4. Mock Document Format in Demo
Problem: Demo interpreters returned plain dicts but parse_output
expected document objects with page_content
attribute
Fix: Created MockDocument class in demo
class MockDocument:
def __init__(self, page_content, metadata):
self.page_content = page_content
self.metadata = metadata
5. JavaScript String Escaping in Test Page
Problem: Literal newline characters in JavaScript strings caused syntax errors
Error: SyntaxError: '' string literal contains an unescaped line break
Fix: Properly escaped newlines in JavaScript strings within Python triple-quoted strings
# Before (incorrect)
const lines = buffer.split('\n');
# After (correct)
const lines = buffer.split('\\n');
6. Error Handler Logging
Problem: log.error()
doesn't accept exc_info
parameter in StandardLoggerWrapper
Fix: Used traceback.format_exc() instead
import traceback
log.error(f"Error in SSE generator: {e}\n{traceback.format_exc()}")
Testing Commands
Basic SSE Test
curl -X POST http://localhost:8000/vac/streaming/demo/sse \
-H "Content-Type: application/json" \
-d '{"user_input": "Tell me a story"}'
Expected output:
data: {"chunk": "Hello! I'm a demo async streaming interpreter. \n\n"}
data: {"chunk": "You asked: \"Tell me a story\". \n\n"}
data: {"chunk": "Here's my streaming response..."}
data: {"answer": "...", "source_documents": [...]}
data: [DONE]
Interactive Test Page
Visit http://localhost:8000/test for an interactive test interface with both Plain Text and SSE streaming options.
Key Implementation Details
The Callback Bridge Architecture
LLM → callback.on_llm_new_token() → ContentBuffer → async generator → StreamingResponse
Async/Sync Interpreter Detection
- Async interpreters: Run directly with
await
- Sync interpreters: Run in thread executor with queue-based communication
Common Pitfalls to Avoid
- Don't await sync functions - Check if a function is async before using await
- Escape strings in triple-quoted strings - Use
\\n
not\n
for JavaScript strings - Check for empty yields - Don't yield empty strings in streaming responses
- Match document format - Ensure mock data matches expected format for parsers
- Use proper error handling - StandardLoggerWrapper has limited parameters
Verification Steps
- Start the demo server:
python examples/fastapi_vac_demo.py
- Test SSE streaming with curl (should complete with [DONE])
- Test interactive page at /test (both buttons should work)
- Verify sources are included in final response
- Check that connection properly terminates