# jan-dyndor/llm_spam architecture

> Architecture diagram of the GitHub repository jan-dyndor/llm_spam, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/jan-dyndor/llm_spam
- Repository: https://github.com/jan-dyndor/llm_spam

## Overview

LLM Spam Classifier is an authenticated FastAPI service that classifies message text with Gemini, validates structured results, caches them, and stores prediction history. Its other documented product workflow evaluates the model against a golden dataset and persists metrics and per-example outputs. The graph also includes the documented logging and metrics observability stack. Router excerpts are partial, so links for unsampled endpoint behavior are based on README descriptions; peripheral wiring is omitted.

Main entry points: [`src/app/routers/v1.py`](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/routers/v1.py) (v1 API router), [`src/app/services/spam_classification.py`](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/services/spam_classification.py) (Spam classification), [`src/app/main.py`](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/main.py) (App lifecycle and telemetry), [`src/app/db/database.py`](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/db/database.py) (Async database access)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_api["API and identity"]
  node_router["v1 API router<br/>[v1.py]"]
  node_auth["JWT and passwords<br/>[auth.py]"]
  node_schemas["Request and response schemas"]
end

subgraph group_classification["Classification"]
  node_service["Spam classification"]
  node_prompt["Classification prompt<br/>[prompt_v1.py]"]
  node_gemini_client["Gemini client<br/>[gemini.py]"]
  node_retry["Retry policy<br/>[retry.py]"]
  node_redis[("Redis cache")]
end

subgraph group_data["Persistence"]
  node_database["Async database access<br/>[database.py]"]
  node_models["Persistent models<br/>[db_models.py]"]
end

subgraph group_evaluation["Model evaluation"]
  node_evaluation["Evaluation workflow<br/>[evaluate_model.py]"]
  node_golden_data["Golden dataset<br/>[golden_data.py]"]
end

subgraph group_observability["Observability"]
  node_main["App lifecycle and telemetry<br/>[main.py]"]
  node_prometheus[("Prometheus")]
  node_prom_config["Prometheus scrape config<br/>[prometheus.yml]"]
  node_alloy["Alloy log collection<br/>[config.alloy]"]
  node_loki[("Loki log store<br/>[loki-config.yml]")]
  node_grafana["Grafana dashboards<br/>[app_dashboard.json]"]
end

node_client(("API client"))
node_gemini{{"Google Gemini"}}
node_postgres[("PostgreSQL")]

node_client -->|"sends requests"| node_router
node_router -->|"validates data"| node_schemas
node_router -->|"verifies credentials"| node_auth
node_router -->|"queries and saves"| node_database
node_router -->|"classifies text"| node_service
node_router -->|"reads and writes cache"| node_redis
node_service -->|"uses prompt"| node_prompt
node_service -->|"requests inference"| node_gemini_client
node_service -->|"validates output"| node_schemas
node_service -->|"uses retry policy"| node_retry
node_gemini_client -->|"sends inference request"| node_gemini
node_main -->|"initializes client"| node_gemini_client
node_main -->|"creates schema and sessions"| node_database
node_main -->|"connects and clears"| node_redis
node_database -->|"reads and writes"| node_postgres
node_database -->|"maps records"| node_models
node_router -->|"runs evaluation"| node_evaluation
node_evaluation -->|"reads examples"| node_golden_data
node_evaluation -->|"classifies examples"| node_service
node_router -->|"persists evaluation results"| node_models
node_main -->|"exposes metrics"| node_prometheus
node_prom_config -->|"configures scraping"| node_prometheus
node_alloy -->|"ships logs"| node_loki
node_grafana -->|"visualizes metrics"| node_prometheus
node_grafana -->|"visualizes logs"| node_loki

click node_router "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/routers/v1.py"
click node_auth "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/authentication/auth.py"
click node_schemas "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/schemas/pydantic_schemas.py"
click node_service "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/services/spam_classification.py"
click node_prompt "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/prompts/prompt_v1.py"
click node_gemini_client "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/llm_clients/gemini.py"
click node_retry "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/retry_utils/retry.py"
click node_database "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/db/database.py"
click node_models "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/db/db_models.py"
click node_evaluation "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/evaluation/evaluate_model.py"
click node_golden_data "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/evaluation/golden_data_set/golden_data.py"
click node_main "https://github.com/jan-dyndor/llm_spam/blob/main/src/app/main.py"
click node_prom_config "https://github.com/jan-dyndor/llm_spam/blob/main/prometheus/prometheus.yml"
click node_alloy "https://github.com/jan-dyndor/llm_spam/blob/main/alloy/config.alloy"
click node_loki "https://github.com/jan-dyndor/llm_spam/blob/main/loki/loki-config.yml"
click node_grafana "https://github.com/jan-dyndor/llm_spam/blob/main/grafana/dashboards/app_dashboard.json"

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_router,node_auth,node_schemas,node_client toneBlue
class node_service,node_prompt,node_gemini_client,node_retry,node_redis,node_postgres toneAmber
class node_database,node_models toneMint
class node_evaluation,node_golden_data toneRose
class node_main,node_prometheus,node_prom_config,node_alloy,node_loki,node_grafana,node_gemini toneIndigo
```

## Components

### API and identity

- [v1 API router](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/routers/v1.py): `src/app/routers/v1.py`
- [JWT and passwords](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/authentication/auth.py): `src/app/authentication/auth.py`
- [Request and response schemas](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/schemas/pydantic_schemas.py): `src/app/schemas/pydantic_schemas.py`

### Classification

- [Spam classification](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/services/spam_classification.py): `src/app/services/spam_classification.py`
- [Classification prompt](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/prompts/prompt_v1.py): `src/app/prompts/prompt_v1.py`
- [Gemini client](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/llm_clients/gemini.py): `src/app/llm_clients/gemini.py`
- [Retry policy](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/retry_utils/retry.py): `src/app/retry_utils/retry.py`
- **Redis cache**

### Persistence

- [Async database access](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/db/database.py): `src/app/db/database.py`
- [Persistent models](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/db/db_models.py): `src/app/db/db_models.py`

### Model evaluation

- [Evaluation workflow](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/evaluation/evaluate_model.py): `src/app/evaluation/evaluate_model.py`
- [Golden dataset](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/evaluation/golden_data_set/golden_data.py): `src/app/evaluation/golden_data_set/golden_data.py`

### Observability

- [App lifecycle and telemetry](https://github.com/jan-dyndor/llm_spam/blob/main/src/app/main.py): `src/app/main.py`
- **Prometheus**
- [Prometheus scrape config](https://github.com/jan-dyndor/llm_spam/blob/main/prometheus/prometheus.yml): `prometheus/prometheus.yml`
- [Alloy log collection](https://github.com/jan-dyndor/llm_spam/blob/main/alloy/config.alloy): `alloy/config.alloy`
- [Loki log store](https://github.com/jan-dyndor/llm_spam/blob/main/loki/loki-config.yml): `loki/loki-config.yml`
- [Grafana dashboards](https://github.com/jan-dyndor/llm_spam/blob/main/grafana/dashboards/app_dashboard.json): `grafana/dashboards/app_dashboard.json`

### Other components

- **API client**
- **Google Gemini**
- **PostgreSQL**

## Connections

- API client → v1 API router: sends requests
- v1 API router → Request and response schemas: validates data
- v1 API router → JWT and passwords: verifies credentials
- v1 API router → Async database access: queries and saves
- v1 API router → Spam classification: classifies text
- v1 API router → Redis cache: reads and writes cache
- Spam classification → Classification prompt: uses prompt
- Spam classification → Gemini client: requests inference
- Spam classification → Request and response schemas: validates output
- Spam classification → Retry policy: uses retry policy
- Gemini client → Google Gemini: sends inference request
- App lifecycle and telemetry → Gemini client: initializes client
- App lifecycle and telemetry → Async database access: creates schema and sessions
- App lifecycle and telemetry → Redis cache: connects and clears
- Async database access → PostgreSQL: reads and writes
- Async database access → Persistent models: maps records
- v1 API router → Evaluation workflow: runs evaluation
- Evaluation workflow → Golden dataset: reads examples
- Evaluation workflow → Spam classification: classifies examples
- v1 API router → Persistent models: persists evaluation results
- App lifecycle and telemetry → Prometheus: exposes metrics
- Prometheus scrape config → Prometheus: configures scraping
- Alloy log collection → Loki log store: ships logs
- Grafana dashboards → Prometheus: visualizes metrics
- Grafana dashboards → Loki log store: visualizes logs
