# Architecture Documentation ## System Overview The Chest X-Ray Assistant is a distributed web application with a clear separation of concerns: ``` ┌─────────────────────────────────────────────────────────┐ │ USER BROWSER │ │ (Chrome, Safari, Firefox, etc.) │ └────────────────────┬────────────────────────────────────┘ │ HTTPS/443 │ ┌────────────────────▼────────────────────────────────────┐ │ NEXT.JS FRONTEND │ │ Deployed on Vercel │ │ │ │ • Landing page (app/page.tsx) │ │ • Assistant interface (app/assistant/page.tsx) │ │ • Chat UI with image upload │ │ • Medical-grade design system │ │ • Client-side React logic │ └────────────────────┬────────────────────────────────────┘ │ HTTPS API Calls │ POST /api/chat │ GET /health │ ┌────────────────────▼────────────────────────────────────┐ │ FASTAPI BACKEND │ │ Deployed on Railway/Render/AWS │ │ │ │ • RESTful API endpoints │ │ • Request validation │ │ • Image preprocessing │ │ • PyTorch model inference │ │ • Groq LLM integration │ │ • Deterministic output generation │ └─────────────────────────────────────────────────────────┘ ``` ## Component Details ### 1. Frontend (Next.js) **Responsibilities:** - User interface and interaction - Chat interface - Image upload handling - Display of analysis results - Navigation and routing **Key Files:** - `app/page.tsx` - Landing page - `app/assistant/page.tsx` - Main chat interface - `app/layout.tsx` - Root layout - `app/globals.css` - Global styles - `lib/utils.ts` - Utility functions **Data Flow:** ``` User Input → Form State → HTTP Request → Backend API ↓ Response ← State Update ← JSON Response ← Processing ``` **Design System:** ```typescript Colors: - medical-* (50-900): Neutral, professional tones - accent-* (500-600): Primary action colors Components: - Rounded corners (rounded-2xl, rounded-lg) - Soft shadows (shadow-medical, shadow-medical-lg) - Clean typography - Healthcare icons only ``` ### 2. Backend (FastAPI) **Responsibilities:** - API endpoint management - Input validation - Image preprocessing - Model inference - LLM interpretation - Response formatting **Key Files:** - `backend/main.py` - All backend logic **Core Functions:** ```python # 1. Image Preprocessing preprocess_image(image_bytes: bytes) -> torch.Tensor - Load image from bytes - Convert to grayscale (1 channel) - Resize to 224x224 - Convert to tensor - Normalize with fixed values - Return batch tensor # 2. Model Inference run_inference(image_tensor: torch.Tensor) -> Dict[str, float] - Load model (if not loaded) - Run forward pass (no gradient) - Apply sigmoid activation - Return structured probabilities # 3. LLM Interpretation interpret_with_llm(conditions: Dict, message: str) -> str - Format probabilities for prompt - Call Groq API with LLaMA model - Enforce safety constraints - Return educational explanation # 4. Chat Without Image chat_without_image(message: str) -> str - Handle general medical questions - Provide educational info only - No image data implication ``` **Endpoints:** ``` POST /api/chat Input: FormData with optional 'message' and/or 'image' Output: { "response": str, "has_image_analysis": bool, "conditions": Dict[str, float] | null } GET /health Output: { "status": "healthy", "model_loaded": bool, "device": str } ``` ## Deterministic Pipeline The system guarantees deterministic behavior through: ### 1. Preprocessing Determinism ```python # Fixed transformations - no randomness transform = transforms.Compose([ transforms.Resize((224, 224)), # Fixed size transforms.ToTensor(), # Deterministic conversion transforms.Normalize([0.5], [0.5]), # Fixed values ]) ``` ### 2. Model Inference Determinism ```python # Eval mode - no dropout model.eval() # No gradient - deterministic forward pass with torch.no_grad(): outputs = model(image_tensor) # Sigmoid - deterministic activation probabilities = torch.sigmoid(outputs) ``` ### 3. LLM Determinism ```python # Low temperature for consistent outputs temperature=0.3 # Strict system prompt prevents hallucination system_prompt = """ You must NOT hallucinate conditions. You must NOT diagnose. You must ALWAYS include a disclaimer. """ ``` ## Data Flow Diagrams ### Image Analysis Flow ``` User uploads X-ray image ↓ Frontend validates file type and size ↓ FormData sent to backend ↓ Backend validates content-type ↓ preprocess_image() - Load image - Convert to grayscale - Resize to 224x224 - Normalize ↓ run_inference() - Load model (once) - Forward pass (no grad) - Apply sigmoid ↓ interpret_with_llm() - Format probabilities - Call Groq API - Enforce safety ↓ Return JSON to frontend ↓ Display results with disclaimers ``` ### Chat Without Image Flow ``` User types medical question ↓ Frontend sends text message ↓ Backend detects no image ↓ chat_without_image() - Call Groq API - Provide educational info - No image implication ↓ Return response to frontend ↓ Display in chat interface ``` ## Model Architecture ### CheXpert CNN ``` Input: [1, 224, 224] (grayscale image) ↓ ┌─────────────────────────────┐ │ Conv2d(1, 32, 3x3) │ │ BatchNorm2d(32) │ │ ReLU │ │ MaxPool2d(2x2) │ → [32, 112, 112] └─────────────────────────────┘ ↓ ┌─────────────────────────────┐ │ Conv2d(32, 64, 3x3) │ │ BatchNorm2d(64) │ │ ReLU │ │ MaxPool2d(2x2) │ → [64, 56, 56] └─────────────────────────────┘ ↓ ┌─────────────────────────────┐ │ Conv2d(64, 128, 3x3) │ │ BatchNorm2d(128) │ │ ReLU │ │ MaxPool2d(2x2) │ → [128, 28, 28] └─────────────────────────────┘ ↓ ┌─────────────────────────────┐ │ Conv2d(128, 256, 3x3) │ │ BatchNorm2d(256) │ │ ReLU │ │ MaxPool2d(2x2) │ → [256, 14, 14] └─────────────────────────────┘ ↓ Flatten: 256 × 14 × 14 = 50176 ↓ ┌─────────────────────────────┐ │ Linear(50176, 512) │ │ ReLU │ │ Dropout(0.5) │ │ Linear(512, 14) │ → [14] (logits) └─────────────────────────────┘ ↓ Sigmoid activation ↓ Output: [14] probabilities (0-1) ``` ### CheXpert Conditions ``` Index Condition 0 No Finding 1 Enlarged Cardiomediastinum 2 Cardiomegaly 3 Lung Opacity 4 Lung Lesion 5 Edema 6 Consolidation 7 Pneumonia 8 Atelectasis 9 Pneumothorax 10 Pleural Effusion 11 Pleural Other 12 Fracture 13 Support Devices ``` ## Safety Architecture ### 1. Medical Safety **Input Validation:** ```python # Image type check if not image.content_type.startswith('image/'): raise HTTPException(status_code=400) # File size limit (frontend) if (file.size > 10 * 1024 * 1024): alert('File too large') ``` **Output Constraints:** ```python system_prompt = """ CRITICAL RULES (you must follow all): 1. You are NOT a doctor and do NOT provide medical diagnoses 2. DO NOT claim any condition is definitely present or absent 3. Always emphasize uncertainty 4. Include a clear disclaimer at the end 5. Reference only the conditions provided 6. Do NOT hallucinate or invent conditions """ ``` **UI Disclaimers:** ```typescript // Every AI response includes disclaimer
Important: This tool is for educational purposes only...