Next-Generation Human-AI Interaction Through Autonomous Voice Conversations with RAG-Powered Memory & Knowledge Retrieval
π Repository: https://github.com/AteetVatan/echo-ai
- Project Overview
- Key Features
- Architecture Overview
- System Architecture Diagram
- RAG System Deep Dive
- RAG Pipeline Flow Diagram
- Agent Collaboration Workflow
- Service Layer Architecture
- Design Patterns
- Frontend Architecture
- Exception Hierarchy
- WebSocket Protocol Diagram
- Technology Stack
- Project Structure
- How It Works
- Installation
- How to Run
- API Endpoints
- Usage Examples
- Configuration Reference
- Performance Metrics
- Troubleshooting
- Future Roadmap
- Contributing
- License
- Acknowledgments
- Support & Community
EchoAI is a cutting-edge, real-time voice-interactive AI system that enables natural, autonomous conversations with an AI clone. Built on the principles of agentic intelligence and Retrieval-Augmented Generation (RAG), EchoAI combines real-time speech processing, semantic memory retrieval, and autonomous reasoning to create the most natural human-AI interaction experience possible.
Traditional voice assistants are reactive and lack contextual memory. EchoAI represents the next evolution: an AI that can:
- Remember previous conversations and build long-term relationships through RAG-powered semantic search
- Reason autonomously about complex topics using retrieved knowledge
- Adapt its personality and responses based on interaction history and stored knowledge
- Learn from conversations to improve future interactions with persistent memory
This project pushes the boundaries of what's possible in human-AI communication, making AI interactions feel truly natural and meaningful through intelligent knowledge retrieval and context-aware responses.
- Ultra-low latency STT using Faster-Whisper (local) with OpenAI Whisper fallback
- Instant TTS synthesis with Edge-TTS (Microsoft neural voices β free, no API key)
- Audio streaming via WebSocket for natural conversational flow
- Audio chunking & normalization with tail-padding and RMS-based gain control
- Multi-mode audio input: complete audio, streaming chunks, and real-time buffered streams
- Semantic vector search using Supabase pgvector with cosine similarity (IVFFlat index)
- Self-Info Knowledge Base loaded and indexed from
self_info.json(career, skills, projects, personality) - Reply Cache System with dual-layer matching: MD5 hash exact match β semantic similarity fallback
- Context-aware responses with multi-turn conversation history (configurable window size)
- Intelligent caching with configurable similarity thresholds (95% semantic cache, 85% reply cache)
- Text splitting with LangChain
RecursiveCharacterTextSplitter(chunk size 500, overlap 50)
- Multi-LLM orchestration: DeepSeek AI (primary) with Mistral AI (fallback)
- LangChain RAG chain using
RetrievalQAwithstuffchain type - Custom persona prompt for personality-consistent responses
- Autonomous reasoning with graceful fallback mechanisms
- Session-based conversation management with unique session IDs
- WebSocket streaming for real-time bidirectional audio transmission
- Concurrent async processing with
asyncio-based architecture throughout - Multi-level caching: in-memory LRU cache β Supabase audio cache β pgvector semantic cache
- Cache warm-up on startup with common phrases
- Performance monitoring with per-component latency tracking and statistics
- Configurable timeouts for STT (5s), LLM (10s), TTS (8s)
- Typed exception hierarchy:
EchoAIErrorβSTTError,LLMError,TTSError,RAGError,PipelineError,DatabaseError,AudioProcessingError - Automatic LLM fallback from DeepSeek β Mistral on failure
- Automatic STT fallback from Faster-Whisper β OpenAI Whisper on failure
- MockVectorStore fallback when pgvector initialization fails
- Connection management with graceful WebSocket disconnect/cleanup
- Supabase PostgreSQL for all persistent storage with connection pooling (
asyncpg) - pgvector extension for 384-dim vector similarity search (IVFFlat indexes)
- Supabase Storage for audio file hosting (TTS cache, session recordings)
- Next.js 16 + React 19 + TypeScript 5 β modern App Router with server/client components
- Tailwind CSS 4 β utility-first responsive styling with glassmorphism and micro-animations
- 12 TSX components across 3 domains: Chat (ChatContainer, ChatInput, MessageBubble, TypingIndicator), Home (HeroSection, FeaturesSection, StatsBar, AIVisualization, NeuralBackground), Layout (Header, Footer, LayoutShell)
- Custom
useChathook β encapsulates WebSocket lifecycle, message state, audio recording/playback, and voice toggle - Real-time WebSocket communication with visual status indicators
- Responsive design β optimised for mobile (320pxβ768px), tablet (768pxβ1024px), and desktop
π Standalone Mermaid diagrams are available in
docs/diagrams/as.mmdfiles for use in external tools, CI pipelines, or documentation generators.
flowchart TD
A[WebSocket/HTTP Client] --> B[Audio Input]
B --> C[STT Pipeline]
C --> D[Text Processing]
D --> E[RAG Semantic Search]
E --> F{Response in Cache?}
F -->|Yes| G[Audio Cache Hit]
F -->|No| H[Knowledge Base Search]
H --> I[Self-Info Knowledge Base]
I --> J{Relevant Knowledge?}
J -->|Yes| K[LangChain RAG Chain]
J -->|No| L[Direct LLM Generation]
K --> M[Context Assembly]
M --> N[LLM Reasoning]
N --> O[Response Generation]
L --> O
O --> P[TTS Synthesis]
P --> Q[Audio Streaming]
G --> R[Instant Audio Response]
Q --> R
R --> S[Client Audio Output]
subgraph "RAG Memory Layer"
T[pgvector Store]
U[Reply Cache Database]
V[Self-Info Knowledge Base]
W[Conversation History]
end
E --> T
G --> U
H --> V
N --> W
flowchart LR
subgraph "API Layer"
A1[FastAPI App]
A2[WebSocket Endpoint]
A3[REST Endpoints]
A4[Connection Manager]
end
subgraph "Service Layer"
S1[VoicePipeline]
S2[STTService]
S3[LLMService]
S4[TTSService]
end
subgraph "Agent Layer"
AG1[LangChainRAGAgent]
AG2[ReplyCacheManager]
end
subgraph "Knowledge Layer"
KL1[QueryRouter]
KL2[SelfInfoRetriever]
KL3[SelfInfoRAG]
KL4[SelfInfoVectorStore]
KL5[SelfInfoLoader]
KL6[EvidenceLoader]
end
subgraph "Data Layer"
D1[DBOperations - Supabase Postgres]
D2[Supabase Storage]
D3[pgvector Facts Index]
D4[pgvector Evidence Index]
D5[Self-Info JSON]
D6[rag_persona_db/]
end
subgraph "Utility Layer"
U1[Config - Pydantic Settings]
U2[Logging - Structured]
U3[Performance Monitor]
U4[Audio Processor]
U5[Audio Stream Processor]
end
A1 --> A2 & A3
A2 --> A4
A2 & A3 --> S1
S1 --> S2 & S3 & S4
S1 --> AG1
AG1 --> AG2
AG1 --> KL3
KL3 --> KL2
KL2 --> KL1
KL2 --> KL4
KL4 --> KL5 & KL6
KL4 --> D3 & D4
KL5 --> D5
KL6 --> D6
AG2 --> D1 & D3
S4 --> D1
S2 --> U4 & U5
S1 & S2 & S3 & S4 --> U1 & U2 & U3
flowchart TD
subgraph "Input Processing"
IN1[WebSocket Audio] --> DECODE[Audio Decode & Normalize]
IN2[Text Message] --> DIRECT[Direct Text Input]
IN3[Streaming Buffer] --> ACCUMULATE[Chunk Accumulator]
ACCUMULATE --> DECODE
end
subgraph "STT Stage"
DECODE --> FW[Faster-Whisper Local]
FW -->|Failure| OW[OpenAI Whisper API]
FW --> TEXT[Transcribed Text]
OW --> TEXT
end
subgraph "RAG Stage"
TEXT --> RC{Reply Cache Lookup}
DIRECT --> RC
RC -->|Exact Hash Match| HIT[Cache Hit]
RC -->|Semantic β₯95%| HIT
RC -->|Miss| QR[Query Router]
QR -->|factual/default| FACTS[Facts Index Search]
QR -->|evidence| EVIDENCE[Evidence Index Search]
QR -->|timeline/both| BOTH[Dual-Index Search]
FACTS --> MERGE[Hybrid Merge β Vector + BM25]
EVIDENCE --> MERGE
BOTH --> MERGE
MERGE -->|Relevant Docs| RAGCHAIN[LangChain RetrievalQA]
MERGE -->|No Docs| DIRECTLLM[Direct LLM Call]
end
subgraph "LLM Stage"
RAGCHAIN --> DS[DeepSeek AI Primary]
DIRECTLLM --> DS
DS -->|Failure| MI[Mistral AI Fallback]
DS --> RESP[Response Text]
MI --> RESP
end
subgraph "TTS Stage"
RESP --> TC{TTS Cache Check}
TC -->|Cached| CAUDIO[Cached Audio]
TC -->|Miss| EDGE[Edge-TTS Synthesis]
EDGE --> NAUDIO[New Audio]
NAUDIO --> STORE[Store in Cache]
end
subgraph "Output"
HIT --> WS[WebSocket Response]
CAUDIO --> WS
NAUDIO --> WS
STORE --> SUPA[(Supabase Postgres)]
STORE --> STORAGE[(Supabase Storage)]
end
- Embedding Model:
all-MiniLM-L6-v2(384-dim, viatransformersAutoModel) - Vector Database: Supabase pgvector with IVFFlat cosine indexes
- Search Strategy: Hybrid β vector similarity + BM25 keyword matching with configurable
k - Tables:
documents_reply_cacheβ reply caching for fast audio reusedocuments_self_info_factsβ atomic Q&A records fromself_info.jsondocuments_self_info_evidenceβ chunked evidence documents (READMEs, CV, LinkedIn CSVs)
- Performance: Sub-50ms similarity search latency
The knowledge base uses a dual-index strategy with separate pgvector tables:
| Index | Table | Source | Chunking |
|---|---|---|---|
| Facts | documents_self_info_facts |
self_info.json β atomic Q&A records |
One document per Q&A pair |
| Evidence | documents_self_info_evidence |
READMEs, CV, LinkedIn CSVs | Header-aware (MD: 1000/150), paragraph (DOCX: 800/100), row-based (CSV) |
Self-Info JSON Schema β The facts index is loaded from a structured self_info.json file containing:
- Personal information & professional bio
- Career history & work experience
- Technical skills & expertise
- Featured projects & portfolio
- Education & certifications
- Contact information
- Personality traits & communication style
Evidence Vault β The evidence index ingests multi-format documents from rag_persona_db/document/:
- π Markdown (
.md) β GitHub project READMEs (ApplyBots, Galileo, ShotGraph, MASX-*, MedAI) - π DOCX β CV / resume documents
- π CSV β LinkedIn data exports (skills, projects, endorsements, languages, learning)
- π PDF β Additional documents (via PyPDF fallback)
All documents receive deterministic stable_id values (SHA-256 for facts, MD5 for evidence) enabling clean upserts without duplication.
The QueryRouter classifies user queries without any LLM call using keyword matching and intent patterns:
| Query Type | Primary Index | Example Queries |
|---|---|---|
| Factual | Facts | "What is your email?", "Tell me about your skills" |
| Evidence | Evidence | "Show me the ApplyBots project", "Describe your CV" |
| Timeline | Both | "Walk me through your career path", "Overview of all projects" |
| Default | Facts | General queries without strong intent signals |
The router scores each category via regex pattern lists and selects primary + secondary indices. If the primary index returns insufficient results, the secondary is queried to supplement.
The SelfInfoRetriever combines two search strategies:
- Vector similarity search β cosine similarity via pgvector (
k=4default) - BM25 keyword search β exact keyword matching over the same document collection
Results are merged with vector-first ordering, deduplicated by stable_id, and post-filtered by doc_type and tags metadata. If filtering reduces results below k, an expanded search is triggered.
The SelfInfoRAG module generates answers with strict grounding rules:
- Temperature hard-locked to 0 (defence-in-depth)
- Uses ONLY retrieved context β never invents facts
- If context is insufficient β explicit refusal: "I don't have that information in my self_info knowledge base."
- Returns structured output:
answer,key_facts,sources,route
flowchart TD
subgraph "Data Sources"
JSON["self_info.json"]
README_FILES["GitHub READMEs"]
CV["CV / .docx"]
CSV["LinkedIn CSVs"]
end
subgraph "Loaders"
SIL["SelfInfoLoader + Pydantic"]
EL["EvidenceLoader MD/DOCX/CSV/PDF"]
end
subgraph "Dual-Index Vector Store"
FACTS_IDX[("pgvector Facts")]
EVIDENCE_IDX[("pgvector Evidence")]
end
subgraph "Query Processing"
QR["QueryRouter β No LLM"]
RET["Hybrid: Vector + BM25"]
RAG["Grounded RAG Chain β temp=0"]
end
JSON --> SIL --> FACTS_IDX
README_FILES & CV & CSV --> EL --> EVIDENCE_IDX
QR --> RET --> FACTS_IDX & EVIDENCE_IDX
RET --> RAG --> OUTPUT["answer, key_facts, sources, route"]
- Dual-layer lookup:
- Hash-based: MD5 hash for exact text match (O(1) lookup via SQLite)
- Semantic search: Cosine similarity β₯ 85% threshold via pgvector
- Storage: Supabase
reply_cachetable + pgvectordocuments_reply_cachevector embeddings - Deterministic IDs:
MD5(user_text)used for both DB and vectorstable_idto enable clean upserts - Audio file reuse: Cached audio files stored in Supabase Storage and referenced by path
flowchart TD
INPUT["User Query"] --> L1
subgraph "Level 1 β In-Memory LRU"
L1{"In-Memory Dict (max 1000)"}
L1 -->|Hit| L1_HIT["Instant Return ~0ms"]
L1 -->|Miss| L2
end
subgraph "Level 2 β Reply Cache"
L2{"MD5 Hash Lookup (SQLite)"}
L2 -->|Exact Match| L2_HIT["Cached Response + Audio"]
L2 -->|Miss| L3
L3{"Semantic Search (pgvector β₯95%)"}
L3 -->|Hit| L3_HIT["Similar Response + Audio"]
L3 -->|Miss| KB
end
subgraph "Level 3 β Knowledge Base RAG"
KB["Query Router β Hybrid Search β LLM"]
end
subgraph "Level 4 β TTS Audio Cache"
KB --> TTS_CHECK{"Audio Cached?"}
TTS_CHECK -->|Hit| TTS_HIT["Load from Disk"]
TTS_CHECK -->|Miss| TTS_GEN["Edge-TTS Synthesis β Store"]
end
L1_HIT & L2_HIT & L3_HIT & TTS_HIT & TTS_GEN --> RESPOND["π Response"]
sequenceDiagram
participant User
participant STT
participant RAG_Engine
participant VectorDB
participant KnowledgeBase
participant LLM
participant TTS
User->>STT: π€ Voice Input
STT->>RAG_Engine: Processed Text
RAG_Engine->>VectorDB: Semantic Search
VectorDB-->>RAG_Engine: Similar Responses
alt Cache Hit (β₯95% similarity)
RAG_Engine->>TTS: Cached Audio
TTS->>User: π΅ Instant Response
else No Cache
RAG_Engine->>KnowledgeBase: Search Self-Info
KnowledgeBase-->>RAG_Engine: Relevant Knowledge
alt Knowledge Found
RAG_Engine->>LLM: RAG Chain Query
LLM->>LLM: Context + Knowledge Processing
LLM->>RAG_Engine: Grounded Response
else No Knowledge
RAG_Engine->>LLM: Direct Generation
LLM->>RAG_Engine: Generated Response
end
RAG_Engine->>TTS: New Response Text
TTS->>TTS: Text β Audio
TTS->>User: π΅ Synthesized Response
RAG_Engine->>VectorDB: Store New Interaction
end
sequenceDiagram
participant User
participant STT_Agent
participant RAG_Agent
participant Search_Agent
participant Knowledge_Agent
participant Reasoning_Agent
participant TTS_Agent
participant Memory_Layer
User->>STT_Agent: π€ Voice Input
STT_Agent->>STT_Agent: Audio β Text
STT_Agent->>RAG_Agent: Processed Text
RAG_Agent->>Search_Agent: Initiate Semantic Search
Search_Agent->>Memory_Layer: Vector Database Query
Memory_Layer-->>Search_Agent: Similar Responses
alt Cache Hit
Search_Agent->>TTS_Agent: Retrieve Cached Audio
TTS_Agent->>User: π΅ Instant Response
else No Cache
Search_Agent->>Knowledge_Agent: Search Self-Info
Knowledge_Agent->>Memory_Layer: Knowledge Base Query
Memory_Layer-->>Knowledge_Agent: Relevant Knowledge
alt Knowledge Available
Knowledge_Agent->>Reasoning_Agent: RAG Chain Processing
Reasoning_Agent->>Reasoning_Agent: Context + Knowledge Assembly
Reasoning_Agent->>Reasoning_Agent: LLM Reasoning
Reasoning_Agent->>TTS_Agent: Generated Response
else No Knowledge
Knowledge_Agent->>Reasoning_Agent: Direct LLM Generation
Reasoning_Agent->>TTS_Agent: Generated Response
end
TTS_Agent->>TTS_Agent: Text β Audio
TTS_Agent->>User: π΅ Synthesized Response
RAG_Agent->>Memory_Layer: Store New Interaction
end
EchoAI employs several well-known software design patterns to achieve modularity, resilience, and performance.
π Standalone diagram:
docs/diagrams/design_patterns.mmd
| Pattern | Implementation | Purpose |
|---|---|---|
| Pipeline | VoicePipeline |
Chains STT β RAG β LLM β TTS as sequential stages; each stage is independently replaceable |
| Strategy | STTService, LLMService |
Runtime selection between primary (Faster-Whisper / DeepSeek) and fallback (OpenAI Whisper / Mistral) providers β swap without changing callers |
| Repository | DBOperations, SelfInfoVectorStore |
Abstracts storage behind a uniform interface (Supabase PostgreSQL + pgvector) |
| Facade | SelfInfoRAG |
Exposes a single query() entrypoint that internally orchestrates QueryRouter, SelfInfoRetriever, SelfInfoVectorStore, and EvidenceLoader |
| Observer | ConnectionManager |
Manages N WebSocket connections; broadcasts events and handles per-session lifecycle |
| Cache-Aside | ReplyCacheManager, TTSService |
Four-level cache hierarchy (In-Memory LRU β MD5 Hash β Semantic β TTS Disk) each checked before computation |
| Chain of Responsibility | QueryRouter |
Classifies queries into factual, evidence, timeline, or default routes β each handler tries its index before forwarding |
| Template Method | EchoAIError hierarchy |
Base exception defines the contract; STTError, LLMError, TTSError, etc. specialise the error type |
flowchart LR
subgraph "Pipeline Pattern"
PP1["VoicePipeline"]
PP2["STT β RAG β LLM β TTS"]
PP1 --> PP2
end
subgraph "Strategy Pattern"
SP1["STT Strategy"]
SP2["Faster-Whisper"]
SP3["OpenAI Whisper"]
SP4["LLM Strategy"]
SP5["DeepSeek AI"]
SP6["Mistral AI"]
SP1 --> SP2 & SP3
SP4 --> SP5 & SP6
end
subgraph "Facade Pattern"
FP1["SelfInfoRAG"]
FP2["QueryRouter"]
FP3["SelfInfoRetriever"]
FP4["SelfInfoVectorStore"]
FP5["EvidenceLoader"]
FP1 --> FP2 & FP3 & FP4 & FP5
end
subgraph "Cache-Aside Pattern"
CP1["L1: In-Memory LRU"]
CP2["L2: MD5 Hash β SQLite"]
CP3["L3: Semantic β pgvector"]
CP4["L4: TTS Audio Disk"]
CP1 --> CP2 --> CP3 --> CP4
end
subgraph "Chain of Responsibility"
CR1["QueryRouter"]
CR2["Factual β Facts Index"]
CR3["Evidence β Evidence Index"]
CR4["Timeline β Both Indices"]
CR1 --> CR2 & CR3 & CR4
end
The frontend is a Next.js 16 application using the App Router, React 19, TypeScript 5, and Tailwind CSS 4. All real-time communication flows through a custom useChat hook that manages WebSocket lifecycle, message state, and audio recording/playback.
π Standalone diagram:
docs/diagrams/frontend_architecture.mmd
flowchart TD
subgraph "Next.js App Router"
LAYOUT["layout.tsx β RootLayout"]
SHELL["LayoutShell β Header + Footer wrapper"]
HOME_PAGE["page.tsx β Landing Page"]
CHAT_PAGE["chat/page.tsx β Chat Page"]
ERROR["error.tsx β Error Boundary"]
end
subgraph "Landing Page Components"
HERO["HeroSection β CTA + Animated text"]
FEATURES["FeaturesSection β Feature cards grid"]
STATS["StatsBar β Live statistics counters"]
NEURAL["NeuralBackground β Canvas particle animation"]
AIVIZ["AIVisualization β 3D-style AI visual"]
end
subgraph "Chat Components"
CONTAINER["ChatContainer β Main chat orchestrator"]
INPUT["ChatInput β Text + voice input bar"]
BUBBLE["MessageBubble β User/AI message display"]
TYPING["TypingIndicator β AI thinking animation"]
end
subgraph "Shared Layout"
HEADER["Header β Navigation + branding"]
FOOTER["Footer β Links + credits"]
end
subgraph "Data Layer"
HOOK["useChat Hook β WebSocket + state management"]
API_LIB["lib/api.ts β API base URL config"]
TYPES["lib/types.ts β TypeScript interfaces"]
end
subgraph "Backend Connection"
WS["WebSocket ws://host:8000/ws/{sessionId}"]
REST["REST API http://host:8000/api/*"]
end
LAYOUT --> SHELL
SHELL --> HEADER & FOOTER
LAYOUT --> HOME_PAGE & CHAT_PAGE & ERROR
HOME_PAGE --> HERO & FEATURES & STATS
HOME_PAGE --> NEURAL & AIVIZ
CHAT_PAGE --> CONTAINER
CONTAINER --> INPUT & BUBBLE & TYPING
CONTAINER --> HOOK
HOOK --> WS
HOOK --> API_LIB
HOOK --> TYPES
API_LIB --> REST
| Layer | Technology | Details |
|---|---|---|
| Framework | Next.js 16.1.6 | App Router with server/client components |
| Rendering | React 19.2.3 | Concurrent features, server components |
| Language | TypeScript 5 | Full type safety across components |
| Styling | Tailwind CSS 4 | Utility-first with glassmorphism effects |
| State | useChat custom hook |
WebSocket, messages, audio, voice toggle |
| Build | PostCSS + SWC | Lightning-fast compilation |
| Linting | ESLint 9 (flat config) | eslint-config-next rule set |
All service, agent, and pipeline code raises typed exceptions from a single hierarchy rooted in EchoAIError. Callers catch specific subtypes to implement fallback behaviour.
π Standalone diagram:
docs/diagrams/exception_hierarchy.mmd
classDiagram
class EchoAIError {
<<Base Exception>>
Base exception for all EchoAI errors
}
class STTError {
Speech-to-Text processing failure
}
class LLMError {
Language-model generation failure
}
class TTSError {
Text-to-Speech synthesis failure
}
class RAGError {
RAG retrieval or agent failure
}
class PipelineError {
Voice-pipeline orchestration failure
}
class DatabaseError {
Database operation failure
}
class AudioProcessingError {
Audio conversion / processing failure
}
EchoAIError <|-- STTError
EchoAIError <|-- LLMError
EchoAIError <|-- TTSError
EchoAIError <|-- RAGError
EchoAIError <|-- PipelineError
EchoAIError <|-- DatabaseError
EchoAIError <|-- AudioProcessingError
Visual diagram of the full WebSocket message lifecycle β connection, audio modes, text chat, and keep-alive.
π Standalone diagram:
docs/diagrams/websocket_protocol.mmd
sequenceDiagram
participant Client as Web Client
participant WS as WebSocket Server
participant CM as ConnectionManager
participant VP as VoicePipeline
participant RAG as RAG Agent
Note over Client,RAG: Connection Lifecycle
Client->>WS: Connect ws://host:8000/ws/{session_id}
WS->>CM: connect(websocket, session_id)
CM-->>Client: {"type": "connection", "status": "connected"}
Note over Client,RAG: Complete Audio Mode
Client->>WS: {"type": "audio", "data": "base64..."}
WS->>VP: process_voice_input(audio_data)
VP->>VP: STT β Text
VP->>RAG: process_query(text)
RAG-->>VP: response + audio
VP-->>WS: PipelineResult
WS-->>Client: {"type": "response", "audio": "base64...", "text": "..."}
Note over Client,RAG: Streaming Audio Mode
Client->>WS: {"type": "start_streaming"}
WS->>CM: set_streaming_status(true)
WS-->>Client: {"type": "streaming_started"}
loop Audio Chunks
Client->>WS: {"type": "audio_chunk", "data": "base64..."}
WS->>CM: add_audio_chunk(session_id, chunk)
WS-->>Client: {"type": "chunk_received"}
end
Client->>WS: {"type": "stop_streaming"}
WS->>CM: get_audio_buffer(session_id)
WS->>VP: process_streaming_voice(chunks)
VP-->>WS: PipelineResult
WS-->>Client: {"type": "response", "audio": "base64...", "text": "..."}
Note over Client,RAG: Text Chat Mode
Client->>WS: {"type": "text", "text": "Hello"}
WS->>VP: process_text_input(text)
VP->>RAG: process_query(text)
RAG-->>VP: response + audio
VP-->>WS: PipelineResult
WS-->>Client: {"type": "response", "audio": "base64...", "text": "..."}
Note over Client,RAG: Keep-Alive
Client->>WS: {"type": "ping"}
WS-->>Client: {"type": "pong"}
| Category | Technology | Purpose |
|---|---|---|
| Frontend Framework | Next.js 16.1.6 (App Router) | React-based SSR/SSG framework |
| UI Library | React 19.2.3 + React DOM | Component-based UI rendering |
| Language (Frontend) | TypeScript 5 | Static typing for frontend code |
| Styling | Tailwind CSS 4 | Utility-first CSS framework |
| Web Framework | FastAPI 0.104+ | REST API + WebSocket server |
| Primary LLM | DeepSeek AI (deepseek-chat) |
Main language model for response generation |
| Fallback LLM | Mistral AI (mistral-large-latest) |
Fallback language model |
| RAG Framework | LangChain 0.3+ | RAG pipeline, chains, and retrieval |
| Vector Database | Supabase pgvector | Semantic vector storage and similarity search |
| Embeddings | all-MiniLM-L6-v2 (384-dim, via transformers) |
Text embedding generation |
| STT (Primary) | Faster-Whisper (small model) |
Local speech-to-text |
| STT (Fallback) | OpenAI Whisper API | Cloud STT fallback |
| TTS | Edge-TTS (Microsoft Neural Voices) | Free text-to-speech synthesis |
| Cloud Database | Supabase PostgreSQL (asyncpg) |
Persistent storage + vector search |
| ML Framework | PyTorch + Transformers | Model loading and inference |
| Audio Processing | soundfile, imageio-ffmpeg, av | Audio I/O, format conversion |
| Config | Pydantic Settings + python-dotenv | Typed settings from .env |
| HTTP | aiohttp, httpx | Async HTTP client calls |
| Linting | ESLint 9 + eslint-config-next | Frontend code quality |
| Containerization | Docker | Production deployment |
EchoAI/
βββ readme.md # This file
βββ requirements.txt # Python dependencies
βββ Dockerfile # Docker image (Python 3.11-slim)
βββ env.example # Environment variable template
βββ run_dev.py # Development startup script
β
βββ backend/ # Backend source code root
β βββ __init__.py # Package init (version, author)
β βββ constants.py # Enums & numeric thresholds
β βββ exceptions.py # Typed exception hierarchy
β β
β βββ api/ # API layer
β β βββ __init__.py
β β βββ main.py # FastAPI app, WebSocket endpoints, REST routes
β β βββ connection_manager.py # WebSocket session & buffer management
β β
β βββ services/ # Service layer
β β βββ __init__.py
β β βββ voice_pipeline.py # Orchestrates STT β RAG β TTS flow
β β βββ stt_service.py # Speech-to-Text (Whisper + OpenAI)
β β βββ llm_service.py # LLM (DeepSeek + Mistral fallback)
β β βββ tts_service.py # Text-to-Speech (Edge-TTS + caching)
β β
β βββ agents/ # Agent layer
β β βββ __init__.py
β β βββ langchain_rag_agent.py # LangChain RAG agent, reply cache manager
β β βββ query_expansions.py # Query expansion synonym lists
β β
β βββ knowledge/ # β Self-Info RAG knowledge layer
β β βββ __init__.py
β β βββ query_router.py # Deterministic query router (no LLM)
β β βββ self_info_rag.py # Grounded RAG answer chain (temp=0)
β β βββ self_info_retriever.py # Hybrid retriever (vector + BM25)
β β βββ self_info_vectorstore.py # Dual-index pgvector store manager
β β βββ self_info_loader.py # JSON loader with Pydantic validation
β β βββ self_info_schema.py # Pydantic v2 schema for Q&A records
β β βββ self_info_documents.py # SelfInfoItem β LangChain Document
β β βββ evidence_loader.py # Multi-format evidence loader (MD/DOCX/CSV/PDF)
β β
β βββ db/ # Data layer
β β βββ __init__.py
β β βββ db_operations.py # Supabase PostgreSQL + Storage operations
β β
β βββ documents/ # Knowledge source data
β β βββ self_info.json # Personal/professional knowledge base (~90KB)
β β
β βββ tools/ # CLI utilities
β β βββ self_info_cli.py # Build index & ask questions via CLI
β β
β βββ utils/ # Utility modules
β βββ __init__.py
β βββ config.py # Pydantic Settings (env vars)
β βββ logging.py # Structured logging + decorators
β βββ performance_monitor.py # Component-level perf metrics
β βββ audio/ # Audio processing utilities
β βββ __init__.py
β βββ audio_processor.py # Decode, normalize, convert audio
β βββ audio_stream_processor.py # Real-time stream processing
β βββ audio_utils.py # Shared audio helpers
β
βββ frontend/ # π Next.js 16 Web Client
β βββ package.json # Dependencies (Next 16, React 19, Tailwind 4)
β βββ tsconfig.json # TypeScript configuration
β βββ next.config.ts # Next.js configuration
β βββ postcss.config.mjs # PostCSS + Tailwind CSS config
β βββ eslint.config.mjs # ESLint 9 flat config
β β
β βββ app/ # Next.js App Router pages
β β βββ layout.tsx # Root layout (HTML, fonts, metadata)
β β βββ page.tsx # Landing page (/)
β β βββ globals.css # Global styles & Tailwind directives
β β βββ error.tsx # Error boundary component
β β βββ chat/
β β βββ page.tsx # Chat page (/chat)
β β
β βββ components/ # React components
β β βββ chat/ # Chat UI components
β β β βββ ChatContainer.tsx # Main chat orchestrator
β β β βββ ChatInput.tsx # Text & voice input bar
β β β βββ MessageBubble.tsx # User/AI message display
β β β βββ TypingIndicator.tsx # AI thinking animation
β β βββ home/ # Landing page components
β β β βββ HeroSection.tsx # CTA + animated headline
β β β βββ FeaturesSection.tsx # Feature cards grid
β β β βββ StatsBar.tsx # Live statistics counters
β β β βββ AIVisualization.tsx # 3D-style AI visual
β β β βββ NeuralBackground.tsx # Canvas particle animation
β β βββ layout/ # Shared layout components
β β βββ Header.tsx # Navigation + branding
β β βββ Footer.tsx # Links + credits
β β βββ LayoutShell.tsx # Header + Footer wrapper
β β
β βββ hooks/ # Custom React hooks
β β βββ useChat.ts # WebSocket + chat state management
β β
β βββ lib/ # Shared utilities
β β βββ api.ts # API base URL configuration
β β βββ types.ts # TypeScript interfaces
β β
β βββ public/ # Static assets
β
βββ backend/tests/ # Unit & smoke tests
β βββ test_self_info_loader.py # SelfInfoLoader validation tests
β βββ test_self_info_retriever.py # Hybrid retriever tests
β βββ test_self_info_rag_smoke.py # End-to-end RAG smoke test
β
βββ docs/diagrams/ # Standalone Mermaid diagrams (.mmd)
β βββ system_architecture.mmd # Full system architecture
β βββ service_layer.mmd # Service + knowledge layer
β βββ data_flow.mmd # End-to-end data flow
β βββ rag_pipeline.mmd # RAG pipeline sequence
β βββ knowledge_layer.mmd # Knowledge layer deep dive
β βββ agent_collaboration.mmd # Agent collaboration workflow
β βββ websocket_protocol.mmd # WebSocket message protocol
β βββ caching_strategy.mmd # Multi-level caching strategy
β βββ exception_hierarchy.mmd # Exception class hierarchy
β βββ frontend_architecture.mmd # Next.js component hierarchy
β βββ design_patterns.mmd # Design patterns overview
β
βββ audio_cache/ # Cached TTS audio files (*.mp3)
β
βββ rag_persona_db/ # RAG evidence documents
βββ document/
βββ ApplyBots_README.md # ApplyBots project documentation
βββ Galileo_README.md # Galileo project documentation
βββ ShotGraph_README.md # ShotGraph project documentation
βββ masx-forecasting_README.md # MASX Forecasting documentation
βββ masx-geosignal_README.md # MASX GeoSignal documentation
βββ masx-hotspots_README.md # MASX Hotspots documentation
βββ medAI_README.md # MedAI project documentation
User speaks β Audio capture β STT processing β Text extraction
- Real-time audio streaming via WebSocket (
ws://host:8000/ws/{session_id}) - Three input modes: complete audio (
audio), streaming chunks (audio_chunk), and real-time buffer (streaming_buffer) - Faster-Whisper (local
smallmodel) with automatic OpenAI Whisper API fallback - Audio normalization with configurable target RMS (0.1) and max gain (10x)
- Tail-padding (10ms) for clean chunk boundaries
Text query β Vector embedding β Cache lookup β Knowledge retrieval β Context assembly
- Step 1 β Reply Cache: Check for exact hash match or semantic similarity β₯ 95% in pgvector
- Step 2 β Self-Info Search: Query the pgvector
documents_self_info_factstable for relevant knowledge (top-5 docs) - Step 3 β Context Assembly: Combine retrieved documents + conversation history into the prompt
- Multi-level caching hierarchy: in-memory dict β Supabase reply cache β pgvector semantic store
Context + query β LangChain RAG Chain β LLM reasoning β Response text
- LangChain
RetrievalQAchain withstuffstrategy for knowledge-grounded responses - DeepSeek AI as primary LLM with Mistral AI automatic fallback
- Custom persona prompt for consistent personality in voice responses
- Response cleaning: max 1000 chars, stripped markdown artifacts
- Conversation history maintained (last 10 turns) for multi-turn context
Generated text β TTS β Audio streaming β Client playback β Cache storage
- Edge-TTS with configurable Microsoft neural voice (default:
en-IN-PrabhatNeural) - Streaming chunk synthesis for low-latency first-byte delivery
- Sentence-level splitting for chunked synthesis
- Persistent audio cache with SQLite metadata and file-based storage
- In-memory LRU cache (max 1000 entries) with auto-eviction
- Python 3.9+
- Docker & Docker Compose (optional, for containerized deployment)
- API keys for: DeepSeek AI, OpenAI, Mistral AI
- (Optional) Supabase project for cloud database
# Clone the repository
git clone https://github.com/AteetVatan/echo-ai.git
cd echo-ai
# Copy environment configuration
cp env.example .env
# Edit .env with your API keys
nano .env # or use your preferred editor
# Build and run
docker build -t echoai .
docker run -p 8000:8000 --env-file .env echoai# Clone the repository
git clone https://github.com/AteetVatan/echo-ai.git
cd echo-ai
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install dependencies
pip install -r backend/requirements.txt
# Set up environment variables
cp env.example .env
# Edit .env with your actual API keys# .env file β Required keys
DEEPSEEK_API_KEY=sk-... # Primary LLM
OPENAI_API_KEY=sk-... # STT fallback
MISTRAL_API_KEY=... # Fallback LLM
# Model Configuration
DEEPSEEK_MODEL=deepseek-chat
DEEPSEEK_API_BASE=https://api.deepseek.com
MISTRAL_MODEL=mistral-large-latest
MISTRAL_API_BASE=https://api.mistral.ai
OPENAI_MODEL=gpt-4o-mini
# Edge-TTS Configuration
EDGE_TTS_VOICE=en-IN-PrabhatNeural # Free Microsoft neural voice
# Latency Tuning
STT_CHUNK_DURATION=2.0 # seconds
LLM_TEMPERATURE=0.0 # deterministic responses
TTS_STREAMING=True
TTS_CACHE_ENABLED=True
# Database (Supabase β optional)
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_ANON_KEY=xxx
SUPABASE_SERVICE_ROLE_KEY=xxx
SUPABASE_DB_PASSWORD=xxx
SUPABASE_DB_URL=postgresql://...
# Server
HOST=0.0.0.0
PORT=8000
LOG_LEVEL=INFO
DEBUG=False
# Audio
SAMPLE_RATE=16000
CHANNELS=1
AUDIO_FORMAT=wav
STT_TIMEOUT=5.0
LLM_TIMEOUT=10.0
TTS_TIMEOUT=8.0# Recommended: starts FastAPI and the Next.js frontend together
python backend/run_dev.py
# Or manually, in two terminals
uvicorn backend.api.main:app --host 0.0.0.0 --port 8000 --reload
cd frontend && npm run dev -- -H 0.0.0.0 -p 3000Development URLs:
| URL | Purpose |
|---|---|
http://localhost:8000 |
Backend API root |
http://localhost:3000 |
Next.js web client UI |
http://localhost:8000/frontend |
Legacy dev redirect to the web client |
http://localhost:8000/docs |
Swagger API documentation |
ws://localhost:8000/ws/{session_id} |
WebSocket voice chat |
# With Docker
docker build -t echoai .
docker run -d -p 8000:8000 --env-file .env --name echoai echoai
# Or with Gunicorn
gunicorn backend.api.main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000# ββ Self-Info RAG CLI ββββββββββββββββββββββββββββββββββββββββββββββ
# Build (or rebuild) the dual-index vector store
python -m backend.tools.self_info_cli build
python -m backend.tools.self_info_cli build --rebuild
# Ask questions via grounded RAG chain
python -m backend.tools.self_info_cli ask "What is your email address?"
python -m backend.tools.self_info_cli ask "Tell me about ApplyBots" --index evidence
python -m backend.tools.self_info_cli ask "What are your skills?" --doc-type about_me --tag hr
# ββ Unit & Smoke Tests ββββββββββββββββββββββββββββββββββββββββββββ
python -m pytest backend/tests/ -v
python -m pytest backend/tests/test_self_info_loader.py -v # Pydantic validation
python -m pytest backend/tests/test_self_info_retriever.py -v # Hybrid retriever
python -m pytest backend/tests/test_self_info_rag_smoke.py -v # End-to-end RAG
# ββ Service Smoke Tests βββββββββββββββββββββββββββββββββββββββββββ
# Test RAG agent
python -c "from backend.agents.langchain_rag_agent import rag_agent; print('RAG Agent loaded successfully')"
# Test TTS service
python -m backend.services.tts_service
# Test STT service
python -m backend.services.stt_service| Method | Path | Description |
|---|---|---|
GET |
/ |
Root β API info and version |
GET |
/frontend |
Redirect to the Next.js dev client when DEBUG=True |
GET |
/health |
Health check with service status |
GET |
/stats |
System performance statistics |
POST |
/clear |
Clear conversation history |
Endpoint: ws://host:8000/ws/{session_id}
Client β Server Messages:
| Type | Description |
|---|---|
audio |
Complete audio message (base64-encoded) |
audio_chunk |
Streaming audio chunk |
start_streaming |
Begin streaming session |
stop_streaming |
End streaming, trigger processing |
streaming_buffer |
Real-time audio buffer |
text |
Text message (bypasses STT) |
ping |
Keep-alive ping |
Server β Client Messages:
| Type | Description |
|---|---|
connection |
Connection established confirmation |
processing |
Processing stage notifications |
response |
Full audio + text response |
text_response |
Text-only response |
streaming_response |
Streaming partial response |
streaming_started |
Streaming session started |
streaming_stopped |
Streaming session ended |
chunk_received |
Audio chunk acknowledgment |
error |
Error notification |
pong |
Keep-alive pong |
User Input: "What did we discuss about machine learning yesterday?"
RAG Process:
- Semantic Search: Vector similarity search in reply cache
- Knowledge Retrieval: Found relevant ML discussion context in self-info
- Response Generation: LLM generates grounded response using retrieved knowledge
AI Response: "Yesterday we discussed the differences between supervised and unsupervised learning, specifically focusing on clustering algorithms..."
User Input: "Tell me about your experience with AI engineering"
RAG Process:
- Self-Info Search: Query pgvector
documents_self_info_factstable - Context Assembly: Combine career data, project history, and skills
- Personalized Response: Generate response in Ateet's authentic voice using persona prompt
User: "What's your approach to system architecture?"
AI: "I believe in clean, modular, and scalable architecture. I always start
with clear requirements..."
User: "Can you give me a specific example from your experience?"
AI: "Absolutely! In my previous role, I designed a microservices architecture
for an AI platform..."
Conversation history is maintained server-side (up to 10 turns), so follow-up questions retain full context.
Send a text type message over WebSocket (or use the frontend text input) to bypass STT entirely. The query goes directly through RAG β LLM β TTS.
| Constant | Value | Description |
|---|---|---|
SEMANTIC_CACHE_SIMILARITY_THRESHOLD |
0.95 | Minimum similarity for semantic cache hit |
REPLY_CACHE_SIMILARITY_THRESHOLD |
0.85 | Minimum similarity for reply cache match |
IN_MEMORY_CACHE_MAX_SIZE |
1000 | Max entries in in-memory TTS cache |
IN_MEMORY_CACHE_EVICT_COUNT |
100 | Entries evicted when cache is full |
MAX_CONVERSATION_HISTORY |
10 | Max conversation turns to retain |
LLM_RESPONSE_MAX_LENGTH |
1000 | Max characters in LLM response |
RAG_RETRIEVER_TOP_K |
5 | Top-K documents retrieved from knowledge base |
TEXT_SPLITTER_CHUNK_SIZE |
500 | Characters per text chunk for indexing |
TEXT_SPLITTER_CHUNK_OVERLAP |
50 | Character overlap between chunks |
AUDIO_CHUNK_MAX_BYTES |
1 MB | Max size per audio chunk |
AUDIO_BUFFER_MAX_BYTES |
10 MB | Max total audio buffer per session |
| Enum | Values | Purpose |
|---|---|---|
WSMessageType |
audio, audio_chunk, start_streaming, stop_streaming, text, ping, pong, streaming_buffer, connection, processing, response, text_response, streaming_response, etc. |
WebSocket message types |
PipelineSource |
cache, rag_self_info, llm_fallback, llm_direct, error_fallback, error, pipeline, agent |
Response source tracking |
ModelName |
deepseek_ai, mistral_ai, openai_gpt4o_mini, edge_tts, faster_whisper_small, openai_whisper, langchain_rag_agent, etc. |
Model identifiers |
ChatRole |
user, assistant, system |
Conversation roles |
KnowledgeType |
self_info, reply_cache, cv_profile |
Knowledge category tags |
PgvectorTable |
documents_reply_cache, documents_self_info_facts, documents_self_info_evidence |
pgvector table names |
| Metric | Target |
|---|---|
| Vector Search Latency | < 50ms |
| Knowledge Retrieval | < 100ms |
| Cache Hit Rate | 85%+ for similar queries |
| Semantic Matching Threshold | 0.85+ |
| Metric | Target |
|---|---|
| STT Processing | < 200ms |
| LLM Response | < 2s |
| TTS Generation | < 1s |
| End-to-End Latency | < 4s |
| Metric | Capacity |
|---|---|
| Concurrent Users | 100+ WebSocket connections |
| Knowledge Base | 1M+ vector entries |
| In-Memory Cache | 1000 entries (LRU eviction) |
| Memory per Session | < 2GB |
Vector Search Not Working
# Verify pgvector connection
python -c "from backend.knowledge.self_info_vectorstore import _get_supabase_client; print(_get_supabase_client())"
# Verify embeddings model
python -c "from backend.knowledge.self_info_vectorstore import _get_embeddings; e = _get_embeddings(); print(len(e.embed_query('test')))"Knowledge Base Empty
# Check self_info.json exists and is valid
python -c "import json; json.load(open('backend/documents/self_info.json'))"
# Verify knowledge base initialization
python -c "from backend.agents.langchain_rag_agent import rag_agent; print('KB:', rag_agent.self_info_knowledge_base)"Cache Not Working
# Check Supabase reply cache
python -c "from backend.db.db_operations import DBOperations; import asyncio; db = DBOperations(); asyncio.run(db.initialize()); print('DB OK')"Audio Not Playing
# Verify TTS service
curl -X GET "http://localhost:8000/health"
# Test Edge-TTS directly
python -c "import asyncio; import edge_tts; asyncio.run(edge_tts.Communicate('Hello', 'en-IN-PrabhatNeural').save('test.mp3'))"WebSocket Connection Failed
# Check if server is running
curl http://localhost:8000/
# Test WebSocket endpoint
wscat -c ws://localhost:8000/ws/test-sessionDeepSeek API Failures
- Verify
DEEPSEEK_API_KEYin.env - The system will automatically fall back to Mistral AI
- Check logs for fallback messages
Mistral Fallback Also Failing
- Verify
MISTRAL_API_KEYin.env - Check
MISTRAL_API_BASEURL - Review error logs:
python -c "from backend.services.llm_service import llm_service; print(llm_service.get_performance_stats())"
- Multi-modal RAG (text + audio + visual)
- Dynamic knowledge base updates via API
- Cross-conversation knowledge linking
- Advanced similarity algorithms (hybrid BM25 + vector)
- Multi-agent reasoning chains
- External knowledge integration (web search, APIs)
- Autonomous task execution
- Learning from user feedback
- Distributed vector database
- Multi-tenant knowledge bases
- Edge computing support
- Offline mode capabilities
We welcome contributions! See the GitHub repository for open issues.
# Fork and clone
git clone https://github.com/AteetVatan/echo-ai.git
cd echo-ai
# Create feature branch
git checkout -b feature/amazing-feature
# Install dependencies
pip install -r backend/requirements.txt
# Make changes and commit
git add .
git commit -m "Add amazing feature"
# Push and create PR
git push origin feature/amazing-feature- Follow PEP 8 for Python code
- Use type hints for all function parameters
- Write docstrings for all public functions
- Use typed exceptions from
backend/exceptions.py - Use constants/enums from
backend/constants.py(no magic strings) - Follow conventional commits for commit messages
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests and documentation
- Ensure all tests pass
- Submit a pull request with clear description
- API Docs (Swagger) β Interactive API documentation (available when server is running)
- GitHub Repository β Source code, issues, and discussions
This project is licensed under the MIT License β see the LICENSE file for details.
- DeepSeek AI for primary LLM capabilities
- Microsoft Edge-TTS for free neural voice synthesis
- LangChain for RAG framework and retrieval chains
- Supabase for PostgreSQL cloud database and pgvector
- Mistral AI for fallback LLM capabilities
- OpenAI for Whisper STT and GPT models
- FastAPI for the excellent async web framework
- Hugging Face for Transformers and embedding models
- Open Source Community for inspiration and contributions
- GitHub Issues: Report bugs and request features
- GitHub Discussions: Join community conversations
- Repository: https://github.com/AteetVatan/echo-ai
Made by Ateet
Empowering the future of human-AI interaction through RAG-powered autonomous voice intelligence.