Oliver-ai-bot_2.0/backend
Vadym Samoilenko 9c7bf5b1fa feat: purge orphaned Qdrant vectors button
Backend: POST /admin/knowledge/purge-orphaned-vectors — scrolls all Qdrant
vectors, finds sharepoint_ids with no matching DB document_key, deletes them.
Frontend: "Purge Orphans" button in Documents table toolbar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 22:11:13 +01:00
..
alembic fix: migration 030 down_revision to match 029's actual revision ID 2026-03-31 21:31:58 +01:00
app feat: purge orphaned Qdrant vectors button 2026-03-31 22:11:13 +01:00
scripts fix: import all models in sync script to resolve all SQLAlchemy relationships 2026-03-30 18:47:01 +01:00
.env.example Phase 3: Corrective RAG, Trust Scoring, Smart Memory, Parallel Tools 2026-03-04 21:51:25 +00:00
alembic.ini Initial commit: Phases 1-5 Complete + Frontend Setup 2026-02-12 19:10:28 +00:00
celery_app.py feat: proactive Graph token refresh + needs_reconsent flag 2026-03-31 21:29:38 +01:00
cloud_run_service.py debug: add INFO logging for chunk count in extract_and_chunk and Cloud Run service 2026-03-05 19:11:56 +00:00
cloudbuild-processor.yaml Add Cloud Build config for processor service (Dockerfile.cloud-run) 2026-03-05 11:05:11 +00:00
Dockerfile Phase 4: Production hardening, Cloud Run worker, deploy pipeline 2026-03-04 22:42:10 +00:00
Dockerfile.cloud-run Fix spinner, OLIVER brand redesign, Cloud Run document processor 2026-03-05 10:37:21 +00:00
Dockerfile.worker Phase 4: Production hardening, Cloud Run worker, deploy pipeline 2026-03-04 22:42:10 +00:00
entrypoint.sh fix: entrypoint.sh passes through args (needed for alembic in deploy.sh) 2026-03-05 18:18:33 +00:00
README.md Initial commit: Phases 1-5 Complete + Frontend Setup 2026-02-12 19:10:28 +00:00
requirements.txt fix: Qdrant upsert timeout — increase client timeout and batch upserts 2026-03-09 12:28:03 +00:00
seed_data.py Initial commit: Phases 1-5 Complete + Frontend Setup 2026-02-12 19:10:28 +00:00

Enterprise AI Hub "Nexus" - Backend

FastAPI backend with Microsoft Entra ID authentication, PostgreSQL, Redis, and Qdrant integration.

🚀 Quick Start

1. Set up environment variables

Create a .env file in the backend directory:

cp .env.example .env

Edit .env and fill in your credentials:

  • Microsoft Entra ID credentials
  • Database password
  • JWT secret (generate with: openssl rand -hex 32)
  • LLM API keys (optional for Phase 2)

2. Run with Docker Compose

From the project root:

# Start all services
docker-compose up -d

# View logs
docker-compose logs -f backend

# Stop services
docker-compose down

3. Run database migrations

# Enter backend container
docker exec -it nexus-backend bash

# Run migrations
alembic upgrade head

# Seed initial data (regions/departments)
python seed_data.py

# Exit container
exit

4. Access the API

📋 API Endpoints

Authentication

  • POST /api/v1/auth/login - Login with Microsoft Entra ID
  • POST /api/v1/auth/refresh - Refresh access token

Health

  • GET /api/v1/health - System health check

🔐 Authentication Flow

  1. Frontend redirects to Microsoft Entra ID login
  2. User authenticates and grants permissions
  3. Entra ID redirects back with authorization code
  4. Frontend sends code to /api/v1/auth/login
  5. Backend:
    • Exchanges code for Entra ID access token
    • Fetches user profile from MS Graph
    • Auto-provisions user in database (first login)
    • Generates JWT access token (15min) and refresh token (7 days)
  6. Frontend stores tokens and uses access token for API calls

🗄️ Database Schema

Phase 2 Tables:

  • regions: Geographical regions (UK, US, APAC, EU)
  • departments: Departments within regions (UK/HR, US/IT, etc.)
  • users: User accounts with RBAC roles

See implementation_plan.md for complete schema.

🛠️ Development

Local Development (without Docker)

# Install dependencies
pip install -r requirements.txt

# Run migrations
alembic upgrade head

# Seed data
python seed_data.py

# Run development server
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Create a new migration

# Auto-generate migration from model changes
alembic revision --autogenerate -m "Description of changes"

# Review the generated migration file
# Edit if needed: alembic/versions/<timestamp>_description.py

# Apply migration
alembic upgrade head

Testing

# Run tests (Phase 2+)
pytest

# With coverage
pytest --cov=app tests/

📁 Project Structure

backend/
├── app/
│   ├── __init__.py
│   ├── main.py              # FastAPI app entry point
│   ├── config.py            # Settings (env vars)
│   ├── database.py          # SQLAlchemy async setup
│   ├── models/              # ORM models
│   │   ├── user.py
│   │   └── taxonomy.py
│   ├── schemas/             # Pydantic models
│   │   ├── auth.py
│   │   └── user.py
│   ├── api/v1/
│   │   ├── router.py        # API router
│   │   └── endpoints/
│   │       ├── auth.py      # Authentication
│   │       └── health.py    # Health check
│   ├── core/
│   │   ├── auth.py          # JWT utilities
│   │   └── dependencies.py  # RBAC middleware
│   └── utils/               # Utility functions
├── alembic/                 # Database migrations
├── tests/                   # Unit tests
├── requirements.txt
├── Dockerfile
└── seed_data.py             # Initial data seeding

🔧 Environment Variables

See .env.example for all available configuration options.

Required:

  • DATABASE_URL
  • POSTGRES_PASSWORD
  • REDIS_URL
  • QDRANT_URL
  • ENTRA_CLIENT_ID
  • ENTRA_CLIENT_SECRET
  • ENTRA_TENANT_ID
  • JWT_SECRET

Optional (for future phases):

  • OPENAI_API_KEY
  • GOOGLE_API_KEY
  • ANTHROPIC_API_KEY
  • NOTEBOOKLLAMA_URL

🎯 Phase 5: NotebookLlama Integration

Phase 5 implements the BFF (Backend for Frontend) pattern for NotebookLlama integration.

What Was Implemented

  1. Database Models (app/models/notebook.py)

    • NotebookSession: Maps internal sessions to external NotebookLlama sessions
    • UploadedFile: Tracks files uploaded to sessions
  2. Database Migration (alembic/versions/003_notebook_mode.py)

    • Creates notebook_sessions and uploaded_files tables
  3. NotebookLlama Client (app/core/notebook_client.py)

    • Wraps HTTP calls to external NotebookLlama API
    • Methods: create_notebook(), upload_document(), chat_stream()
  4. API Endpoints (app/api/v1/endpoints/notebook.py)

    • POST /api/v1/notebook/create - Create new notebook session
    • POST /api/v1/notebook/{id}/upload - Upload file to session
    • POST /api/v1/notebook/{id}/chat - Chat with streaming (SSE)
    • POST /api/v1/notebook/{id}/pin - Pin session (prevent expiration)
    • GET /api/v1/notebook/{id} - Get session details
    • DELETE /api/v1/notebook/{id} - Delete session

Key Features

  • Auto-expiration: Sessions expire after 24 hours by default
  • Pin feature: Users can pin sessions to prevent expiration
  • Quota management: Tracks total file size per session (100MB limit)
  • File upload: Validates file size, stores locally, proxies to NotebookLlama
  • Chat streaming: Uses Server-Sent Events (SSE) for real-time responses

Usage Example

# 1. Create a notebook session
curl -X POST "http://localhost:8000/api/v1/notebook/create" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{"title": "Financial Analysis"}'

# 2. Upload a file
curl -X POST "http://localhost:8000/api/v1/notebook/{session_id}/upload" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -F "file=@document.pdf"

# 3. Chat (frontend uses EventSource for SSE)
# See frontend documentation for streaming chat implementation

# 4. Pin the session
curl -X POST "http://localhost:8000/api/v1/notebook/{session_id}/pin" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Configuration

Update your .env file:

# NotebookLlama service URL
NOTEBOOKLLAMA_URL=http://internal-notebook-server:8080

# File upload settings
MAX_UPLOAD_SIZE_MB=100
UPLOAD_DIR=/app/uploads

Apply Migration

# Run the Phase 5 migration
alembic upgrade head

📝 Next Steps

Phase 3: SharePoint ingestion pipeline Phase 4: RAG logic & LLM router Phase 5: NotebookLlama integration COMPLETE Phase 6: Frontend development

See implementation_plan.md for details.