An intelligent SQL analytics agent that converts natural language queries into SQL, executes them against a Chinook database, and presents results with visualizations. Features real-time streaming of agent reasoning steps and token-by-token response generation.
Technology Stack:
- React 18 with TypeScript
- Tailwind CSS for styling
- Vega-Lite for data visualizations
- Server-Sent Events (SSE) for real-time streaming
Key Components:
- ChatInterface: Main UI with glassmorphism design
- ThinkingProcess: Real-time visualization of agent steps (timeline view)
- VisualizationRenderer: Embeds Vega-Lite charts
- useChat Hook: Manages SSE connection and state
Data Flow:
User Input → SSE Connection → Event Stream Parser → UI Updates
↓
[token events, node_update events]
FastAPI Router (/api/chat)
- Accepts user queries via POST
- Returns StreamingResponse with SSE
- Streams two types of events:
updates: State changes (SQL, visualizations, node completions)custom: Token-by-token text streaming
Stream Modes:
stream_mode=["updates", "custom"]State Management:
AgentState {
user_query: string
refined_query: string
relevance: "relevant" | "irrelevant"
selected_tables: string[]
generated_sql: string
is_valid_sql: boolean
validation_error: string
retry_count: number
query_result: any[]
natural_response: string
visualization_spec: object
}Agent Graph Flow:
START
↓
Query Router ──→ [irrelevant] ──→ General Agent ──→ END
↓ [relevant]
Query Rewriter
↓
Table Selector
↓
SQL Generator ←──┐ (retry loop, max 3)
↓ │
SQL Validator ───┘ [invalid]
↓ [valid]
SQL Executor
↓
Response Synthesizer ──→ Visualization Planner ──→ Visualization Generator
↓ ↓
END ←────────────────────────────────────────────────────────┘
- Purpose: Determines if query is relevant to database domain
- LLM: GPT-4
- Output:
relevance("relevant" | "irrelevant")
- Purpose: Refines user query for clarity
- LLM: GPT-4
- Output:
refined_query
- Purpose: Handles out-of-scope queries with helpful guidance
- LLM: GPT-4
- Streaming: Uses
get_stream_writer()for token streaming - Output:
natural_response
- Purpose: Identifies relevant database tables
- LLM: GPT-4
- Input: Database schema
- Output:
selected_tables
- Purpose: Generates SQL query from natural language
- LLM: GPT-4
- Features: Self-correction using validation errors
- Output:
generated_sql, incrementsretry_count
- Purpose: Validates SQL safety (prevents DROP, DELETE, etc.)
- Logic: Regex-based validation
- Output:
is_valid_sql,validation_error
- Purpose: Executes validated SQL against SQLite database
- Database: Chinook (music store data)
- Output:
query_result
- Purpose: Converts query results into natural language
- LLM: GPT-4
- Streaming: Uses
get_stream_writer()for token streaming - Output:
natural_response
- Purpose: Determines if data should be visualized
- LLM: GPT-4
- Output: Decision to create visualization
- Purpose: Creates Vega-Lite specification
- LLM: GPT-4
- Output:
visualization_spec(JSON)
Token Streaming Pattern:
# In Agent Node
from langgraph.config import get_stream_writer
writer = get_stream_writer()
async for chunk in openai_stream:
content = chunk.choices[0].delta.content
writer(content) # Emits to 'custom' stream
full_response += contentAPI Consumption:
async for mode, payload in graph.astream(inputs, stream_mode=["updates", "custom"]):
if mode == "updates":
# Handle state changes (SQL, visualizations, node completions)
elif mode == "custom":
# Handle token chunksFrontend Handling:
if (event.type === 'token') {
message.content += event.content; // Append tokens
} else if (event.type === 'node_update') {
// Update thinking process timeline
}LangGraph Checkpointer:
- Type: SQLite-based MemorySaver
- Purpose: Maintains conversation state across requests
- Thread ID: Identifies conversation sessions
Database:
- Type: SQLite (Chinook database)
- Schema: Music store (Artists, Albums, Tracks, Customers, Invoices)
Real-Time Thinking Process:
- Displays each agent step as it executes
- Timeline visualization with icons and status
- Shows SQL queries and intermediate results
Token Streaming:
- Character-by-character response rendering
- Smooth typing effect using native LangGraph streaming
- No custom queue implementation needed
SQL Validation & Retry:
- Automatic retry loop (max 3 attempts)
- Self-correction using validation errors
- Prevents unsafe SQL operations
Premium UI/UX:
- Glassmorphism design
- Smooth animations and transitions
- Custom scrollbars and hover effects
- Responsive layout
Backend:
- FastAPI (API framework)
- LangGraph (Agent orchestration)
- OpenAI SDK (LLM interactions)
- SQLite (Database)
- Python 3.13
Frontend:
- React 18 + TypeScript
- Vite (Build tool)
- Tailwind CSS (Styling)
- Vega-Lite (Visualizations)
- Lucide React (Icons)
Infrastructure:
- SSE for real-time communication
- Context-based streaming (no WebSockets)
- Thread-based conversation management
- No LangChain Dependency: Direct OpenAI SDK usage for maximum control
- Native Streaming: LangGraph's
get_stream_writer()for custom data - Separation of Concerns: Clear boundaries between agents, API, and UI
- User Transparency: Visible agent reasoning process
- Graceful Degradation: Retry loops and fallback responses
- Premium Experience: Modern UI with real-time feedback