| title | MediScan AI |
|---|---|
| emoji | π©Ί |
| colorFrom | blue |
| colorTo | purple |
| sdk | docker |
| app_port | 7860 |
| pinned | false |
| short_description | AI-powered lab report analyzer β LangGraph + CrewAI + RAG |
AI-powered lab report analysis pipeline β Upload a blood test PDF or paste raw lab values, get a plain-English health report written by 6 AI agents, validated by a judge model, and downloadable as a PDF.
Most people receive lab reports they can't understand. MediScan AI takes those reports and:
- Extracts every test value using a structured LLM extraction agent
- Enriches missing reference ranges from a WHO-sourced RAG database
- Calculates derived clinical metrics (eGFR, LDL, Non-HDL, VLDL, ratios)
- Researches abnormal values using live web search
- Writes a plain-English explanation using CrewAI multi-agent system
- Validates the output with a Qwen reasoning judge (loops back if quality is poor)
- Delivers a styled web report + downloadable PDF
User (text / PDF)
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FastAPI Backend β
β β
β βββββββββββββββββ LangGraph Pipeline ββββββββββββββββ β
β β β β
β β [1] Extractor Node βββΊ [2] RAG Lookup Node β β
β β β β β β
β β βΌ βΌ β β
β β [3] Calculator Node βββΊ [4] Researcher Node β β
β β β β β
β β βΌ β β
β β [5] CrewAI Node β β
β β (2 AI agents) β β
β β β β β
β β βΌ β β
β β [6] Judge Node (Qwen) β β
β β pass ββββββββββΊ [7] Finalizeβ β
β β fail βββββ retry (max 2) β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β /analyze/text /analyze/pdf /report/{id} β
β /download/{id} /metrics /health β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
Frontend (Vanilla JS + CSS)
βββββββββββββββββββββββββββββββββββ
β β’ Animated results rendering β
β β’ HIGH β / LOW β badges β
β β’ Calculated metrics cards β
β β’ PDF download (Arial TTF) β
βββββββββββββββββββββββββββββββββββ
| Layer | Technology | Purpose |
|---|---|---|
| Orchestration | LangGraph | Stateful multi-agent pipeline with conditional retry loop |
| Agent Framework | CrewAI | Explainer + Report Architect agents (sequential) |
| LLM (Pipeline) | Groq β llama-3.3-70b-versatile |
Extraction, Research, Judge (12K TPM pool) |
| LLM (Crew) | Groq β llama-4-scout-17b-16e-instruct |
Report writing (30K TPM pool β separated to avoid rate limits) |
| Judge | Groq β qwen/qwen3-32b |
Quality validation with pass/fail + feedback |
| RAG | ChromaDB + all-MiniLM-L6-v2 |
WHO reference range lookup for missing test values |
| Web Search | Tavily API | Real-time context for abnormal lab values |
| PDF Extraction | PyMuPDF (fitz) | Extracts text from uploaded lab report PDFs |
| PDF Generation | fpdf2 + Arial TTF | Unicode-capable health report PDF output |
| API | FastAPI + Uvicorn | REST endpoints for analysis, reports, metrics |
| Frontend | Vanilla HTML/CSS/JS | No framework overhead β fast, no build step |
| CI/CD | GitHub Actions + Render | Unit tests on push, auto-deploy on main |
UltimateAiProject/
βββ backend/
β βββ main.py # FastAPI app + all endpoints
β βββ graph/
β β βββ graph.py # LangGraph assembly + metrics logger
β β βββ nodes.py # 6 agent nodes (extract, rag, calc, research, crew, judge, finalize)
β β βββ state.py # Shared state TypedDict
β βββ crew/
β β βββ agents.py # CrewAI agent definitions (Llama4-Scout)
β β βββ tasks.py # CrewAI task definitions + run_crew()
β βββ tools/
β β βββ calculator.py # Medical formulas (eGFR, LDL, Non-HDL, BMI, ratios)
β β βββ search.py # Tavily web search wrapper
β βββ utils/
β β βββ report_generator.py # fpdf2 PDF generation (Arial TTF, Unicode-safe)
β βββ ingest.py # ChromaDB ingestion + retrieval
βββ frontend/
β βββ index.html # Single-page app
β βββ style.css # Dark theme + animations + badge styles
β βββ script.js # API calls + markdown rendering + badge injection
βββ documents/
β βββ medical_ranges.txt # WHO reference ranges corpus (RAG source)
βββ tests/
β βββ test_calculator.py # 8 unit tests β medical formula correctness
β βββ test_pdf.py # 8 unit tests β PDF generation + Unicode safety
βββ .github/workflows/ci.yml # GitHub Actions CI (runs on push/PR)
βββ render.yaml # Render.com deployment config
βββ metrics.jsonl # Per-request performance log (auto-generated)
βββ test_pipeline.py # Integration test (requires live server)
βββ requirements.txt
- Python 3.11
- Conda (or venv)
- A Groq API key (free)
- A Tavily API key (free tier β 1000 searches/month)
git clone https://github.com/Mahajan-Sachin/HealthReport.git
cd mediscan-ai
conda create -n langgraph_env python=3.11
conda activate langgraph_env
pip install -r requirements.txtCreate a .env file in the project root:
GROQ_API_KEY=your_groq_api_key_here
TAVILY_API_KEY=your_tavily_api_key_here
GENERATOR_MODEL=meta-llama/llama-3.3-70b-versatile
JUDGE_MODEL=qwen/qwen3-32b
CREW_MODEL=groq/meta-llama/llama-4-scout-17b-16e-instructpython -c "from backend.ingest import ingest_documents; ingest_documents()"python -m uvicorn backend.main:app --host 0.0.0.0 --port 8000 --reloadOpen http://localhost:8000 in your browser.
| Method | Endpoint | Description |
|---|---|---|
POST |
/analyze/text |
Analyze pasted lab report text |
POST |
/analyze/pdf |
Upload and analyze a lab report PDF |
GET |
/report/{report_id} |
Fetch full structured report JSON |
GET |
/download/{report_id} |
Download report as PDF |
GET |
/metrics |
View last 20 request performance metrics |
GET |
/health |
Server health check |
curl -X POST http://localhost:8000/analyze/text \
-H "Content-Type: application/json" \
-d '{
"report_text": "Hemoglobin: 9.2 g/dL [L]\nTotal Cholesterol: 238 mg/dL [H]",
"patient_name": "Test Patient",
"patient_age": 42,
"patient_sex": "male"
}'Every request is automatically logged to metrics.jsonl. View via:
GET /metrics
{
"total_requests_logged": 5,
"averages": { "total_seconds": 43.3, "tests_found": 14 },
"requests": [{
"timestamp": "2026-06-20T01:20:57",
"total_seconds": 43.33,
"node_timings": {
"extract": 1.88,
"rag": 0.02,
"calculate": 0.0,
"research": 13.95,
"crew": 14.59,
"judge": 12.88
},
"tests_found": 16,
"abnormal_count": 14,
"judge_iterations": 2,
"status": "success"
}]
}Key insight: extract + rag + calculate = ~2s (4% of total time). research + crew + judge = ~41s (96%). The LLM nodes dominate β future optimization target is parallel execution of research and crew.
# Unit tests only (no API keys needed, runs in ~3 seconds)
python -m pytest tests/ -v
# Integration test (requires live server + real API keys)
python test_pipeline.py| Test Suite | Tests | What It Covers |
|---|---|---|
test_calculator.py |
8 | eGFR formula, Friedewald LDL, Non-HDL, BUN ratio, edge cases |
test_pdf.py |
8 | PDF generation, Unicode safety, markdown stripping |
- CI: GitHub Actions runs all unit tests on every push to
main/devand on PRs - CD: Render auto-deploys on every merge to
main
Push to main
β
βββ GitHub Actions CI
β βββ python -m pytest tests/ -v β must pass
β
βββ Render Auto-Deploy
βββ pip install + uvicorn start
- Push this repo to GitHub
- Go to render.com β New Web Service β Connect repo
- Add secrets in Render dashboard:
GROQ_API_KEY,TAVILY_API_KEY - Deploy β
render.yamlhandles the rest
Why two separate Groq models?
Groq enforces TPM limits per model. Using llama-3.3-70b (12K TPM) for LangGraph nodes and llama-4-scout-17b (30K TPM) for CrewAI separates the workloads across two independent rate limit pools, preventing one from starving the other.
Why no LLM output caching? Lab report values change between visits β the same patient with the same name/age could have completely different results after an illness. Caching on patient identity would return stale analysis. The only valid cache is the RAG reference range data (ChromaDB), which doesn't change per-request.
Why Vanilla JS (no React/Next.js)?
No build step. No bundler. The frontend is served as static files by FastAPI. Any change to script.js or style.css is live immediately β ideal for rapid iteration on a single-page tool.
- Rate limits: Groq free tier limits throughput. Concurrent users will queue at the API level.
- PDF scans: Scanned/image-based PDFs are not supported (only text-extractable PDFs). OCR (Tesseract) not yet integrated.
- In-memory report store: Reports are lost on server restart. Acceptable for a public demo tool β would need Redis/SQLite for persistent doctor-facing use.
- Arial font: PDF generation requires Arial TTF (available on Windows). Linux deployments fall back to ASCII-safe mode.
MIT β free to use, modify, and deploy.
Built with LangGraph + CrewAI + Groq + FastAPI