Spaces:
Runtime error
Runtime error
| # System Architecture & Data Flow | |
| ## ποΈ System Architecture Diagram | |
| ``` | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β HUGGING FACE SPACES β | |
| β (Free CPU Tier) β | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ | |
| β β | |
| β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β | |
| β β GRADIO UI (Chat Interface) β β | |
| β β - Display chat messages β β | |
| β β - Take user input β β | |
| β β - Show predictions β β | |
| β ββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ β | |
| β β β | |
| β ββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ β | |
| β β app/main.py β β | |
| β β (Chat Function & Orchestration) β β | |
| β β - Coordinates all services β β | |
| β β - Manages conversation flow β β | |
| β ββββββ¬βββββββββββββββββββ¬βββββββββββββββββββ¬ββββββββββββββββ β | |
| β β β β β | |
| β βββββββΌβββββββ ββββββββββΌβββββββ ββββββββββΌβββββββ β | |
| β β LLM β β Memory β β Predictor β β | |
| β β Extractor β β Manager β β Service β β | |
| β β β β β β β β | |
| β β Input: β β Input: β β Input: β β | |
| β β "I'm 45..." β β Extracted β β Feature β β | |
| β β β β features β β vector β β | |
| β β Output: β β β β β β | |
| β β JSON with β β Output: β β Output: β β | |
| β β features β β Full state β β Prediction β β | |
| β βββββββ¬βββββββ β (16 features) β β + confidence β β | |
| β β ββββββββββ¬βββββββ βββββββββ¬ββββββββ β | |
| β β β β β | |
| β βββββββΌββββββ ββββββββββΌβββ βββββββββββββΌββββ β | |
| β β GROQ β β app/ β β Feature β β | |
| β β Llama 3 β β memory.py β β Builder β β | |
| β β (Free API) β β β β β β | |
| β β β β State: β β Validates & β β | |
| β β Cloud- β β { β β prepares β β | |
| β β based β β Age: 45, β β feature β β | |
| β β β β Glucose: β β vector for β β | |
| β β β β 150, β β ML model β β | |
| β β β β ... β β β β | |
| β β β β ... β β (Validates β β | |
| β β β β } β β ranges) β β | |
| β β β β β β β β | |
| β ββββββββββββββ βββββββββββββ ββββββββββ¬βββββββ β | |
| β β β | |
| β ββββββββββββββββββΌβββββββββββ β | |
| β β Predictor Service β β | |
| β β (app/services/ β β | |
| β β predictor.py) β β | |
| β β β β | |
| β β Loads: β β | |
| β β GradientBoosting_ β β | |
| β β model.pkl β β | |
| β β β β | |
| β β Inputs: [16 floats] β β | |
| β β Outputs: class + prob β β | |
| β ββββββββββββββ¬ββββββββββββββ β | |
| β β β | |
| β ββββββββββββββΌβββββββββββ β | |
| β β scikit-learn β β | |
| β β GradientBoosting β β | |
| β β Classifier β β | |
| β β β β | |
| β β (Runs locally on CPU) β β | |
| β ββββββββββββββββββββββββββ β | |
| β β | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ``` | |
| --- | |
| ## π Data Flow Sequence | |
| ### Step 1: User Inputs Text | |
| ``` | |
| User: "I'm 45 years old and my glucose is 150" | |
| β | |
| [Sent to main.py] | |
| ``` | |
| ### Step 2: LLM Extraction (Groq API) | |
| ``` | |
| app/main.py | |
| β | |
| call: extract_features_from_text(message) | |
| β | |
| llm_extractor.py | |
| β | |
| Groq API (Cloud) | |
| β | |
| βββ llama-3.1-8b-instant | |
| (Processes: "I'm 45... glucose 150...") | |
| β | |
| Returns JSON: { | |
| "Age": 45, | |
| "Glucose": 150, | |
| "Smoking": null, | |
| "HbA1c": null, | |
| ... (rest null) | |
| } | |
| β | |
| [Returns to main.py] | |
| ``` | |
| ### Step 3: Update Memory | |
| ``` | |
| current_state = { | |
| "Age": null, | |
| "Glucose": null, | |
| ... (all null) | |
| } | |
| β | |
| extracted = {"Age": 45, "Glucose": 150, ...} | |
| β | |
| memory.update_state(current_state, extracted) | |
| β | |
| new_state = { | |
| "Age": 45, | |
| "Glucose": 150, | |
| "Smoking": null, | |
| ... (rest null) | |
| } | |
| ``` | |
| ### Step 4: Check Missing Features | |
| ``` | |
| missing_features = get_missing_features(state) | |
| β | |
| Result: ["Smoking", "Family History", "HbA1c", ... (12 more)] | |
| β | |
| len(missing) = 14 features still needed | |
| β | |
| DECISION: Not ready for prediction yet | |
| ``` | |
| ### Step 5: Generate Question | |
| ``` | |
| next_missing = missing_features[0] # "Smoking" | |
| β | |
| question = generate_question("Smoking") | |
| β | |
| Result: "Do you smoke? (yes/no)" | |
| β | |
| Send to user in chat | |
| ``` | |
| ### Step 6: User Answers (Loop Back to Step 1) | |
| ``` | |
| User: "No, I don't smoke" | |
| β | |
| [Loop back to Step 1] | |
| β | |
| (Repeat until all 16 features collected) | |
| ``` | |
| ### Step 7: All Features Collected - Ready for Prediction | |
| ``` | |
| state = { | |
| "Age": 45, | |
| "Glucose": 150, | |
| "Smoking": 0, | |
| "Family History": 1, | |
| ... (all 16 features filled) | |
| } | |
| β | |
| missing_features = [] # Empty! | |
| β | |
| DECISION: Ready for prediction! | |
| ``` | |
| ### Step 8: Feature Builder - Prepare for ML Model | |
| ``` | |
| feature_builder.prepare_feature_vector(state) | |
| β | |
| Validation: | |
| - Check each value in valid range | |
| - Convert types to float | |
| - Handle missing with defaults | |
| β | |
| Output: [45.0, 150.0, 0.0, 1.0, ... (16 floats total)] | |
| β | |
| This vector is ready for ML model | |
| ``` | |
| ### Step 9: Prediction | |
| ``` | |
| feature_vector = [45.0, 150.0, 0.0, 1.0, ...] | |
| β | |
| predictor = get_predictor() # Loads model.pkl | |
| β | |
| result = predictor.predict(feature_vector) | |
| β | |
| Model processes: | |
| - Input: 16 features | |
| - Runs through GradientBoosting | |
| - Output: class (0 or 1) + probability | |
| β | |
| Returns: PredictionResponse { | |
| "prediction": 1, | |
| "probability": 0.85, | |
| "risk_level": "High", | |
| "explanation": "Model predicts class 1 with 85% confidence" | |
| } | |
| ``` | |
| ### Step 10: Display Results to User | |
| ``` | |
| Chatbot: "β All information collected! | |
| Prediction Results: | |
| - Prediction: Class 1 | |
| - Confidence: 85.0% | |
| - Risk Level: High | |
| - Details: Model predicts class 1 with 85% confidence" | |
| ``` | |
| --- | |
| ## π Complete Conversation Example | |
| ``` | |
| USER: "I'm 45 years old, my glucose is 150, I smoke, and my stress is high" | |
| STEP 1 (Extract): | |
| Groq extracts: {Age: 45, Glucose: 150, Smoking: 1, StressLevel: null} | |
| STEP 2 (Update Memory): | |
| state = {Age: 45, Glucose: 150, Smoking: 1, StressLevel: null, ...} | |
| STEP 3 (Check Missing): | |
| missing = ["Family History", "HbA1c", "StressLevel", ... (12 more)] | |
| STEP 4 (Ask Question): | |
| BOT: "Do you have a family history of disease? (yes/no)" | |
| USER: "Yes" | |
| STEP 1 (Extract): | |
| Groq extracts: {FamilyHistory: 1} | |
| STEP 2 (Update Memory): | |
| state = {Age: 45, Glucose: 150, Smoking: 1, FamilyHistory: 1, ...} | |
| STEP 3 (Check Missing): | |
| missing = ["HbA1c", "StressLevel", ... (12 more)] | |
| STEP 4 (Ask Question): | |
| BOT: "What is your HbA1c level?" | |
| ... (repeat until all 16 features) | |
| STEP 7 (All Collected): | |
| state = {Age: 45, Glucose: 150, Smoking: 1, FamilyHistory: 1, | |
| HbA1c: 7.2, BMI: 28, ... (all 16 filled)} | |
| STEP 8 (Prepare): | |
| feature_vector = [45.0, 150.0, 1.0, 1.0, 7.2, ... (16 values)] | |
| STEP 9 (Predict): | |
| ML Model processes vector | |
| Returns: {prediction: 1, probability: 0.82, risk_level: "High"} | |
| STEP 10 (Display): | |
| BOT: "β Prediction: Class 1 (82% confidence)" | |
| ``` | |
| --- | |
| ## π File Dependencies & Data Flow | |
| ``` | |
| βββββββββββββββββββ | |
| β app/main.py β β ORCHESTRATOR (coordinates everything) | |
| ββββββββββ¬βββββββββ | |
| β | |
| ββββββΌβββββ¬βββββββββββββββββ¬βββββββββββββββ | |
| β β β β β | |
| βΌ βΌ βΌ βΌ βΌ | |
| βββββββββ ββββββββββββ ββββββββββββββββ βββββββββββββββ | |
| βmemory β βllm_ β βfeature_ β βpredictor β | |
| β.py β βextractor β βbuilder.py β β.py β | |
| β β β.py β β β β β | |
| β ββββ β β ββββββββ β β βββββββββββ β β ββββββββββ β | |
| β β β β β βGroq β β β βValidate β β β βLoad β β | |
| β β β β β βAPI β β β βFeatures β β β βModel β β | |
| β ββββ β β ββββββββ β β β β β β β pkl β β | |
| β β β β β βPrepare β β β β β β | |
| βTracks β βExtracts β β βVector β β β βPredict β β | |
| βState β βFeatures β β β β β β βResult β β | |
| β β β(JSON) β β β β β β β β β | |
| βββββββββ ββββββββββββ βββββββββββ¬ββ β βββββ¬βββββ¬ββ β | |
| β β β β β | |
| β β β ββββββΌβββ | |
| β ββββββββΌββββββββββ β | |
| β β β | |
| βΌ βΌ βΌ | |
| ββββββββββββββββ βββββββββββββββββββ | |
| βapp/schemas.pyβ βmodels/ β | |
| β(Validation) β βGradientBoosting β | |
| β β β_model.pkl β | |
| β ββββββββββββ β β β | |
| β βPydantic β β β (scikit-learn) β | |
| β βModels β β β Binary Classifier | |
| β β(Types) β β β 16 Features β | |
| β ββββββββββββ β β Input β Output β | |
| ββββββββββββββββ βββββββββββββββββββ | |
| ββββββββββββββββββββββββββββββββ | |
| βapp/config.py β | |
| β(Constants & Configuration) β | |
| β β’ Paths β | |
| β β’ API settings β | |
| β β’ Feature ranges β | |
| β β’ Feature list β | |
| ββββββββββββββββββββββββββββββββ | |
| ββββββββββββββββββββββββββββββββ | |
| βapp/utils/helpers.py β | |
| β(Question Mapping) β | |
| β Feature β Question lookup β | |
| ββββββββββββββββββββββββββββββββ | |
| ``` | |
| --- | |
| ## π Integration Points | |
| ### 1. **Groq API β LLM Extractor** | |
| ``` | |
| Input: User text (string) | |
| Process: HTTP request to Groq cloud | |
| Output: JSON with features | |
| Error: Timeout, invalid JSON, API errors | |
| ``` | |
| ### 2. **LLM Extractor β Memory** | |
| ``` | |
| Input: JSON from Groq | |
| Process: Merge into state dict | |
| Output: Updated state with new values | |
| Error: Type mismatch, null values (OK) | |
| ``` | |
| ### 3. **Memory β Feature Builder** | |
| ``` | |
| Input: State dict with all features | |
| Process: Validate ranges, convert types | |
| Output: Prepared feature vector | |
| Error: Out of range, type errors | |
| ``` | |
| ### 4. **Feature Builder β Predictor** | |
| ``` | |
| Input: Feature vector [16 floats] | |
| Process: Load model, make prediction | |
| Output: Prediction class + probability | |
| Error: Model not found, predict error | |
| ``` | |
| ### 5. **Predictor β Main App** | |
| ``` | |
| Input: Request for prediction | |
| Process: Get result from model | |
| Output: PredictionResponse object | |
| Error: Model errors, input errors | |
| ``` | |
| --- | |
| ## π― Key Design Decisions | |
| ### Why Separate Services? | |
| - **llm_extractor.py**: Handles all Groq API logic | |
| - **feature_builder.py**: Handles all validation logic | |
| - **predictor.py**: Handles all ML model logic | |
| - **memory.py**: Handles state management | |
| - **helpers.py**: Handles UI text generation | |
| **Benefits**: | |
| - Easy to test each independently | |
| - Easy to modify without breaking others | |
| - Clear separation of concerns | |
| - Reusable components | |
| ### Why Pydantic Schemas? | |
| - Type validation | |
| - Automatic conversion | |
| - Error messages | |
| - Documentation | |
| - IDE autocomplete | |
| ### Why Groq Instead of Local LLM? | |
| - Free tier (very generous) | |
| - Fast inference (cloud-based) | |
| - No GPU needed | |
| - No local setup required | |
| - Easy to deploy on CPU-only Spaces | |
| ### Why scikit-learn Model? | |
| - Lightweight (fast on CPU) | |
| - Works on HF Spaces free tier | |
| - Easy to load/save (joblib) | |
| - No deep learning overhead | |
| - Deterministic results | |
| --- | |
| ## π Performance Considerations | |
| ### Typical Response Times | |
| | Step | Time | Notes | | |
| |------|------|-------| | |
| | Groq API call | 1-3s | Cloud-based, depends on load | | |
| | Feature extraction | <0.1s | JSON parsing | | |
| | Memory update | <0.01s | Dict operations | | |
| | Feature validation | <0.01s | Simple checks | | |
| | Prediction | <0.1s | scikit-learn inference | | |
| | **Total** | **1-3s** | User sees response in 1-3 seconds | | |
| ### Scalability | |
| - **Concurrent Users**: HF Spaces free CPU can handle ~10-20 concurrent users | |
| - **API Rate**: Groq free tier: very generous (1000s of calls/day) | |
| - **Model Size**: GradientBoosting small (<5MB) | |
| - **Memory Usage**: ~200MB for app + model | |
| --- | |
| ## π Security Considerations | |
| ### Secrets Handling | |
| - GROQ_API_KEY: Stored in .env locally, HF Spaces secrets in production | |
| - Model file: Public (no sensitive info) | |
| - User data: In-memory only (not persisted) | |
| ### Input Validation | |
| - All user inputs validated via Pydantic | |
| - Feature ranges checked | |
| - Type conversion safe | |
| ### Privacy | |
| - No data logged | |
| - No external APIs called except Groq | |
| - No user data persisted | |
| --- | |
| ## β‘ Optimization Opportunities (Future) | |
| 1. **Caching**: Cache similar predictions | |
| 2. **Batching**: Process multiple users' requests together | |
| 3. **Model**: Use faster model variant | |
| 4. **LLM**: Use smaller Groq model for faster extraction | |
| 5. **Storage**: Add database for history (optional) | |
| --- | |
| This architecture is designed for: | |
| - β Clarity & maintainability | |
| - β Testability | |
| - β Deployability on free Spaces | |
| - β Easy debugging | |
| - β Extensibility | |
| Ready to implement? Follow the GUIDES.md file step-by-step! | |