Spaces:
Configuration error
Configuration error
| # Import Libraries | |
| import os | |
| import gradio as gr | |
| import google.generativeai as genai | |
| import fitz # PyMuPDF | |
| from PIL import Image, ImageEnhance | |
| import io | |
| import re | |
| import json | |
| import numpy as np | |
| import pandas as pd | |
| from datetime import datetime | |
| import base64 | |
| # Blood Report Analyzer Implementation | |
| # Configure Google Gemini API | |
| def configure_genai(api_key): | |
| genai.configure(api_key=api_key) | |
| # Use Gemini Pro Vision for image analysis | |
| vision_model = genai.GenerativeModel('gemini-pro-vision') | |
| # Use Gemini Pro for text analysis (better for structured text) | |
| text_model = genai.GenerativeModel('gemini-pro') | |
| return vision_model, text_model | |
| # Image preprocessing to improve OCR | |
| def preprocess_image(image): | |
| # Convert to grayscale | |
| img_gray = image.convert('L') | |
| # Enhance contrast | |
| enhancer = ImageEnhance.Contrast(img_gray) | |
| img_enhanced = enhancer.enhance(2.0) | |
| # Increase sharpness | |
| sharpness = ImageEnhance.Sharpness(img_enhanced) | |
| img_sharp = sharpness.enhance(2.0) | |
| return img_sharp | |
| # Extract text from PDF with advanced techniques | |
| def extract_text_from_pdf(pdf_file): | |
| doc = fitz.open(stream=pdf_file, filetype="pdf") | |
| complete_text = "" | |
| images = [] | |
| tables = [] | |
| for page_num in range(len(doc)): | |
| page = doc.load_page(page_num) | |
| # Get text with improved layout preservation | |
| text = page.get_text("dict") | |
| blocks = text.get("blocks", []) | |
| # Process text blocks to preserve table-like structures | |
| page_text = "" | |
| for block in blocks: | |
| if block.get("type") == 0: # Text block | |
| for line in block.get("lines", []): | |
| line_text = " ".join([span.get("text", "") for span in line.get("spans", [])]) | |
| page_text += line_text + "\n" | |
| complete_text += page_text + "\n\n" | |
| # Extract tables using heuristics | |
| # Look for grid-like structures in the text | |
| table_candidates = re.findall(r'(?:\w+[\t ]+){2,}(?:\d+\.?\d*[\t ]+){2,}', page_text) | |
| if table_candidates: | |
| tables.extend(table_candidates) | |
| # Extract images for visual analysis | |
| image_list = page.get_images(full=True) | |
| for img_index, img in enumerate(image_list): | |
| xref = img[0] | |
| base_image = doc.extract_image(xref) | |
| image_bytes = base_image["image"] | |
| image = Image.open(io.BytesIO(image_bytes)) | |
| # Only keep images that might be charts or reports | |
| # (filter out logos and decorative elements) | |
| if image.width > 200 and image.height > 200: | |
| # Preprocess image to improve readability | |
| processed_image = preprocess_image(image) | |
| images.append(processed_image) | |
| return complete_text, images, tables | |
| # Blood markers dictionary for reference | |
| BLOOD_MARKERS = { | |
| "Vitamin D": ["25-OH Vitamin D", "Vitamin D, 25-Hydroxy", "25(OH)D", "Calcidiol"], | |
| "Vitamin B12": ["Cobalamin", "Cyanocobalamin", "Methylcobalamin", "B-12"], | |
| "Folate": ["Vitamin B9", "Folic Acid"], | |
| "Vitamin A": ["Retinol", "Beta-carotene"], | |
| "Vitamin E": ["Tocopherol", "Alpha-tocopherol"], | |
| "Vitamin K": ["Phylloquinone", "Menaquinone"], | |
| "Vitamin C": ["Ascorbic Acid", "L-ascorbic acid"], | |
| "Vitamin B1": ["Thiamine", "Thiamin"], | |
| "Vitamin B2": ["Riboflavin"], | |
| "Vitamin B3": ["Niacin", "Nicotinic acid"], | |
| "Vitamin B5": ["Pantothenic acid"], | |
| "Vitamin B6": ["Pyridoxine", "Pyridoxal", "Pyridoxamine"], | |
| "Vitamin B7": ["Biotin"], | |
| "Iron": ["Ferritin", "Transferrin", "TIBC", "UIBC", "Serum Iron"], | |
| "Calcium": ["Ca", "Serum Calcium", "Ionized Calcium"], | |
| "Magnesium": ["Mg", "Serum Magnesium"], | |
| "Zinc": ["Zn", "Serum Zinc"], | |
| "Selenium": ["Se", "Serum Selenium"], | |
| "Iodine": ["I", "Urinary Iodine"] | |
| } | |
| # Normal ranges reference (based on Indian standards) | |
| REFERENCE_RANGES = { | |
| "Vitamin D": {"unit": "ng/mL", "min": 30, "max": 100, | |
| "deficiency": "<20", "insufficiency": "20-29"}, | |
| "Vitamin B12": {"unit": "pg/mL", "min": 211, "max": 911, | |
| "deficiency": "<200", "insufficiency": "200-300"}, | |
| "Folate": {"unit": "ng/mL", "min": 5.9, "max": 24.8, | |
| "deficiency": "<5.9"}, | |
| "Ferritin": {"unit": "ng/mL", "min_male": 30, "max_male": 400, | |
| "min_female": 13, "max_female": 150, | |
| "deficiency_male": "<30", "deficiency_female": "<13"}, | |
| "Hemoglobin": {"unit": "g/dL", | |
| "min_male": 13.5, "max_male": 17.5, | |
| "min_female": 12.0, "max_female": 15.5, | |
| "deficiency_male": "<13.5", "deficiency_female": "<12.0"}, | |
| "Calcium": {"unit": "mg/dL", "min": 8.6, "max": 10.3, | |
| "deficiency": "<8.6"}, | |
| "Magnesium": {"unit": "mg/dL", "min": 1.7, "max": 2.2, | |
| "deficiency": "<1.7"}, | |
| "Zinc": {"unit": "ΞΌg/dL", "min": 70, "max": 120, | |
| "deficiency": "<70"} | |
| } | |
| # Extract blood markers and values from text | |
| def extract_blood_markers(text): | |
| extracted_markers = {} | |
| # Iterate through all known markers and their aliases | |
| for vitamin, aliases in BLOOD_MARKERS.items(): | |
| all_terms = aliases + [vitamin] | |
| for term in all_terms: | |
| # Look for the marker and its value | |
| # Pattern matches: Marker name: value unit | |
| # Or: Marker name value unit | |
| pattern = r'(?i)(%s)\s*[:=-]?\s*(\d+\.?\d*)' % re.escape(term) | |
| matches = re.findall(pattern, text) | |
| if matches: | |
| for match in matches: | |
| marker, value = match | |
| # Convert to float if possible | |
| try: | |
| value = float(value) | |
| extracted_markers[vitamin] = value | |
| break # Found a value for this vitamin, move to next | |
| except ValueError: | |
| continue | |
| return extracted_markers | |
| # Analyze report with Gemini using structured approach | |
| def analyze_report(vision_model, text_model, content, extracted_markers, is_text=False): | |
| # Create structured input for better analysis | |
| analysis_prompt = f""" | |
| I need a detailed analysis of this blood test report. Focus specifically on vitamin, mineral and nutritional deficiencies. | |
| The report is from India, so provide recommendations relevant to Indian context, diet, and healthcare practices. | |
| For each identified deficiency: | |
| 1. Specify the exact deficiency (vitamin/mineral name) | |
| 2. Current level from report and normal reference range | |
| 3. Severity (mild/moderate/severe) | |
| 4. Recommended daily dosage in appropriate units (mg, mcg, IU) for supplementation | |
| 5. Duration of recommended supplementation | |
| 6. Specific health impacts this deficiency is causing or may cause | |
| 7. Recommended foods available in India that address this deficiency (include both vegetarian and non-vegetarian options) | |
| 8. Any additional blood tests that should be considered for confirmation | |
| Also provide: | |
| - A comprehensive summary of all nutritional findings | |
| - Lifestyle modifications specific to Indian context | |
| - Any concerning values that require immediate medical attention | |
| - Follow-up testing recommendations with timeline | |
| If you cannot confidently determine specific deficiencies, explain why and suggest further tests. | |
| The extracted markers I've identified include: {json.dumps(extracted_markers)} | |
| Format your response as structured JSON with the following schema: | |
| {{ | |
| "deficiencies": [ | |
| {{ | |
| "nutrient": "string", | |
| "current_level": "string", | |
| "reference_range": "string", | |
| "severity": "string", | |
| "recommended_dosage": "string", | |
| "supplementation_duration": "string", | |
| "health_impacts": ["string"], | |
| "recommended_foods": {{ | |
| "vegetarian": ["string"], | |
| "non_vegetarian": ["string"] | |
| }}, | |
| "confirmation_tests": ["string"] | |
| }} | |
| ], | |
| "summary": "string", | |
| "lifestyle_modifications": ["string"], | |
| "urgent_concerns": ["string"] or null, | |
| "followup_recommendations": {{ | |
| "tests": ["string"], | |
| "timeline": "string" | |
| }} | |
| }} | |
| """ | |
| try: | |
| if is_text: | |
| full_content = content + "\n\nExtracted markers: " + json.dumps(extracted_markers) | |
| response = text_model.generate_content([analysis_prompt, full_content]) | |
| else: | |
| # For image, combine extracted markers with the image | |
| response = vision_model.generate_content([analysis_prompt, content]) | |
| # Extract JSON from response | |
| response_text = response.text | |
| # Find JSON object in the response | |
| json_match = re.search(r'```json\s*([\s\S]*?)\s*```', response_text) | |
| if json_match: | |
| json_str = json_match.group(1) | |
| else: | |
| # Try to find JSON without code blocks | |
| json_match = re.search(r'({[\s\S]*})', response_text) | |
| if json_match: | |
| json_str = json_match.group(1) | |
| else: | |
| return {"error": "Failed to parse JSON response", "raw_response": response_text} | |
| # Parse JSON | |
| try: | |
| result = json.loads(json_str) | |
| return result | |
| except json.JSONDecodeError: | |
| return {"error": "Invalid JSON response", "raw_response": response_text} | |
| except Exception as e: | |
| return {"error": f"Analysis failed: {str(e)}"} | |
| # Generate personalized recommendation report | |
| def generate_recommendation_html(analysis_result, patient_info=None): | |
| if "error" in analysis_result: | |
| return f"<div class='error'>Error in analysis: {analysis_result['error']}</div>" | |
| # Current date for the report | |
| current_date = datetime.now().strftime("%d %B, %Y") | |
| # Start building HTML | |
| html = f""" | |
| <div style="font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; line-height: 1.6;"> | |
| <div style="text-align: center; border-bottom: 2px solid #2c3e50; padding-bottom: 10px; margin-bottom: 20px;"> | |
| <h1 style="color: #2c3e50;">Nutritional Analysis Report</h1> | |
| <p>Generated on: {current_date}</p> | |
| {f"<p>Patient: {patient_info['name']} | Age: {patient_info['age']} | Gender: {patient_info['gender']}</p>" if patient_info else ""} | |
| </div> | |
| <div style="background-color: #f9f9f9; border-left: 4px solid #3498db; padding: 15px; margin-bottom: 25px;"> | |
| <h2 style="color: #3498db; margin-top: 0;">Summary</h2> | |
| <p>{analysis_result.get('summary', 'No summary available')}</p> | |
| </div> | |
| """ | |
| # Add deficiencies section | |
| deficiencies = analysis_result.get('deficiencies', []) | |
| if deficiencies: | |
| html += '<h2 style="color: #2c3e50; border-bottom: 1px solid #ddd; padding-bottom: 8px;">Detected Deficiencies</h2>' | |
| for deficiency in deficiencies: | |
| severity_color = { | |
| "mild": "#f39c12", | |
| "moderate": "#e67e22", | |
| "severe": "#c0392b" | |
| }.get(deficiency.get('severity', '').lower(), "#7f8c8d") | |
| html += f""" | |
| <div style="margin-bottom: 30px; background-color: #f8f9fa; border-radius: 5px; padding: 15px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"> | |
| <h3 style="color: {severity_color}; margin-top: 0;"> | |
| {deficiency.get('nutrient', 'Unknown')} | |
| <span style="font-size: 0.8em; background-color: {severity_color}; color: white; padding: 3px 8px; border-radius: 3px; margin-left: 10px;"> | |
| {deficiency.get('severity', 'Unknown')} deficiency | |
| </span> | |
| </h3> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 15px;"> | |
| <div> | |
| <p><strong>Current Level:</strong> {deficiency.get('current_level', 'N/A')}</p> | |
| <p><strong>Reference Range:</strong> {deficiency.get('reference_range', 'N/A')}</p> | |
| <p><strong>Recommended Dosage:</strong> {deficiency.get('recommended_dosage', 'N/A')}</p> | |
| <p><strong>Duration:</strong> {deficiency.get('supplementation_duration', 'N/A')}</p> | |
| </div> | |
| <div> | |
| <p><strong>Health Impacts:</strong></p> | |
| <ul style="margin-top: 5px; padding-left: 20px;"> | |
| """ | |
| # Add health impacts | |
| for impact in deficiency.get('health_impacts', ['N/A']): | |
| html += f"<li>{impact}</li>" | |
| html += """ | |
| </ul> | |
| </div> | |
| </div> | |
| <div style="margin-top: 15px;"> | |
| <h4 style="color: #2c3e50; margin-bottom: 8px;">Recommended Foods</h4> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> | |
| <div> | |
| <h5 style="color: #27ae60; margin-bottom: 5px;">Vegetarian Options</h5> | |
| <ul style="margin-top: 5px; padding-left: 20px;"> | |
| """ | |
| # Add vegetarian foods | |
| veg_foods = deficiency.get('recommended_foods', {}).get('vegetarian', ['N/A']) | |
| for food in veg_foods: | |
| html += f"<li>{food}</li>" | |
| html += """ | |
| </ul> | |
| </div> | |
| <div> | |
| <h5 style="color: #c0392b; margin-bottom: 5px;">Non-Vegetarian Options</h5> | |
| <ul style="margin-top: 5px; padding-left: 20px;"> | |
| """ | |
| # Add non-vegetarian foods | |
| non_veg_foods = deficiency.get('recommended_foods', {}).get('non_vegetarian', ['N/A']) | |
| for food in non_veg_foods: | |
| html += f"<li>{food}</li>" | |
| html += """ | |
| </ul> | |
| </div> | |
| </div> | |
| </div> | |
| <div style="margin-top: 15px; background-color: #eaf2f8; padding: 10px; border-radius: 4px;"> | |
| <h4 style="color: #2980b9; margin-top: 0; margin-bottom: 8px;">Additional Tests</h4> | |
| <ul style="margin-top: 5px; padding-left: 20px;"> | |
| """ | |
| # Add confirmation tests | |
| tests = deficiency.get('confirmation_tests', ['None recommended']) | |
| for test in tests: | |
| html += f"<li>{test}</li>" | |
| html += """ | |
| </ul> | |
| </div> | |
| </div> | |
| """ | |
| else: | |
| html += '<div style="padding: 15px; background-color: #e8f8f5; border-radius: 5px; margin-bottom: 25px;"><p>No specific deficiencies detected.</p></div>' | |
| # Add lifestyle modifications | |
| lifestyle = analysis_result.get('lifestyle_modifications', []) | |
| if lifestyle: | |
| html += """ | |
| <h2 style="color: #2c3e50; border-bottom: 1px solid #ddd; padding-bottom: 8px;">Lifestyle Recommendations</h2> | |
| <div style="background-color: #f2f6fc; padding: 15px; border-radius: 5px; margin-bottom: 25px;"> | |
| <ul style="padding-left: 20px;"> | |
| """ | |
| for item in lifestyle: | |
| html += f"<li>{item}</li>" | |
| html += """ | |
| </ul> | |
| </div> | |
| """ | |
| # Add urgent concerns | |
| urgent = analysis_result.get('urgent_concerns', []) | |
| if urgent and urgent != [None]: | |
| html += """ | |
| <h2 style="color: #c0392b; border-bottom: 1px solid #ddd; padding-bottom: 8px;">β οΈ Urgent Considerations</h2> | |
| <div style="background-color: #fdf2f0; padding: 15px; border-radius: 5px; border-left: 4px solid #c0392b; margin-bottom: 25px;"> | |
| <ul style="padding-left: 20px;"> | |
| """ | |
| for item in urgent: | |
| html += f"<li>{item}</li>" | |
| html += """ | |
| </ul> | |
| <p style="margin-top: 10px; font-weight: bold;">Please consult with a healthcare provider promptly regarding these concerns.</p> | |
| </div> | |
| """ | |
| # Add follow-up recommendations | |
| followup = analysis_result.get('followup_recommendations', {}) | |
| if followup and followup.get('tests'): | |
| html += f""" | |
| <h2 style="color: #2c3e50; border-bottom: 1px solid #ddd; padding-bottom: 8px;">Follow-up Recommendations</h2> | |
| <div style="background-color: #f9f9f9; padding: 15px; border-radius: 5px; margin-bottom: 25px;"> | |
| <p><strong>Timeline:</strong> {followup.get('timeline', 'As advised by your healthcare provider')}</p> | |
| <p><strong>Recommended Tests:</strong></p> | |
| <ul style="padding-left: 20px;"> | |
| """ | |
| for test in followup.get('tests', []): | |
| html += f"<li>{test}</li>" | |
| html += """ | |
| </ul> | |
| </div> | |
| """ | |
| # Disclaimer | |
| html += """ | |
| <div style="border-top: 1px solid #ddd; margin-top: 30px; padding-top: 15px; font-size: 0.9em; color: #7f8c8d;"> | |
| <p><strong>Disclaimer:</strong> This analysis is generated by an AI system and should not replace professional medical advice. | |
| Always consult with a healthcare provider before making any changes to your diet, lifestyle, or supplementation regimen.</p> | |
| </div> | |
| </div> | |
| """ | |
| return html | |
| # Calculate nutritional recommendations based on deficiencies | |
| def calculate_recommendations(analysis_result, weight_kg=70, height_cm=165, activity_level="moderate"): | |
| if not analysis_result or "deficiencies" not in analysis_result: | |
| return None | |
| # Basic calculations | |
| bmi = weight_kg / ((height_cm/100) ** 2) | |
| # Activity level multipliers | |
| activity_multipliers = { | |
| "sedentary": 1.2, | |
| "light": 1.375, | |
| "moderate": 1.55, | |
| "active": 1.725, | |
| "very active": 1.9 | |
| } | |
| # Calculate basal metabolic rate (BMR) using Mifflin-St Jeor equation | |
| bmr = 10 * weight_kg + 6.25 * height_cm - 5 * 30 + 5 # Assuming age 30 for example | |
| # Calculate total daily energy expenditure | |
| tdee = bmr * activity_multipliers.get(activity_level.lower(), 1.55) | |
| # Create recommendation dictionary | |
| recommendations = { | |
| "anthropometrics": { | |
| "bmi": round(bmi, 1), | |
| "bmi_category": get_bmi_category(bmi), | |
| "estimated_energy_needs": round(tdee) | |
| }, | |
| "supplements": [] | |
| } | |
| # Process each deficiency | |
| for deficiency in analysis_result["deficiencies"]: | |
| nutrient = deficiency["nutrient"] | |
| severity = deficiency["severity"].lower() | |
| # Extract dosage value and unit | |
| dosage_match = re.search(r'(\d+[\.\d]*)\s*([a-zA-Z]+)', deficiency["recommended_dosage"]) | |
| if dosage_match: | |
| amount = float(dosage_match.group(1)) | |
| unit = dosage_match.group(2) | |
| # Adjust based on severity | |
| if severity == "severe": | |
| adjusted_amount = amount * 1.2 # 20% higher for severe | |
| elif severity == "mild": | |
| adjusted_amount = amount * 0.9 # 10% lower for mild | |
| else: | |
| adjusted_amount = amount | |
| recommendations["supplements"].append({ | |
| "nutrient": nutrient, | |
| "dosage": f"{round(adjusted_amount, 2)} {unit}", | |
| "original_dosage": f"{amount} {unit}", | |
| "severity": severity, | |
| "duration": deficiency["supplementation_duration"], | |
| "frequency": "Daily", | |
| "best_time": get_best_time_for_supplement(nutrient), | |
| "interactions": get_supplement_interactions(nutrient) | |
| }) | |
| return recommendations | |
| # Helper functions for recommendations | |
| def get_bmi_category(bmi): | |
| if bmi < 18.5: | |
| return "Underweight" | |
| elif bmi < 25: | |
| return "Normal weight" | |
| elif bmi < 30: | |
| return "Overweight" | |
| else: | |
| return "Obese" | |
| def get_best_time_for_supplement(nutrient): | |
| # Time recommendations based on Indian context | |
| nutrient_lower = nutrient.lower() | |
| if any(term in nutrient_lower for term in ["d", "a", "e", "k"]): | |
| return "With meals containing some fat (lunch or dinner)" | |
| elif "b12" in nutrient_lower: | |
| return "Morning, with breakfast" | |
| elif "iron" in nutrient_lower: | |
| return "On empty stomach, 1 hour before meals with Vitamin C" | |
| elif "calcium" in nutrient_lower: | |
| return "Between meals, avoid taking with iron supplements" | |
| elif "zinc" in nutrient_lower: | |
| return "1-2 hours after meals, not with calcium supplements" | |
| else: | |
| return "As directed by healthcare provider" | |
| def get_supplement_interactions(nutrient): | |
| # Common interactions for Indian medications and supplements | |
| nutrient_lower = nutrient.lower() | |
| if "iron" in nutrient_lower: | |
| return ["Calcium supplements", "Tea/coffee", "Antacids", "Certain antibiotics"] | |
| elif "calcium" in nutrient_lower: | |
| return ["Iron supplements", "Certain antibiotics", "Thyroid medications"] | |
| elif "b12" in nutrient_lower: | |
| return ["Metformin", "Acid-reducing medications", "Colchicine"] | |
| elif "d" in nutrient_lower: | |
| return ["Steroids", "Weight loss medications", "Certain cholesterol medications"] | |
| else: | |
| return [] | |
| # File upload handler for Hugging Face | |
| def upload_and_process_file(file, api_key, name, age, gender): | |
| if not api_key: | |
| return "Please enter a valid Google API key", None | |
| try: | |
| if file is None: | |
| return "No file was uploaded", None | |
| # Get file extension | |
| file_extension = file.name.split('.')[-1].lower() | |
| file_content = file.read() | |
| # Process based on file type | |
| if file_extension == 'pdf': | |
| report_text, extracted_images, tables = extract_text_from_pdf(file_content) | |
| extracted_markers = extract_blood_markers(report_text) | |
| vision_model, text_model = configure_genai(api_key) | |
| # If text extraction worked well and we found markers | |
| if len(extracted_markers) > 0: | |
| analysis_result = analyze_report(vision_model, text_model, report_text, extracted_markers, is_text=True) | |
| # If text extraction didn't yield much, use the images | |
| elif extracted_images: | |
| # Use the first image as primary, but include text context | |
| analysis_result = analyze_report(vision_model, text_model, | |
| [report_text, extracted_images[0]], | |
| extracted_markers) | |
| else: | |
| return "Could not extract sufficient data from the PDF. Please try uploading a clearer document.", None | |
| elif file_extension in ['jpg', 'jpeg', 'png']: | |
| img = Image.open(io.BytesIO(file_content)) | |
| processed_img = preprocess_image(img) | |
| vision_model, text_model = configure_genai(api_key) | |
| analysis_result = analyze_report(vision_model, text_model, processed_img, {}) | |
| else: | |
| return f"Unsupported file format: {file_extension}. Please upload a PDF or image (JPG, PNG).", None | |
| # Create patient info dictionary if provided | |
| patient_info = None | |
| if name or age or gender: | |
| patient_info = { | |
| "name": name, | |
| "age": age, | |
| "gender": gender | |
| } | |
| # Generate HTML report | |
| html_report = generate_recommendation_html(analysis_result, patient_info) | |
| return html_report, analysis_result | |
| except Exception as e: | |
| return f"An error occurred: {str(e)}", None | |
| # Create the Gradio Interface for Hugging Face | |
| def create_interface(): | |
| with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo")) as app: | |
| gr.Markdown( | |
| """ | |
| # π©Έ Blood Report Analyzer | |
| ## Analyze blood test reports for vitamin deficiencies and get personalized recommendations | |
| This application uses Gemini AI to analyze your blood test results and provide detailed insights | |
| on nutritional deficiencies with recommendations tailored to Indian health needs. | |
| """ | |
| ) | |
| with gr.Tab("π Report Analysis"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| api_key = gr.Textbox( | |
| label="Google Gemini API Key", | |
| placeholder="Enter your Gemini API key", | |
| type="password" | |
| ) | |
| with gr.Accordion("Instructions for Using This Tool", open=False): | |
| gr.Markdown( | |
| """ | |
| ## How to Use This Tool | |
| ### 1. Prepare Your Report | |
| - Ensure your blood report is clear and readable | |
| - PDF format is preferred | |
| - If using images, ensure good lighting and focus | |
| ### 2. Get a Gemini API Key | |
| - Visit [Google AI Studio](https://ai.google.dev/) | |
| - Create an account or sign in | |
| - Navigate to API keys and create a new key | |
| ### 3. Upload and Analyze | |
| - Enter your API key in the designated field | |
| - (Optional) Enter patient information for personalized results | |
| - Upload your blood report file | |
| - Click "Analyze Report" | |
| ### 4. Review Results | |
| - The analysis will display deficiencies found, their severity, and recommendations | |
| - For personalized supplementation, enter weight, height, and activity level | |
| - Click "Generate Supplement Plan" for customized dosage recommendations | |
| ### 5. Share Results | |
| - You can save the HTML report by right-clicking and selecting "Save as" | |
| - Share the results with your healthcare provider | |
| ### Important Notes | |
| - This tool is for informational purposes only | |
| - Always consult with healthcare professionals before making health decisions | |
| - Your data is not stored and is only used for analysis | |
| """ | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| with gr.Group(): | |
| gr.Markdown("### Patient Information (Optional)") | |
| name = gr.Textbox(label="Name", placeholder="Enter patient name") | |
| with gr.Row(): | |
| age = gr.Textbox(label="Age", placeholder="e.g., 35") | |
| gender = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"], value="Male") | |
| upload_file = gr.File(label="Upload Blood Report") | |
| analyze_button = gr.Button("π Analyze Report", variant="primary") | |
| with gr.Column(scale=2): | |
| output = gr.HTML(label="Analysis Results") | |
| raw_output = gr.JSON(label="Raw Analysis Data", visible=False) | |
| with gr.Row(): | |
| with gr.Column(): | |
| with gr.Group(): | |
| gr.Markdown("### Supplement Recommendations") | |
| with gr.Row(): | |
| weight = gr.Number(label="Weight (kg)", value=70) | |
| height = gr.Number(label="Height (cm)", value=165) | |
| activity = gr.Dropdown( | |
| label="Activity Level", | |
| choices=["Sedentary", "Light", "Moderate", "Active", "Very Active"], | |
| value="Moderate" | |
| ) | |
| supplement_button = gr.Button("π Generate Supplement Plan") | |
| supplement_output = gr.JSON(label="Personalized Supplement Plan") | |
| # Connect the buttons to functions | |
| analyze_button.click( | |
| fn=upload_and_process_file, | |
| inputs=[upload_file, api_key, name, age, gender], | |
| outputs=[output, raw_output] | |
| ) | |
| supplement_button.click( | |
| fn=calculate_recommendations, | |
| inputs=[raw_output, weight, height, activity], | |
| outputs=[supplement_output] | |
| ) | |
| with gr.Tab("π About"): | |
| gr.Markdown( | |
| """ | |
| ## About Blood Report Analyzer | |
| This tool was developed to help people in India better understand their blood test results, | |
| with a focus on identifying nutritional deficiencies that are common in the Indian population. | |
| ### How it Works | |
| 1. The tool uses advanced OCR and AI to extract relevant information from your blood report | |
| 2. Google's Gemini AI models analyze the data to identify deficiencies | |
| 3. Recommendations are tailored to the Indian context, including: | |
| - Locally available foods | |
| - Cultural dietary considerations | |
| - Regional supplementation guidelines | |
| ### Privacy & Security | |
| - Your data remains private and is not stored | |
| - Analysis happens in real-time | |
| - API keys are only used for processing and are not saved | |
| ### Limitations | |
| - This tool is for informational purposes only | |
| - It does not replace medical advice from healthcare professionals | |
| - Accuracy depends on the quality of the uploaded report | |
| - Some rare deficiencies may not be detected | |
| ### Acknowledgements | |
| This application uses Google's Gemini AI models and is built with Gradio for Hugging Face Spaces. | |
| """ | |
| ) | |
| return app | |
| # Export the interface | |
| app = create_interface() | |
| # Launch the app | |
| if __name__ == "__main__": | |
| app.launch() | |
| app.launch(share=True) |