Bonosa2's picture
Update app.py
c0531db verified
raw
history blame
28.4 kB
# -*- coding: utf-8
# πŸ₯ Gemma 3N SOAP Note Generator
#-*- coding: utf-8
# πŸ₯ Gemma 3N SOAP Note Generator
# Enable widgets
# Enable widgets
import torch
from transformers import AutoProcessor, AutoModelForImageTextToText
import gradio as gr
import ipywidgets as widgets
from IPython.display import display, clear_output
import io
import base64
from datetime import datetime
from huggingface_hub import login
import getpass
# Authenticate with HuggingFace
# Replace the authentication section (lines around the getpass part) with this:
# Import libraries and authenticate
import torch
from transformers import AutoProcessor, AutoModelForImageTextToText
import gradio as gr
import ipywidgets as widgets
from IPython.display import display, clear_output
import io
import base64
from datetime import datetime
from huggingface_hub import login
import os
import easyocr
from PIL import Image
# Authenticate with HuggingFace
print("πŸ” HuggingFace Authentication Required")
# Try to get token from environment variable first (for production/HF Spaces)
hf_token = os.environ.get('HF_TOKEN') or os.environ.get('HUGGINGFACE_TOKEN')
if hf_token:
print("βœ… Found HF token in environment variables")
try:
login(token=hf_token)
print("βœ… Successfully authenticated with HuggingFace!")
except Exception as e:
print(f"❌ Authentication failed: {e}")
print("Please check your token and try again.")
# Check GPU availability
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "" # Hide all GPUs from PyTorch
device = "cuda" if torch.cuda.is_available() else "cpu"
device = "cpu"
print(f"πŸ–₯️ Using device: {device}")
if torch.cuda.is_available():
print(f"πŸš€ GPU: {torch.cuda.get_device_name(0)}")
print(f"πŸ’Ύ GPU Memory: {torch.cuda.get_device_properties(0).total_memory / 1e9:.1f} GB")
else:
print("⚠️ Running on CPU - this will be slower")
# Load Gemma 3N model
print("πŸ“‘ Loading Gemma 3N model...")
model_id = "google/gemma-3n-e2b-it"
print("πŸ”§ Loading processor...")
processor = AutoProcessor.from_pretrained(model_id)
print("πŸ€– Loading Gemma 3N model (this may take a few minutes)...")
model = AutoModelForImageTextToText.from_pretrained(
model_id,
torch_dtype=torch.float16 if device == "cuda" else torch.float32,
low_cpu_mem_usage=True,
).to(device)
print("βœ… Gemma 3N model loaded successfully!")
print(f"πŸ“Š Model size: ~2.9GB")
print(f"🎯 Ready for SOAP note generation!")
# SOAP Note Generation Function
def generate_soap_note(doctor_notes, include_timestamp=True):
"""
Generate a SOAP note from unstructured doctor's notes
"""
if not doctor_notes.strip():
return "❌ Please enter some medical notes to process."
prompt = f"""You are a medical AI assistant. Convert the following unstructured doctor's notes into a professional SOAP note format.
Doctor's Notes:
{doctor_notes}
Please generate a structured SOAP note with the following sections:
- SUBJECTIVE: Patient's reported symptoms and history
- OBJECTIVE: Physical examination findings, vital signs, and test results
- ASSESSMENT: Clinical diagnosis and reasoning
- PLAN: Treatment plan, medications, and follow-up
Format your response as a proper medical SOAP note with specific details extracted from the notes."""
try:
# Process input
inputs = processor(text=prompt, return_tensors="pt").to(device)
# Generate response
print("πŸ”„ Generating SOAP note with Gemma 3N...")
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=512,
temperature=0.3, # Lower temperature for medical precision
do_sample=True,
pad_token_id=processor.tokenizer.eos_token_id
)
# Decode response
generated_text = processor.decode(outputs[0], skip_special_tokens=True)
# Extract only the generated part (remove the prompt)
soap_response = generated_text[len(prompt):].strip()
# Add header if requested
if include_timestamp:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
header = f"""πŸ“‹ SOAP NOTE - Generated by Gemma 3N
πŸ• Timestamp: {timestamp}
πŸ€– Model: google/gemma-3n-e2b-it
πŸ”’ Processed locally on device: {device.upper()}
{'='*60}
"""
return header + soap_response
return soap_response
except Exception as e:
return f"❌ Error generating SOAP note: {str(e)}"
print("βœ… SOAP generation function ready!")
"""## πŸ“ Interactive SOAP Note Generator
### Enter medical notes below and generate professional SOAP documentation
"""
# Create interactive widgets
print("🎨 Creating interactive interface...")
# Text input area
notes_input = widgets.Textarea(
value='',
placeholder='Enter unstructured doctor notes here...\n\nExample:\nPatient John Smith, 45yo male, came in complaining of chest pain for 2 days. Pain is sharp, 7/10 intensity, worse with movement. Vital signs: BP 140/90, HR 88, Temp 98.6F...',
description='Medical Notes:',
layout=widgets.Layout(width='100%', height='200px')
)
# File upload widget
file_upload = widgets.FileUpload(
accept='.txt,.doc,.docx,.pdf',
multiple=False,
description='Or upload file:',
layout=widgets.Layout(width='300px')
)
# Generate button
generate_btn = widgets.Button(
description='πŸ€– Generate SOAP Note',
button_style='primary',
layout=widgets.Layout(width='200px', height='40px')
)
# Output area
output_area = widgets.HTML(
value='<p style="color: #666;">πŸ“‹ Ready to generate SOAP notes! Enter medical notes above or upload a file.</p>',
layout=widgets.Layout(width='100%', height='400px', overflow='auto', border='1px solid #ddd', padding='10px')
)
# Example buttons
example1_btn = widgets.Button(description='πŸ“‹ Chest Pain Example', button_style='info', layout=widgets.Layout(width='180px'))
example2_btn = widgets.Button(description='🩺 Diabetes Follow-up', button_style='info', layout=widgets.Layout(width='180px'))
example3_btn = widgets.Button(description='πŸ‘Ά Pediatric Visit', button_style='info', layout=widgets.Layout(width='180px'))
# Clear button
clear_btn = widgets.Button(description='πŸ—‘οΈ Clear', button_style='warning', layout=widgets.Layout(width='100px'))
print("βœ… Interface widgets created!")
# Example medical notes
examples = {
'chest_pain': """Patient John Smith, 45yo male, came in complaining of chest pain for 2 days. Pain is sharp, 7/10 intensity, worse with movement. No radiation to arms. Vital signs: BP 140/90, HR 88, Temp 98.6F, RR 16, O2 sat 98%. Physical exam shows tenderness over left chest wall, no murmurs. EKG normal sinus rhythm. Chest X-ray clear. Diagnosed with costochondritis. Prescribed ibuprofen 600mg TID and advised rest. Follow up in 1 week if symptoms persist.""",
'diabetes': """Sarah Johnson, 62yo female with Type 2 diabetes, here for routine follow-up. Says blood sugars have been running high lately, 180-220 mg/dL. Taking metformin 1000mg BID. Diet has been poor due to holiday stress. Weight increased 5 lbs since last visit. BP 150/85, BMI 32. HbA1c 8.2% (was 7.1% 3 months ago). Feet exam normal, no neuropathy. Plan to increase metformin to 1000mg TID, refer to nutritionist, recheck labs in 3 months.""",
'pediatric': """Tommy Rodriguez, 8yo male, brought by mother for fever and cough x3 days. Fever up to 102F, productive cough with yellow sputum. Decreased appetite, no vomiting or diarrhea. Vital signs: Temp 101.2F, HR 110, RR 24, BP 95/60. Exam shows bilateral crackles in lower lobes, no wheeze. Throat clear. Diagnosed with bacterial pneumonia. Prescribed amoxicillin 500mg BID x10 days. Return if fever persists >48 hours on antibiotics."""
}
# Event handlers
def on_generate_click(b):
with output_area:
output_area.value = '<p style="color: #007bff;">πŸ”„ Processing with Gemma 3N... Please wait...</p>'
# Get text from input or uploaded file
text_to_process = notes_input.value
# Check if file was uploaded
if file_upload.value and len(file_upload.value) > 0:
try:
uploaded_file = list(file_upload.value.values())[0]
file_content = uploaded_file['content'].decode('utf-8')
text_to_process = file_content
notes_input.value = file_content # Show in text area
except Exception as e:
output_area.value = f'<p style="color: #dc3545;">❌ Error reading file: {str(e)}</p>'
return
if not text_to_process.strip():
output_area.value = '<p style="color: #dc3545;">❌ Please enter medical notes or upload a file!</p>'
return
# Generate SOAP note
soap_note = generate_soap_note(text_to_process)
# Format output as HTML
formatted_output = f'<pre style="font-family: monospace; font-size: 12px; line-height: 1.4; white-space: pre-wrap;">{soap_note}</pre>'
output_area.value = formatted_output
def on_example1_click(b):
notes_input.value = examples['chest_pain']
output_area.value = '<p style="color: #28a745;">βœ… Chest pain example loaded! Click "Generate SOAP Note" to process.</p>'
def on_example2_click(b):
notes_input.value = examples['diabetes']
output_area.value = '<p style="color: #28a745;">βœ… Diabetes follow-up example loaded! Click "Generate SOAP Note" to process.</p>'
def on_example3_click(b):
notes_input.value = examples['pediatric']
output_area.value = '<p style="color: #28a745;">βœ… Pediatric example loaded! Click "Generate SOAP Note" to process.</p>'
def on_clear_click(b):
notes_input.value = ''
file_upload.value = ()
output_area.value = '<p style="color: #666;">πŸ“‹ Ready to generate SOAP notes! Enter medical notes above or upload a file.</p>'
# Bind event handlers
generate_btn.on_click(on_generate_click)
example1_btn.on_click(on_example1_click)
example2_btn.on_click(on_example2_click)
example3_btn.on_click(on_example3_click)
clear_btn.on_click(on_clear_click)
print("βœ… Event handlers configured!")
# Define example medical notes first
example_notes_1 = """
Patient: John Smith, 45-year-old male
Chief Complaint: Chest pain for 2 hours
History: Patient reports sudden onset of sharp chest pain while at work. Pain is 7/10 intensity, located substernal, radiating to left arm. Associated with shortness of breath and diaphoresis. No previous cardiac history. Denies nausea or vomiting.
Physical Exam: VS: BP 150/90, HR 110, RR 22, O2 Sat 96% on RA. Patient appears anxious and diaphoretic. Heart: Regular rhythm, no murmurs. Lungs: Clear bilaterally. Extremities: No edema.
Assessment: Acute chest pain, rule out myocardial infarction
Plan: EKG, cardiac enzymes, chest X-ray, aspirin 325mg, continuous cardiac monitoring
"""
example_notes_2 = """
Patient: Sarah Johnson, 28-year-old female
Chief Complaint: Severe headache and fever
History: 3-day history of progressive headache, fever up to 101.5Β°F, photophobia, and neck stiffness. Patient reports this is the worst headache of her life. No recent travel or sick contacts. No rash noted.
Physical Exam: VS: T 101.2Β°F, BP 130/80, HR 95, RR 18. Patient appears ill and photophobic. HEENT: Pupils equal and reactive. Neck: Stiff with positive Kernig's sign. Neurologic: Alert and oriented x3, no focal deficits.
Assessment: Suspected meningitis
Plan: Lumbar puncture, blood cultures, empiric antibiotics, supportive care
"""
example_notes_3 = """
Patient: Robert Davis, 62-year-old male
Chief Complaint: Shortness of breath and leg swelling
History: 2-week history of progressive dyspnea on exertion, orthopnea, and bilateral lower extremity edema. Patient has history of hypertension and diabetes. Reports sleeping on 3 pillows due to breathing difficulty.
Physical Exam: VS: BP 140/85, HR 88, RR 24, O2 Sat 92% on RA. Heart: S3 gallop present, JVD elevated. Lungs: Bilateral rales in lower fields. Extremities: 2+ pitting edema bilaterally.
Assessment: Congestive heart failure exacerbation
Plan: Chest X-ray, BNP, echocardiogram, furosemide, ACE inhibitor, daily weights
"""
# Event handlers
def on_generate_click(b):
try:
# Update the HTML widget directly
output_area.value = '<p style="color: #007bff;">πŸ”„ Processing with Gemma 3N... Please wait...</p>'
# Get input text
input_text = notes_input.value.strip()
# Check if file was uploaded
if file_upload.value:
try:
# Process uploaded file
uploaded_file = list(file_upload.value.values())[0]
file_content = uploaded_file['content'].decode('utf-8')
input_text = file_content
except Exception as upload_error:
output_area.value = f'<p style="color: #ff6b6b;">❌ File upload error: {str(upload_error)}</p>'
return
if not input_text:
output_area.value = '<p style="color: #ff6b6b;">⚠️ Please enter medical notes or upload a file first!</p>'
return
# Check if generate_soap_note function exists
if 'generate_soap_note' not in globals():
output_area.value = '<p style="color: #ff6b6b;">❌ Error: generate_soap_note function not found. Please define it first.</p>'
return
# Generate SOAP note using Gemma
soap_note = generate_soap_note(input_text)
# Escape HTML in soap_note to prevent rendering issues
import html
escaped_soap_note = html.escape(soap_note)
# Display result
output_area.value = f'''
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #28a745;">
<h4 style="color: #28a745; margin-top: 0;">βœ… Generated SOAP Note:</h4>
<pre style="white-space: pre-wrap; font-family: 'Courier New', monospace; background: white; padding: 15px; border-radius: 5px; border: 1px solid #ddd;">{escaped_soap_note}</pre>
</div>
'''
except Exception as e:
import traceback
error_details = traceback.format_exc()
output_area.value = f'''
<div style="color: #ff6b6b; background: #ffe6e6; padding: 15px; border-radius: 5px;">
<h4>❌ Error Details:</h4>
<p><strong>Error:</strong> {str(e)}</p>
<details>
<summary>Click for full traceback</summary>
<pre style="font-size: 12px; background: #fff; padding: 10px; border-radius: 3px; margin-top: 10px;">{error_details}</pre>
</details>
</div>
'''
def on_clear_click(b):
try:
notes_input.value = ""
file_upload.value = ()
output_area.value = '<p>πŸ“‹ Ready to generate SOAP notes! Enter medical notes above or upload a file.</p>'
except Exception as e:
output_area.value = f'<p style="color: #ff6b6b;">❌ Clear error: {str(e)}</p>'
def on_example_click(example_text):
def handler(b):
try:
notes_input.value = example_text
output_area.value = '<p style="color: #28a745;">πŸ“‹ Example loaded! Click "Generate SOAP Note" to process.</p>'
except Exception as e:
output_area.value = f'<p style="color: #ff6b6b;">❌ Example load error: {str(e)}</p>'
return handler
# Connect event handlers to buttons
try:
generate_btn.on_click(on_generate_click)
clear_btn.on_click(on_clear_click)
example1_btn.on_click(on_example_click(example_notes_1))
example2_btn.on_click(on_example_click(example_notes_2))
example3_btn.on_click(on_example_click(example_notes_3))
print("βœ… Event handlers connected successfully!")
print("πŸ“‹ Example notes loaded:")
print(" - Example 1: Chest pain case")
print(" - Example 2: Suspected meningitis")
print(" - Example 3: Heart failure")
except Exception as e:
print(f"❌ Error connecting event handlers: {str(e)}")
import traceback
traceback.print_exc()
"""## 🌐 Alternative: Gradio Web Interface
### Run this cell for a shareable web interface
"""
# Install required packages for image processing and OCR
import gradio as gr
import torch
from PIL import Image
import pytesseract
import cv2
import numpy as np
import easyocr
import io
# First, make sure you have the examples dictionary defined
examples = {
'chest_pain': """Patient: John Smith, 45-year-old male
Chief Complaint: Chest pain for 2 hours
History: Patient reports sudden onset of sharp chest pain while at work. Pain is 7/10 intensity, located substernal, radiating to left arm. Associated with shortness of breath and diaphoresis. No previous cardiac history. Denies nausea or vomiting.
Physical Exam: VS: BP 150/90, HR 110, RR 22, O2 Sat 96% on RA. Patient appears anxious and diaphoretic. Heart: Regular rhythm, no murmurs. Lungs: Clear bilaterally. Extremities: No edema.
Assessment: Acute chest pain, rule out myocardial infarction
Plan: EKG, cardiac enzymes, chest X-ray, aspirin 325mg, continuous cardiac monitoring""",
'diabetes': """Patient: Maria Garcia, 52-year-old female
Chief Complaint: Increased thirst and frequent urination for 3 weeks
History: Patient reports polyuria, polydipsia, and unintentional weight loss of 10 lbs over past month. Family history of diabetes. Denies fever, abdominal pain, or vision changes.
Physical Exam: VS: BP 140/85, HR 88, RR 16, BMI 28. Patient appears well but slightly dehydrated. HEENT: Dry mucous membranes. Cardiovascular: Regular rate and rhythm. Extremities: No diabetic foot changes noted.
Assessment: New onset diabetes mellitus, likely Type 2
Plan: HbA1c, fasting glucose, comprehensive metabolic panel, diabetic education, metformin initiation""",
'pediatric': """Patient: Emma Thompson, 8-year-old female
Chief Complaint: Fever and sore throat for 2 days
History: Mother reports fever up to 102Β°F, sore throat, difficulty swallowing, and decreased appetite. No cough or runny nose. Several classmates have been sick with similar symptoms.
Physical Exam: VS: T 101.8Β°F, HR 110, RR 20, O2 Sat 99%. Patient appears mildly ill but alert. HEENT: Throat erythematous with tonsillar exudate, anterior cervical lymphadenopathy. Heart and lungs: Normal.
Assessment: Streptococcal pharyngitis (probable)
Plan: Rapid strep test, throat culture, amoxicillin if positive, supportive care, return if worsening"""
}
# Initialize EasyOCR reader (better for handwritten text)
try:
ocr_reader = easyocr.Reader(['en'])
print("βœ… EasyOCR initialized successfully")
except:
ocr_reader = None
print("⚠️ EasyOCR not available, using Tesseract only")
def preprocess_image_for_ocr(image):
"""
Preprocess image to improve OCR accuracy
"""
# Convert PIL Image to numpy array
img_array = np.array(image)
# Convert to grayscale if needed
if len(img_array.shape) == 3:
gray = cv2.cvtColor(img_array, cv2.COLOR_RGB2GRAY)
else:
gray = img_array
# Apply image preprocessing for better OCR
# 1. Resize image if too small
height, width = gray.shape
if height < 300 or width < 300:
scale_factor = max(300/height, 300/width)
new_width = int(width * scale_factor)
new_height = int(height * scale_factor)
gray = cv2.resize(gray, (new_width, new_height), interpolation=cv2.INTER_CUBIC)
# 2. Noise removal
denoised = cv2.medianBlur(gray, 3)
# 3. Contrast enhancement
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
enhanced = clahe.apply(denoised)
# 4. Thresholding
_, thresh = cv2.threshold(enhanced, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
return thresh
def extract_text_from_image(image):
"""
Extract text from image using multiple OCR methods
"""
if image is None:
return "❌ No image provided"
try:
# Preprocess image
processed_img = preprocess_image_for_ocr(image)
# Method 1: Try EasyOCR (better for handwritten text)
if ocr_reader is not None:
try:
# Convert back to PIL Image for EasyOCR
pil_img = Image.fromarray(processed_img)
results = ocr_reader.readtext(np.array(pil_img))
# Extract text from EasyOCR results
easyocr_text = ' '.join([result[1] for result in results])
if len(easyocr_text.strip()) > 20: # If we got good results
return clean_extracted_text(easyocr_text)
except Exception as e:
print(f"EasyOCR failed: {e}")
# Method 2: Tesseract OCR (fallback)
try:
# Configure Tesseract for medical text
custom_config = r'--oem 3 --psm 6'
tesseract_text = pytesseract.image_to_string(processed_img, config=custom_config)
if len(tesseract_text.strip()) > 10:
return clean_extracted_text(tesseract_text)
except Exception as e:
print(f"Tesseract failed: {e}")
return "❌ Could not extract text from image. Please try a clearer image or enter text manually."
except Exception as e:
return f"❌ Error processing image: {str(e)}"
def clean_extracted_text(text):
"""
Clean up extracted text
"""
# Remove excessive whitespace and empty lines
lines = [line.strip() for line in text.split('\n') if line.strip()]
cleaned_text = '\n'.join(lines)
# Remove special characters that might interfere
cleaned_text = cleaned_text.replace('|', '').replace('_', ' ')
return cleaned_text.strip()
def gradio_generate_soap(medical_notes, uploaded_image):
"""
Modified Gradio interface function for SOAP generation from images
"""
text_to_process = medical_notes.strip() if medical_notes else ""
# If image is uploaded, extract text using OCR
if uploaded_image is not None:
try:
print("πŸ” Extracting text from uploaded image...")
extracted_text = extract_text_from_image(uploaded_image)
# Check if OCR was successful
if extracted_text.startswith("❌"):
return extracted_text
# Use extracted text if manual text is empty or append to manual text
if not text_to_process:
text_to_process = extracted_text
else:
text_to_process = f"{text_to_process}\n\n--- Extracted from image ---\n{extracted_text}"
except Exception as e:
return f"❌ Error processing image: {str(e)}"
if not text_to_process:
return "❌ Please enter medical notes manually or upload a PNG/JPG image with medical text"
# Check if generate_soap_note function exists
if 'generate_soap_note' not in globals():
return "❌ Error: generate_soap_note function not found. Please define it first."
try:
return generate_soap_note(text_to_process)
except Exception as e:
return f"❌ Error generating SOAP note: {str(e)}"
# Create example images (you can replace these with actual medical note images)
def create_example_image(text, filename):
"""
Create example images from text (for demonstration)
"""
from PIL import Image, ImageDraw, ImageFont
# Create a white image
img = Image.new('RGB', (800, 600), color='white')
draw = ImageDraw.Draw(img)
try:
# Try to use a default font
font = ImageFont.load_default()
except:
font = None
# Add text to image
lines = text.split('\n')
y_offset = 20
for line in lines[:15]: # Limit to first 15 lines
draw.text((20, y_offset), line, fill='black', font=font)
y_offset += 25
return img
# Create Gradio interface
gradio_interface = gr.Interface(
fn=gradio_generate_soap,
inputs=[
gr.Textbox(
lines=6,
placeholder="Enter medical notes manually (optional)...\n\nOr upload an image below and text will be extracted automatically.",
label="πŸ“ Medical Notes (Manual Entry)"
),
gr.Image(
type="pil",
label="πŸ“· Upload Medical Image (PNG/JPG only)",
sources=["upload", "webcam"], # FIXED: Changed "camera" to "webcam"
image_mode="RGB"
)
],
outputs=[
gr.Textbox(
lines=15,
label="πŸ“‹ Generated SOAP Note",
show_copy_button=True
)
],
title="πŸ₯ Medical Image SOAP Note Generator",
description="""
Transform medical images (PNG/JPG) into professional SOAP documentation using OCR + Gemma 3N model.
πŸ“Έ **How to use:**
1. Upload a PNG or JPG image of medical notes (typed or handwritten)
2. Or enter text manually in the text box above
3. The system will extract text from images using OCR
4. Generate structured SOAP notes automatically
πŸ’‘ **Tips for better OCR results:**
- Use clear, high-resolution images
- Ensure good lighting and contrast
- Keep text horizontal (not tilted)
- Handwritten text works best when clearly written
""",
examples=[
[examples['chest_pain'], None],
[examples['diabetes'], None],
[examples['pediatric'], None]
],
theme=gr.themes.Soft(),
flagging_mode="never"
)
# Launch Gradio interface with flexible port selection
print("πŸš€ Launching Medical Image SOAP Generator...")
try:
# Try different ports if 7860 is busy
for port in [7860, 7861, 7862, 7863, 7864]:
try:
gradio_interface.launch(
share=True, # Creates a public shareable link
server_port=port,
show_error=True,
quiet=False
)
print(f"βœ… Interface launched successfully on port {port}")
break
except OSError as port_error:
print(f"⚠️ Port {port} is busy, trying next port...")
continue
else:
# If all ports are busy, let Gradio choose automatically
print("πŸ”„ All preferred ports busy, letting Gradio choose automatically...")
gradio_interface.launch(
share=True,
show_error=True,
quiet=False
)
except Exception as e:
print(f"❌ Error launching Gradio interface: {str(e)}")
print("πŸ’‘ Alternative: Try running without share=True:")
print("gradio_interface.launch(show_error=True)")
print("🎯 Medical Image SOAP Generator ready!")
print("πŸ“Έ Upload PNG/JPG images of medical notes for automatic text extraction and SOAP generation")
"""## πŸ“Š Usage Statistics & Model Info"""
# Display model and system information
import psutil
import GPUtil
def show_system_info():
print("πŸ”§ SYSTEM INFORMATION")
print("="*50)
print(f"πŸ–₯️ Device: {device.upper()}")
print(f"🧠 CPU Usage: {psutil.cpu_percent(interval=1):.1f}%")
print(f"πŸ’Ύ RAM Usage: {psutil.virtual_memory().percent:.1f}%")
if torch.cuda.is_available():
try:
gpus = GPUtil.getGPUs()
if gpus:
gpu = gpus[0]
print(f"πŸš€ GPU: {gpu.name}")
print(f"πŸ“Š GPU Usage: {gpu.load*100:.1f}%")
print(f"πŸ”₯ GPU Memory: {gpu.memoryUsed}/{gpu.memoryTotal} MB ({gpu.memoryPercent:.1f}%)")
print(f"🌑️ GPU Temp: {gpu.temperature}°C")
except:
print(f"πŸš€ GPU Memory: {torch.cuda.memory_allocated()/1e9:.1f}GB / {torch.cuda.memory_reserved()/1e9:.1f}GB")
print("\nπŸ€– MODEL INFORMATION")
print("="*50)
print(f"πŸ“‘ Model ID: {model_id}")
print(f"🎯 Model Type: Multimodal (Text, Image, Audio)")
print(f"πŸ“Š Model Size: ~2.9GB")
print(f"πŸ”’ Parameters: ~2.9B")
print(f"🌍 Languages: 140 text + 35 multimodal")
print(f"πŸ’½ Precision: {model.dtype}")
print("\nβœ… Ready for SOAP note generation!")
show_system_info()
"""---
## πŸ“‹ SOAP Note Format Reference
**S - SUBJECTIVE**: Patient's reported symptoms and history
**O - OBJECTIVE**: Observable clinical findings
**A - ASSESSMENT**: Clinical diagnosis/impression
**P - PLAN**: Treatment and follow-up plan
---
*πŸ€– Powered by Google's Gemma 3N Model | πŸ”’ All processing performed locally*
"""