diff --git a/README.md b/README.md index 2fb50ae..f1062ef 100644 --- a/README.md +++ b/README.md @@ -30,83 +30,105 @@ - [Contributing](#contributing) - [License](#license) - ## Overview InterXAI is an AI-powered interview automation platform designed to make technical hiring smarter, faster, and more scalable. It simulates real interview experiences by dynamically generating follow-up questions based on candidate responses, evaluating answers in real time using large language models, and maintaining a natural conversational flow throughout the entire interview process. Organizations create fully customized interviews with domain-specific questions and DSA challenges. Candidates apply by submitting their resumes, which are automatically evaluated and scored by an LLM agent against the job requirements - all without manual intervention. To ensure interview integrity, the platform integrates proctoring features including tab-switch detection, page-refresh monitoring, and OpenCV-based malpractice detection. +## Quick Start + +```bash +# Clone repository +git clone https://github.com/your-username/InterXAI.git + +# Backend setup +cd backend +uv sync --dev +uv run alembic upgrade head +uv run uvicorn app.main:app --reload +``` + +## Frontend setup + +```bash +cd frontend +npm install +npm run dev +``` ## Features ### For Organizations + - **Custom Interview Builder** - Create structured interviews with tailored questions, DSA topics, and evaluation criteria - **Automated Resume Screening** - LLM-powered analysis that scores and shortlists candidates automatically - **AI-Driven Evaluations** - Real-time answer evaluation with structured, unbiased scoring - **Candidate Dashboard** - Track all applications, review scores, and access AI-generated feedback reports ### For Candidates + - **Seamless Application Flow** - Upload your resume and let the AI evaluate your fit for the role - **Conversational Interviews** - Experience dynamic, follow-up-rich interviews that adapt to your responses - **Instant Feedback** - Receive structured feedback on your performance after each session - **Multi-Round Sessions** - Navigate through Q&A, DSA, and resume-based rounds in a single interview ### Platform Intelligence + - **Dynamic Question Generation** - LLMs generate context-aware follow-up questions based on candidate answers - **Resume Intelligence** - Extracts, standardizes, and evaluates resume content against job requirements - **Interview Proctoring** - Tab-switch detection, page-refresh monitoring, and OpenCV-based malpractice detection ensure integrity - **Event-Driven Processing** - Asynchronous background jobs via TaskIQ + Redis ensure interviews scale without bottlenecks - ## Tech Stack -| Layer | Technology | -|---|---| -| **Backend API** | FastAPI, Python 3.12+ | -| **Frontend** | React 19, TypeScript, Vite, TailwindCSS 4 | -| **Database** | PostgreSQL via Neon (production) / SQLite (development) | -| **ORM & Migrations** | SQLAlchemy 2.0 (async), Alembic | -| **Background Jobs** | TaskIQ + Redis | -| **AI / LLM** | LangChain, LiteLLM, Groq | -| **File Storage** | Supabase Storage | -| **Auth** | JWT (PyJWT), bcrypt | -| **State Management** | Zustand, React Query | -| **Package Manager** | `uv` (backend), `npm` (frontend) | -| **Containerization** | Docker, Docker Compose | - +| Layer | Technology | +| -------------------- | ------------------------------------------------------- | +| **Backend API** | FastAPI, Python 3.12+ | +| **Frontend** | React 19, TypeScript, Vite, TailwindCSS 4 | +| **Database** | PostgreSQL via Neon (production) / SQLite (development) | +| **ORM & Migrations** | SQLAlchemy 2.0 (async), Alembic | +| **Background Jobs** | TaskIQ + Redis | +| **AI / LLM** | LangChain, LiteLLM, Groq | +| **File Storage** | Supabase Storage | +| **Auth** | JWT (PyJWT), bcrypt | +| **State Management** | Zustand, React Query | +| **Package Manager** | `uv` (backend), `npm` (frontend) | +| **Containerization** | Docker, Docker Compose | ## Architecture ``` + ┌─────────────────────────────────────────────────────────────────┐ -│ Client (React) │ -│ React Query · Zustand · React Hook Form · Zod │ +│ Client (React) │ +│ React Query · Zustand · React Hook Form · Zod │ └───────────────────────────┬─────────────────────────────────────┘ - │ REST / JSON +│ REST / JSON ┌───────────────────────────▼─────────────────────────────────────┐ -│ FastAPI Backend │ -│ /users /organizations /interviews /applications /health │ -│ │ -│ ┌────────────────┐ ┌──────────────────┐ ┌────────────────┐ │ -│ │ Auth (JWT + │ │ Routers / │ │ Exception │ │ -│ │ bcrypt) │ │ Business Logic │ │ Handlers │ │ -│ └────────────────┘ └────────┬─────────┘ └────────────────┘ │ +│ FastAPI Backend │ +│ /users /organizations /interviews /applications /health │ +│ │ +│ ┌────────────────┐ ┌──────────────────┐ ┌────────────────┐ │ +│ │ Auth (JWT + │ │ Routers / │ │ Exception │ │ +│ │ bcrypt) │ │ Business Logic │ │ Handlers │ │ +│ └────────────────┘ └────────┬─────────┘ └────────────────┘ │ └────────────────────────────────┼────────────────────────────────┘ - │ - ┌─────────────────┼──────────────────┐ - │ │ │ - ┌──────────▼───────┐ ┌───────▼──────────┐ ┌────▼────────────┐ - │ PostgreSQL / │ │ TaskIQ + Redis │ │ Supabase Storage│ - │ SQLite │ │ Worker │ │ (Resume PDFs) │ - │ (SQLAlchemy ORM) │ └───────┬──────────┘ └─────────────────┘ - └──────────────────┘ │ - ┌────────▼────────┐ - │ LLM Pipeline │ - │ LiteLLM/Groq │ - │ LangChain │ - │ ResumeEvaluator│ - └─────────────────┘ +│ +┌─────────────────┼──────────────────┐ +│ │ │ +┌──────────▼───────┐ ┌───────▼──────────┐ ┌────▼────────────┐ +│ PostgreSQL / │ │ TaskIQ + Redis │ │ Supabase Storage│ +│ SQLite │ │ Worker │ │ (Resume PDFs) │ +│ (SQLAlchemy ORM) │ └───────┬──────────┘ └─────────────────┘ +└──────────────────┘ │ +┌────────▼────────┐ +│ LLM Pipeline │ +│ LiteLLM/Groq │ +│ LangChain │ +│ ResumeEvaluator│ +└─────────────────┘ + ``` ### Request Lifecycle @@ -120,61 +142,63 @@ Organizations create fully customized interviews with domain-specific questions ### Resume Processing Pipeline ``` + POST /applications/{interview_id} - │ - ├── Create Application record (status: pending) - └── Return 202 to client immediately +│ +├── Create Application record (status: pending) +└── Return 202 to client immediately TaskIQ Worker (async): - ├── Decode base64 PDF - ├── Upload PDF → Supabase Storage - ├── Extract text (PyPDF2) - ├── ResumeEvaluator.evaluate() - │ ├── Build ChatPromptTemplate - │ ├── Call LiteLLM/Groq - │ └── Parse structured JSON response - │ score · shortlisting_decision · feedback - └── Update Application record with evaluation results - (Delete Application on failure) -``` +├── Decode base64 PDF +├── Upload PDF → Supabase Storage +├── Extract text (PyPDF2) +├── ResumeEvaluator.evaluate() +│ ├── Build ChatPromptTemplate +│ ├── Call LiteLLM/Groq +│ └── Parse structured JSON response +│ score · shortlisting_decision · feedback +└── Update Application record with evaluation results +(Delete Application on failure) +``` ## Project Structure ``` + InterXAI-re/ -├── backend/ # FastAPI application -│ ├── app/ -│ │ ├── ai/ # LLM agents and prompt templates -│ │ ├── background/ -│ │ │ ├── taskiq/ # TaskIQ broker & resume task -│ │ │ └── celery/ # Legacy (deprecated) -│ │ ├── exceptions/ # Custom exception hierarchy -│ │ ├── interfaces/ # Abstract base classes -│ │ ├── models/ # SQLAlchemy ORM models -│ │ ├── routers/ # API route handlers -│ │ ├── schemas/ # Pydantic request/response schemas -│ │ ├── utils/ # Concrete implementations -│ │ ├── config.py # Pydantic settings (env-driven) -│ │ ├── database.py # Async DB session factory -│ │ └── main.py # App factory, lifespan, middleware -│ ├── alembic/ # Database migrations -│ ├── Dockerfile # API server image -│ ├── Dockerfile.taskiq # Worker image -│ └── pyproject.toml -├── frontend/ # React + TypeScript SPA -│ ├── src/ -│ │ ├── app/ # App routing and layout shells -│ │ ├── components/ # Shared, reusable UI components -│ │ ├── features/ # Feature-scoped modules -│ │ └── services/ # Axios-based API client layer -│ └── package.json -├── docker-compose.yml # Multi-service orchestration +├── backend/ # FastAPI application +│ ├── app/ +│ │ ├── ai/ # LLM agents and prompt templates +│ │ ├── background/ +│ │ │ ├── taskiq/ # TaskIQ broker & resume task +│ │ │ └── celery/ # Legacy (deprecated) +│ │ ├── exceptions/ # Custom exception hierarchy +│ │ ├── interfaces/ # Abstract base classes +│ │ ├── models/ # SQLAlchemy ORM models +│ │ ├── routers/ # API route handlers +│ │ ├── schemas/ # Pydantic request/response schemas +│ │ ├── utils/ # Concrete implementations +│ │ ├── config.py # Pydantic settings (env-driven) +│ │ ├── database.py # Async DB session factory +│ │ └── main.py # App factory, lifespan, middleware +│ ├── alembic/ # Database migrations +│ ├── Dockerfile # API server image +│ ├── Dockerfile.taskiq # Worker image +│ └── pyproject.toml +├── frontend/ # React + TypeScript SPA +│ ├── src/ +│ │ ├── app/ # App routing and layout shells +│ │ ├── components/ # Shared, reusable UI components +│ │ ├── features/ # Feature-scoped modules +│ │ └── services/ # Axios-based API client layer +│ └── package.json +├── docker-compose.yml # Multi-service orchestration ├── LICENSE └── tools/ - └── backend_lint # One-shot ruff + mypy quality check -``` +└── backend_lint # One-shot ruff + mypy quality check +``` ## Getting Started @@ -193,18 +217,18 @@ Create a `.env` file inside the `backend/` directory: cp backend/.env.example backend/.env ``` -| Variable | Default | Description | -|---|---|---| -| `DATABASE_URL` | `sqlite+aiosqlite:///./dev.db` | PostgreSQL URL for production | -| `REDIS_URL` | `redis://localhost:6379/0` | TaskIQ broker + result backend | -| `SECRET_KEY` | `secret` | JWT signing key - **change in production** | -| `ALGORITHM` | `HS256` | JWT signing algorithm | -| `ACCESS_TOKEN_EXPIRE_MINUTES` | `30000` | Token lifetime | -| `GROQ_API_KEY` | - | Required for LLM inference | -| `SUPABASE_URL` | - | Supabase project URL | -| `SUPABASE_KEY` | - | Supabase service role key | -| `SUPABASE_BUCKET_NAME` | `resumes` | Storage bucket for resume PDFs | -| `LLM_MODEL_NAME` | `groq/openai/gpt-oss-120b` | LiteLLM model string | +| Variable | Default | Description | +| ----------------------------- | ------------------------------ | ------------------------------------------ | +| `DATABASE_URL` | `sqlite+aiosqlite:///./dev.db` | PostgreSQL URL for production | +| `REDIS_URL` | `redis://localhost:6379/0` | TaskIQ broker + result backend | +| `SECRET_KEY` | `secret` | JWT signing key - **change in production** | +| `ALGORITHM` | `HS256` | JWT signing algorithm | +| `ACCESS_TOKEN_EXPIRE_MINUTES` | `30000` | Token lifetime | +| `GROQ_API_KEY` | - | Required for LLM inference | +| `SUPABASE_URL` | - | Supabase project URL | +| `SUPABASE_KEY` | - | Supabase service role key | +| `SUPABASE_BUCKET_NAME` | `resumes` | Storage bucket for resume PDFs | +| `LLM_MODEL_NAME` | `groq/openai/gpt-oss-120b` | LiteLLM model string | ### Option A - Docker (Recommended) @@ -250,7 +274,6 @@ npm run dev The frontend dev server runs at `http://localhost:5173`. - ## API Reference FastAPI auto-generates interactive documentation: @@ -260,24 +283,23 @@ FastAPI auto-generates interactive documentation: ### Endpoints Summary -| Method | Endpoint | Auth | Description | -|---|---|---|---| -| `GET` | `/health` | - | Health check | -| `POST` | `/users/signup` | - | Register a candidate account | -| `POST` | `/users/login` | - | Authenticate and receive JWT | -| `GET` | `/users/{user_id}` | User | Get user profile | -| `PUT` | `/users/{user_id}` | User | Update user profile | -| `DELETE` | `/users/{user_id}` | User | Delete user account | -| `POST` | `/organizations/signup` | - | Register an organization | -| `GET` | `/organizations/{org_id}` | Org | Get organization details | -| `PUT` | `/organizations/{org_id}` | Org | Update organization | -| `POST` | `/interviews/` | Org | Create a new interview | -| `GET` | `/interviews/` | Any | List interviews | -| `GET` | `/interviews/applied` | User | Get applied interviews | -| `GET` | `/interviews/{interview_id}` | Org | Get full interview details | -| `POST` | `/applications/{interview_id}` | User | Apply with resume (PDF) | -| `GET` | `/applications/{interview_id}` | Org | Get all applications | - +| Method | Endpoint | Auth | Description | +| -------- | ------------------------------ | ---- | ---------------------------- | +| `GET` | `/health` | - | Health check | +| `POST` | `/users/signup` | - | Register a candidate account | +| `POST` | `/users/login` | - | Authenticate and receive JWT | +| `GET` | `/users/{user_id}` | User | Get user profile | +| `PUT` | `/users/{user_id}` | User | Update user profile | +| `DELETE` | `/users/{user_id}` | User | Delete user account | +| `POST` | `/organizations/signup` | - | Register an organization | +| `GET` | `/organizations/{org_id}` | Org | Get organization details | +| `PUT` | `/organizations/{org_id}` | Org | Update organization | +| `POST` | `/interviews/` | Org | Create a new interview | +| `GET` | `/interviews/` | Any | List interviews | +| `GET` | `/interviews/applied` | User | Get applied interviews | +| `GET` | `/interviews/{interview_id}` | Org | Get full interview details | +| `POST` | `/applications/{interview_id}` | User | Apply with resume (PDF) | +| `GET` | `/applications/{interview_id}` | Org | Get all applications | ## Data Models @@ -303,7 +325,6 @@ InterviewSession **Round Types:** `QUESTIONS` · `DSA` · `RESUME` - ## Development ### Running Code Quality Checks @@ -332,7 +353,6 @@ uv run alembic upgrade head uv run alembic revision --autogenerate -m "add column to applications" ``` - ## Contributing Contributions are welcome. Please follow these steps: @@ -351,12 +371,10 @@ Contributions are welcome. Please follow these steps: - Type annotations are mandatory - `mypy --strict` must pass without errors - Line length: 100 characters (enforced by Ruff) - ## License This project is licensed under the MIT License. See [LICENSE](LICENSE) for details. -