Skip to content

Architecture

RAG Pipeline

The assistant processes user queries through a Retrieval-Augmented Generation pipeline:

  1. Upload — files are uploaded via POST /upload, parsed, and chunked. Images are captioned via the vision model.
  2. Index — chunks are embedded and stored in Qdrant as vector documents
  3. Chat — at query time, relevant chunks are retrieved and injected into the prompt; the LLM autonomously calls skill tools to fetch live data
  4. Stream — the response is streamed back to the client via SSE

All of it shares one Qdrant collection: curated training material, administrator-shared files, and every member's own uploads. What separates them is metadata that the retrieval query does not currently read — see the companion's knowledge before changing anything on this path.

Component Overview

Component Module Role
FastAPI application main.py HTTP server (create_app factory), route registration, lifespan hooks
RAG pipeline rag.py LlamaIndex index, retrieval, query engine
Auth auth.py JWT verification via trusted headers or JWKS
History history.py Conversation and message persistence
Uploads uploads.py File storage, attachment management
Chat streaming openai_stream.py SSE token streaming with agentic tool-calling loop
Vision openai_vision.py Image captioning via the vision model
Model endpoint llm.py Clients for the configured OpenAI-compatible endpoint, embeddings, startup check
Document processing document_processing.py MIME detection and text extraction for uploads
Skills skills/ Modular skill system: Digital Twin, Weather, Flexibility, REC Registry, Documents
Suggestions suggestions.py Localized prompt suggestions and tool labels
Knowledge bases kb_collections.py Per-community alias naming, embedding fingerprint, generations, startup check (ADR-0008)
Knowledge sources kb_sources.py, kb_store.py Registered git/directory sources per community; incremental Markdown indexing
Attachment indexing attachment_index.py Extraction and indexing shared by uploads and rebuilds
Knowledge-base operations kb_admin.py, cli.py celine-assistant kb: status, sync, reindex, prune, migrate-legacy
Settings settings.py Pydantic-settings environment configuration

Modules that are not part of the pipeline

Present in src/, reachable from nothing, and easy to mistake for the supported path:

Module What it looks like What it is
src/celine/assistant/skills/datasets.py a dataset-query skill deliberately disabled — dataset-api needs a service token, and this service holds only the caller's (ADR-0005)

Deleting them is owed work, not a decision to re-take.

Frontend

This repository is a pure API backend. The chat UI is maintained separately in celine-frontend:

  • apps/assistant — standalone full-page assistant app

The frontend communicates with this API at apiBaseUrl.

Service Dependencies

Service Purpose
Model endpoint (OpenAI-compatible, LLM_BASE_URL) Chat completions, text embeddings, and vision (image captioning)
Qdrant Vector storage and similarity search
PostgreSQL Conversation history, attachment metadata
Digital Twin Energy data, weather, and forecast queries via skills
REC Registry Membership, assets, and delivery point queries via skills
Flexibility API Load-shift suggestions and gamification via skills
Keycloak / oauth2_proxy JWT authentication

Data Flow

Upload path:

POST /upload -> parse file -> (if image: caption via vision model) -> split into chunks -> embed (model endpoint) -> upsert (Qdrant) -> store metadata (PostgreSQL)

Chat path:

POST /chat -> verify JWT -> load history -> load authorized attachments -> retrieve context (Qdrant) -> build prompt -> stream (model endpoint, SSE with agentic tool-calling loop)

Database Models

PostgreSQL (async via SQLAlchemy + asyncpg). Alembic handles migrations. Models:

  • Conversation — linked to a user identity, the verified token's sub claim (REQ-0047)
  • Message — role (user/assistant), content, timestamp, optional attachment refs
  • Attachment — file metadata: name, MIME type, Qdrant collection reference, scope (user/system)