# anonymousbeliever/pocket-lawyer architecture

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

- Interactive diagram: https://gitdiagram.com/anonymousbeliever/pocket-lawyer
- Repository: https://github.com/anonymousbeliever/pocket-lawyer

## Overview

Pocket Lawyer Kenya serves legal-information questions with answers grounded in Kenyan legal sources and citations. The main workflow enters through the FastAPI ask route: optional intent classification sends conversational input to a direct reply, while legal questions go through retrieval, reranking, and grounded generation. A separate ingestion workflow extracts, cleans, structures, validates, chunks, embeds, and stores legal documents for retrieval. The graph reflects documented ingestion stages and sampled runtime wiring; unsampled subsystem links are kept conservative.

Main entry points: [`data_pipeline/run.py`](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/data_pipeline/run.py) (Ingestion runner), [`backend/app/api/routes.py`](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/api/routes.py) (Ask and health routes), [`backend/app/ai/rag.py`](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/rag.py) (Legal RAG), [`backend/app/ai/retriever.py`](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/retriever.py) (Hybrid retriever)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_api["API and Routing"]
  node_api_app["FastAPI app<br/>[main.py]"]
  node_routes["Ask and health routes<br/>[routes.py]"]
  node_intent["Intent classifier<br/>[intent.py]"]
  node_direct_reply["Conversational reply<br/>[intent.py]"]
end

subgraph group_answer["Legal Answering"]
  node_rag["Legal RAG<br/>[rag.py]"]
  node_retriever["Hybrid retriever<br/>[retriever.py]"]
  node_reranker["Passage reranker<br/>[reranker.py]"]
  node_generator["Answer generation<br/>[llm.py]"]
  node_answer_format["Citation and answer format<br/>[answer.py]"]
end

subgraph group_ingest["Legal Data Ingestion"]
  node_legal_sources["Legal source documents"]
  node_pipeline["Ingestion runner<br/>[run.py]"]
  node_extractor["PDF extraction<br/>[pdf_extractor.py]"]
  node_cleaners["Document cleaners"]
  node_structure["Legal structure adapters"]
  node_validators["Content validators"]
  node_chunker["Passage chunking<br/>[chunker.py]"]
  node_ingest_store["Embedding and ingestion<br/>[ingest.py]"]
end

subgraph group_storage["Models and Storage"]
  node_qdrant[("Qdrant collection")]
  node_embedding_model["Embedding model"]
  node_openai["OpenAI API"]
end

node_user(("Questioner"))
node_legal_reader(("Legal information seeker"))

node_legal_reader -->|"submits question"| node_api_app
node_api_app -->|"mounts routes"| node_routes
node_routes -->|"classifies query"| node_intent
node_routes -->|"answers conversational"| node_direct_reply
node_routes -->|"asks legal question"| node_rag
node_rag -->|"retrieves passages"| node_retriever
node_rag -->|"reranks candidates"| node_reranker
node_rag -->|"generates grounded answer"| node_generator
node_generator -->|"validates citations"| node_answer_format
node_retriever -->|"searches vectors"| node_qdrant
node_retriever -->|"embeds query"| node_embedding_model
node_generator -->|"requests generation"| node_openai
node_routes -->|"returns answer"| node_legal_reader
node_legal_sources -->|"provides documents"| node_pipeline
node_pipeline -->|"extracts text"| node_extractor
node_pipeline -->|"cleans text"| node_cleaners
node_pipeline -->|"parses legal units"| node_structure
node_pipeline -->|"validates content"| node_validators
node_pipeline -->|"builds chunks"| node_chunker
node_pipeline -->|"ingests chunks"| node_ingest_store
node_ingest_store -->|"embeds passages"| node_embedding_model
node_ingest_store -->|"upserts vectors"| node_qdrant

click node_api_app "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/main.py"
click node_routes "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/api/routes.py"
click node_intent "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/intent.py"
click node_direct_reply "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/intent.py"
click node_rag "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/rag.py"
click node_retriever "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/retriever.py"
click node_reranker "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/reranker.py"
click node_generator "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/llm.py"
click node_answer_format "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/answer.py"
click node_pipeline "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/data_pipeline/run.py"
click node_extractor "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/data_pipeline/extractors/pdf_extractor.py"
click node_cleaners "https://github.com/anonymousbeliever/pocket-lawyer/tree/master/data_pipeline/cleaners"
click node_structure "https://github.com/anonymousbeliever/pocket-lawyer/tree/master/data_pipeline/structure"
click node_validators "https://github.com/anonymousbeliever/pocket-lawyer/tree/master/data_pipeline/validators"
click node_chunker "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/data_pipeline/chunking/chunker.py"
click node_ingest_store "https://github.com/anonymousbeliever/pocket-lawyer/blob/master/data_pipeline/vectorstore/ingest.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_api_app,node_routes,node_intent,node_direct_reply toneBlue
class node_rag,node_retriever,node_reranker,node_generator,node_answer_format toneAmber
class node_legal_sources,node_pipeline,node_extractor,node_cleaners,node_structure,node_validators,node_chunker,node_ingest_store toneMint
class node_qdrant,node_embedding_model,node_openai toneRose
class node_user,node_legal_reader toneIndigo
```

## Components

### API and Routing

- [FastAPI app](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/main.py): `backend/app/main.py`
- [Ask and health routes](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/api/routes.py): `backend/app/api/routes.py`
- [Intent classifier](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/intent.py): `backend/app/ai/intent.py`
- [Conversational reply](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/intent.py): `backend/app/ai/intent.py`

### Legal Answering

- [Legal RAG](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/rag.py): `backend/app/ai/rag.py`
- [Hybrid retriever](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/retriever.py): `backend/app/ai/retriever.py`
- [Passage reranker](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/reranker.py): `backend/app/ai/reranker.py`
- [Answer generation](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/llm.py): `backend/app/ai/llm.py`
- [Citation and answer format](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/backend/app/ai/answer.py): `backend/app/ai/answer.py`

### Legal Data Ingestion

- **Legal source documents**
- [Ingestion runner](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/data_pipeline/run.py): `data_pipeline/run.py`
- [PDF extraction](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/data_pipeline/extractors/pdf_extractor.py): `data_pipeline/extractors/pdf_extractor.py`
- [Document cleaners](https://github.com/anonymousbeliever/pocket-lawyer/tree/master/data_pipeline/cleaners): `data_pipeline/cleaners`
- [Legal structure adapters](https://github.com/anonymousbeliever/pocket-lawyer/tree/master/data_pipeline/structure): `data_pipeline/structure`
- [Content validators](https://github.com/anonymousbeliever/pocket-lawyer/tree/master/data_pipeline/validators): `data_pipeline/validators`
- [Passage chunking](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/data_pipeline/chunking/chunker.py): `data_pipeline/chunking/chunker.py`
- [Embedding and ingestion](https://github.com/anonymousbeliever/pocket-lawyer/blob/master/data_pipeline/vectorstore/ingest.py): `data_pipeline/vectorstore/ingest.py`

### Models and Storage

- **Qdrant collection**
- **Embedding model**
- **OpenAI API**

### Other components

- **Questioner**
- **Legal information seeker**

## Connections

- Legal information seeker → FastAPI app: submits question
- FastAPI app → Ask and health routes: mounts routes
- Ask and health routes → Intent classifier: classifies query
- Ask and health routes → Conversational reply: answers conversational
- Ask and health routes → Legal RAG: asks legal question
- Legal RAG → Hybrid retriever: retrieves passages
- Legal RAG → Passage reranker: reranks candidates
- Legal RAG → Answer generation: generates grounded answer
- Answer generation → Citation and answer format: validates citations
- Hybrid retriever → Qdrant collection: searches vectors
- Hybrid retriever → Embedding model: embeds query
- Answer generation → OpenAI API: requests generation
- Ask and health routes → Legal information seeker: returns answer
- Legal source documents → Ingestion runner: provides documents
- Ingestion runner → PDF extraction: extracts text
- Ingestion runner → Document cleaners: cleans text
- Ingestion runner → Legal structure adapters: parses legal units
- Ingestion runner → Content validators: validates content
- Ingestion runner → Passage chunking: builds chunks
- Ingestion runner → Embedding and ingestion: ingests chunks
- Embedding and ingestion → Embedding model: embeds passages
- Embedding and ingestion → Qdrant collection: upserts vectors
