Architecture is the skeleton of every application. Just as in nature - a strong structure allows an organism to survive and thrive!
1βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
2β Presentation Layer β
3β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
4β β REST API β β WebSocket β β CLI β β
5β ββββββββ¬βββββββ ββββββββ¬βββββββ ββββββββ¬βββββββ β
6βββββββββββΌβββββββββββββββββΌβββββββββββββββββΌββββββββββββββββββ€
7β ββββββββββββββββββΌβββββββββββββββββ β
8β βΌ β
9β Application Layer β
10β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
11β β Use Cases / Services β β
12β β ββββββββββββ ββββββββββββ ββββββββββββ β β
13β β β Query β β Upload β β Search β β β
14β β β Service β β Service β β Service β β β
15β β ββββββββββββ ββββββββββββ ββββββββββββ β β
16β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
17βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
18β Domain Layer β
19β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
20β β Entities & Business Logic β β
21β β Document β Query β Response β User β Embedding β β
22β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
23βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
24β Infrastructure Layer β
25β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
26β β Vector DBβ β LLM β β Database β β Cache β β
27β β Qdrant β β OpenAI β β Postgres β β Redis β β
28β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
29βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ1from dataclasses import dataclass, field
2from datetime import datetime
3from uuid import UUID, uuid4
4from abc import ABC, abstractmethod
5
6# Entities
7@dataclass
8class Document:
9 id: UUID = field(default_factory=uuid4)
10 title: str = ""
11 content: str = ""
12 metadata: dict = field(default_factory=dict)
13 created_at: datetime = field(default_factory=datetime.now)
14 chunks: list["DocumentChunk"] = field(default_factory=list)
15
16@dataclass
17class DocumentChunk:
18 id: UUID = field(default_factory=uuid4)
19 document_id: UUID = None
20 content: str = ""
21 embedding: list[float] = field(default_factory=list)
22 metadata: dict = field(default_factory=dict)
23
24@dataclass
25class Query:
26 id: UUID = field(default_factory=uuid4)
27 text: str = ""
28 user_id: UUID = None
29 created_at: datetime = field(default_factory=datetime.now)
30
31@dataclass
32class Response:
33 query_id: UUID = None
34 answer: str = ""
35 sources: list[DocumentChunk] = field(default_factory=list)
36 confidence: float = 0.0
37 latency_ms: float = 0.01from abc import ABC, abstractmethod
2from typing import Optional
3
4class DocumentRepository(ABC):
5 @abstractmethod
6 async def save(self, document: Document) -> Document:
7 pass
8
9 @abstractmethod
10 async def get_by_id(self, doc_id: UUID) -> Optional[Document]:
11 pass
12
13 @abstractmethod
14 async def search(self, query_embedding: list[float], limit: int) -> list[DocumentChunk]:
15 pass
16
17class QdrantDocumentRepository(DocumentRepository):
18 def __init__(self, client, collection_name: str):
19 self.client = client
20 self.collection = collection_name
21
22 async def save(self, document: Document) -> Document:
23 # Implementation
24 pass
25
26 async def get_by_id(self, doc_id: UUID) -> Optional[Document]:
27 # Implementation
28 pass
29
30 async def search(self, query_embedding: list[float], limit: int) -> list[DocumentChunk]:
31 results = await self.client.search(
32 collection_name=self.collection,
33 query_vector=query_embedding,
34 limit=limit
35 )
36 return [self._to_chunk(r) for r in results]1from functools import lru_cache
2
3class Container:
4 """Simple DI container."""
5
6 def __init__(self):
7 self._services = {}
8
9 def register(self, interface: type, implementation):
10 self._services[interface] = implementation
11
12 def resolve(self, interface: type):
13 return self._services.get(interface)
14
15# Setup
16container = Container()
17container.register(DocumentRepository, QdrantDocumentRepository(...))
18container.register(LLMService, OpenAILLMService(...))
19
20# Usage in FastAPI
21@lru_cache
22def get_container() -> Container:
23 return container
24
25def get_document_repo(container: Container = Depends(get_container)):
26 return container.resolve(DocumentRepository)Good architecture is the foundation of a scalable application. In the next lesson, we will cover testing!