# cpf-cadt/legal-rag architecture

> Architecture diagram of the GitHub repository cpf-cadt/legal-rag, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-10). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/cpf-cadt/legal-rag
- Repository: https://github.com/cpf-cadt/legal-rag

## Overview

LegalRAG serves Cambodian legal search and source-grounded answers. Users enter through the web client or Telegram; API requests are routed to retrieval or answering, and answers retain legal sources as references. The corpus path covers document acquisition, OCR/preparation, and separate BM25 and dense indexes. The graph also includes query correction and the Telegram delivery branch. Several pipeline, runtime, and client implementations were not excerpted, so their links are shown only where documentation or indexed references support them; dashed links are unverified.

Main entry points: [`apps/core/runtime_factory.py`](https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/runtime_factory.py) (Legal retrievers), [`apps/react-client/src/App.tsx`](https://github.com/cpf-cadt/legal-rag/blob/main/apps/react-client/src/App.tsx) (Web application), [`apps/api/main.py`](https://github.com/cpf-cadt/legal-rag/blob/main/apps/api/main.py) (HTTP routes), [`apps/core/answer_service.py`](https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/answer_service.py) (Grounded answer service)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_clients["User clients"]
  node_web["Web application<br/>[App.tsx]"]
  node_chat["Chat and search pages<br/>[ChatPage.tsx]"]
  node_search_page["Search results"]
  node_article_page["Article view<br/>[ArticlePage.tsx]"]
  node_api_client["Web API client<br/>[apiClient.ts]"]
end

subgraph group_api["API services"]
  node_api_routes["HTTP routes<br/>[main.py]"]
  node_search_service["Search use case<br/>[application.py]"]
  node_summary_service["Summary use case<br/>[application.py]"]
  node_runtime["Runtime assembly<br/>[infrastructure.py]"]
end

subgraph group_retrieval["Retrieval and answers"]
  node_retriever["Legal retrievers<br/>[runtime_factory.py]"]
  node_bm25_runtime["SQLite BM25 search"]
  node_dense_runtime["Dense search<br/>[retriever.py]"]
  node_query_correction["Khmer query correction"]
  node_answer_service["Grounded answer service<br/>[answer_service.py]"]
  node_generator["LLM generation<br/>[llm_generator.py]"]
end

subgraph group_corpus["Corpus and indexes"]
  node_download["Document acquisition<br/>[scraper.py]"]
  node_ocr["OCR processing<br/>[processor.py]"]
  node_bm25_pipeline["BM25 index builder<br/>[pipeline.py]"]
  node_bm25_store[("SQLite FTS index<br/>[sqlite_index.py]")]
  node_tokenizer["Khmer tokenizer<br/>[tokenizer.py]"]
  node_dense_pipeline["Dense index builder<br/>[pipeline.py]"]
  node_preprocess["Text preparation<br/>[text_preprocess.py]"]
  node_embeddings["Embedding generation<br/>[embeddings.py]"]
  node_chroma[("Chroma vector index<br/>[chroma_index.py]")]
end

subgraph group_bot["Telegram bot"]
  node_bot_entry["Bot entry and dispatch<br/>[main.py]"]
  node_bot_handlers["Message handlers<br/>[handlers.py]"]
  node_bot_client["API client<br/>[api_client.py]"]
end

node_user(("Legal information seeker"))
node_telegram(("Telegram user"))

node_user -->|"uses"| node_web
node_web -->|"routes to"| node_chat
node_web -->|"routes to"| node_search_page
node_web -->|"routes to"| node_article_page
node_chat -.->|"requests"| node_api_client
node_search_page -->|"requests"| node_api_client
node_api_client -.->|"calls"| node_api_routes
node_api_routes -->|"dispatches search"| node_search_service
node_api_routes -->|"dispatches summary"| node_summary_service
node_api_routes -->|"builds runtime"| node_runtime
node_runtime -->|"constructs"| node_retriever
node_search_service -->|"searches"| node_retriever
node_summary_service -->|"answers via"| node_answer_service
node_answer_service -->|"retrieves evidence"| node_retriever
node_answer_service -->|"generates answer"| node_generator
node_retriever -.->|"selects implementation"| node_bm25_runtime
node_retriever -.->|"selects implementation"| node_dense_runtime
node_bm25_runtime -->|"corrects query"| node_query_correction
node_dense_runtime -->|"corrects query"| node_query_correction
node_download -.->|"supplies documents"| node_ocr
node_bm25_pipeline -->|"builds index"| node_bm25_store
node_bm25_store -->|"uses"| node_tokenizer
node_dense_pipeline -->|"prepares text"| node_preprocess
node_dense_pipeline -->|"embeds chunks"| node_embeddings
node_dense_pipeline -->|"builds index"| node_chroma
node_telegram -->|"sends message"| node_bot_entry
node_bot_entry -->|"registers handlers"| node_bot_handlers
node_bot_handlers -->|"requests answer"| node_answer_service
node_bot_entry -->|"creates client"| node_bot_client

click node_web "https://github.com/cpf-cadt/legal-rag/blob/main/apps/react-client/src/App.tsx"
click node_chat "https://github.com/cpf-cadt/legal-rag/blob/main/apps/react-client/src/pages/ChatPage.tsx"
click node_search_page "https://github.com/cpf-cadt/legal-rag/blob/main/apps/react-client/src/pages/SearchResultsPage.tsx"
click node_article_page "https://github.com/cpf-cadt/legal-rag/blob/main/apps/react-client/src/pages/ArticlePage.tsx"
click node_api_client "https://github.com/cpf-cadt/legal-rag/blob/main/apps/react-client/src/services/apiClient.ts"
click node_api_routes "https://github.com/cpf-cadt/legal-rag/blob/main/apps/api/main.py"
click node_search_service "https://github.com/cpf-cadt/legal-rag/blob/main/apps/api/application.py"
click node_summary_service "https://github.com/cpf-cadt/legal-rag/blob/main/apps/api/application.py"
click node_runtime "https://github.com/cpf-cadt/legal-rag/blob/main/apps/api/infrastructure.py"
click node_retriever "https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/runtime_factory.py"
click node_bm25_runtime "https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/bm25/sqlite_retriever.py"
click node_dense_runtime "https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/dense/retriever.py"
click node_query_correction "https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/shared/query_correction.py"
click node_answer_service "https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/answer_service.py"
click node_generator "https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/llm_generator.py"
click node_download "https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/automation-process/download/scraper.py"
click node_ocr "https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/automation-process/ocr/processor.py"
click node_bm25_pipeline "https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/bm25/pipeline.py"
click node_bm25_store "https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/bm25/sqlite_index.py"
click node_tokenizer "https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/bm25/tokenizer.py"
click node_dense_pipeline "https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/dense_retrieval/pipeline.py"
click node_preprocess "https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/dense_retrieval/text_preprocess.py"
click node_embeddings "https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/dense_retrieval/embeddings.py"
click node_chroma "https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/dense_retrieval/chroma_index.py"
click node_bot_entry "https://github.com/cpf-cadt/legal-rag/blob/main/apps/telegram_bot/main.py"
click node_bot_handlers "https://github.com/cpf-cadt/legal-rag/blob/main/apps/telegram_bot/handlers.py"
click node_bot_client "https://github.com/cpf-cadt/legal-rag/blob/main/apps/telegram_bot/api_client.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_web,node_chat,node_search_page,node_article_page,node_api_client,node_telegram toneBlue
class node_api_routes,node_search_service,node_summary_service,node_runtime toneAmber
class node_retriever,node_bm25_runtime,node_dense_runtime,node_query_correction,node_answer_service,node_generator toneMint
class node_download,node_ocr,node_bm25_pipeline,node_bm25_store,node_tokenizer,node_dense_pipeline,node_preprocess,node_embeddings,node_chroma toneRose
class node_bot_entry,node_bot_handlers,node_bot_client,node_user toneIndigo
```

## Components

### User clients

- [Web application](https://github.com/cpf-cadt/legal-rag/blob/main/apps/react-client/src/App.tsx): `apps/react-client/src/App.tsx`
- [Chat and search pages](https://github.com/cpf-cadt/legal-rag/blob/main/apps/react-client/src/pages/ChatPage.tsx): `apps/react-client/src/pages/ChatPage.tsx`
- [Search results](https://github.com/cpf-cadt/legal-rag/blob/main/apps/react-client/src/pages/SearchResultsPage.tsx): `apps/react-client/src/pages/SearchResultsPage.tsx`
- [Article view](https://github.com/cpf-cadt/legal-rag/blob/main/apps/react-client/src/pages/ArticlePage.tsx): `apps/react-client/src/pages/ArticlePage.tsx`
- [Web API client](https://github.com/cpf-cadt/legal-rag/blob/main/apps/react-client/src/services/apiClient.ts): `apps/react-client/src/services/apiClient.ts`

### API services

- [HTTP routes](https://github.com/cpf-cadt/legal-rag/blob/main/apps/api/main.py): `apps/api/main.py`
- [Search use case](https://github.com/cpf-cadt/legal-rag/blob/main/apps/api/application.py): `apps/api/application.py`
- [Summary use case](https://github.com/cpf-cadt/legal-rag/blob/main/apps/api/application.py): `apps/api/application.py`
- [Runtime assembly](https://github.com/cpf-cadt/legal-rag/blob/main/apps/api/infrastructure.py): `apps/api/infrastructure.py`

### Retrieval and answers

- [Legal retrievers](https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/runtime_factory.py): `apps/core/runtime_factory.py`
- [SQLite BM25 search](https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/bm25/sqlite_retriever.py): `apps/core/bm25/sqlite_retriever.py`
- [Dense search](https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/dense/retriever.py): `apps/core/dense/retriever.py`
- [Khmer query correction](https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/shared/query_correction.py): `apps/core/shared/query_correction.py`
- [Grounded answer service](https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/answer_service.py): `apps/core/answer_service.py`
- [LLM generation](https://github.com/cpf-cadt/legal-rag/blob/main/apps/core/llm_generator.py): `apps/core/llm_generator.py`

### Corpus and indexes

- [Document acquisition](https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/automation-process/download/scraper.py): `data-pipeline/automation-process/download/scraper.py`
- [OCR processing](https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/automation-process/ocr/processor.py): `data-pipeline/automation-process/ocr/processor.py`
- [BM25 index builder](https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/bm25/pipeline.py): `data-pipeline/bm25/pipeline.py`
- [SQLite FTS index](https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/bm25/sqlite_index.py): `data-pipeline/bm25/sqlite_index.py`
- [Khmer tokenizer](https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/bm25/tokenizer.py): `data-pipeline/bm25/tokenizer.py`
- [Dense index builder](https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/dense_retrieval/pipeline.py): `data-pipeline/dense_retrieval/pipeline.py`
- [Text preparation](https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/dense_retrieval/text_preprocess.py): `data-pipeline/dense_retrieval/text_preprocess.py`
- [Embedding generation](https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/dense_retrieval/embeddings.py): `data-pipeline/dense_retrieval/embeddings.py`
- [Chroma vector index](https://github.com/cpf-cadt/legal-rag/blob/main/data-pipeline/dense_retrieval/chroma_index.py): `data-pipeline/dense_retrieval/chroma_index.py`

### Telegram bot

- [Bot entry and dispatch](https://github.com/cpf-cadt/legal-rag/blob/main/apps/telegram_bot/main.py): `apps/telegram_bot/main.py`
- [Message handlers](https://github.com/cpf-cadt/legal-rag/blob/main/apps/telegram_bot/handlers.py): `apps/telegram_bot/handlers.py`
- [API client](https://github.com/cpf-cadt/legal-rag/blob/main/apps/telegram_bot/api_client.py): `apps/telegram_bot/api_client.py`

### Other components

- **Legal information seeker**
- **Telegram user**

## Connections

- Legal information seeker → Web application: uses (evidence: `README.md`)
- Web application → Chat and search pages: routes to
- Web application → Search results: routes to
- Web application → Article view: routes to
- Chat and search pages → Web API client: requests
- Search results → Web API client: requests (evidence: `apps/react-client/src/pages/SearchResultsPage.tsx`)
- Web API client → HTTP routes: calls
- HTTP routes → Search use case: dispatches search (evidence: `apps/api/main.py`)
- HTTP routes → Summary use case: dispatches summary (evidence: `apps/api/main.py`)
- HTTP routes → Runtime assembly: builds runtime (evidence: `apps/api/main.py`)
- Runtime assembly → Legal retrievers: constructs (evidence: `apps/api/infrastructure.py`)
- Search use case → Legal retrievers: searches (evidence: `apps/api/application.py`)
- Summary use case → Grounded answer service: answers via (evidence: `apps/api/application.py`)
- Grounded answer service → Legal retrievers: retrieves evidence (evidence: `apps/core/answer_service.py`)
- Grounded answer service → LLM generation: generates answer (evidence: `apps/core/answer_service.py`)
- Legal retrievers → SQLite BM25 search: selects implementation
- Legal retrievers → Dense search: selects implementation
- SQLite BM25 search → Khmer query correction: corrects query (evidence: `apps/core/bm25/sqlite_retriever.py`)
- Dense search → Khmer query correction: corrects query (evidence: `apps/core/dense/retriever.py`)
- Document acquisition → OCR processing: supplies documents
- BM25 index builder → SQLite FTS index: builds index (evidence: `data-pipeline/bm25/pipeline.py`)
- SQLite FTS index → Khmer tokenizer: uses (evidence: `data-pipeline/bm25/sqlite_index.py`)
- Dense index builder → Text preparation: prepares text (evidence: `data-pipeline/dense_retrieval/pipeline.py`)
- Dense index builder → Embedding generation: embeds chunks (evidence: `data-pipeline/dense_retrieval/pipeline.py`)
- Dense index builder → Chroma vector index: builds index (evidence: `data-pipeline/dense_retrieval/pipeline.py`)
- Telegram user → Bot entry and dispatch: sends message (evidence: `apps/telegram_bot/main.py`)
- Bot entry and dispatch → Message handlers: registers handlers (evidence: `apps/telegram_bot/main.py`)
- Message handlers → Grounded answer service: requests answer (evidence: `apps/telegram_bot/handlers.py`)
- Bot entry and dispatch → API client: creates client
