# igoralekseev-dev/rag-vector-chat architecture

> Architecture diagram of the GitHub repository igoralekseev-dev/rag-vector-chat, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-28). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/igoralekseev-dev/rag-vector-chat
- Repository: https://github.com/igoralekseev-dev/rag-vector-chat

## Overview

1. This repository is a self-hosted RAG chat application built as a FastAPI backend with server-rendered HTML. The UI is not a SPA: it uses Jinja2 templates plus HTMX-style partial updates to refresh chat, document, and message fragments from the server.

2. The codebase is split into two main application domains: `chat` and `documents`. `chat` owns chat lifecycle, message history, and response generation. `documents` owns PDF upload, parsing, chunking, embedding, and indexing into the vector store.

3. `src/main.py` is the application bootstrap point. It likely assembles the FastAPI app, registers routers from both domains, and wires startup configuration and shared dependencies such as database and vector/LLM clients.

4. `src/config.py` centralizes runtime settings from environment variables, including the SQLite database URL, Qdrant endpoint, and OpenAI-compatible LLM credentials/model name. This makes the app portable across local and Docker Compose deployments.

5. `src/database.py` is the relational persistence boundary. The README indicates SQLite is used to store chat history, messages, and uploaded file metadata. This relational layer keeps the app lightweight and acts as the source of truth for chat/session state.

6. The vector-search boundary is Qdrant. Documents are split into chunks, embedded with Sentence Transformers, and stored in Qdrant with metadata tied to `chat_id`. That `chat_id` filter is the key isolation mechanism that prevents retrieval from mixing content across chats.

7. The `documents` subsystem likely follows a pipeline: receive PDF upload through `documents/router.py`, parse and normalize file content in `documents/utils.py`, then persist document records and upsert vectors via `documents/service.py`. The relational DB records the file, while Qdrant stores the semantic index.

8. The `chat` subsystem exposes routes for creating/opening chats and sending messages. `chat/models.py` and `chat/schemas.py` define the data shape for persisted chat entities and API/request-response payloads, while `chat/service.py` handles the business logic for message persistence, retrieval of relevant chunks, prompt assembly, and calling the language model.

9. LLM generation is externalized behind an OpenAI-compatible API. The repository does not appear to hardcode a specific provider; instead, the model endpoint, API key, and model name are configurable, which is an important architectural boundary for swapping providers without changing the UI or domain logic.

10. The rendered UI is composed of reusable partials under `src/templates/partials/`. These fragments correspond to distinct functional areas such as the sidebar chat list, the active chat workspace, message pairs, document cards, and “new chat” responses. That indicates a page layout driven by incremental server-side updates rather than client-side state management.

11. The end-to-end data flow is: user creates/selects a chat, uploads one or more PDFs, documents are chunked and indexed, then the user asks a question. On message submit, the backend searches Qdrant only within that chat, injects the relevant context into the prompt, sends it to the LLM, stores the answer in SQLite, and returns updated HTML fragments to the browser.

12. Deployment is designed around local or containerized execution. `docker-compose.yml` runs the app alongside Qdrant, and the README notes that the project can be run entirely self-hosted. The dependency set in `pyproject.toml` supports async Python web execution, PDF parsing, vector search, and templated HTML rendering.

13. From an architecture-diagram perspective, the important boundaries are: browser/UI, FastAPI server, SQLite relational store, Qdrant vector store, and external LLM API. The `chat` and `documents` modules sit inside the FastAPI boundary as separate vertical slices that share config and database infrastructure but have distinct responsibilities.

Main entry points: [`src/chat/service.py`](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/chat/service.py) (Chat Service), [`src/main.py`](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/main.py) (Bootstrap), [`src/documents/service.py`](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/documents/service.py) (Doc Service), [`src/chat/router.py`](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/chat/router.py) (Chat Routes)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ui["Browser UI"]
  node_browser(("Browser<br/>client"))
  node_templates_index["Index Page<br/>jinja2 page<br/>[index.html]"]
  node_templates_partials["Partial Views<br/>jinja2 partials"]
end

subgraph group_app["FastAPI App"]
  node_main{{"Bootstrap<br/>app entry<br/>[main.py]"}}
  node_config["Config<br/>settings<br/>[config.py]"]
end

subgraph group_chat["Chat Domain"]
  node_chat_router["Chat Routes<br/>http routes<br/>[router.py]"]
  node_chat_service{{"Chat Service<br/>domain logic<br/>[service.py]"}}
  node_chat_models["Chat Models<br/>orm models<br/>[models.py]"]
  node_chat_schemas["Chat Schemas<br/>api schemas<br/>[schemas.py]"]
end

subgraph group_docs["Documents Domain"]
  node_doc_router["Doc Routes<br/>http routes<br/>[router.py]"]
  node_doc_service{{"Doc Service<br/>pipeline logic<br/>[service.py]"}}
  node_doc_utils["Doc Utils<br/>pdf helpers<br/>[utils.py]"]
end

subgraph group_data["Data Stores"]
  node_database[("Database<br/>sqlite boundary<br/>[database.py]")]
end

subgraph group_ext["External Services"]
  node_qdrant[("Qdrant<br/>vector store")]
  node_llm_api["LLM API<br/>external model"]
end

node_browser -->|"load UI"| node_templates_index
node_browser -->|"chat actions"| node_chat_router
node_browser -->|"upload PDFs"| node_doc_router
node_main -->|"reads settings"| node_config
node_main -->|"registers"| node_chat_router
node_main -->|"registers"| node_doc_router
node_main -->|"connects"| node_database
node_chat_router -->|"delegates"| node_chat_service
node_chat_service -->|"persists"| node_chat_models
node_chat_service -->|"reads/writes"| node_database
node_chat_service -->|"retrieves context"| node_qdrant
node_chat_service -->|"generates reply"| node_llm_api
node_chat_service -->|"renders fragments"| node_templates_partials
node_doc_router -->|"delegates"| node_doc_service
node_doc_service -->|"parses files"| node_doc_utils
node_doc_service -->|"stores metadata"| node_database
node_doc_service -->|"indexes chunks"| node_qdrant
node_templates_index -->|"composes"| node_templates_partials
node_qdrant -->|"endpoint"| node_config
node_llm_api -->|"credentials"| node_config

click node_templates_index "https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/templates/index.html"
click node_templates_partials "https://github.com/igoralekseev-dev/rag-vector-chat/tree/main/src/templates/partials"
click node_main "https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/main.py"
click node_config "https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/config.py"
click node_database "https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/database.py"
click node_chat_router "https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/chat/router.py"
click node_chat_service "https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/chat/service.py"
click node_chat_models "https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/chat/models.py"
click node_chat_schemas "https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/chat/schemas.py"
click node_doc_router "https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/documents/router.py"
click node_doc_service "https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/documents/service.py"
click node_doc_utils "https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/documents/utils.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_browser,node_templates_index,node_templates_partials toneBlue
class node_main,node_config toneAmber
class node_chat_router,node_chat_service,node_chat_models,node_chat_schemas toneMint
class node_doc_router,node_doc_service,node_doc_utils toneRose
class node_database toneIndigo
class node_qdrant,node_llm_api toneTeal
```

## Components

### Browser UI

Server-rendered HTML interface with partial updates.

- **Browser**: client · User-facing browser session interacting with server-rendered pages.
- [Index Page](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/templates/index.html): jinja2 page · Main server-rendered shell for the chat application. · `src/templates/index.html`
- [Partial Views](https://github.com/igoralekseev-dev/rag-vector-chat/tree/main/src/templates/partials): jinja2 partials · Reusable fragments for chat, documents, and message updates. · `src/templates/partials`

### FastAPI App

Application bootstrap and domain routes.

- [Bootstrap](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/main.py): app entry · Creates the FastAPI app and wires shared dependencies and routers. · `src/main.py`
- [Config](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/config.py): settings · Environment-driven runtime settings for database, Qdrant, and LLM access. · `src/config.py`

### Chat Domain

Chat lifecycle, history, and answer generation.

- [Chat Routes](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/chat/router.py): http routes · Endpoints for chat creation, selection, and message submission. · `src/chat/router.py`
- [Chat Service](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/chat/service.py): domain logic · Coordinates history, retrieval, prompt assembly, and response generation. · `src/chat/service.py`
- [Chat Models](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/chat/models.py): orm models · Persistent chat and message entities. · `src/chat/models.py`
- [Chat Schemas](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/chat/schemas.py): api schemas · Request and response payload shapes for the chat domain. · `src/chat/schemas.py`

### Documents Domain

PDF upload, parsing, chunking, and indexing.

- [Doc Routes](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/documents/router.py): http routes · Endpoints for PDF upload and document management. · `src/documents/router.py`
- [Doc Service](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/documents/service.py): pipeline logic · Handles parsing, chunking, embedding, and vector indexing. · `src/documents/service.py`
- [Doc Utils](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/documents/utils.py): pdf helpers · File parsing and normalization helpers for document ingestion. · `src/documents/utils.py`

### Data Stores

Relational and vector persistence boundaries.

- [Database](https://github.com/igoralekseev-dev/rag-vector-chat/blob/main/src/database.py): sqlite boundary · Relational persistence layer for chats, messages, and file metadata. · `src/database.py`

### External Services

LLM and vector infrastructure used by the app.

- **Qdrant**: vector store · Semantic index for document chunks filtered by chat.
- **LLM API**: external model · OpenAI-compatible completion endpoint used for response generation.

## Connections

- Browser → Index Page: load UI · The browser requests the server-rendered application shell.
- Browser → Chat Routes: chat actions · User interactions submit chat and message requests to the backend.
- Browser → Doc Routes: upload PDFs · Document uploads are sent to the documents endpoints.
- Bootstrap → Config: reads settings · Bootstrap loads runtime configuration from the environment.
- Bootstrap → Chat Routes: registers · Chat routes are mounted on the FastAPI app.
- Bootstrap → Doc Routes: registers · Document routes are mounted on the FastAPI app.
- Bootstrap → Database: connects · Shared relational persistence is initialized at startup.
- Chat Routes → Chat Service: delegates · HTTP handlers pass work into chat business logic.
- Chat Service → Chat Models: persists · Chat and message records are stored through the domain models.
- Chat Service → Database: reads/writes · The chat service uses SQLite-backed state and history.
- Chat Service → Qdrant: retrieves context · Relevant chunks are fetched from the vector store using chat-scoped filters.
- Chat Service → LLM API: generates reply · Prompted context is sent to the external language model endpoint.
- Chat Service → Partial Views: renders fragments · Updated message and workspace fragments are returned to the browser.
- Doc Routes → Doc Service: delegates · Upload handlers pass documents into the ingestion pipeline.
- Doc Service → Doc Utils: parses files · Helper routines normalize PDF content before chunking.
- Doc Service → Database: stores metadata · Uploaded document records are persisted relationally.
- Doc Service → Qdrant: indexes chunks · Embedded chunks are upserted into the vector database.
- Index Page → Partial Views: composes · The main page is assembled from reusable partial fragments.
- Qdrant → Config: endpoint · Vector-store connection details come from shared configuration.
- LLM API → Config: credentials · Model endpoint, API key, and model name are configured centrally.
