# vedhavyav/legalrag architecture

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

- Interactive diagram: https://gitdiagram.com/vedhavyav/legalrag
- Repository: https://github.com/vedhavyav/legalrag

## Overview

LegalRAG ingests Indian Kanoon judgments, normalizes them, and saves raw and processed documents; its README describes chunking, indexing, retrieval, and grounded local-LLM answering as the intended user workflow. The sampled runtime shows hybrid retrieval feeding answer generation, and retrieval evaluation comparing BM25, semantic, and hybrid methods. The excerpts do not establish how processed files enter the database or how chunks are populated, so those ingestion-to-index links are omitted. The README also describes answer-quality evaluation, but no such implementation is shown.

Main entry points: [`app/retrieval/index.py`](https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/index.py) (Chunk loader and index), [`app/ingestion/pipeline.py`](https://github.com/vedhavyav/legalrag/blob/main/app/ingestion/pipeline.py) (Ingestion pipeline), [`app/retrieval/search.py`](https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/search.py) (BM25 search), [`app/retrieval/hybrid_search.py`](https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/hybrid_search.py) (Hybrid search)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ingestion["Legal Ingestion"]
  node_main["Ingestion entry<br/>[main.py]"]
  node_kanoon_client["Kanoon client<br/>[indiankanoon.py]"]
  node_ingest_pipeline["Ingestion pipeline<br/>[pipeline.py]"]
  node_normalizer["Document parser<br/>[parser.py]"]
  node_raw_processed["Raw and processed files<br/>[pipeline.py]"]
end

subgraph group_storage["Corpus Storage"]
  node_chunker["Chunking<br/>[chunker.py]"]
  node_chunk_persistence["Chunk persistence<br/>[chunks.py]"]
  node_document_repository["Document repository<br/>[repository.py]"]
  node_database_connection["Database connection<br/>[connection.py]"]
  node_legal_database[("Legal database<br/>[schema.sql]")]
end

subgraph group_retrieval["Retrieval"]
  node_bm25["BM25 ranking<br/>[bm25.py]"]
  node_tokenizer["Tokenizer<br/>[tokenizer.py]"]
  node_retrieval_index["Chunk loader and index<br/>[index.py]"]
  node_bm25_search["BM25 search<br/>[search.py]"]
  node_embedding_index["Embedding index<br/>[embeddings.py]"]
  node_semantic_search["Semantic search<br/>[semantic_search.py]"]
  node_hybrid_search["Hybrid search<br/>[hybrid_search.py]"]
end

subgraph group_answers["Answering"]
  node_ask_entry["Question entry<br/>[ask.py]"]
  node_answer_generator["Answer generator"]
end

subgraph group_evaluation["Evaluation"]
  node_retrieval_evaluation["Retrieval evaluation"]
end

node_researcher(("Legal user"))
node_ollama["Ollama runtime"]

node_main -->|"creates"| node_kanoon_client
node_main -->|"calls"| node_ingest_pipeline
node_ingest_pipeline -->|"fetches documents"| node_kanoon_client
node_ingest_pipeline -->|"normalizes"| node_normalizer
node_ingest_pipeline -->|"writes files"| node_raw_processed
node_chunk_persistence -.->|"uses"| node_chunker
node_document_repository -->|"opens connection"| node_database_connection
node_chunk_persistence -.->|"opens connection"| node_database_connection
node_retrieval_index -->|"loads chunks"| node_database_connection
node_retrieval_index -->|"reads chunks"| node_legal_database
node_document_repository -->|"upserts documents"| node_legal_database
node_retrieval_index -->|"builds index"| node_bm25
node_retrieval_index -->|"tokenizes corpus"| node_tokenizer
node_bm25 -->|"tokenizes text"| node_tokenizer
node_bm25_search -->|"loads chunks"| node_retrieval_index
node_bm25_search -->|"checks query"| node_tokenizer
node_embedding_index -->|"loads chunks"| node_retrieval_index
node_semantic_search -->|"reads vectors"| node_embedding_index
node_hybrid_search -->|"retrieves candidates"| node_bm25_search
node_hybrid_search -->|"retrieves candidates"| node_semantic_search
node_answer_generator -->|"retrieves passages"| node_hybrid_search
node_answer_generator -->|"requests completion"| node_ollama
node_retrieval_evaluation -->|"evaluates retrieval"| node_bm25_search
node_retrieval_evaluation -->|"evaluates retrieval"| node_semantic_search
node_retrieval_evaluation -->|"evaluates retrieval"| node_hybrid_search
node_researcher -.->|"asks question"| node_ask_entry
node_ask_entry -.->|"dispatches question"| node_answer_generator

click node_main "https://github.com/vedhavyav/legalrag/blob/main/app/main.py"
click node_kanoon_client "https://github.com/vedhavyav/legalrag/blob/main/app/ingestion/indiankanoon.py"
click node_ingest_pipeline "https://github.com/vedhavyav/legalrag/blob/main/app/ingestion/pipeline.py"
click node_normalizer "https://github.com/vedhavyav/legalrag/blob/main/app/ingestion/parser.py"
click node_raw_processed "https://github.com/vedhavyav/legalrag/blob/main/app/ingestion/pipeline.py"
click node_chunker "https://github.com/vedhavyav/legalrag/blob/main/app/chunking/chunker.py"
click node_chunk_persistence "https://github.com/vedhavyav/legalrag/blob/main/app/db/chunks.py"
click node_document_repository "https://github.com/vedhavyav/legalrag/blob/main/app/db/repository.py"
click node_database_connection "https://github.com/vedhavyav/legalrag/blob/main/app/db/connection.py"
click node_legal_database "https://github.com/vedhavyav/legalrag/blob/main/app/db/schema.sql"
click node_bm25 "https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/bm25.py"
click node_tokenizer "https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/tokenizer.py"
click node_retrieval_index "https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/index.py"
click node_bm25_search "https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/search.py"
click node_embedding_index "https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/embeddings.py"
click node_semantic_search "https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/semantic_search.py"
click node_hybrid_search "https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/hybrid_search.py"
click node_ask_entry "https://github.com/vedhavyav/legalrag/blob/main/app/ask.py"
click node_answer_generator "https://github.com/vedhavyav/legalrag/blob/main/app/generation/answer_generator.py"
click node_retrieval_evaluation "https://github.com/vedhavyav/legalrag/blob/main/app/evaluation/evaluate_retrieval.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_main,node_kanoon_client,node_ingest_pipeline,node_normalizer,node_raw_processed,node_researcher toneBlue
class node_chunker,node_chunk_persistence,node_document_repository,node_database_connection,node_legal_database toneAmber
class node_bm25,node_tokenizer,node_retrieval_index,node_bm25_search,node_embedding_index,node_semantic_search,node_hybrid_search toneMint
class node_ask_entry,node_answer_generator toneRose
class node_retrieval_evaluation,node_ollama toneIndigo
```

## Components

### Legal Ingestion

- [Ingestion entry](https://github.com/vedhavyav/legalrag/blob/main/app/main.py): `app/main.py`
- [Kanoon client](https://github.com/vedhavyav/legalrag/blob/main/app/ingestion/indiankanoon.py): `app/ingestion/indiankanoon.py`
- [Ingestion pipeline](https://github.com/vedhavyav/legalrag/blob/main/app/ingestion/pipeline.py): `app/ingestion/pipeline.py`
- [Document parser](https://github.com/vedhavyav/legalrag/blob/main/app/ingestion/parser.py): `app/ingestion/parser.py`
- [Raw and processed files](https://github.com/vedhavyav/legalrag/blob/main/app/ingestion/pipeline.py): `app/ingestion/pipeline.py`

### Corpus Storage

- [Chunking](https://github.com/vedhavyav/legalrag/blob/main/app/chunking/chunker.py): `app/chunking/chunker.py`
- [Chunk persistence](https://github.com/vedhavyav/legalrag/blob/main/app/db/chunks.py): `app/db/chunks.py`
- [Document repository](https://github.com/vedhavyav/legalrag/blob/main/app/db/repository.py): `app/db/repository.py`
- [Database connection](https://github.com/vedhavyav/legalrag/blob/main/app/db/connection.py): `app/db/connection.py`
- [Legal database](https://github.com/vedhavyav/legalrag/blob/main/app/db/schema.sql): `app/db/schema.sql`

### Retrieval

- [BM25 ranking](https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/bm25.py): `app/retrieval/bm25.py`
- [Tokenizer](https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/tokenizer.py): `app/retrieval/tokenizer.py`
- [Chunk loader and index](https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/index.py): `app/retrieval/index.py`
- [BM25 search](https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/search.py): `app/retrieval/search.py`
- [Embedding index](https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/embeddings.py): `app/retrieval/embeddings.py`
- [Semantic search](https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/semantic_search.py): `app/retrieval/semantic_search.py`
- [Hybrid search](https://github.com/vedhavyav/legalrag/blob/main/app/retrieval/hybrid_search.py): `app/retrieval/hybrid_search.py`

### Answering

- [Question entry](https://github.com/vedhavyav/legalrag/blob/main/app/ask.py): `app/ask.py`
- [Answer generator](https://github.com/vedhavyav/legalrag/blob/main/app/generation/answer_generator.py): `app/generation/answer_generator.py`

### Evaluation

- [Retrieval evaluation](https://github.com/vedhavyav/legalrag/blob/main/app/evaluation/evaluate_retrieval.py): `app/evaluation/evaluate_retrieval.py`

### Other components

- **Legal user**
- **Ollama runtime**

## Connections

- Ingestion entry → Kanoon client: creates (evidence: `app/main.py`)
- Ingestion entry → Ingestion pipeline: calls (evidence: `app/main.py`)
- Ingestion pipeline → Kanoon client: fetches documents (evidence: `app/ingestion/pipeline.py`)
- Ingestion pipeline → Document parser: normalizes (evidence: `app/ingestion/pipeline.py`)
- Ingestion pipeline → Raw and processed files: writes files (evidence: `app/ingestion/pipeline.py`)
- Chunk persistence → Chunking: uses (evidence: `app/db/chunks.py`)
- Document repository → Database connection: opens connection (evidence: `app/db/repository.py`)
- Chunk persistence → Database connection: opens connection (evidence: `app/db/chunks.py`)
- Chunk loader and index → Database connection: loads chunks (evidence: `app/retrieval/index.py`)
- Chunk loader and index → Legal database: reads chunks (evidence: `app/retrieval/index.py`)
- Document repository → Legal database: upserts documents (evidence: `app/db/repository.py`)
- Chunk loader and index → BM25 ranking: builds index (evidence: `app/retrieval/index.py`)
- Chunk loader and index → Tokenizer: tokenizes corpus (evidence: `app/retrieval/index.py`)
- BM25 ranking → Tokenizer: tokenizes text (evidence: `app/retrieval/bm25.py`)
- BM25 search → Chunk loader and index: loads chunks (evidence: `app/retrieval/search.py`)
- BM25 search → Tokenizer: checks query (evidence: `app/retrieval/search.py`)
- Embedding index → Chunk loader and index: loads chunks (evidence: `app/retrieval/embeddings.py`)
- Semantic search → Embedding index: reads vectors (evidence: `app/retrieval/semantic_search.py`)
- Hybrid search → BM25 search: retrieves candidates (evidence: `app/retrieval/hybrid_search.py`)
- Hybrid search → Semantic search: retrieves candidates (evidence: `app/retrieval/hybrid_search.py`)
- Answer generator → Hybrid search: retrieves passages (evidence: `app/generation/answer_generator.py`)
- Answer generator → Ollama runtime: requests completion (evidence: `app/generation/answer_generator.py`)
- Retrieval evaluation → BM25 search: evaluates retrieval (evidence: `app/evaluation/evaluate_retrieval.py`)
- Retrieval evaluation → Semantic search: evaluates retrieval (evidence: `app/evaluation/evaluate_retrieval.py`)
- Retrieval evaluation → Hybrid search: evaluates retrieval (evidence: `app/evaluation/evaluate_retrieval.py`)
- Legal user → Question entry: asks question
- Question entry → Answer generator: dispatches question (evidence: `app/ask.py`)
