From 92c6945f55f79a0d1c16226d4d069136aa0a6d2b Mon Sep 17 00:00:00 2001 From: Artem-Darius Weber Date: Fri, 25 Jul 2025 16:15:41 +0300 Subject: [PATCH 1/2] Update 'architecture-diagram.md' --- architecture-diagram.md | 111 +++++++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 42 deletions(-) diff --git a/architecture-diagram.md b/architecture-diagram.md index 4e45a3d..50be704 100644 --- a/architecture-diagram.md +++ b/architecture-diagram.md @@ -3,35 +3,48 @@ ```mermaid graph TB %% External Layer - User[👤 User] --> GradioUI[🖥️ Gradio Web Interface] - + EndUser[👤 User] --> GradioUI[🖥️ Gradio Web Interface] + %% Presentation Layer subgraph "Presentation Layer" - GradioUI --> |Web Requests| GradioApp[gradio_app.py] + GradioUI --> |HTTP/Web Requests| GradioApp[gradio_app.py] end - + %% Application Layer subgraph "Application Layer" GradioApp --> RegisterUC[📝 RegisterFaceUseCase] GradioApp --> VerifyUC[🔍 VerifyFaceUseCase] GradioApp --> IdentifyUC[🔎 IdentifyFaceUseCase] + + %% Асинхронная публикация задач + RegisterUC --> TaskPublisher[📨 TaskPublisher] + VerifyUC --> TaskPublisher + IdentifyUC --> TaskPublisher - RegisterUC --> FaceService[⚙️ FaceRecognitionService] - VerifyUC --> FaceService - IdentifyUC --> FaceService + %% Хранилище статусов задач (поллинг/вебсокет) + GradioApp --> TaskStatusRepo[📊 TaskStatusRepository] + end + + %% Scalability / Async Layer + subgraph "Scalability Layer (Async, flipped-buffer)" + TaskPublisher --> RabbitMQ[(🐇 RabbitMQ)] + FaceWorkerPool[👷‍♂️ FaceWorker Pool - N instances] --> RabbitMQ + FaceWorkerPool --> TaskStatusRepo end - + %% Domain Layer subgraph "Domain Layer" - FaceService --> Face[👤 Face Entity] + FaceService[⚙️ FaceRecognitionService] --> Face[👤 Face Entity] FaceService --> User[👨‍💼 User Entity] FaceService --> VResult[✅ VerificationResult] FaceService --> IResult[🎯 IdentificationResult] - + FaceRepo[📊 FaceRepository Interface] VectorStore[🗂️ VectorStore Interface] + UserRepoIface[👨‍💼 UserRepository Interface] + ObjectStorageIface[📁 ObjectStorage Interface] end - + %% Infrastructure Layer subgraph "Infrastructure Layer" %% ML Components @@ -42,9 +55,10 @@ graph TB %% Storage Components subgraph "Storage Components" - MongoDB[🗄️ MongoDBFaceRepository] - ChromaDB[🔗 ChromaDBVectorStore] - FileSystem[📁 FileSystemStorage] + MongoDBRepo[🗄️ MongoDBFaceRepository] + MongoUserRepo[👨‍💼 MongoDBUserRepository] + ChromaDBStore[🔗 ChromaDBVectorStore] + S3Storage[🪣 S3ObjectStorage] end %% Configuration & Logging @@ -53,60 +67,73 @@ graph TB Logger[📋 Logging System] end end - + %% External Systems subgraph "External Systems" MongoDBServer[(🗄️ MongoDB Database)] ChromaDBServer[(🔗 ChromaDB Vector DB)] - FileStorage[(📁 File System)] + S3Bucket[(🪣 S3 Bucket)] ONNXModel[🧠 SFace ONNX Model] + RedisOrMongo[(📊 Redis/Mongo for Task Status)] end - - %% Service Dependencies + + %% Service Dependencies (исполняются внутри воркеров) + FaceWorkerPool --> FaceService FaceService --> RetinaFace FaceService --> SFaceRec FaceService --> FaceRepo FaceService --> VectorStore - FaceService --> FileSystem - + FaceService --> ObjectStorageIface + %% Repository Implementations - FaceRepo -.->|implements| MongoDB - VectorStore -.->|implements| ChromaDB - + FaceRepo -.->|implements| MongoDBRepo + VectorStore -.->|implements| ChromaDBStore + UserRepoIface -.->|implements| MongoUserRepo + ObjectStorageIface -.->|implements| S3Storage + %% External Connections - MongoDB --> MongoDBServer - ChromaDB --> ChromaDBServer - FileSystem --> FileStorage + MongoDBRepo --> MongoDBServer + MongoUserRepo --> MongoDBServer + ChromaDBStore --> ChromaDBServer + S3Storage --> S3Bucket SFaceRec --> ONNXModel - - %% Use Case Dependencies - RegisterUC --> UserRepo[👨‍💼 MongoDBUserRepository] - VerifyUC --> UserRepo - IdentifyUC --> UserRepo - UserRepo --> MongoDBServer - + TaskStatusRepo --> RedisOrMongo + + %% Use Case Dependencies (чтение пользователей/статусов) + RegisterUC --> MongoUserRepo + VerifyUC --> MongoUserRepo + IdentifyUC --> MongoUserRepo + %% Logging Dependencies RetinaFace -.-> Logger SFaceRec -.-> Logger FaceService -.-> Logger - + FaceWorkerPool -.-> Logger + TaskPublisher -.-> Logger + %% Configuration Dependencies FaceService -.-> Config - MongoDB -.-> Config - ChromaDB -.-> Config - + MongoDBRepo -.-> Config + MongoUserRepo -.-> Config + ChromaDBStore -.-> Config + S3Storage -.-> Config + RabbitMQ -.-> Config + TaskStatusRepo -.-> Config + %% Styling classDef presentation fill:#e1f5fe classDef application fill:#f3e5f5 classDef domain fill:#e8f5e8 classDef infrastructure fill:#fff3e0 classDef external fill:#ffebee - + classDef scalability fill:#ede7f6 + class GradioUI,GradioApp presentation - class RegisterUC,VerifyUC,IdentifyUC,FaceService application - class Face,User,VResult,IResult,FaceRepo,VectorStore domain - class RetinaFace,SFaceRec,MongoDB,ChromaDB,FileSystem,Config,Logger,UserRepo infrastructure - class MongoDBServer,ChromaDBServer,FileStorage,ONNXModel external + class RegisterUC,VerifyUC,IdentifyUC,TaskPublisher,TaskStatusRepo application + class Face,User,VResult,IResult,FaceRepo,VectorStore,UserRepoIface,ObjectStorageIface,FaceService domain + class RetinaFace,SFaceRec,MongoDBRepo,ChromaDBStore,S3Storage,Config,Logger,MongoUserRepo infrastructure + class MongoDBServer,ChromaDBServer,S3Bucket,ONNXModel,RedisOrMongo external + class RabbitMQ,FaceWorkerPool scalability ``` ## Architecture Overview From 69f3c37fb9d4829f5b301c9beb19f1a0811cc01c Mon Sep 17 00:00:00 2001 From: Artem-Darius Weber Date: Fri, 25 Jul 2025 16:16:08 +0300 Subject: [PATCH 2/2] Update 'sequence-diagrams.md' --- sequence-diagrams.md | 356 +++++++++++++++++++++++-------------------- 1 file changed, 187 insertions(+), 169 deletions(-) diff --git a/sequence-diagrams.md b/sequence-diagrams.md index 460dba4..e12bf36 100644 --- a/sequence-diagrams.md +++ b/sequence-diagrams.md @@ -8,18 +8,21 @@ sequenceDiagram participant GradioUI as Gradio Interface participant RegisterUC as RegisterFaceUseCase participant UserRepo as MongoDBUserRepository - participant FaceService as FaceRecognitionService + participant S3 as S3ObjectStorage + participant TaskPub as TaskPublisher + participant MQ as RabbitMQ + participant StatusRepo as TaskStatusRepository + participant Worker as FaceWorker participant Detector as RetinaFaceDetector participant Recognizer as SFaceRecognizer participant FaceRepo as MongoDBFaceRepository participant VectorStore as ChromaDBVectorStore - participant FileStorage as FileSystemStorage participant MongoDB as MongoDB Database participant ChromaDB as ChromaDB Vector DB User->>GradioUI: Upload images + username GradioUI->>RegisterUC: execute(username, images) - + RegisterUC->>UserRepo: get_user_by_name(username) UserRepo->>MongoDB: Query user by name MongoDB-->>UserRepo: User data or null @@ -31,60 +34,53 @@ sequenceDiagram MongoDB-->>UserRepo: User ID UserRepo-->>RegisterUC: User ID end - + loop For each image - RegisterUC->>FaceService: register_face(user_id, image) - - FaceService->>Detector: detect_faces(image) - Detector-->>FaceService: List of detected faces - - alt No faces detected - FaceService-->>RegisterUC: null - else Face detected - FaceService->>Detector: calculate_quality_score(best_face) - Detector-->>FaceService: Quality score - - alt Quality too low - FaceService-->>RegisterUC: null - else Quality acceptable - FaceService->>Detector: align_face(image, landmarks) - Detector-->>FaceService: Aligned face image - - FaceService->>Recognizer: extract_embedding(aligned_face) - Recognizer-->>FaceService: Face embedding - - FaceService->>FileStorage: save_image(aligned_face, user_id) - FileStorage-->>FaceService: Image path - - FaceService->>FaceRepo: save(face_entity) - FaceRepo->>MongoDB: Insert face record - MongoDB-->>FaceRepo: Success - FaceRepo-->>FaceService: Success - - FaceService->>VectorStore: add(face_id, embedding, metadata) - VectorStore->>ChromaDB: Store embedding vector - ChromaDB-->>VectorStore: Success - VectorStore-->>FaceService: Success - - FaceService-->>RegisterUC: Face ID - end + RegisterUC->>S3: put_object(image) + S3-->>RegisterUC: s3_uri + + RegisterUC->>TaskPub: publish_register_task(user_id, s3_uri) + TaskPub->>MQ: enqueue(task) + end + + RegisterUC->>StatusRepo: wait/poll for task_ids status + StatusRepo-->>RegisterUC: Completed/Failed + results + + alt All tasks completed + RegisterUC->>StatusRepo: get_mean_embedding(user_id) / or compute later + RegisterUC-->>GradioUI: Success message + stats + else Some tasks failed + RegisterUC-->>GradioUI: Partial success + failed items + end + GradioUI-->>User: Registration result (async aware) + + %% Worker side + loop Worker Pool + MQ-->>Worker: task(user_id, s3_uri) + Worker->>S3: get_object(s3_uri) + Worker->>Detector: detect_faces(image) + Detector-->>Worker: faces + + alt No faces or low quality + Worker->>StatusRepo: update(task_id, failed_reason) + else Face OK + Worker->>Detector: align_face(image, landmarks) + Detector-->>Worker: aligned_face + + Worker->>Recognizer: extract_embedding(aligned_face) + Recognizer-->>Worker: embedding + + Worker->>FaceRepo: save(face_entity) + FaceRepo->>MongoDB: insert face record + MongoDB-->>FaceRepo: ok + + Worker->>VectorStore: add(face_id, embedding, metadata) + VectorStore->>ChromaDB: store vector + ChromaDB-->>VectorStore: ok + + Worker->>StatusRepo: update(task_id, success, embedding_id) end end - - RegisterUC->>FaceService: update_user_mean_embedding(user_id) - FaceService->>FaceRepo: get_by_user_id(user_id) - FaceRepo->>MongoDB: Query faces by user_id - MongoDB-->>FaceRepo: Face records - FaceRepo-->>FaceService: Face entities - FaceService-->>RegisterUC: Mean embedding - - RegisterUC->>UserRepo: update_user(user) - UserRepo->>MongoDB: Update user record - MongoDB-->>UserRepo: Success - UserRepo-->>RegisterUC: Success - - RegisterUC-->>GradioUI: Success message - GradioUI-->>User: Registration result ``` ## 2. Face Verification Flow @@ -95,7 +91,11 @@ sequenceDiagram participant GradioUI as Gradio Interface participant VerifyUC as VerifyFaceUseCase participant UserRepo as MongoDBUserRepository - participant FaceService as FaceRecognitionService + participant S3 as S3ObjectStorage + participant TaskPub as TaskPublisher + participant MQ as RabbitMQ + participant StatusRepo as TaskStatusRepository + participant Worker as FaceWorker participant Detector as RetinaFaceDetector participant Recognizer as SFaceRecognizer participant FaceRepo as MongoDBFaceRepository @@ -103,50 +103,53 @@ sequenceDiagram User->>GradioUI: Upload image + username GradioUI->>VerifyUC: execute(username, image) - + VerifyUC->>UserRepo: get_user_by_name(username) UserRepo->>MongoDB: Query user by name MongoDB-->>UserRepo: User data or null UserRepo-->>VerifyUC: User entity or null - + alt User not found VerifyUC-->>GradioUI: VerificationResult(false, 0.0) + GradioUI-->>User: result else User found - VerifyUC->>FaceService: verify_face(user_id, image) - - FaceService->>Detector: detect_faces(image) - Detector-->>FaceService: List of detected faces - - alt No faces detected - FaceService-->>VerifyUC: (false, 0.0) - else Face detected - FaceService->>Detector: align_face(image, landmarks) - Detector-->>FaceService: Aligned face image - - FaceService->>Recognizer: extract_embedding(aligned_face) - Recognizer-->>FaceService: Query embedding - - FaceService->>FaceRepo: get_by_user_id(user_id) - FaceRepo->>MongoDB: Query registered faces - MongoDB-->>FaceRepo: Face records - FaceRepo-->>FaceService: User's face entities - - alt No registered faces - FaceService-->>VerifyUC: (false, 0.0) - else Compare with registered faces - loop For each registered face - FaceService->>Recognizer: calculate_similarity(query_embedding, face_embedding) - Recognizer-->>FaceService: Similarity score - end - - FaceService-->>VerifyUC: (is_verified, max_similarity) - end - end - + VerifyUC->>S3: put_object(image) + S3-->>VerifyUC: s3_uri + + VerifyUC->>TaskPub: publish_verify_task(user_id, s3_uri) + TaskPub->>MQ: enqueue(task) + VerifyUC->>StatusRepo: wait/poll task_id + StatusRepo-->>VerifyUC: (is_verified, score) + VerifyUC-->>GradioUI: VerificationResult + GradioUI-->>User: result + end + + %% Worker side + MQ-->>Worker: task(user_id, s3_uri) + Worker->>S3: get_object(s3_uri) + Worker->>Detector: detect_faces(image) + Detector-->>Worker: faces + + alt No faces + Worker->>StatusRepo: update(task_id, false, 0.0) + else + Worker->>Detector: align_face(image, landmarks) + Detector-->>Worker: aligned + + Worker->>Recognizer: extract_embedding(aligned) + Recognizer-->>Worker: query_embedding + + Worker->>FaceRepo: get_by_user_id(user_id) + FaceRepo->>MongoDB: query faces + MongoDB-->>FaceRepo: records + FaceRepo-->>Worker: embeddings + + Worker->>Recognizer: calculate_similarity(query_embedding, user_embeddings) + Recognizer-->>Worker: max_score + + Worker->>StatusRepo: update(task_id, max_score>=threshold, max_score) end - - GradioUI-->>User: Verification result ``` ## 3. Face Identification Flow @@ -156,109 +159,124 @@ sequenceDiagram participant User participant GradioUI as Gradio Interface participant IdentifyUC as IdentifyFaceUseCase - participant UserRepo as MongoDBUserRepository - participant FaceService as FaceRecognitionService + participant S3 as S3ObjectStorage + participant TaskPub as TaskPublisher + participant MQ as RabbitMQ + participant StatusRepo as TaskStatusRepository + participant Worker as FaceWorker participant Detector as RetinaFaceDetector participant Recognizer as SFaceRecognizer participant VectorStore as ChromaDBVectorStore participant ChromaDB as ChromaDB Vector DB + participant UserRepo as MongoDBUserRepository participant MongoDB as MongoDB Database User->>GradioUI: Upload image GradioUI->>IdentifyUC: execute(image) - - IdentifyUC->>FaceService: identify_face(image) - - FaceService->>Detector: detect_faces(image) - Detector-->>FaceService: List of detected faces - - alt No faces detected - FaceService-->>IdentifyUC: (null, 0.0, []) - else Face detected - FaceService->>Detector: align_face(image, landmarks) - Detector-->>FaceService: Aligned face image - - FaceService->>Recognizer: extract_embedding(aligned_face) - Recognizer-->>FaceService: Query embedding - - FaceService->>VectorStore: search_similar(query_embedding, top_k=10) - VectorStore->>ChromaDB: Vector similarity search - ChromaDB-->>VectorStore: Similar face vectors - VectorStore-->>FaceService: Similar faces with metadata - - alt No similar faces above threshold - FaceService-->>IdentifyUC: (null, 0.0, []) - else Similar faces found - note over FaceService: Group by user_id and calculate best scores - FaceService-->>IdentifyUC: (best_user_id, confidence, candidates) - end - end - - loop For each candidate user_id + + IdentifyUC->>S3: put_object(image) + S3-->>IdentifyUC: s3_uri + + IdentifyUC->>TaskPub: publish_identify_task(s3_uri, top_k=10) + TaskPub->>MQ: enqueue(task) + + IdentifyUC->>StatusRepo: wait/poll task_id + StatusRepo-->>IdentifyUC: (best_user_id, confidence, candidate_user_ids) + + loop For each candidate_user_id IdentifyUC->>UserRepo: get_by_id(user_id) - UserRepo->>MongoDB: Query user by ID - MongoDB-->>UserRepo: User data + UserRepo->>MongoDB: query + MongoDB-->>UserRepo: user data UserRepo-->>IdentifyUC: User entity end - - alt User identified - IdentifyUC->>UserRepo: get_by_id(best_user_id) - UserRepo->>MongoDB: Query identified user - MongoDB-->>UserRepo: User data - UserRepo-->>IdentifyUC: User entity - end - + IdentifyUC-->>GradioUI: IdentificationResult - GradioUI-->>User: Identification result + GradioUI-->>User: result + + %% Worker + MQ-->>Worker: task(s3_uri) + Worker->>S3: get_object(s3_uri) + Worker->>Detector: detect_faces(image) + Detector-->>Worker: faces + + alt No faces + Worker->>StatusRepo: update(task_id, null, 0.0, []) + else + Worker->>Detector: align_face(image, landmarks) + Detector-->>Worker: aligned + Worker->>Recognizer: extract_embedding(aligned) + Recognizer-->>Worker: query_embedding + + Worker->>VectorStore: search_similar(query_embedding, top_k=10) + VectorStore->>ChromaDB: search + ChromaDB-->>VectorStore: results with metadata (face_id, user_id, score) + VectorStore-->>Worker: candidates + + alt No scores above threshold + Worker->>StatusRepo: update(task_id, null, 0.0, []) + else + note over Worker: Group by user_id, choose best_user_id + confidence + Worker->>StatusRepo: update(task_id, best_user_id, confidence, candidate_user_ids) + end + end ``` ## 4. System Initialization Flow ```mermaid sequenceDiagram - participant Main as main.py + participant Main as main.py (API) participant Config as Settings - participant MongoDB as MongoDBFaceRepository + participant MongoDBRepo as MongoDBFaceRepository + participant MongoUserRepo as MongoDBUserRepository participant ChromaDB as ChromaDBVectorStore - participant FileStorage as FileSystemStorage - participant Detector as RetinaFaceDetector - participant Recognizer as SFaceRecognizer - participant FaceService as FaceRecognitionService - participant UseCases as Use Cases + participant S3 as S3ObjectStorage + participant Rabbit as RabbitMQ + participant StatusRepo as TaskStatusRepository + participant Publisher as TaskPublisher participant GradioApp as Gradio Interface + participant WorkerMain as worker_main.py (Workers) + participant WConfig as Settings + participant WDetector as RetinaFaceDetector + participant WRecognizer as SFaceRecognizer + participant WFaceService as FaceRecognitionService + participant WFaceRepo as MongoDBFaceRepository + participant WVector as ChromaDBVectorStore + participant WS3 as S3ObjectStorage + participant WRabbit as RabbitMQ + participant WStatusRepo as TaskStatusRepository + participant WPool as FaceWorkerPool + + %% API init Main->>Config: Load configuration Config-->>Main: Settings object - - Main->>MongoDB: Initialize with MongoDB URL - MongoDB-->>Main: Repository instance - - Main->>ChromaDB: Initialize with Chroma host/port - ChromaDB-->>Main: Vector store instance - - Main->>FileStorage: Initialize with upload directory - FileStorage-->>Main: File storage instance - - Main->>Detector: Initialize RetinaFace - note over Detector: Load ONNX models, prepare ctx - Detector-->>Main: Detector instance - - Main->>Recognizer: Initialize SFace - note over Recognizer: Download/load SFace ONNX model - Recognizer-->>Main: Recognizer instance - - Main->>FaceService: Initialize with dependencies - FaceService-->>Main: Service instance - - Main->>UseCases: Initialize use cases with service - UseCases-->>Main: Use case instances - - Main->>GradioApp: create_gradio_interface(use_cases) - GradioApp-->>Main: Gradio app instance - - Main->>GradioApp: launch(server_name, server_port) - note over GradioApp: Start web server on port 7860 - GradioApp-->>Main: Server running + + Main->>MongoDBRepo: Initialize with Mongo URL + Main->>MongoUserRepo: Initialize with Mongo URL + Main->>ChromaDB: Initialize with host/port + Main->>S3: Initialize with bucket/creds + Main->>Rabbit: Connect/create queues + Main->>StatusRepo: Initialize (Redis/Mongo) + Main->>Publisher: Initialize with Rabbit + Main->>GradioApp: create_gradio_interface(use_cases, publisher, status_repo) + Main->>GradioApp: launch(server_name, port) + + %% Worker init (can be on separate machines) + WorkerMain->>WConfig: Load configuration + WConfig-->>WorkerMain: Settings + + WorkerMain->>WRabbit: Connect/subscribe queues + WorkerMain->>WStatusRepo: Initialize + WorkerMain->>WDetector: Initialize RetinaFace + note over WDetector: Load ONNX models, prepare ctx + WorkerMain->>WRecognizer: Initialize SFace + note over WRecognizer: Load/Download ONNX model + WorkerMain->>WFaceRepo: Initialize with Mongo URL + WorkerMain->>WVector: Initialize with Chroma host/port + WorkerMain->>WS3: Initialize with bucket/creds + WorkerMain->>WFaceService: Initialize with dependencies + WorkerMain->>WPool: Start consuming tasks ``` ## Flow Descriptions