Interviu — AI Mock Interview Platform
Full-stack platform for AI-powered mock interviews with live voice-to-voice conversations, real-time audio streaming, and AI-generated feedback.
Project Links
Technology Stack
Elevator Pitch
Interviu is an end-to-end, voice-first mock interview platform designed to simulate realistic technical, system design, and behavioral interviews. Instead of relying on turn-based text prompts, Interviu establishes a bidirectional, low-latency WebSockets connection to stream audio in real-time, matching the natural cadence of a human conversation.
🛠️ The Challenge
- —**Real-Time Audio Latency**: Standard REST calls or chat completion models have high time-to-first-token (TTFT) latency, which ruins the conversational pacing of a real interview.
- —**Monaco Editor Sync**: Injecting Monaco Editor updates on every keystroke without overloading the model's token window or causing context confusion.
- —**Connection Resiliency**: Handling network flickers and dropped WebSocket connections mid-interview without losing the user's progress.
- —**Analytical Evaluation**: Providing objective, bias-free grading of the candidate's performance across communication, code quality, and problem-solving.
🏗️ Architectural Core
Real-Time VOIP & Dual-Model Pipeline
The Session Lifecycle
- •**Initialization**: The user selects their interview type (Technical/Coding, System Design, or Behavioral) and duration. The server initializes metadata, reads their resume text, and constructs a customized system prompt (~1,000 lines).
- •**Real-time Session**: The client connects to the backend over a custom WebSocket protocol, which in turn establishes a persistent connection to the Gemini Live API. Audio packages are sent continuously.
- •**Editor Synchronization**: If it's a coding round, code editor updates are captured on the client, sent to the server, and injected into the AI's prompt stream asynchronously as background updates (`[EDITOR_UPDATE]`).
- •**Graceful Disconnects**: If a client drops, the session state, interview progress, and transcript are safely held in Redis. The user can resume within a grace period.
- •**Evaluation**: When the interview finishes, the transcript is flushed to PostgreSQL, and a background worker triggers Claude to parse the transcript and compile structured JSON feedback.
🛠️ Technical Challenges & Solutions
Challenge 1: Minimizing Audio Stream Latency (400–500ms Response Times)
Standard REST calls or chat completion models have high time-to-first-token (TTFT) latency, which ruins the conversational pacing of a real interview.
Implemented a raw WebSocket proxy server. The client records user voice snippets in raw PCM format (16kHz sample rate) and streams them down the WebSocket. The server instantly pipes this binary buffer to the Google GenAI Live API connection. By avoiding HTTP overhead and complex audio conversions, the round-trip latency was compressed to 400–500ms.
Challenge 2: Live Monaco Code Editor Sync with AI Prompts
For technical rounds, the interviewer needs to look at the candidate's code real-time to ask relevant questions. However, sending the entire code editor state on every keystroke to the AI is highly resource-intensive and triggers model confusion.
Created an asynchronous update throttle. The client tracks code changes via a Monaco Editor container and debounces updates. The backend formats these updates as a special payload format `[EDITOR_UPDATE]` injected directly into Gemini's live context window silently. The system prompt instructs the AI to read these updates in the background, avoid commenting on partial code, and only address bugs or patterns naturally when the candidate speaks.
Challenge 3: Connection Resiliency & State Persistence
Voice packets are highly prone to network flickers. If a socket disconnects, losing the candidate's interview mid-way is a poor user experience.
Engineered a Redis-based session caching layer. The server caches active session details (including the Gemini token, elapsed time, current transcript arrays, and original prompt structure) with a 1-hour TTL. If a connection drops, a 'Ghost Timer' is started. If the user reconnects within 30 seconds, the server uses the cached session metadata to resume the Gemini session handle instead of spinning up a fresh session from scratch.
Challenge 4: Avoiding Evaluator Bias using Dual-Model Orchestration
Using the same LLM connection for conducting the interview and grading the candidate creates a conflict of interest and often results in shallow evaluations.
Decoupled the feedback pipeline entirely. The Gemini connection focuses solely on pacing, voice generation, and interviewer behavior. When the session terminates, the full compiled JSON transcript is sent to Anthropic's Claude 3.5 Sonnet. Claude parses the transcript against the job description and candidate seniority, producing a highly analytical evaluation containing scores, strengths, focus areas, and next steps.
📊 Key Highlights & Observability
Robust Schema Validation
Designed a custom parser that processes raw AI JSON structures, guaranteeing database schema validation and saving feedback correctly even if LLM outputs include minor syntax inconsistencies.
State Synchronization
Achieved resilient real-time state synchronization, successfully testing simultaneous code typing, voice responses, and network recovery flows.
Scaled Backend DB Load
Used Redis as a write-through buffer for short-term transactional reads during active sessions, saving Postgres resources exclusively for final evaluation records.