# razin-ccc/chatbot architecture

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

- Interactive diagram: https://gitdiagram.com/razin-ccc/chatbot
- Repository: https://github.com/razin-ccc/chatbot

## Overview

1. **Overall shape**
   This is a two-tier full-stack chatbot: a **Next.js frontend** talks to a **FastAPI backend**. The backend is not a simple request/response API; it centralizes the product logic in a **LangGraph state machine** that routes each message to chat, document RAG, weather, or bug-report handling.

2. **Frontend boundary**
   The frontend lives under `frontend/Chatbot` and uses the Next.js App Router. Its main user surfaces are:
   - public marketing pages
   - `/login` and `/register`
   - `/chat` for the main assistant experience
   - `/admin` for ticket review
   The UI is mostly a thin client over backend APIs, with dedicated hooks and API wrappers for auth, chat, conversations, documents, and admin flows.

3. **Primary backend boundary**
   The backend lives under `backend/app` and is organized around FastAPI route modules:
   - `auth/` for JWT, refresh cookies, scopes, and RBAC
   - `api/routes/` for chat, conversations, documents, admin, and health
   - `services/` for the actual business logic
   - `services/graph/` for the LangGraph orchestration layer
   This separation makes the HTTP layer relatively thin while the orchestration and integrations sit in services.

4. **Core chat flow**
   All assistant interactions go through a single `POST /chat` endpoint. The frontend does not choose the mode; it sends the message, conversation ID, and auth token, and the backend decides the path. Responses are streamed back with **Server-Sent Events**, which the frontend parses incrementally so the assistant can render token-by-token output.

5. **LangGraph orchestration**
   The center of the system is `services/graph/runner.py` and the nodes under `services/graph/nodes/`. The graph first classifies the message, then routes to one of four paths:
   - general chat
   - document RAG
   - weather
   - bug report
   The classifier uses simple pattern matching first, then Gemini-based structured classification when needed. This is the main architectural boundary between “user intent” and the concrete capability that handles it.

6. **Document RAG subsystem**
   Documents are scoped to a conversation. Uploads go through the documents API, are parsed and chunked, embedded with a local **ONNX BGE-small model**, and stored in a **vector store**. Retrieval uses query embedding, vector search, and reranking before the writer node streams a grounded answer. The design keeps document Q&A isolated to the active conversation and its documents rather than searching globally.

7. **Storage model**
   The persistent state is split by purpose:
   - **PostgreSQL** stores durable records: users, sessions, conversations, messages, documents, and pending Jira tickets
   - **Redis** stores hot conversation state, summaries, and rate-limit keys
   - **Vector store / Pinecone** stores document embeddings for RAG
   This dual-memory pattern means the assistant can keep recent context quickly while still rehydrating from durable history when needed.

8. **Authentication and authorization**
   Auth is JWT-based with a short-lived access token and an **httpOnly refresh cookie**. The `auth/` package also implements permissions/scopes, with role-based access control for admin-only actions like `ticket:manage`. The frontend has separate login/register flows, and protected UI areas depend on the authenticated user and their permissions.

9. **Bug report to Jira workflow**
   Bug reports are handled as a human-reviewed pipeline, not an automatic ticket dump. The graph extracts a title and description, inserts a `pending_jira_tickets` row, and returns a confirmation in chat. The admin dashboard then approves or rejects the item:
   - approval creates a Jira issue and sends email
   - rejection sends a rejection email
   This workflow is intentionally gated by admin permissions and backed by database state for traceability.

10. **External integrations**
   The backend integrates with several external systems that materially shape the architecture:
   - **Google Gemini** for chat, classification, summarization, and ticket extraction
   - **Open-Meteo** for weather lookup
   - **Cohere Rerank** for RAG quality improvement
   - **Jira Cloud** for approved bug tickets
   - **SMTP** for notifications
   These integrations are isolated behind service modules so the API routes and graph nodes do not directly embed external protocol logic.

11. **Data access and persistence lifecycle**
   Chat turns are streamed, then persisted after completion. The runner loads conversation state, streams graph events to the client, and finally writes message history and updated summaries back to storage. Document indexing is asynchronous, which means a conversation may temporarily have uploaded PDFs that are not yet eligible for RAG routing until indexing finishes.

12. **Deployment and runtime**
   The backend is containerized with a multi-stage Docker build, and the repo includes `docker-compose.yml` for running the stack together. The backend uses Python tooling (`uv`, Alembic migrations, SQLAlchemy async), while the frontend is a separate Node/Next.js runtime. The local ONNX model files are checked into the backend tree because embeddings run on CPU locally rather than via a hosted embedding API.

13. **What to draw in an architecture diagram**
   The key boxes are: frontend pages/components, FastAPI route layer, auth subsystem, LangGraph orchestrator, RAG/document pipeline, Redis, PostgreSQL, vector store, and external services (Gemini, Jira, SMTP, Open-Meteo, Cohere). The most important arrows are:
   - frontend SSE chat traffic to `POST /chat`
   - `POST /chat` to LangGraph runner
   - graph nodes to Redis/PostgreSQL/vector store and external APIs
   - admin actions from `/admin` to PostgreSQL, Jira, and email

Main entry points: [`backend/app/api/routes`](https://github.com/razin-ccc/chatbot/tree/main/backend/app/api/routes) (API Routes), [`backend/app/services/graph/runner.py`](https://github.com/razin-ccc/chatbot/blob/main/backend/app/services/graph/runner.py) (Graph Runner), [`backend/app/services/graph/nodes`](https://github.com/razin-ccc/chatbot/tree/main/backend/app/services/graph/nodes) (Graph Nodes), [`backend/app/services/rag.py`](https://github.com/razin-ccc/chatbot/blob/main/backend/app/services/rag.py) (RAG Pipeline)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["Frontend"]
  node_frontend_app["App Router<br/>Next.js UI"]
  node_frontend_chat["Chat UI<br/>client chat"]
  node_frontend_hooks["Client Hooks<br/>state hooks"]
  node_frontend_api["API Client<br/>fetch layer"]
  node_frontend_stream["SSE Parser<br/>stream parser<br/>[sseParser.ts]"]
end

subgraph group_backend["Backend"]
  node_backend_main["FastAPI App<br/>HTTP app<br/>[main.py]"]
  node_backend_routes["API Routes<br/>route layer"]
  node_backend_auth["Auth Stack<br/>jwt/rbac"]
  node_backend_graph{{"Graph Runner<br/>orchestration<br/>[runner.py]"}}
  node_backend_classifier["Intent Classifier<br/>routing logic<br/>[classifier.py]"]
  node_backend_nodes["Graph Nodes<br/>capabilities"]
  node_backend_rag["RAG Pipeline<br/>document qa<br/>[rag.py]"]
  node_backend_memory[("Conversation Memory<br/>state service<br/>[memory.py]")]
  node_backend_persist["Data Services<br/>persistence"]
end

subgraph group_storage["Storage"]
  node_storage_db[("PostgreSQL<br/>durable store")]
  node_storage_redis[("Redis<br/>hot state")]
  node_storage_vector[("Vector Store<br/>embeddings store")]
end

subgraph group_external["External"]
  node_external_ai(("AI Services<br/>LLM/embed/rerank<br/>[model.onnx]"))
  node_external_ops(("Ops Services<br/>jira/email/weather"))
end

node_frontend_app -->|"calls APIs"| node_frontend_api
node_frontend_chat -->|"parses SSE"| node_frontend_stream
node_frontend_chat -->|"uses hooks"| node_frontend_hooks
node_frontend_hooks -->|"requests data"| node_frontend_api
node_frontend_api -->|"HTTP/SSE"| node_backend_routes
node_backend_main -->|"mounts"| node_backend_routes
node_backend_routes -->|"protects"| node_backend_auth
node_backend_routes -->|"POST /chat"| node_backend_graph
node_backend_routes -->|"admin/docs"| node_backend_persist
node_backend_graph -->|"routes intent"| node_backend_classifier
node_backend_classifier -->|"selects node"| node_backend_nodes
node_backend_nodes -->|"grounded answers"| node_backend_rag
node_backend_graph -->|"loads state"| node_backend_memory
node_backend_memory -->|"hot context"| node_storage_redis
node_backend_persist -->|"stores records"| node_storage_db
node_backend_rag -->|"retrieves embeddings"| node_storage_vector
node_backend_rag -->|"embed/re-rank"| node_external_ai
node_backend_graph -->|"LLM calls"| node_external_ai
node_backend_nodes -->|"integrates"| node_external_ops
node_backend_persist -->|"users/roles"| node_backend_auth

click node_frontend_app "https://github.com/razin-ccc/chatbot/tree/main/frontend/Chatbot/app"
click node_frontend_chat "https://github.com/razin-ccc/chatbot/tree/main/frontend/Chatbot/components/chat"
click node_frontend_hooks "https://github.com/razin-ccc/chatbot/tree/main/frontend/Chatbot/hooks"
click node_frontend_api "https://github.com/razin-ccc/chatbot/tree/main/frontend/Chatbot/lib/api"
click node_frontend_stream "https://github.com/razin-ccc/chatbot/blob/main/frontend/Chatbot/lib/stream/sseParser.ts"
click node_backend_main "https://github.com/razin-ccc/chatbot/blob/main/backend/app/main.py"
click node_backend_routes "https://github.com/razin-ccc/chatbot/tree/main/backend/app/api/routes"
click node_backend_auth "https://github.com/razin-ccc/chatbot/tree/main/backend/app/auth"
click node_backend_graph "https://github.com/razin-ccc/chatbot/blob/main/backend/app/services/graph/runner.py"
click node_backend_classifier "https://github.com/razin-ccc/chatbot/blob/main/backend/app/services/graph/classifier.py"
click node_backend_nodes "https://github.com/razin-ccc/chatbot/tree/main/backend/app/services/graph/nodes"
click node_backend_rag "https://github.com/razin-ccc/chatbot/blob/main/backend/app/services/rag.py"
click node_backend_memory "https://github.com/razin-ccc/chatbot/blob/main/backend/app/services/memory.py"
click node_backend_persist "https://github.com/razin-ccc/chatbot/tree/main/backend/app/services"
click node_external_ai "https://github.com/razin-ccc/chatbot/blob/main/backend/app/models/onnx/baai-bge-small/model.onnx"

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_frontend_app,node_frontend_chat,node_frontend_hooks,node_frontend_api,node_frontend_stream toneBlue
class node_backend_main,node_backend_routes,node_backend_auth,node_backend_graph,node_backend_classifier,node_backend_nodes,node_backend_rag,node_backend_memory,node_backend_persist toneAmber
class node_storage_db,node_storage_redis,node_storage_vector toneMint
class node_external_ai,node_external_ops toneRose
```

## Components

### Frontend

Next.js app and client-side feature modules

- [App Router](https://github.com/razin-ccc/chatbot/tree/main/frontend/Chatbot/app): Next.js UI · Public pages plus chat, login, register, and admin routes · `frontend/Chatbot/app`
- [Chat UI](https://github.com/razin-ccc/chatbot/tree/main/frontend/Chatbot/components/chat): client chat · Streaming chat shell, conversation list, documents panel, and message rendering · `frontend/Chatbot/components/chat`
- [Client Hooks](https://github.com/razin-ccc/chatbot/tree/main/frontend/Chatbot/hooks): state hooks · Auth, chat, conversation, and document hooks that wrap backend APIs · `frontend/Chatbot/hooks`
- [API Client](https://github.com/razin-ccc/chatbot/tree/main/frontend/Chatbot/lib/api): fetch layer · Typed API wrappers for auth, chat, conversations, documents, and admin · `frontend/Chatbot/lib/api`
- [SSE Parser](https://github.com/razin-ccc/chatbot/blob/main/frontend/Chatbot/lib/stream/sseParser.ts): stream parser · Parses streamed assistant responses into incremental UI updates · `frontend/Chatbot/lib/stream/sseParser.ts`

### Backend

FastAPI app, orchestration, and services

- [FastAPI App](https://github.com/razin-ccc/chatbot/blob/main/backend/app/main.py): HTTP app · Application entrypoint, middleware, and route registration · `backend/app/main.py`
- [API Routes](https://github.com/razin-ccc/chatbot/tree/main/backend/app/api/routes): route layer · Chat, conversations, documents, admin, and health endpoints · `backend/app/api/routes`
- [Auth Stack](https://github.com/razin-ccc/chatbot/tree/main/backend/app/auth): jwt/rbac · JWT access tokens, refresh cookies, scopes, and role checks · `backend/app/auth`
- [Graph Runner](https://github.com/razin-ccc/chatbot/blob/main/backend/app/services/graph/runner.py): orchestration · LangGraph state machine that classifies intent and coordinates response paths · `backend/app/services/graph/runner.py`
- [Intent Classifier](https://github.com/razin-ccc/chatbot/blob/main/backend/app/services/graph/classifier.py): routing logic · Pattern-first then Gemini-backed classification into chat, RAG, weather, or bug report · `backend/app/services/graph/classifier.py`
- [Graph Nodes](https://github.com/razin-ccc/chatbot/tree/main/backend/app/services/graph/nodes): capabilities · Chat, RAG, weather, and bug-report nodes executed by the graph · `backend/app/services/graph/nodes`
- [RAG Pipeline](https://github.com/razin-ccc/chatbot/blob/main/backend/app/services/rag.py): document qa · Upload, parse, chunk, embed, retrieve, rerank, and answer from conversation-scoped documents · `backend/app/services/rag.py`
- [Conversation Memory](https://github.com/razin-ccc/chatbot/blob/main/backend/app/services/memory.py): state service · Loads, summarizes, and persists conversation state across turns · `backend/app/services/memory.py`
- [Data Services](https://github.com/razin-ccc/chatbot/tree/main/backend/app/services): persistence · User, conversation, message, document, and ticket data access · `backend/app/services`

### Storage

Persistent and hot state stores

- **PostgreSQL**: durable store · Users, sessions, conversations, messages, documents, and pending Jira tickets
- **Redis**: hot state · Conversation summaries, active state, and rate-limit keys
- **Vector Store**: embeddings store · Document embeddings used for retrieval augmented generation

### External

Third-party APIs and local ML assets

- [AI Services](https://github.com/razin-ccc/chatbot/blob/main/backend/app/models/onnx/baai-bge-small/model.onnx): LLM/embed/rerank · Gemini, Cohere rerank, and local ONNX embeddings model · `backend/app/models/onnx/baai-bge-small/model.onnx`
- **Ops Services**: jira/email/weather · Jira Cloud, SMTP notifications, and Open-Meteo weather lookup

## Connections

- App Router → API Client: calls APIs · Pages and routes delegate data operations to typed client wrappers
- Chat UI → SSE Parser: parses SSE · Streaming chat UI incrementally renders assistant output
- Chat UI → Client Hooks: uses hooks · Chat screens coordinate state through custom hooks
- Client Hooks → API Client: requests data · Hooks invoke backend endpoints through API wrappers
- API Client → API Routes: HTTP/SSE · Client talks to chat, auth, conversation, document, and admin endpoints
- FastAPI App → API Routes: mounts · FastAPI application registers the route modules
- API Routes → Auth Stack: protects · Protected endpoints validate tokens, cookies, and scopes
- API Routes → Graph Runner: POST /chat · Chat endpoint hands messages to the orchestration runner
- API Routes → Data Services: admin/docs · Conversation, document, and ticket flows persist through service layer
- Graph Runner → Intent Classifier: routes intent · Runner classifies each turn before selecting a capability path
- Intent Classifier → Graph Nodes: selects node · Classification chooses chat, RAG, weather, or bug-report execution
- Graph Nodes → RAG Pipeline: grounded answers · RAG node delegates document retrieval and answer synthesis
- Graph Runner → Conversation Memory: loads state · Runner rehydrates and updates conversation context
- Conversation Memory → Redis: hot context · Summaries and active conversation state live in Redis
- Data Services → PostgreSQL: stores records · Durable app data is written to PostgreSQL
- RAG Pipeline → Vector Store: retrieves embeddings · Document chunks are searched in the vector store
- RAG Pipeline → AI Services: embed/re-rank · Uses ONNX embeddings and Cohere reranking for retrieval quality
- Graph Runner → AI Services: LLM calls · Gemini powers chat generation, classification fallback, summarization, and ticket extraction
- Graph Nodes → Ops Services: integrates · Weather lookup, Jira creation, and email notifications are handled externally
- Data Services → Auth Stack: users/roles · Auth subsystem depends on user and permission records
