| # CliniqAI — Setup & Run Instructions |
|
|
| > Complete guide for **Windows (WSL2)** and **macOS** (Intel + Apple Silicon). |
|
|
| --- |
|
|
| ## Table of Contents |
|
|
| 1. [How the application runs](#1-how-the-application-runs) |
| 2. [Prerequisites by operating system](#2-prerequisites-by-operating-system) |
| - [Windows — install WSL2 first](#21-windows--install-wsl2-first) |
| - [macOS](#22-macos) |
| 3. [Get the code](#3-get-the-code) |
| 4. [Install Python tooling with uv](#4-install-python-tooling-with-uv) |
| 5. [Configure environment variables](#5-configure-environment-variables) |
| - [Required — LLM provider](#51-required--llm-provider) |
| - [Optional integrations](#52-optional-integrations) |
| 6. [Start infrastructure (Docker)](#6-start-infrastructure-docker) |
| 7. [Apply the database schema](#7-apply-the-database-schema) |
| 8. [Run the application](#8-run-the-application) |
| - [Minimal mode (no Celery)](#81-minimal-mode-no-celery) |
| - [Full mode (all processes)](#82-full-mode-all-processes) |
| 9. [Verify everything is working](#9-verify-everything-is-working) |
| 10. [Stopping the application](#10-stopping-the-application) |
| 11. [Hugging Face Spaces deployment](#11-hugging-face-spaces-deployment) |
| 12. [Troubleshooting by OS](#12-troubleshooting-by-os) |
|
|
| --- |
|
|
| ## 1. How the application runs |
|
|
| CliniqAI consists of several cooperating processes. Understanding what each one does prevents confusion when something stops working. |
|
|
| | Process | Command | Port | What it does | Required for | |
| |---|---|---|---|---| |
| | PostgreSQL | `make up` | 5432 | Stores appointments, staff, SOAP drafts, audit log | Everything | |
| | Redis | `make up` | 6379 | Celery task broker + result backend | Scheduled reminders | |
| | Langfuse | `make up` | 3001 | LLM call observability dashboard | Observability (optional) | |
| | FastAPI backend | `make api` | 8000 | All agent HTTP endpoints | Everything | |
| | Gradio UI | `make ui` | 7860 | Doctor / Patient / Nurse tabs | The web interface | |
| | Celery worker | `make worker` | — | Executes scheduled reminder tasks | T-24h / T-3h / T-2h reminders | |
| | Celery beat | `make beat` | — | Triggers the 6-hour sweep cron | Post-discharge sweep | |
|
|
| **Minimum to run the demo:** Docker (PostgreSQL + Redis), FastAPI, and Gradio. |
| The Celery worker and beat are only needed for timed notifications and scheduled sweeps. |
|
|
| --- |
|
|
| ## 2. Prerequisites by operating system |
|
|
| ### 2.1 Windows — install WSL2 first |
|
|
| Native Windows is not supported. All development happens inside WSL2 (Windows Subsystem for Linux). Docker Desktop runs on Windows but mounts into WSL2. |
|
|
| #### Step 1 — Enable WSL2 |
|
|
| Open PowerShell **as Administrator** and run: |
|
|
| ```powershell |
| wsl --install |
| ``` |
|
|
| This installs WSL2 and Ubuntu by default. If you already have WSL1, upgrade: |
|
|
| ```powershell |
| wsl --set-default-version 2 |
| wsl --install -d Ubuntu-24.04 |
| ``` |
|
|
| Restart your machine when prompted. |
|
|
| #### Step 2 — Verify WSL2 is running |
|
|
| ```powershell |
| wsl --list --verbose |
| ``` |
|
|
| The `VERSION` column must show `2`. If it shows `1`, run: |
|
|
| ```powershell |
| wsl --set-version Ubuntu-24.04 2 |
| ``` |
|
|
| #### Step 3 — Install Docker Desktop for Windows |
|
|
| Download from: https://www.docker.com/products/docker-desktop |
|
|
| During installation, on the **Configuration** screen, make sure **"Use WSL 2 instead of Hyper-V"** is checked. |
|
|
| After installation: |
| 1. Open Docker Desktop → Settings → Resources → WSL Integration |
| 2. Enable integration for your Ubuntu distribution |
| 3. Click **Apply & Restart** |
|
|
| Verify inside WSL: |
|
|
| ```bash |
| # Open Ubuntu from the Start menu, then: |
| docker --version |
| docker compose version |
| ``` |
|
|
| Both commands must work inside the WSL terminal. If `docker` is not found inside WSL, go back to Docker Desktop → WSL Integration and re-enable your distro. |
|
|
| #### Step 4 — Install build tools inside WSL |
|
|
| ```bash |
| sudo apt update && sudo apt upgrade -y |
| sudo apt install -y build-essential git curl wget make python3-dev |
| ``` |
|
|
| #### Step 5 — Verify Make is available |
|
|
| ```bash |
| make --version |
| ``` |
|
|
| If missing: `sudo apt install -y make` |
|
|
| --- |
|
|
| ### 2.2 macOS |
|
|
| macOS works natively — no virtualization layer needed. |
|
|
| #### Step 1 — Install Xcode Command Line Tools |
|
|
| This provides `git`, `make`, and the C compiler: |
|
|
| ```bash |
| xcode-select --install |
| ``` |
|
|
| Click Install in the dialog that appears. This takes a few minutes. |
|
|
| #### Step 2 — Install Homebrew |
|
|
| ```bash |
| /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" |
| ``` |
|
|
| After installation, follow the instructions in the terminal to add Homebrew to your PATH. For Apple Silicon Macs, this is usually: |
|
|
| ```bash |
| echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile |
| eval "$(/opt/homebrew/bin/brew shellenv)" |
| ``` |
|
|
| For Intel Macs, Homebrew installs to `/usr/local` which is already on PATH. |
|
|
| Verify: |
|
|
| ```bash |
| brew --version |
| ``` |
|
|
| #### Step 3 — Install Docker Desktop for macOS |
|
|
| Download the correct version for your chip: |
| - **Apple Silicon (M1/M2/M3/M4):** https://docs.docker.com/desktop/install/mac-install/ — choose **Apple Chip** |
| - **Intel:** same page — choose **Intel Chip** |
|
|
| After installation, open Docker Desktop from Applications and wait for the whale icon in the menu bar to stop animating (means Docker engine is ready). |
|
|
| Verify: |
|
|
| ```bash |
| docker --version |
| docker compose version |
| ``` |
|
|
| --- |
|
|
| ## 3. Get the code |
|
|
| **Windows users:** Clone inside WSL, not on the Windows filesystem (`/mnt/c/...`). The Windows filesystem is mounted via 9P protocol and causes dramatic slowdowns with Python tooling. |
|
|
| ```bash |
| # Good — inside WSL home directory |
| cd ~ |
| git clone https://github.com/your-org/clinical-pilot-hf.git |
| cd clinical-pilot-hf |
| |
| # Bad — this is slow |
| # cd /mnt/c/Users/yourname/projects |
| ``` |
|
|
| **macOS users:** Clone anywhere in your home directory. |
|
|
| ```bash |
| cd ~/projects # or wherever you keep code |
| git clone https://github.com/your-org/clinical-pilot-hf.git |
| cd clinical-pilot-hf |
| ``` |
|
|
| --- |
|
|
| ## 4. Install Python tooling with uv |
|
|
| `uv` is the package manager used by this project. It is faster than pip and manages Python versions automatically. |
|
|
| ### Install uv |
|
|
| **WSL (Ubuntu) and macOS:** |
|
|
| ```bash |
| curl -LsSf https://astral.sh/uv/install.sh | sh |
| ``` |
|
|
| After installation, reload your shell: |
|
|
| ```bash |
| source ~/.bashrc # WSL / bash users |
| source ~/.zshrc # macOS zsh users (default since macOS Catalina) |
| ``` |
|
|
| Verify: |
|
|
| ```bash |
| uv --version |
| ``` |
|
|
| ### Install Python 3.12 and all project dependencies |
|
|
| From the project root directory: |
|
|
| ```bash |
| make install |
| ``` |
|
|
| This runs `uv sync` under the hood, which: |
| 1. Downloads Python 3.12 if not present on your machine |
| 2. Creates a virtual environment at `.venv/` |
| 3. Installs all packages from `pyproject.toml` |
|
|
| > **Note on `torch` and `transformers`:** These are large packages (torch alone is ~2 GB). The first `make install` will take several minutes while they download. Subsequent installs are cached. |
|
|
| > **Apple Silicon note:** `torch` ships with Metal (MPS) support on Apple Silicon. No special flags needed — the package auto-detects the chip. |
|
|
| Verify the virtual environment was created: |
|
|
| ```bash |
| ls .venv/ |
| ``` |
|
|
| You should see `bin/`, `lib/`, and `pyvenv.cfg`. |
|
|
| --- |
|
|
| ## 5. Configure environment variables |
|
|
| Copy the template to a local file that is gitignored: |
|
|
| ```bash |
| cp .env.example .env.local |
| ``` |
|
|
| Now edit `.env.local`. The sections below explain every variable. |
|
|
| ```bash |
| # WSL / macOS — use any editor |
| nano .env.local |
| # or |
| code .env.local # VS Code (works in both WSL and macOS) |
| ``` |
|
|
| ### 5.1 Required — LLM provider |
|
|
| The application needs **at least one** LLM provider key to run real agent calls. Without any key the app falls back to mock responses, which is fine for UI testing but means no real SOAP notes, routing, or appointment confirmation messages will be generated. |
|
|
| #### Option A — Groq (recommended, free, no credit card) |
|
|
| 1. Go to https://console.groq.com |
| 2. Sign up or log in |
| 3. Click **API Keys** in the left sidebar |
| 4. Click **Create API Key** |
| 5. Copy the key (it starts with `gsk_`) |
|
|
| Set in `.env.local`: |
|
|
| ```env |
| GROQ_API_KEY=gsk_your_key_here |
| ``` |
|
|
| Groq gives you free access to Qwen3-32B (used for SOAP notes and handovers) and Llama 3.1 8B (used for routing and reminders). No billing required. |
|
|
| #### Option B — OpenRouter (free tier fallback) |
|
|
| 1. Go to https://openrouter.ai |
| 2. Create an account |
| 3. Go to **Keys** → **Create Key** |
| 4. Copy the key (it starts with `sk-or-`) |
|
|
| Set in `.env.local`: |
|
|
| ```env |
| OPENROUTER_API_KEY=sk-or-your_key_here |
| ``` |
|
|
| Free models on OpenRouter have a limit of 20 requests per minute and 200 per day. Use this as a backup when Groq rate limits. |
|
|
| #### Option C — Ollama (offline, no API key needed) |
|
|
| For fully offline operation, install Ollama: |
|
|
| **macOS:** |
|
|
| ```bash |
| brew install ollama |
| ollama serve & # starts the Ollama daemon in background |
| ollama pull qwen2.5:32b # downloads the model (~20 GB — do this once) |
| ``` |
|
|
| **WSL:** |
|
|
| ```bash |
| curl -fsSL https://ollama.com/install.sh | sh |
| ollama serve & |
| ollama pull qwen2.5:32b |
| ``` |
|
|
| Set in `.env.local`: |
|
|
| ```env |
| OLLAMA_BASE_URL=http://localhost:11434 |
| ``` |
|
|
| > **Disk requirement:** Qwen2.5 32B requires approximately 20 GB of free disk space. The model downloads once and is cached at `~/.ollama/models/`. |
|
|
| ### 5.2 Optional integrations |
|
|
| These are all optional. The application runs and demos without any of them. |
|
|
| #### Telegram notifications |
|
|
| Required if you want instant push notifications when appointments are booked or cancelled. |
|
|
| 1. Open Telegram and search for `@BotFather` |
| 2. Send `/newbot` |
| 3. Follow the prompts to choose a name and username for your bot |
| 4. Copy the HTTP API token BotFather gives you (format: `1234567890:ABCdefGhIJKlmNoPQRsTUVwxyZ`) |
| 5. Add your bot to a group or channel, or start a direct chat with it and send a message |
| 6. Fetch `https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates` in a browser |
| 7. Copy the `chat.id` value from the response (negative number for groups, positive for DMs) |
|
|
| ```env |
| TELEGRAM_BOT_TOKEN=1234567890:ABCdefGhIJKlmNoPQRsTUVwxyZ |
| TELEGRAM_CHAT_ID=-1001234567890 |
| ``` |
|
|
| #### Langfuse observability (optional but useful) |
|
|
| Langfuse is already included in the Docker stack. It runs at http://localhost:3001. |
|
|
| 1. Open http://localhost:3001 in your browser (after `make up`) |
| 2. Create an account (local — not sent anywhere) |
| 3. Create a project called `cliniqai` |
| 4. Go to Settings → API Keys |
| 5. Copy the public key and secret key |
|
|
| ```env |
| LANGFUSE_HOST=http://localhost:3001 |
| LANGFUSE_PUBLIC_KEY=pk-lf-your_public_key |
| LANGFUSE_SECRET_KEY=sk-lf-your_secret_key |
| ``` |
|
|
| #### WhatsApp via Twilio (optional — for production) |
|
|
| The demo uses Gradio's chat widget instead of WhatsApp. WhatsApp requires Meta approval which takes days, so it is a post-hackathon integration. |
|
|
| ```env |
| TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
| TWILIO_AUTH_TOKEN=your_auth_token |
| TWILIO_WHATSAPP_FROM=whatsapp:+14155238886 |
| ``` |
|
|
| #### Google Calendar and Gmail MCP (optional) |
|
|
| Required only if you want real Google Calendar slot checking instead of the local Postgres calendar backend (which is the default). The local backend works for demos without any Google credentials. |
|
|
| The calendar backend is controlled by: |
|
|
| ```env |
| CALENDAR_BACKEND=local # default — uses Postgres, no Google needed |
| # CALENDAR_BACKEND=google # uncomment to use Google Calendar MCP |
| ``` |
|
|
| ### 5.3 Complete .env.local reference |
|
|
| Below is a fully annotated `.env.local` with every field explained. Copy this and fill in the values you have. |
|
|
| ```env |
| # ============================================================ |
| # DATABASE — do not change these for local dev |
| # They match what docker-compose.dev.yml creates |
| # ============================================================ |
| POSTGRES_USER=cliniq |
| POSTGRES_PASSWORD=cliniq |
| POSTGRES_DB=cliniq |
| POSTGRES_HOST=localhost |
| POSTGRES_PORT=5432 |
| DATABASE_URL=postgresql+psycopg://cliniq:cliniq@localhost:5432/cliniq |
| |
| # ============================================================ |
| # REDIS — do not change for local dev |
| # ============================================================ |
| REDIS_URL=redis://localhost:6379/0 |
| CELERY_BROKER_URL=redis://localhost:6379/1 |
| CELERY_RESULT_BACKEND=redis://localhost:6379/2 |
| |
| # ============================================================ |
| # LLM PROVIDERS — set at least one |
| # ============================================================ |
| GROQ_API_KEY= # https://console.groq.com — free, no card |
| OPENROUTER_API_KEY= # https://openrouter.ai — free fallback |
| OLLAMA_BASE_URL=http://localhost:11434 # local offline option |
| |
| # ============================================================ |
| # WHISPER TRANSCRIPTION |
| # groq — uses Groq API (fast, needs GROQ_API_KEY) |
| # local — uses local transformers pipeline (slow first run, offline) |
| # auto — tries groq, falls back to local if GROQ_API_KEY unset |
| # ============================================================ |
| WHISPER_MODEL=openai/whisper-large-v3-turbo |
| WHISPER_BACKEND=groq |
| |
| # ============================================================ |
| # TELEGRAM (optional — for instant push notifications) |
| # ============================================================ |
| TELEGRAM_BOT_TOKEN= # from @BotFather |
| TELEGRAM_CHAT_ID= # numeric id from getUpdates |
| |
| # ============================================================ |
| # CALENDAR BACKEND |
| # local — Postgres-backed mini calendar (default, no Google needed) |
| # google — Google Calendar MCP (requires OAuth token) |
| # ============================================================ |
| CALENDAR_BACKEND=local |
| |
| # ============================================================ |
| # LANGFUSE OBSERVABILITY (optional) |
| # Runs locally at :3001 after `make up` |
| # ============================================================ |
| LANGFUSE_HOST=http://localhost:3001 |
| LANGFUSE_PUBLIC_KEY= # from http://localhost:3001 after first login |
| LANGFUSE_SECRET_KEY= |
| |
| # ============================================================ |
| # TWILIO WHATSAPP (optional — production only) |
| # Demo uses Gradio chat widget on the same code path |
| # ============================================================ |
| TWILIO_ACCOUNT_SID= |
| TWILIO_AUTH_TOKEN= |
| TWILIO_WHATSAPP_FROM=whatsapp:+14155238886 |
| |
| # ============================================================ |
| # GOOGLE MCP URLS — leave as-is unless changing backends |
| # ============================================================ |
| GOOGLE_CALENDAR_MCP_URL=https://calendarmcp.googleapis.com |
| GMAIL_MCP_URL=https://gmailmcp.googleapis.com |
| GOOGLE_DRIVE_MCP_URL=https://drivemcp.googleapis.com |
| |
| # ============================================================ |
| # APP |
| # ============================================================ |
| CLINIQ_ENV=dev |
| CLINIQ_API_KEY=dev-local-key |
| HF_SPACE_BACKEND_URL=http://localhost:8000 |
| ``` |
|
|
| --- |
|
|
| ## 6. Start infrastructure (Docker) |
|
|
| Make sure Docker Desktop is running (the whale icon in the system tray / menu bar is active and not animating). |
|
|
| From the project root: |
|
|
| ```bash |
| make up |
| ``` |
|
|
| This starts three containers: |
| - `cliniqai-postgres` — PostgreSQL 16 on port 5432 |
| - `cliniqai-redis` — Redis 7 on port 6379 |
| - `cliniqai-langfuse` — Langfuse on port 3001 |
|
|
| Verify all three containers are healthy: |
|
|
| ```bash |
| docker compose ps |
| ``` |
|
|
| Expected output: |
|
|
| ``` |
| NAME STATUS |
| cliniqai-postgres Up (healthy) |
| cliniqai-redis Up (healthy) |
| cliniqai-langfuse Up (healthy) |
| ``` |
|
|
| If any container shows `unhealthy` or `Exiting`, check logs: |
|
|
| ```bash |
| docker compose logs postgres |
| docker compose logs redis |
| docker compose logs langfuse |
| ``` |
|
|
| --- |
|
|
| ## 7. Apply the database schema |
|
|
| This creates all tables (patients, appointments, staff, shifts, soap_drafts, audit_log, etc.): |
|
|
| ```bash |
| make migrate |
| ``` |
|
|
| You should see Alembic output ending with: |
|
|
| ``` |
| INFO [alembic.runtime.migration] Running upgrade -> 0001_init, initial schema |
| ``` |
|
|
| If you see `connection refused` errors, Docker has not finished starting yet. Wait 10 seconds and retry. |
|
|
| Verify tables were created: |
|
|
| ```bash |
| docker exec -it cliniqai-postgres psql -U cliniq -d cliniq -c "\dt" |
| ``` |
|
|
| Expected output lists: `appointments`, `audit_log`, `discharges`, `messages`, `patients`, `shifts`, `soap_drafts`, `staff`. |
|
|
| --- |
|
|
| ## 8. Run the application |
|
|
| Each process below needs its own terminal window. Open new terminals before running each command. In VS Code you can use the split terminal button (`Ctrl+Shift+5` / `Cmd+Shift+5`) to open multiple panes. |
|
|
| ### 8.1 Minimal mode (no Celery) |
|
|
| This is sufficient for the demo — UI works, agents work, mocks work. Timed reminders (T-3h, T-24h) will not fire, but instant Telegram notifications still work. |
|
|
| **Terminal 1 — FastAPI backend:** |
|
|
| ```bash |
| make api |
| ``` |
|
|
| Wait until you see: |
|
|
| ``` |
| INFO: Application startup complete. |
| INFO: Uvicorn running on http://0.0.0.0:8000 |
| ``` |
|
|
| **Terminal 2 — Gradio UI:** |
|
|
| ```bash |
| make ui |
| ``` |
|
|
| Wait until you see: |
|
|
| ``` |
| Running on local URL: http://127.0.0.1:7860 |
| ``` |
|
|
| Open http://localhost:7860 in your browser. You should see the CliniqAI tabs: Doctor, Patient, Nurse & Admin. |
|
|
| ### 8.2 Full mode (all processes) |
|
|
| Open five separate terminals from the project root. |
|
|
| **Terminal 1 — Infrastructure (if not already running):** |
|
|
| ```bash |
| make up |
| ``` |
|
|
| **Terminal 2 — FastAPI backend:** |
|
|
| ```bash |
| make api |
| ``` |
|
|
| **Terminal 3 — Gradio UI:** |
|
|
| ```bash |
| make ui |
| ``` |
|
|
| **Terminal 4 — Celery worker:** |
|
|
| ```bash |
| make worker |
| ``` |
|
|
| Wait until you see: |
|
|
| ``` |
| [tasks] Registered: appointment.send_reminder |
| [tasks] Registered: appointment.check_no_show |
| celery@hostname ready. |
| ``` |
|
|
| **Terminal 5 — Celery beat (cron scheduler):** |
|
|
| ```bash |
| make beat |
| ``` |
|
|
| Wait until you see: |
|
|
| ``` |
| beat: Starting... |
| Scheduler: PersistentScheduler |
| ``` |
|
|
| #### Terminal layout reference |
|
|
| ``` |
| ┌─────────────────────┬─────────────────────┐ |
| │ Terminal 1 │ Terminal 2 │ |
| │ make up │ make api │ |
| │ (infrastructure) │ (FastAPI :8000) │ |
| ├─────────────────────┼─────────────────────┤ |
| │ Terminal 3 │ Terminal 4 │ |
| │ make ui │ make worker │ |
| │ (Gradio :7860) │ (Celery worker) │ |
| ├─────────────────────┴─────────────────────┤ |
| │ Terminal 5 │ |
| │ make beat (Celery beat / cron) │ |
| └───────────────────────────────────────────┘ |
| ``` |
|
|
| --- |
|
|
| ## 9. Verify everything is working |
|
|
| Run these checks after starting all processes. Each check is independent — run them in any free terminal. |
|
|
| ### Check 1 — Health endpoint |
|
|
| ```bash |
| curl http://localhost:8000/health |
| ``` |
|
|
| Expected: |
|
|
| ```json |
| {"status": "ok", "env": "dev", "service": "cliniqai-backend"} |
| ``` |
|
|
| ### Check 2 — Orchestrator routing |
|
|
| ```bash |
| curl -s -X POST http://localhost:8000/orchestrate \ |
| -H "content-type: application/json" \ |
| -d '{"utterance": "book me an appointment"}' | python3 -m json.tool |
| ``` |
|
|
| Expected: a JSON object with `current_agent: "appointment"` and a `communication` field containing an appointment reply draft. |
|
|
| ### Check 3 — SOAP note mock |
|
|
| ```bash |
| curl -s -X POST http://localhost:8000/documentation/draft \ |
| -H "content-type: application/json" \ |
| -d '{"patient_id": "p-001"}' | python3 -m json.tool |
| ``` |
|
|
| Expected: a JSON object with `draft_id`, `soap` (subjective/objective/assessment/plan), `icd10_suggestions`, and `sources`. |
|
|
| ### Check 4 — Roster generation (mock data) |
|
|
| ```bash |
| curl -s -X POST http://localhost:8000/roster/generate \ |
| -H "content-type: application/json" \ |
| -d '{}' | python3 -m json.tool |
| ``` |
|
|
| Expected: a JSON object with `roster_id`, `assignments` (array of shift objects), and `fairness_score`. |
|
|
| ### Check 5 — Handover brief |
|
|
| ```bash |
| curl -s -X POST http://localhost:8000/handover/generate \ |
| -H "content-type: application/json" \ |
| -d '{"ward_id": "ward-A"}' | python3 -m json.tool |
| ``` |
|
|
| Expected: a JSON object with `brief_id`, `patients` array ordered urgent → watch → stable. |
|
|
| ### Check 6 — Database connectivity |
|
|
| ```bash |
| curl -s -X POST http://localhost:8000/appointment/book \ |
| -H "content-type: application/json" \ |
| -d '{"patient_id": "p-test-001"}' | python3 -m json.tool |
| ``` |
|
|
| Expected: a `BookingResult` with `appointment_id`, `slot_iso`, and `status: "confirmed"`. If you see `connection refused` or a 500 error mentioning PostgreSQL, the database container is not running. |
|
|
| ### Check 7 — Full test suite |
|
|
| ```bash |
| make test |
| ``` |
|
|
| Expected: all tests pass. Contract tests and routing smoke tests run without any external keys. |
|
|
| ### Check 8 — Linter |
|
|
| ```bash |
| make lint |
| ``` |
|
|
| Expected: no output (clean). Warnings are acceptable, errors mean something changed in contracts. |
|
|
| ### Check 9 — OpenAPI docs |
|
|
| Open http://localhost:8000/docs in your browser. You should see the Swagger UI with all agent endpoints grouped by tag: documentation, appointment, clerical, discharge, roster, handover. |
|
|
| ### Check 10 — Telegram (if configured) |
|
|
| ```bash |
| python3 -c " |
| from dotenv import load_dotenv |
| load_dotenv('.env.local') |
| from app.integrations.telegram import send |
| result = send('CliniqAI test message — setup complete') |
| print(result) |
| " |
| ``` |
|
|
| Expected: `{'status': 'sent', 'chat_id': '-100...', 'message_id': 123}` and a message appearing in your Telegram. |
|
|
| If you see `{'status': 'stub', ...}`, the token or chat ID is not set in `.env.local`. See section 5.2. |
|
|
| --- |
|
|
| ## 10. Stopping the application |
|
|
| ### Stop individual processes |
|
|
| Press `Ctrl+C` in each terminal. Gradio, FastAPI, Celery worker, and beat all respond to `Ctrl+C`. |
|
|
| ### Stop Docker containers |
|
|
| ```bash |
| make down |
| ``` |
|
|
| This stops and removes the containers but **preserves data**. PostgreSQL data persists in a Docker volume named `cliniqai_postgres_data`. Your appointments, staff records, and SOAP drafts survive a `make down`. |
|
|
| ### Stop Docker containers and wipe all data |
|
|
| Use this when you want a completely clean slate (e.g., schema changes require recreating the database): |
|
|
| ```bash |
| docker compose down -v |
| ``` |
|
|
| The `-v` flag removes the volumes. Run `make migrate` again after this to recreate the schema. |
|
|
| --- |
|
|
| ## 11. Hugging Face Spaces deployment |
|
|
| The Gradio UI is designed to deploy to Hugging Face Spaces. The FastAPI backend must be deployed separately (e.g., on a cloud VM) because Spaces runs only the Gradio process. |
|
|
| ### Step 1 — Push to Hugging Face Spaces |
|
|
| 1. Create a Space at https://huggingface.co/spaces |
| 2. Choose **Gradio** as the SDK |
| 3. Choose **Python 3.12** as the runtime |
| 4. Set the Space as **private** (HIPAA considerations) |
|
|
| ```bash |
| # Add the HF Space as a remote |
| git remote add space https://huggingface.co/spaces/your-username/cliniqai |
| |
| # Push the deploy folder |
| git subtree push --prefix deploy/hf_space space main |
| ``` |
|
|
| ### Step 2 — Configure Secrets in the Space |
|
|
| In your Space → Settings → Repository secrets, add: |
|
|
| | Secret | Value | |
| |---|---| |
| | `HF_SPACE_BACKEND_URL` | `https://your-backend-api.example.com` | |
| | `GROQ_API_KEY` | Your Groq key | |
| | `TELEGRAM_BOT_TOKEN` | Your bot token | |
| | `TELEGRAM_CHAT_ID` | Your chat ID | |
|
|
| The Space reads secrets as environment variables at runtime. Never commit secrets to git. |
|
|
| ### Step 3 — Verify Space deployment |
|
|
| After the Space builds (watch the build logs in the Spaces UI), open the Space URL and confirm all three tabs load and the backend URL shown at the top matches your deployed API. |
|
|
| --- |
|
|
| ## 12. Troubleshooting by OS |
|
|
| ### Windows / WSL |
|
|
| --- |
|
|
| **Problem:** `make: command not found` inside WSL |
|
|
| ```bash |
| sudo apt install -y make |
| ``` |
|
|
| --- |
|
|
| **Problem:** `docker: command not found` inside WSL even though Docker Desktop is installed |
|
|
| Open Docker Desktop → Settings → Resources → WSL Integration. Toggle off, save, toggle on, save again. Then restart the WSL terminal: |
|
|
| ```bash |
| wsl --shutdown # run this in PowerShell |
| # Then reopen Ubuntu |
| ``` |
|
|
| --- |
|
|
| **Problem:** `curl` to `localhost:8000` times out from inside WSL |
|
|
| FastAPI binds to `0.0.0.0:8000` which is accessible from inside WSL as `localhost`. If it still times out, check that FastAPI started without errors and that Windows Firewall is not blocking port 8000. Try from a Windows browser using the IP shown in `ip addr show eth0` inside WSL. |
|
|
| --- |
|
|
| **Problem:** Files cloned on `/mnt/c/` cause very slow `uv sync` |
|
|
| Move the project into the WSL filesystem: |
|
|
| ```bash |
| cp -r /mnt/c/Users/yourname/clinical-pilot-hf ~/clinical-pilot-hf |
| cd ~/clinical-pilot-hf |
| ``` |
|
|
| --- |
|
|
| **Problem:** `psycopg` fails with `library not found for -lssl` |
|
|
| ```bash |
| sudo apt install -y libpq-dev libssl-dev |
| make install # reinstall dependencies |
| ``` |
|
|
| --- |
|
|
| **Problem:** `torch` install fails or takes forever in WSL |
|
|
| `torch` is large (~2 GB download). If it hangs, check your WSL memory limit. Create `%USERPROFILE%\.wslconfig` on Windows with: |
|
|
| ```ini |
| [wsl2] |
| memory=8GB |
| processors=4 |
| ``` |
|
|
| Then restart WSL: `wsl --shutdown` in PowerShell. |
|
|
| --- |
|
|
| ### macOS |
|
|
| --- |
|
|
| **Problem:** `make install` fails with `error: externally-managed-environment` |
|
|
| This means system Python is being used instead of uv's managed Python. Make sure you installed uv and that `~/.local/bin` (or `~/.cargo/bin`) is on your PATH: |
|
|
| ```bash |
| echo $PATH # should include ~/.local/bin |
| source ~/.zshrc |
| uv --version |
| ``` |
|
|
| --- |
|
|
| **Problem:** `psycopg[binary]` install fails on Apple Silicon |
|
|
| The binary wheel for `psycopg` may not build without libpq. Install it via Homebrew: |
|
|
| ```bash |
| brew install libpq |
| export LDFLAGS="-L/opt/homebrew/opt/libpq/lib" |
| export CPPFLAGS="-I/opt/homebrew/opt/libpq/include" |
| make install |
| ``` |
|
|
| --- |
|
|
| **Problem:** `torch` install is very slow on Apple Silicon |
|
|
| This is expected on first install — PyTorch for Apple Silicon is about 700 MB. Let it complete. Subsequent installs use the uv cache and are instant. |
|
|
| --- |
|
|
| **Problem:** Docker Desktop is not starting on macOS |
|
|
| 1. Open Activity Monitor and search for `Docker` |
| 2. If it is running but unresponsive, force quit it |
| 3. Restart Docker Desktop from Applications |
| 4. If it still fails, reset to factory defaults: Docker menu → Troubleshoot → Reset to factory defaults |
|
|
| --- |
|
|
| **Problem:** Port 5432 already in use |
|
|
| You have a local PostgreSQL installation running alongside the Docker one. Stop it: |
|
|
| ```bash |
| # macOS native Postgres (if installed via Homebrew) |
| brew services stop postgresql@16 |
| # or |
| pg_ctl stop -D /opt/homebrew/var/postgresql@16 |
| ``` |
|
|
| Then re-run `make up`. |
|
|
| --- |
|
|
| **Problem:** Port 6379 already in use |
|
|
| You have a local Redis running: |
|
|
| ```bash |
| brew services stop redis |
| ``` |
|
|
| Then re-run `make up`. |
|
|
| --- |
|
|
| ### Both platforms |
|
|
| --- |
|
|
| **Problem:** `RuntimeError: router: all models in chain for task=... failed` |
|
|
| No LLM provider key is configured or all are rate-limited. Check: |
|
|
| ```bash |
| python3 -c " |
| import os |
| from dotenv import load_dotenv |
| load_dotenv('.env.local') |
| print('GROQ:', bool(os.getenv('GROQ_API_KEY'))) |
| print('OPENROUTER:', bool(os.getenv('OPENROUTER_API_KEY'))) |
| print('OLLAMA:', bool(os.getenv('OLLAMA_BASE_URL'))) |
| " |
| ``` |
|
|
| At least one must print `True`. If all print `False`, your `.env.local` is not being found or the keys are empty. |
|
|
| --- |
|
|
| **Problem:** `connection refused` on port 5432 |
|
|
| PostgreSQL container is not running. Check: |
|
|
| ```bash |
| docker compose ps |
| docker compose logs postgres |
| ``` |
|
|
| Common causes: Docker Desktop is not running, or a previous `docker compose down -v` wiped the data and `make migrate` has not been re-run. |
|
|
| --- |
|
|
| **Problem:** Alembic migration fails with `relation already exists` |
|
|
| The schema was partially applied. Run a full reset: |
|
|
| ```bash |
| docker compose down -v |
| make up |
| # wait 10 seconds for postgres to become ready |
| make migrate |
| ``` |
|
|
| --- |
|
|
| **Problem:** `ModuleNotFoundError: No module named 'app'` |
|
|
| The virtual environment is not activated or the package is not installed in editable mode. Run: |
|
|
| ```bash |
| make install # re-installs everything |
| ``` |
|
|
| Or manually activate: |
|
|
| ```bash |
| source .venv/bin/activate |
| ``` |
|
|
| --- |
|
|
| **Problem:** Gradio UI shows `ConnectionError — backend unreachable` |
|
|
| The FastAPI backend is not running. Make sure `make api` is running in a separate terminal and http://localhost:8000/health returns `{"status":"ok"}`. |
|
|
| --- |
|
|
| **Problem:** `Telegram stub mode` — notifications not arriving |
|
|
| Either `TELEGRAM_BOT_TOKEN` or `TELEGRAM_CHAT_ID` is empty in `.env.local`. Both are required. See section 5.2 for how to obtain them. After setting them, restart FastAPI and the Celery worker. |
|
|
| --- |
|
|
| **Problem:** Celery tasks are queued but never execute |
|
|
| The Celery worker is not running. Open a new terminal and run `make worker`. You should see tasks being picked up within seconds of the next appointment booking. |
|
|
| --- |
|
|
| ## Quick-reference cheat sheet |
|
|
| ```bash |
| # First time only |
| make install # install deps |
| cp .env.example .env.local && nano .env.local |
| make up # start Docker (Postgres + Redis + Langfuse) |
| make migrate # create DB tables |
| |
| # Every day — open 4 terminals |
| make up # terminal 1 (if not already running) |
| make api # terminal 2 |
| make ui # terminal 3 |
| make worker # terminal 4 (only needed for reminders) |
| |
| # Checks |
| curl localhost:8000/health |
| make test |
| make lint |
| |
| # Reset everything |
| docker compose down -v && make up && make migrate |
| |
| # Useful Docker commands |
| docker compose ps # see container status |
| docker compose logs -f # tail all logs |
| docker compose logs postgres # logs for one service |
| ``` |