# Architecture Overview This document provides a comprehensive overview of Local Deep Research's system architecture. ## Table of Contents - [System Components](#system-components) - [Entry Points](#entry-points) - [Research Execution Flow](#research-execution-flow) - [Research Status Lifecycle](#research-status-lifecycle) - [Module Responsibilities](#module-responsibilities) - [Threading Model](#threading-model) - [Configuration System](#configuration-system) - [Key Interfaces](#key-interfaces) --- ## System Components ```mermaid graph TB subgraph "Entry Points" CLI[ldr CLI] WEB[ldr-web Flask App] API[REST API /api/v1] end subgraph "Core Research Engine" SS[SearchSystem
search_system.py] SSF[StrategyFactory
search_system_factory.py] RG[ReportGenerator
report_generator.py] end subgraph "Search Layer" STRAT[32 Search Strategies
advanced_search_system/strategies/] ENG[30+ Search Engines
web_search_engines/engines/] RL[Rate Limiter
rate_limiting/] end subgraph "Data Layer" DB[(SQLCipher DB
Per-User Encrypted)] MODELS[20+ ORM Models
database/models/] CACHE[Memory Cache] end subgraph "LLM Layer" PROV[LLM Providers
Ollama, OpenAI, etc.] EMB[Embeddings
embeddings/] RERANK[Reranker
reranker/] end CLI --> SS WEB --> SS API --> SS SS --> SSF SS --> RG SSF --> STRAT STRAT --> ENG ENG --> RL SS --> PROV SS --> DB MODELS --> DB RG --> PROV ENG --> CACHE ``` --- ## Entry Points ### Web Application (`ldr-web`) **Location:** `src/local_deep_research/web/app.py` The primary user interface. Launches a Flask server with SocketIO for real-time updates. ```mermaid graph LR A[Browser] -->|HTTP/WS| B[Flask App] B --> C[Blueprints] C --> D[research_routes] C --> E[api_routes] C --> F[settings_routes] C --> G[auth_routes] B -->|Real-time| H[SocketIO] ``` **Key files:** - `web/app.py` - Main entry, starts server - `web/app_factory.py` - Flask app creation with middleware - `web/routes/` - Blueprint route handlers - `web/services/` - Business logic services ### REST API (`/api/v1`) **Location:** `src/local_deep_research/web/api.py` Programmatic access for integrations. | Endpoint | Method | Purpose | |----------|--------|---------| | `/api/v1/quick_summary` | POST | Quick research summary | | `/api/v1/generate_report` | POST | Full research report | | `/api/v1/analyze_documents` | POST | Search local collections | | `/api/v1/health` | GET | Health check | --- ## Research Execution Flow ```mermaid sequenceDiagram participant User participant Web as Flask App participant SS as SearchSystem participant SF as StrategyFactory participant Strat as Strategy participant Eng as SearchEngine participant LLM as LLM Provider participant DB as Database User->>Web: Submit Query Web->>SS: start_research() SS->>SF: create_strategy(name) SF-->>SS: Strategy instance loop Research Iterations SS->>Strat: analyze_topic(query) Strat->>LLM: Generate questions LLM-->>Strat: Questions loop Per Question Strat->>Eng: search(question) Eng-->>Strat: Results end Strat->>LLM: Synthesize findings LLM-->>Strat: Synthesis Strat-->>SS: Findings end SS->>DB: Save results SS-->>Web: Research complete Web-->>User: Results via SocketIO ``` ### Research Status Lifecycle ```mermaid stateDiagram-v2 [*] --> QUEUED : Concurrency limit reached [*] --> IN_PROGRESS : Slots available QUEUED --> IN_PROGRESS : Worker picks up task QUEUED --> SUSPENDED : User terminates IN_PROGRESS --> COMPLETED : Research succeeds IN_PROGRESS --> FAILED : Unrecoverable error IN_PROGRESS --> SUSPENDED : User terminates COMPLETED --> [*] FAILED --> [*] SUSPENDED --> [*] note right of FAILED Set by processor_v2 and research_service on errors end note note left of SUSPENDED Set when user clicks terminate/stop end note ``` > **Unused statuses:** `PENDING` (declared as a model default but never set by any creation > path), `ERROR` (never set; predates `FAILED`), and `CANCELLED` (unused by research; used > by benchmarks) exist in `ResearchStatus` for backward compatibility. --- ## Module Responsibilities ### Core Modules | Module | Location | Responsibility | |--------|----------|----------------| | **SearchSystem** | `search_system.py` | Orchestrates research, coordinates strategies and engines | | **StrategyFactory** | `search_system_factory.py` | Creates strategy instances based on configuration | | **ReportGenerator** | `report_generator.py` | Generates structured reports from research findings | | **CitationHandler** | `citation_handler.py` | Processes and validates citations | ### Search System | Module | Location | Responsibility | |--------|----------|----------------| | **BaseSearchEngine** | `web_search_engines/search_engine_base.py` | Abstract base for all search engines | | **SearchEngineFactory** | `web_search_engines/search_engine_factory.py` | Creates engine instances | | **RateLimitTracker** | `web_search_engines/rate_limiting/tracker.py` | Adaptive rate limiting | | **RetrieverRegistry** | `web_search_engines/retriever_registry.py` | LangChain retriever integration | ### Strategy System | Module | Location | Responsibility | |--------|----------|----------------| | **BaseSearchStrategy** | `advanced_search_system/strategies/base_strategy.py` | Abstract base for strategies | | **FindingsRepository** | `advanced_search_system/findings/` | Accumulates research findings | | **QuestionGenerator** | `advanced_search_system/questions/` | Generates research questions | ### Web Application | Module | Location | Responsibility | |--------|----------|----------------| | **SocketIOService** | `web/services/socket_service.py` | Real-time communication | | **ResearchService** | `web/services/research_service.py` | Research execution | | **QueueManager** | `web/queue/` | Background task queue | | **SessionManager** | `web/auth/session_manager.py` | User session handling | ### Data Layer | Module | Location | Responsibility | |--------|----------|----------------| | **Models** | `database/models/` | SQLAlchemy ORM models | | **SessionContext** | `database/session_context.py` | Thread-safe DB sessions | | **EncryptedDB** | `database/encrypted_db.py` | SQLCipher integration | ### LLM Integration | Module | Location | Responsibility | |--------|----------|----------------| | **LLM Providers** | `llm/providers/implementations/` | Provider-specific LLM wrappers | | **AutoDiscovery** | `llm/providers/auto_discovery.py` | Dynamic provider detection | | **LLMRegistry** | `llm/llm_registry.py` | Custom LLM registration | --- ## Threading Model ```mermaid graph TB subgraph "Main Thread" FLASK[Flask Server] SOCKETIO[SocketIO Handler] end subgraph "Research Threads" RT1[Research Thread 1] RT2[Research Thread 2] RTN[Research Thread N] end subgraph "Queue Processor" QP[Queue Processor Thread] end subgraph "Thread-Local Storage" TC[Thread Context
Settings Snapshot] DBS[DB Session
Per-User] end FLASK --> RT1 FLASK --> RT2 FLASK --> RTN RT1 --> TC RT2 --> TC RTN --> TC QP --> RT1 RT1 -.-> SOCKETIO RT2 -.-> SOCKETIO ``` **Key Threading Concepts:** 1. **Thread Context** (`config/thread_settings.py`) - Each research thread has its own settings snapshot - Prevents race conditions on configuration changes 2. **Per-User DB Sessions** (`database/session_context.py`) - Each user has an isolated SQLCipher database - Sessions are thread-local via context manager 3. **Queue Processing** (`web/queue/`) - Background queue for long-running research - Processes items from `QueuedResearch` table 4. **SocketIO Updates** - Research threads emit progress via SocketIO - Uses threading async mode (not asyncio) --- ## Configuration System ```mermaid graph TB subgraph "Configuration Sources" ENV[Environment Variables] DB[(Database Settings
per-user)] JSON[Default Settings
default_settings.json] end subgraph "Settings Management" SM[SettingsManager
manager.py] end subgraph "Runtime Access" SNAP[Settings Snapshot
Thread-safe copy] TC[Thread Context
thread_settings.py] end ENV --> SM JSON --> SM DB --> SM SM --> SNAP SNAP --> TC ``` **Configuration Flow:** 1. **Defaults** - Default settings loaded from JSON 2. **Environment** - Environment variables override defaults 3. **Database** - User settings loaded from encrypted per-user DB 4. **Snapshot** - Thread-safe copy created for each research 5. **Access** - Code reads from snapshot via thread context **Key Settings Categories:** | Category | Examples | |----------|----------| | `llm.*` | Provider, model, temperature, API keys | | `search.*` | Engine selection, max results, rate limits | | `app.*` | Debug mode, logging, UI preferences | | `notifications.*` | Email, webhook configurations | --- ## Key Interfaces ### Search Engine Interface All search engines implement `BaseSearchEngine`: ```python class BaseSearchEngine(ABC): # Classification flags is_public: bool = True is_generic: bool = True is_scientific: bool = False is_local: bool = False is_news: bool = False is_code: bool = False is_lexical: bool = False needs_llm_relevance_filter: bool = False @abstractmethod def run(self, query: str) -> List[Dict[str, Any]]: """Execute search and return results.""" # Returns: [{"title": ..., "link": ..., "snippet": ...}] ``` ### Strategy Interface All strategies implement `BaseSearchStrategy`: ```python class BaseSearchStrategy(ABC): def __init__(self, search, model, all_links_of_system, settings_snapshot, **kwargs): ... @abstractmethod def analyze_topic(self, query: str) -> Dict: """Execute research strategy.""" # Returns: { # "findings": [...], # "iterations": int, # "questions": {...}, # "formatted_findings": str, # "current_knowledge": {...} # } ``` ### LLM Provider Interface All providers extend `BaseLLMProvider` (most extend `OpenAICompatibleProvider`): ```python class OpenAICompatibleProvider(BaseLLMProvider): provider_name: str api_key_setting: str | None # Settings key, or None for no-key providers api_key_optional: bool = False # If True, missing key uses placeholder url_setting: str default_base_url: str default_model: str @classmethod def create_llm(cls, model_name, temperature, **kwargs) -> BaseChatModel: """Create LangChain LLM instance.""" ``` --- ## Directory Structure ``` src/local_deep_research/ ├── search_system.py # Main orchestrator ├── search_system_factory.py # Strategy factory ├── report_generator.py # Report generation ├── citation_handler.py # Citation processing │ ├── web/ # Flask application │ ├── app.py # Entry point │ ├── app_factory.py # App creation │ ├── routes/ # Blueprint handlers │ ├── services/ # Business logic │ ├── queue/ # Task queue │ └── auth/ # Authentication │ ├── advanced_search_system/ # Search strategies │ ├── strategies/ # 32 strategy implementations │ ├── questions/ # Question generation │ ├── findings/ # Findings management │ └── ... │ ├── web_search_engines/ # Search engines │ ├── engines/ # 30+ engine implementations │ ├── search_engine_base.py # Abstract base │ ├── search_engine_factory.py │ └── rate_limiting/ # Adaptive rate limiting │ ├── database/ # Data layer │ ├── models/ # 20+ ORM models │ ├── session_context.py # Session management │ └── encrypted_db.py # SQLCipher │ ├── llm/ # LLM integration │ ├── providers/ # Provider implementations │ └── llm_registry.py # Custom LLM registration │ ├── config/ # Configuration │ ├── llm_config.py # LLM setup │ ├── search_config.py # Search setup │ └── thread_settings.py # Thread context │ ├── settings/ # Settings management │ └── manager.py # SettingsManager │ └── api/ # Programmatic API ├── client.py # HTTP client └── research_functions.py # Direct functions ``` --- ## See Also - [Database Schema](./DATABASE_SCHEMA.md) - Detailed data model documentation - [Semantic Search](./SEMANTIC_SEARCH.md) - Indexing pipeline, search modes, and three-tier merge algorithm - [Extension Guide](../developing/EXTENDING.md) - How to add custom components - [Troubleshooting](../troubleshooting.md) - Common issues and solutions