Project Info
Inspiration
The global radiologist shortage is reaching crisis levels - with over 42,000 radiologists needed by 2033 and patients waiting hours or days for critical chest X-ray diagnoses. We were inspired by the potential to use AI not to replace radiologists, but to extend upon their expertise and ensure no patient waits for a life-saving diagnosis. Emergency departments need instant triage for conditions like pneumothorax, while rural hospitals lack access to in-person specialist expertise entirely.
What it does
XightMD is an AI-powered chest X-ray analysis platform that provides instant triage and structured radiology reports in under 30 seconds. Our multi-agent system coordinates four specialized AI agents: Triage Agent: Analyzes X-rays for 14 lung conditions, assigns urgency scores (1-5), and identifies critical findings Report Agent: Generates structured radiology reports following professional medical standards (Indication, Comparison, Findings, Impression) QA Agent: Validates analysis consistency and flags cases requiring manual review Coordinator Agent: Orchestrates the entire pipeline and manages workflow Intended functionaliy=ty The system provides confidence scores, priority levels, and detailed medical findings while maintaining HIPAA-compliant de-identification processes.
How we built it
Frontend: Next.js 14 with TypeScript and Tailwind CSS for a responsive medical interface Backend: FastAPI server bridging frontend requests to the agent network AI Framework: Fetch.ai's uAgents for multi-agent coordination with Claude 4 for multimodal analysis ML Pipeline: Custom lung disease classifier trained on medical datasets Data: Trained done using the NIH Chest X-ray dataset (100,000+ images) and reports structured using ReXGradient-160K formats Architecture Flow:
Challenges we ran into
Deployment Nightmares: Multiple deployment failures across different platforms, with agent network connectivity issues preventing final deployment despite working locally. Model Architecture Chaos: Experienced difficulties training on the data using various architectures due to poor understanding of the effect that class imbalance has on training multi-class classifiers. Agent Integration Hell: Getting four separate uAgents to communicate reliably was far more complex than expected. Message passing, state management, and coordination between agents broke multiple times, especially under load. Last-Minute Breaks: With hours left before submission, our agent network mysteriously stopped communicating properly, forcing us to implement fallback mock responses to demonstrate the UI. Medical Data Complexity: Real medical datasets are messy - inconsistent formats, missing labels, and strict privacy requirements made training significantly harder than standard ML projects. Time Crunch: Ambitious multi-agent architecture proved too complex for hackathon timeframe - we underestimated the coordination complexity between Claude API, uAgents, and medical data processing.
Accomplishments we're proud of
Built a Working Medical AI Pipeline: Despite challenges, created a functional chest X-ray analysis system that produces medically accurate reports Multi-Agent Architecture: Successfully implemented complex agent coordination using Fetch.ai's uAgents framework with specialized roles Professional Medical Interface: Created a polished healthcare-grade UI that medical professionals could actually use Real Dataset Integration: Trained models on legitimate medical datasets (NIH, ReXGradient-160K) rather than toy examples Technical Innovation: Combined computer vision, natural language processing, and multi-agent systems in a novel healthcare application.
What we learned
Hackathon Projects ≠ Ready Medical Systems: Medical AI is significantly more complex than typical hackathon projects due to regulatory, accuracy, and safety requirements. Multi-Agent Systems Are Hard: Coordinating multiple AI agents reliably requires robust error handling, state management, and fallback mechanisms we didn't initially account for. Deployment is Critical: The most impressive local demo means nothing if you can't deploy it reliably - should have prioritized deployment infrastructure earlier. Medical Data is Unique: Healthcare datasets require specialized preprocessing, privacy handling, and domain expertise that differs drastically from standard ML workflows. Scope Creep Kills: Our ambitious vision of multiple agents, custom ML models, and production-ready features was too much for 24 hours - simpler MVP would have been more successful. Integration Testing Matters: Individual components worked perfectly, but integration between agents, APIs, and frontend broke in unexpected ways under pressure.
What's next
Immediate Fixes: Resolve deployment issues and stabilize agent communication for reliable demo deployment. Model Optimization: Improve lung disease detection accuracy through better handling of class imbalances and more compute time/resources. Clinical Validation: Partner with radiologists to validate our reports against real clinical cases and refine medical accuracy. Expansion: Extend beyond chest X-rays to other imaging modalities (CT, MRI) and anatomical regions. Real-World Pilot: Deploy pilot programs in emergency departments and rural hospitals to demonstrate real clinical impact. Agent Improvements: Enhance multi-agent coordination, add specialized agents for specific conditions, and improve quality assurance algorithms. XightMD represents the future of AI-assisted radiology - not replacing doctors, but empowering them to save more lives, reliably and faster.
XightMD - Chest X-Ray Multi-Label Classification
Model Performance
- Current F1 Score: 0.23 (epoch 60, still training)
- Baseline: Random = 0.067, so 3.43x improvement
- Architecture: EfficientNet-B0 with 2-layer classifier
- Dataset: NIH Chest X-ray 14, ~10k samples
Architecture
OptimizedLungClassifier (lung_classifier.py)
# EfficientNet-B0 backbone
# Custom classifier: 1280 -> 512 -> 15 outputs
# No sigmoid (BCEWithLogitsLoss handles it)
# Dropout: 0.3, 0.2
SimpleLungModel (balanced_lung_trainer.py)
# ResNet18 backbone
# Direct FC: 512 -> 15 outputs
# Used for balanced training experiments
Multi-Label Classification
15 Classes:
Atelectasis, Cardiomegaly, Consolidation, Edema, Effusion,
Emphysema, Fibrosis, Hernia, Infiltration, Mass, Nodule,
Pleural Thickening, Pneumonia, Pneumothorax, No Finding
Problem: Severe class imbalance
- "No Finding": ~60% of samples
- "Hernia": ~0.2% of samples
Solution: Balanced sampling in BalancedNIHDataset
- Limits "No Finding" to 25% of training data
- Ensures minimum samples per pathology class
Training Configuration
Data Processing
# Input: 224x224 RGB (grayscale X-rays converted)
# Augmentation: RandomCrop, HorizontalFlip, Rotation(5°), ColorJitter
# Normalization: ImageNet stats [0.485, 0.456, 0.406], [0.229, 0.224, 0.225]
Training Parameters
# Loss: BCEWithLogitsLoss (multi-label)
# Optimizer: AdamW, lr=0.001, weight_decay=1e-4
# Scheduler: ReduceLROnPlateau(patience=3, factor=0.5)
# Batch size: 16
# Gradient clipping: max_norm=1.0
Thresholds
Per-condition optimized thresholds (not standard 0.5):
'Pneumothorax': 0.25, # Critical condition
'Mass': 0.20, # Cancer screening
'Pneumonia': 0.22,
'Atelectasis': 0.18,
'Hernia': 0.50, # Rare condition
'No Finding': 0.60 # High threshold to reduce false normals
Implementation Details
Prediction Pipeline
def predict(self, image_path: str) -> Dict[str, float]:
# Load image -> RGB conversion -> resize(224,224)
# Forward pass -> sigmoid(logits) -> numpy
# Return dict of condition:probability
Class Imbalance Handling
class BalancedNIHDataset:
# Separate "No Finding" from pathology samples
# Limit pathology samples per condition
# Shuffle and create balanced final dataset
File Structure
backend/utils/lung_classifier.py # Main model definition and inference
balanced_lung_trainer.py # Balanced training pipeline
train_optimized.py # Full training with metrics tracking
Current Results (Epoch 60)
Macro F1: 0.23
- Training trend: Consistent improvement over 60 epochs
- Better performing classes: Cardiomegaly (~0.35), Pneumonia (~0.28)
- Challenging classes: Hernia, Fibrosis (limited training data)
Training stability: Loss decreasing, F1 improving consistently
Technical Challenges Solved
- Double sigmoid issue: Fixed BCEWithLogitsLoss + model architecture mismatch
- Class imbalance: Implemented balanced sampling strategy
- 14 vs 15 class mismatch: Unified architecture to handle all LABELS
- Dataset inconsistency: Standardized on NIH Chest X-ray 14
Benchmarking
NIH Chest X-ray 14 Literature:
- Basic CNN: F1 = 0.15-0.20
- ResNet/DenseNet: F1 = 0.20-0.30 ← Current range
- Ensemble methods: F1 = 0.30-0.40
- SOTA research: F1 = 0.40+
Dependencies
torch==2.7.1
torchvision==0.22.1
datasets==3.6.0
scikit-learn==1.7.0
Pillow==11.2.1
Usage
# Load model
classifier = LungClassifierTrainer('path/to/model.pth')
# Inference
predictions = classifier.predict('xray.jpg')
# Returns: {'Pneumonia': 0.78, 'Effusion': 0.23, ...}
# Apply thresholds
significance = classifier.get_statistical_significance(predictions)
Training Commands
# Balanced training (handles class imbalance)
python balanced_lung_trainer.py
# Full training pipeline
python train_optimized.py --epochs 50 --batch-size 16
Model Files
- Best model:
models/lung_classifier_BEST.pth - Training history:
models/training_history_optimized.json - Balanced model:
balanced_lung_model.pth
Analysis
View
Metric
- 30
- 10
- 3
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- AnthropicIn code
- CSSIn code
- FastAPIIn code
- Hugging FaceIn code
- Next.jsIn code
- PythonIn code
- PyTorchIn code
- ReactIn code
- Tailwind CSSIn code
- TypeScriptIn code
10 of 10 appear in the indexed code.
AI coding agents
- Claude CodeConfig
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
213 KB
Source files
29
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
joannsum/XightMD
62 files · 395.4 MB · @ 4ca850e
Structure
Interface
8 files · 13%Screens, components and styles rendered to the user.
API & routing
4 files · 6%Request entry points: routes, handlers and controllers.
Application logic
12 files · 19%Domain rules, services and shared utilities.
Data & schema
10 files · 16%Schema definitions, migrations and data access.
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Python54%
- TypeScript36%
- Markdown7%
- CSS3%
- Shell0%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
backend/requirements.txt
pypi · 27- aiofiles
- anthropic
- black
- datasets
- fastapi
- httpx
- huggingface-hub
- isort
- numpy
- opencv-python
- pandas
- Pillow
- pydantic
- pytest
- python-dotenv
- python-multipart
- reportlab
- rich
- +9 more
xightmd/package.json
npm · 13- next
- react
- react-dom
- +10 more
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.