AI Interview Assistant is a platform designed to help streamline the interview process by leveraging AI for tasks such as job description analysis, resume parsing, interview question generation, multi-turn interview logging, and comprehensive interview report generation including structured capability assessment.
- Features
- Tech Stack
- Prerequisites
- Installation
- Environment Setup
- Running the Application
- Running Tests
- Database Migrations
- Key Development Highlights & Workflow
- Project Structure
- Potential Future Enhancements
- Contributing
- License
- Job Management: Create, read, update, and delete job postings.
- Candidate Management: Create, read, update, and delete candidate profiles, including AI-powered resume parsing for structured data extraction.
- Interview Scheduling & Management: Schedule and manage interview lifecycles (e.g., status updates from pending questions to report generated).
- AI-Powered Question Generation: Automatically generate interview questions based on AI-analyzed job descriptions and candidate resumes.
- Interactive Interview Logging: A chat-style interface for recording multi-turn interview dialogues, associating dialogue with pre-generated questions or ad-hoc inputs.
- AI-Powered Interview Reports: Generate comprehensive interview assessment reports based on interview dialogues, JD, and resume. Includes:
- Overall assessment.
- Capability dimension analysis with 1-5 scoring.
- Strengths and areas for development.
- Automated extraction of structured capability scores (e.g., for radar charts).
- Report Viewing & Visualization: Display generated reports and associated radar charts for capability assessment.
- Dynamic UI Elements: Features like dynamically loaded "common follow-up questions" via
st.popoverfor enhanced UX.
- Backend: FastAPI, Python 3.13+
- Frontend: Streamlit
- Database: MySQL
- ORM: SQLAlchemy
- Database Migrations: Alembic
- Dependency Management: uv
- Python Version Management: pyenv (optional, for consistency)
- Testing: Pytest,
pytest-dotenv - AI Integrations: Langchain, OpenAI (or compatible APIs)
- Environment Variable Management:
python-dotenv
- Python 3.13+ (managed via
pyenvis recommended for consistency) pyenvinstalled (if used, see pyenv installation guide)uvinstalled (see uv installation guide)- MySQL server running and accessible.
- An OpenAI API key and potentially a base URL if using a proxy or custom endpoint.
-
Clone the repository:
git clone <YOUR_REPOSITORY_URL> # Replace with your actual repo URL cd ai-interview-assistant
-
Set up Python version using pyenv (recommended):
# Ensure .python-version file exists with the target Python version (e.g., 3.13.0) pyenv install $(cat .python-version) pyenv local $(cat .python-version)
-
Install dependencies using uv:
uv pip install -e ".[test]" # Installs main and test dependencies from pyproject.toml
Dependencies are managed via
pyproject.tomlanduv.lock.
This project uses a .env file for environment variables.
.envFile: This file stores sensitive credentials and environment-specific configurations. It is not committed to version control (.gitignoreshould list.env). Create a.envfile in the project root:Populatecp env.example .env # If you provide an env.example, otherwise create manually.envwith the necessary variables. Key variables include:Important:OPENAI_API_KEY="sk-your_openai_api_key_here" OPENAI_API_BASE="https://api.openai.com/v1" # Or your custom base URL if applicable # Database URL for the main application (FastAPI) DATABASE_URL="mysql+pymysql://user:password@host:port/dbname" # Database URL for testing (pytest uses this via pytest-dotenv) TEST_MYSQL_DATABASE_URL="mysql+pymysql://testuser:testpass@localhost:3306/testdb" # Example: API_LOG_LEVEL="INFO"
- Replace placeholders with your actual credentials and database connection strings.
- Ensure the databases specified (e.g.,
dbname,testdb) exist and the users have the necessary permissions. - The backend application (
app/main.py) usespython-dotenvto load these variables. - Pytest uses
pytest-dotenvto load these variables during tests, especiallyTEST_MYSQL_DATABASE_URL. - When using Docker Compose, these variables are primarily managed through the
docker-compose.yamlfile'senvironmentorenv_filesections for each service.
This is the recommended way to run the application as it sets up all services (backend, frontend, database) in isolated containers.
-
Ensure Docker and Docker Compose are installed.
-
Build and start the services: From the project root directory:
docker compose up --build
- To run in detached mode (in the background):
docker compose up --build -d
- To run in detached mode (in the background):
-
Accessing the services:
- FastAPI Backend:
http://localhost:8000- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc
- Swagger UI:
- Streamlit Frontend:
http://localhost:8501 - MySQL Database: Accessible on
localhost:33066(as per defaultdocker-compose.yaml) by database tools or other services.
- FastAPI Backend:
-
Database Migrations (Alembic): When the application starts for the first time, or if there are new database schema changes, migrations need to be applied. The
backendservice indocker-compose.yamlis configured with a command that attempts to run migrations on startup. If you need to run migrations manually while the services are running:docker compose exec backend alembic upgrade headTo generate a new migration (usually done in a local development environment first):
docker compose exec backend alembic revision --autogenerate -m "Your migration message"
Then, after reviewing the script, apply it.
-
Viewing logs:
docker compose logs -f <service_name> # e.g., backend, frontend, db
-
Stopping the services:
docker compose down
- Ensure your virtual environment (if explicitly managed) is active and
.envis populated. - Run database migrations (if this is the first time or if there are new migrations):
alembic upgrade head
- Start the FastAPI development server using Uvicorn:
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
- The API will typically be available at
http://localhost:8000. - Auto-generated API documentation (Swagger UI) will be at
http://localhost:8000/docs. - Alternative documentation (ReDoc) at
http://localhost:8000/redoc.
- The API will typically be available at
- Ensure your virtual environment (if explicitly managed) is active and
.envis populated. (Streamlit also benefits fromOPENAI_API_KEYif any direct client-side calls were made, though typically it interacts via the FastAPI backend). - Run the Streamlit application:
python -m streamlit run streamlit_app/app_navigator.py --server.port 8501
- The Streamlit app will typically be available at
http://localhost:8501.
- The Streamlit app will typically be available at
- Ensure
TEST_MYSQL_DATABASE_URLin.envis correctly configured for your test database. Thepytest-dotenvplugin will automatically load variables from.env. - Run the tests using Pytest:
pytest
- You can run specific tests by specifying the path or markers:
pytest tests/api/v1/test_interviews.py pytest -m "marker_name" # If you use pytest markers
- You can run specific tests by specifying the path or markers:
This project uses Alembic for database schema migrations.
-
To generate a new migration script after making changes to SQLAlchemy models (
app/db/models.py): It's crucial to use--autogenerateto let Alembic detect model changes.alembic revision --autogenerate -m "Describe your changes here, e.g., add_conversation_log_to_interviews"Then, review the generated script in the
alembic/versions/directory. Usually, autogenerated scripts are sufficient, but complex changes might need manual adjustments. -
To apply migrations to your database:
alembic upgrade head
-
To downgrade to a specific version (use with caution):
alembic downgrade <version_identifier_or_relative_step_like_-1>
-
To see the current database revision:
alembic current
This project evolved through several key stages and problem-solving steps, including recent architectural upgrades and bug fixes:
- Enhanced Environment & Testing Setup:
- Integrated
pytest-dotenvto automatically load environment variables (likeTEST_MYSQL_DATABASE_URL) from the.envfile duringpytestexecution. This resolved initial test setup failures and streamlined environment management for testing.
- Integrated
- Improved Database & Model Integrity:
- Addressed
sqlalchemy.exc.DataErrorfor theInterview.statusfield by ensuring that only validInterviewStatusenum members were used during updates (e.g., correcting invalid values like "SCHEDULED"). - Rectified Pydantic schema definitions by adding the
updated_atfield toapp.api.v1.schemas.InterviewInDBBase(and subsequently toInterviewOutputSchema), aligning API responses with test assertions and preventingAssertionErrors due to missing fields.
- Addressed
- Increased Test Suite Robustness:
- Corrected
unittest.mock.patchtargets in API tests (e.g., intests/api/v1/test_interviews.py). Mocks for AI services (likeanalyze_jd) were updated to target the path where the function is looked up (e.g.,'app.api.v1.endpoints.interviews.analyze_jd') rather than where it's defined, ensuring effective isolation of services during tests. - Refined timestamp assertions, for instance in
test_update_interview_success, by parsing datetime strings from API responses into timezone-awaredatetimeobjects before comparison. This made tests more resilient to minor formatting differences and ensured accurate checks (e.g.,updated_at > created_at).
- Corrected
- LangChain v0.3.x Adaptation: Updated LangChain usage to align with v0.3.x standards, primarily involving the adoption of the
Runnableinterface and methods likeainvoke()for asynchronous chain executions. This enhances compatibility with the latest LangChain features and often improves performance for I/O-bound AI calls. (This complements the existing point on "Asynchronous Operations"). - Pydantic V2 Migration: Upgraded the project to use Pydantic V2. This involves leveraging its improved performance, stricter validation rules, and updated API (e.g., changes in model configuration and field definitions). This ensures the project benefits from the latest data validation and serialization capabilities.
- Initial Setup & Testing: Ensured basic LLM calls and
pytestsetup. Encountered and resolved test database URL issues by integratingpytest-dotenv. - Core Interview Logic: Fixed data truncation errors (
DataErrorfor status) and assertion errors in API tests by aligning test payloads with database schema (e.g.,InterviewStatusenum) and Pydantic schemas. - AI Service Mocking: Corrected mock paths for AI service calls in unit tests to ensure proper isolation.
- Timestamp Handling: Addressed timestamp comparison issues in tests by parsing strings to timezone-aware datetime objects.
- Environment Variables for Backend: Resolved OpenAI authentication errors by ensuring
load_dotenv()is called inapp/main.pyto make.envvariables available to the backend. - Structured Interview Logging:
- Evolved from a single
conversation_logtext field to a structuredInterviewLogtable for multi-turn dialogues. - This involved Pydantic schema updates, new API endpoints for log creation/retrieval, and Alembic migrations (
--autogeneratewas key).
- Evolved from a single
- AI Report Generation & Data Extraction:
- Enhanced prompts in
app/core/prompts.pyto instruct AI for Chinese output and structured JSON for capability scores. - Implemented logic in the backend to extract this JSON from the AI's text response and store it separately (e.g.,
radar_datain theInterviewmodel). - Refined prompts to constrain AI scoring (1-5 scale) and minimize extraneous text around the JSON block.
- Enhanced prompts in
- Frontend UX Enhancements (
streamlit_app/):- Interview Management: Improved loading indicators and feedback messages (using candidate names, avoiding duplicate icons).
- Interview Logging:
- Transformed the logging page from a single
st.text_areato an interactive chat interface usingst.chat_messageandst.chat_input. - Dynamically loaded "common follow-up questions" from
app/core/prompts.pyand displayed them usingst.popoverto avoid UI clutter. - Improved display of interview selection (showing candidate/job names, Chinese status).
- Transformed the logging page from a single
- Report Viewing: Ensured correct display of AI-generated report text and associated radar chart data.
- Database Schema Evolution: Handled foreign key constraints (e.g.,
ondelete="SET NULL"forInterviewLog.question_id) during schema changes and question regeneration. - Asynchronous Operations: Migrated AI service calls (e.g., report generation) to use
asyncandawait chain.ainvoke()for better performance and responsiveness, particularly in the FastAPI backend.
.
├── .dockerignore # Specifies intentionally untracked files that Docker should ignore
├── .git/ # Git version control metadata
├── .gitignore # Specifies intentionally untracked files that Git should ignore
├── .pytest_cache/ # Cache directory for pytest
├── .venv/ # Python virtual environment (if used locally)
├── alembic/ # Alembic migration scripts and environment configuration
├── app/ # Main application source code (FastAPI backend)
│ ├── api/ # API specific modules
│ │ └── v1/ # Version 1 of the API
│ │ ├── endpoints/ # API route definitions (FastAPI routers)
│ │ └── schemas.py # Pydantic schemas for request/response validation and serialization
│ ├── core/ # Core application logic, configuration, and prompts
│ │ ├── config.py # Application settings (e.g., loading from environment variables)
│ │ └── prompts.py # Prompts for AI services (e.g., for Langchain)
│ ├── db/ # Database interaction layer
│ │ ├── models.py # SQLAlchemy ORM models defining database tables
│ │ ├── session.py # Database session management (SQLAlchemy SessionLocal)
│ │ └── crud/ # CRUD (Create, Read, Update, Delete) operations for models
│ ├── services/ # Business logic layer, AI service integrations
│ │ ├── ai_services.py # Client for interacting with LLMs (e.g., OpenAI via Langchain)
│ │ └── ai_report_generator.py # Logic for AI report generation
│ ├── utils/ # Utility functions for the backend
│ └── main.py # FastAPI application entry point (creates FastAPI app instance, mounts routers)
├── streamlit_app/ # Streamlit frontend application
│ ├── pages/ # Individual pages of the Streamlit app
│ ├── utils/ # Frontend specific utilities (e.g., API client)
│ ├── assets/ # Static assets for the frontend (e.g., images, CSS - if any)
│ └── app_navigator.py # Main Streamlit application navigator/entry point
├── static/ # Static files (currently minimal, e.g., test_sse_client.html - may be deprecated or for backend specific static files if any)
├── streamlit_tmp/ # Temporary directory, possibly for Streamlit uploads (ensure .gitignore)
├── tests/ # Test suite (Pytest)
│ ├── api/ # API tests (testing FastAPI endpoints)
│ ├── conftest.py # Pytest fixtures and global test configurations
│ └── ... # Other test modules (e.g., unit tests for services)
├── .conda-env # Conda environment file (if using Conda)
├── .envrc # direnv environment configuration file (if using direnv)
├── .python-version # pyenv Python version for the project
├── alembic.ini # Alembic configuration file
├── docker-compose.yaml # Docker Compose configuration for running multi-container application
├── Dockerfile # Dockerfile for the backend service (referenced in docker-compose.yaml)
├── env.example # Example environment variables file
├── init.sql # Initial SQL script for database setup (e.g. for MySQL)
├── LICENSE.md / LICENSE # Project license file(s)
├── main.py # Minimal top-level main.py (if any, role to be clarified or removed if app.main:app is sole entry)
├── migration_sanity_check.py # Script for checking migrations (developer tool)
├── pytest.ini # Pytest configuration file
├── pyproject.toml # Project metadata and dependencies (for Poetry/PEP 517 builds, used by uv)
├── README.md # This file (English README)
├── README_zh.md # Chinese README
├── requirements.txt # Requirements file (potentially for specific contexts or generated by pip freeze)
└── uv.lock # Lock file for uv, ensuring reproducible builds
- **Centralize `