Skip to content

Repository files navigation

YGC Health — Medical Report Intelligence

YGC (Your Guided Care) is a full-stack medical-report platform. Patients upload lab PDFs, prescriptions, and scans. The system extracts structured facts, runs deterministic clinical safety checks, and answers questions in plain language — citing the exact page the answer came from.

It is a review and preparation companion, not a clinician. It does not diagnose, prescribe, or replace professional medical advice.

Upload a report  →  extract labs / meds / allergies  →  run safety rules
                                                         ↓
Ask in plain language  ←  cite the source page  ←  store facts in MongoDB
Layer What it is Default local URL
Frontend React + Vite dashboard http://localhost:5173
Backend Node / Express API http://localhost:4000
RAG service FastAPI clinical pipeline http://127.0.0.1:8000
Database MongoDB (single source of truth) local in-memory, Compose, or Atlas

Table of contents

  1. Features
  2. How complex is this?
  3. Architecture
  4. Modules and what they do
  5. Tech stack — what is used
  6. Prerequisites
  7. Quick start (local)
  8. Environment files
  9. Docker Compose
  10. Demo mode (no account)
  11. Tests
  12. Production deploy
  13. Safety and privacy
  14. Further reading

Features

Document intelligence

  • Upload PDF, PNG, JPG, and WebP reports (digital or scanned).
  • Multi-engine extraction: pdfplumber / PyMuPDF for text-layer PDFs, EasyOCR for scans, optional Tesseract cross-check, optional TrOCR handwriting, optional vision-LLM fallback.
  • Each lab, medication, and allergy keeps page, line, and snippet provenance.
  • Unreadable pages are flagged instead of guessed. Engine disagreement is marked uncorroborated and can require human verification before save.
  • Async extract jobs (queued → ocr → parsing → merging → done) so the UI can poll progress instead of blocking for 60–90 seconds.

Deterministic clinical safety (no LLM)

Safety findings are produced by curated tables and rules, not by the language model:

Check What fires
Drug–drug interactions Curated pairs + RxNav + openFDA
Allergy contradictions Cross-reactivity matrix (e.g. penicillin → amoxicillin)
Duplicate / same-class therapy Exact match and therapeutic-class match
Dose limits Adult / elderly / pediatric max, renal eGFR bands
Drug–lab contradictions e.g. metformin + high creatinine, ARB + hyperkalemia
Lab risk flags Reference-range and critical-value classifier
Longitudinal trends Unit-normalised series, slope, range-crossing
Prompt-injection defence Instruction-like text is stripped at ingest

Grounded chat

  • The LLM (Groq, Llama 3.3 70B by default) is an explanation layer only. It never invents a lab value or a diagnosis.
  • Common “what does my X mean?” questions are answered from 110 curated lab templates.
  • Follow-up pronouns (“is it high?”) resolve through a structured state machine, not chat-memory guessing.
  • Self-consistency: the model is called twice; divergence lowers confidence.
  • LLM answers are hard-capped at 60% confidence. Deterministic / crisis answers keep their own bounds.
  • If Groq is missing or down, answers degrade to templates — they never return empty {}.

Patient workspace

  • Dashboard, report library, upload review, chat assistant.
  • Longitudinal timeline with drift markers and lab sparklines.
  • Auto-built health profile (trends + risk indicators, no inferred diagnoses).
  • Click-to-verify citations open the stored page with the snippet highlighted (PDF.js when original bytes are stored).
  • Human correction workflow for misread labs and doses, with an audit trail.
  • Sync-audit page to resync or clean orphaned / stale clinical facts.
  • Clinician-review dashboard for the curated safety tables.
  • Account: email verification, password reset, optional TOTP 2FA, session list, data export / account delete.
  • PDF medical-history export for appointments.

Judge / demo mode

Open http://localhost:5173/demo — no account, no MongoDB required for the scenario loader. Seven synthetic patients prove the safety features (warfarin bleed, penicillin allergy, renal metformin, hyperkalemia + ARB, mixed-unit glucose, no-hallucination troponin, prompt injection). All demo data is fictional.


How complex is this?

High. This is a three-service clinical system with a rules engine, multi-engine OCR, and a hallucination-resistant chat pipeline — not a CRUD wrapper around an LLM.

Dimension Scale
Application Python (RAG) ~26,000 lines
Node backend ~4,100 lines
React frontend ~16,000 lines
Core clinical modules 26 files under rag_model/core/
RAG test files 58 (test_*.py)
Curated lab explanations 110 analytes
Specialist domains 7 (oncology, autoimmune, pregnancy, pediatric, infection, mental health, rare/genetic)
Dose-limit table 23 drugs with renal bands
Trend thresholds 27 analytes
Runtime processes Frontend + Backend + RAG + MongoDB

Complexity is concentrated where it should be: extraction quality, fail-closed safety rules, and making sure the LLM cannot invent a fact. Auth, storage, and the dashboard are conventional.

What you need to run it locally

  • Comfortable with Node 18+, Python 3.10+, and a .env file.
  • Optional: Docker, a Groq key, Tesseract, MongoDB Atlas.
  • First Python install pulls EasyOCR / PyTorch and can take several minutes and a few GB of disk.

What you can skip

  • Groq key → deterministic / template answers still work.
  • OCR extras → digital (text-layer) PDFs still extract.
  • Atlas → local in-memory MongoDB in the backend, or docker compose Mongo.

Architecture

System topology

flowchart TB
    subgraph Client
        Browser["Browser<br/>React + Vite SPA"]
    end

    subgraph PublicAPI["Backend — Node / Express :4000"]
        Auth["JWT auth · rate limits · CORS"]
        Users["users / sessions / 2FA"]
        Reports["report metadata"]
        ChatProxy["chat + extract proxy"]
        Demo["/api/demo — synthetic only"]
    end

    subgraph RAG["RAG service — FastAPI :8000"]
        Extract["OCR + parser"]
        Rules["Clinical rules engine"]
        Chat["Intent · templates · Groq"]
        Validate["Response validator"]
        Memory["Memory + health profile"]
    end

    subgraph Data["MongoDB — single store"]
        AppDB["users · reports · chats"]
        ClinicalDB["labs · meds · allergies<br/>pages · issue flags · memory"]
    end

    subgraph External["Optional external APIs"]
        Groq["Groq LLM"]
        RxNav["RxNav / RxNorm"]
        FDA["openFDA"]
        Medline["MedlinePlus"]
        Gmail["Gmail API — mail"]
    end

    Browser -->|VITE_API_URL| Auth
    Auth --> Users
    Auth --> Reports
    Auth --> ChatProxy
    Auth --> Demo
    Users --> AppDB
    Reports --> AppDB
    ChatProxy -->|x-internal-api-key| Extract
    ChatProxy --> Chat
    Demo --> Extract
    Extract --> Rules
    Extract --> ClinicalDB
    Rules --> ClinicalDB
    Chat --> Validate
    Chat --> Memory
    Memory --> ClinicalDB
    Chat -.-> Groq
    Rules -.-> RxNav
    Rules -.-> FDA
    Chat -.-> Medline
    Users -.-> Gmail
Loading

The browser talks only to the Node backend. The backend proxies extraction and chat to FastAPI with a shared RAG_INTERNAL_API_KEY. Both services write to the same MongoDB. There is no SQLite.

Request flow — upload

User drops a PDF
        │
        ▼
Frontend  POST /api/reports/extract  (or async job + poll)
        │
        ▼
Backend   auth, size/type checks, multer, rate limit
        │  x-internal-api-key
        ▼
RAG       sanitize → OCR / text extract → parse labs/meds/allergies
          → multi-engine cross-check → clinical JSON + citations
        │
        ▼
Frontend  review grid (human verify if engines disagree)
        │
        ▼
Backend   save report metadata in MongoDB
RAG       persist clinical facts, run rules, write issue flags
          (optional) generate health profile

Request flow — chat

Question
   │
   ├─ crisis / self-harm language?     → crisis resources, no report analysis
   ├─ specialist / out-of-scope?       → specialist module + “cannot conclude”
   ├─ safety intent (interaction…)?    → deterministic issue store
   ├─ “what does my X mean?”           → lab explanation template
   └─ otherwise                        → bounded Groq prompt
                                              │
                                              ├─ self-consistency check
                                              ├─ fact validator
                                              ├─ confidence cap (LLM ≤ 0.60)
                                              └─ citations from stored facts
   If Groq is down → same template / deterministic path. Never an empty answer.

Zero-hallucination principle

┌──────────────────┐     ┌──────────────────────┐     ┌─────────────────────┐
│  Uploaded docs   │     │  Curated KB (signed) │     │  RxNav / openFDA /  │
│  extracted facts │     │  dose / DDI / labs   │     │  MedlinePlus        │
└────────┬─────────┘     └──────────┬───────────┘     └──────────┬──────────┘
         │                          │                            │
         └──────────────┬───────────┴────────────────────────────┘
                        ▼
              Facts database (MongoDB)
                        │
                        ▼
              Rules engine  (0% LLM)
                        │
                        ▼
              Template assembler
                        │
                        ▼
              LLM paraphrase only  ──►  validator  ──►  UI
              (optional, confidence-capped)

The model is a language interface, never a knowledge source. Every factual claim must trace to an uploaded document, a curated table, or an authoritative API.


Modules and what they do

Repository layout

YGC/
├── medreport_dashboard/     React + Vite frontend
├── Backend/                 Node / Express API
├── rag_model/               FastAPI RAG + clinical engine
├── demo_assets/             Synthetic competition dataset
├── deploy/                  Oracle VM + production notes
├── docs/                    Architecture, deploy, eval
├── scripts/                 Dataset, OCR gate, clinician report
├── setup_local.sh           Install all three services
├── run_local.sh             Start all three services
├── docker-compose.yml       mongo + rag + backend + frontend
└── render.yaml              Free-tier Render blueprint

Frontend (medreport_dashboard/src)

Path Role
pages/Landing Marketing site, pipeline explainer, FAQ
pages/auth/* Login, signup, verify email, forgot password
pages/dashboard Metrics, recent reports, quick actions
pages/upload-report Async extract, verification grid, save
pages/my-reports Report library
pages/chat-assistant Grounded Q&A with citations
pages/timeline Longitudinal labs + drift markers
pages/health-profile Generated profile
pages/clinical-review Clinician sign-off of curated tables
pages/sync-audit Resync / cleanup stale facts
pages/demo One-click synthetic evaluation
pages/profile-settings Account, 2FA, sessions, export
components/evidence/* PDF.js viewer + snippet highlight
contexts/AuthContext JWT session

Backend (Backend/)

Path Role
index.js Express app, health, rate limits, graceful shutdown
config/env.js Bootstraps .env, validates secrets
routes/userRoutes.js Signup, login, verify, reset, profile, 2FA
routes/reportRoutes.js Extract, save, list, delete, audit, corrections
routes/chatRoutes.js Proxies chat to the RAG service
routes/demoRoutes.js Unauthenticated synthetic scenarios
controllers/userController.js Auth + account
controllers/chatController.js RAG proxy, 120s timeout
models/{user,report,chat}Model.js Mongoose schemas
middleware/auth.js JWT
middleware/security.js CORS, headers, rate limit
utils/emailService.js Gmail API OAuth2
utils/totp.js Two-factor auth
db/index.js Mongo connect; in-memory fallback in local dev

RAG service (rag_model/)

Path Role
rag_api.py FastAPI surface (extract, chat, timeline, audit, demo)
extraction/parser.py Medical report parser
extraction/ocr.py EasyOCR + Tesseract, rotation / deskew
extraction/cross_validation.py Multi-engine arbitration
extraction/job_queue.py Async extract jobs
extraction/vision_fallback.py Optional GPT-4o page fallback
extraction/handwriting_ocr.py Optional TrOCR
clinical_extraction.py Labs / meds / allergies / visits JSON
clinical_rules.py All deterministic safety rules
clinical_store_mongo.py Clinical persistence
clinical_derivations.py Pure views: trends, timeline, continuity
drug_interaction_service.py Curated + RxNav + openFDA
knowledge_service.py / kb_adapter.py Lab knowledge base
loinc_service.py LOINC normalisation
medlineplus_client.py Patient-education quotes
memory_engine.py Chat + report memory (optional Chroma)
pdf_generator.py Downloadable history PDF
response_validator.py Ground generated text in facts
structured_output.py Strict chat JSON schema
demo_service.py Synthetic scenario loader
chat/intent_detector.py Route to rules vs LLM
chat/response_builders.py Templates, Groq, fallbacks
core/pipeline.py End-to-end RAG orchestration
core/input_safety.py Prompt-injection sanitizer
core/safety_policy.py Query gates, “I don’t know”
core/dose_parser.py / dose_limits.py SIG parse + max-dose table
core/allergy_cross_reactivity.py Family / class matrix
core/risk_classifier.py Lab risk bands
core/unit_converter.py mmol/L ↔ mg/dL etc.
core/canonical.py Brand → generic, lab aliases
core/citations.py / provenance.py Click-to-verify locators
core/explanation_templates.py 110 lab explanations
core/followup_state.py Deterministic “it / that” resolution
core/self_consistency.py Dual LLM call + compare
core/groq_client.py Lazy Groq client, hard timeouts
core/patient_graph.py Structured patient graph
core/sync_worker.py Background fact reconciliation
core/clinical_review.py Clinician sign-off workflow
data/*.json Curated clinical tables

Tech stack — what is used

Languages and runtimes

Piece Version / notes
Node.js 18+ (Express 5, ESM)
Python 3.10+ (FastAPI 0.115)
React 18 + Vite 6
MongoDB 7 (Compose) or Atlas M0

Frontend libraries

React Router 7, Redux Toolkit, Tailwind CSS 3, Radix Slot, Framer Motion, Recharts, D3, pdf.js, react-markdown, react-hook-form, react-hot-toast, axios, lucide-react, date-fns.

Backend libraries

Express, Mongoose, JWT, bcrypt, multer, cors, morgan, winston, dotenv, axios, nodemailer, googleapis (Gmail API), mongodb-memory-server (local fallback).

RAG / AI libraries

FastAPI, Uvicorn, Pydantic, Groq SDK, pdfplumber, PyMuPDF, Pillow, EasyOCR, NumPy, httpx, requests, pymongo, pytest. Optional: Tesseract, OpenAI vision, torch + transformers (TrOCR), ChromaDB vector recall (off by default).

Data and external services

Service Cost Used for
MongoDB Free Atlas M0 or local All durable state
Groq Free tier, optional Natural-language explanations
RxNav / RxNorm (NLM) Free, no key Drug identity + interactions
openFDA Free; optional key raises rate limit Drug labels
MedlinePlus Free, no key Patient-education quotes
Gmail API Free OAuth Verification / reset email
ChromaDB Local, optional Derived vector index only

There is no paid PillChecker / DrugBank key. Paid APIs were replaced by RxNav + openFDA + curated JSON.

Infrastructure

Target Role
Vercel Static frontend
Render Backend + optional lite RAG (render.yaml)
Oracle Always Free VM Full EasyOCR RAG for demo day
Docker Compose One-command local / VM stack
UptimeRobot Keep the free-tier backend awake

Prerequisites

  • Node.js 18+ and npm
  • Python 3.10+ and pip
  • Git
  • Optional: Docker Desktop (Compose path)
  • Optional: Tesseract OCR (tesseract-ocr + eng.traineddata) for the second extraction engine
  • Optional: a free Groq API key for fluent chat
  • Optional: MongoDB Atlas (or any MongoDB URI). Local backend starts an in-memory MongoDB if MONGO_DB_URI is empty.

Quick start (local)

1. Clone

git clone https://github.com/Inkithai/YGC.git
cd YGC

2. Install everything

chmod +x setup_local.sh run_local.sh
./setup_local.sh

This will:

  1. Copy every *.env.example to .env if the target is missing.
  2. Generate a local ACCESS_TOKEN_SECRET in Backend/.env.
  3. npm install in Backend/ and medreport_dashboard/.
  4. Create rag_model/.venv and pip install -r requirements.txt.

3. (Optional) enable full AI chat

Edit rag_model/.env:

GROQ_API_KEY=gsk_your_key_here

Without it, extraction and safety rules still run. Chat uses deterministic templates.

4. Run all three services

./run_local.sh
Service URL
Frontend http://localhost:5173
Backend health http://localhost:4000/health
RAG health http://127.0.0.1:8000/health
Live demo http://localhost:5173/demo
RAG OpenAPI http://127.0.0.1:8000/docs

Press Ctrl+C to stop all three.

Manual start (three terminals)

# Terminal 1 — RAG
cd rag_model
source .venv/bin/activate
uvicorn rag_api:app --host 127.0.0.1 --port 8000 --reload

# Terminal 2 — Backend
cd Backend
npm run dev

# Terminal 3 — Frontend
cd medreport_dashboard
npm start -- --host 0.0.0.0 --port 5173

Environment files

There are four env files. Copy the matching example; never commit a real .env.

cp .env.example                     .env                      # Docker Compose only
cp Backend/.env.example             Backend/.env
cp medreport_dashboard/.env.example medreport_dashboard/.env
cp rag_model/.env.example           rag_model/.env

./setup_local.sh does this for you.

Which file is which?

medreport_dashboard/.env   →  Vite (browser). Only VITE_* are exposed.
Backend/.env               →  Express API.
rag_model/.env             →  FastAPI / OCR / LLM / clinical flags.
.env  (repo root)          →  docker compose env_file. Not used by run_local.sh.

MONGO_DB_URI and RAG_INTERNAL_API_KEY must be identical on the backend and the RAG service whenever you are not on the local in-memory database.


1. Frontend — medreport_dashboard/.env

VITE_API_URL=http://localhost:4000
VITE_MAX_UPLOAD_MB=15
VITE_RAW_TEXT_MAX_CHARS=50000

# Off: chat can contain sensitive medical text.
VITE_ENABLE_LOCAL_CHAT_CACHE=false

# Async extract pipeline (queued → ocr → parsing → merging → done)
VITE_USE_ASYNC_EXTRACT=true
VITE_JOB_POLL_INTERVAL_MS=800
VITE_EXTRACT_TIMEOUT_MS=300000
Variable Required Meaning
VITE_API_URL Yes Backend origin. In production this is https://<ygc-backend>.onrender.com.
VITE_MAX_UPLOAD_MB No Client-side size hint (default 15).
VITE_USE_ASYNC_EXTRACT No Poll jobs instead of one long request.
VITE_ENABLE_LOCAL_CHAT_CACHE No Keep false for medical data.

Vite only exposes variables that start with VITE_. Do not put secrets here.


2. Backend — Backend/.env

NODE_ENV=development
PORT=4000
TRUST_PROXY=false

# Empty = in-memory MongoDB for local dev.
# Production: Atlas SRV string. URL-encode @ : / ? # % in the password.
MONGO_DB_URI=
MONGO_DB_NAME=medreport_local
MONGO_SERVER_SELECTION_TIMEOUT_MS=10000
MONGO_AUTO_RETRY=true
MONGO_RETRY_MAX_ATTEMPTS=10

# openssl rand -base64 48
ACCESS_TOKEN_SECRET=local-dev-secret-change-me-please-32-characters-minimum
REQUIRE_EMAIL_VERIFICATION=false

FRONTEND_URL=http://localhost:5173
CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173

RAG_API_URL=http://127.0.0.1:8000
RAG_INTERNAL_API_KEY=

JSON_BODY_LIMIT=1mb
MAX_UPLOAD_MB=15
STORE_RAW_TEXT=true
RAW_TEXT_MAX_CHARS=50000
AUTH_RATE_LIMIT_MAX=25
CHAT_RATE_LIMIT_MAX=20
UPLOAD_RATE_LIMIT_MAX=10

# Optional — Gmail API OAuth2. Missing config never crashes;
# verification links are also printed to backend logs.
EMAIL_USER=
EMAIL_PASSWORD=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REFRESH_TOKEN=
Variable Required Meaning
ACCESS_TOKEN_SECRET Yes (≥ 32 chars) JWT signing key. setup_local.sh generates one.
MONGO_DB_URI Prod yes Empty locally → in-memory Mongo. Production must be a real URI.
RAG_API_URL Yes FastAPI base URL.
RAG_INTERNAL_API_KEY Prod yes Shared with rag_model/.env. Empty = RAG endpoints are open.
CORS_ORIGINS / FRONTEND_URL Yes Exact browser origin, no trailing slash, never *.
TRUST_PROXY Behind Render Must be the string true or rate-limit breaks on X-Forwarded-For.
REQUIRE_EMAIL_VERIFICATION No false for local / judge day.
DEMO_MODE_ENABLED No Default on. Set false wherever real patient data lives.

Verify Mongo without booting the API:

cd Backend && npm run check:db

Common Atlas copy-paste bugs: &amp; instead of &, leftover <password>, unencoded @ in the password (@ → %40).


3. RAG service — rag_model/.env

# Empty = deterministic / template chat. Extraction still works.
GROQ_API_KEY=
GROQ_MODEL=llama-3.3-70b-versatile
GROQ_REQUEST_TIMEOUT=20
GROQ_MODEL_DISCOVERY_TIMEOUT=15
GROQ_WARMUP_TIMEOUT=15

ENABLE_SELF_CONSISTENCY=true
ENABLE_TEMPLATE_EXPLANATIONS=true
ENABLE_FOLLOWUP_STATE=true
ENABLE_MULTI_ENGINE_OCR=true
LLM_CONFIDENCE_CAP=0.60
CLINICAL_DATA_DISCLAIMER_MODE=governance

RAG_CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
MAX_UPLOAD_MB=15
STORE_RAW_TEXT=true
RAW_TEXT_MAX_CHARS=50000
ENABLE_OCR=true
ENABLE_VECTOR_MEMORY=false
AUTO_GENERATE_HEALTH_PROFILE=false
RAG_INTERNAL_API_KEY=

# MUST match Backend/.env when using a real cluster.
MONGO_DB_URI=mongodb://127.0.0.1:27017/medreport
MONGO_DB_NAME=medreport

FDA_API_KEY=
OPENFDA_API_KEY=
ENABLE_RXNAV=true
ENABLE_OPENFDA=true

# Optional heavier engines (need extra pip packages).
VISION_FALLBACK_ENABLED=false
VISION_FALLBACK_PROVIDER=openai
VISION_FALLBACK_API_KEY=
HANDWRITING_ENABLED=false
Variable Default Meaning
GROQ_API_KEY empty Enables fluent LLM chat.
GROQ_MODEL llama-3.3-70b-versatile Use llama-3.1-8b-instant for cheapest / fastest.
RAG_INTERNAL_API_KEY empty Same value as Backend. Middleware only enforces when non-empty.
MONGO_DB_URI local Same cluster as the backend.
ENABLE_OCR true false on lite deploys (text-layer PDFs only).
ENABLE_MULTI_ENGINE_OCR true Second engine (Tesseract). Single-engine results are marked uncorroborated.
ENABLE_TEMPLATE_EXPLANATIONS true Deterministic “what does my X mean?”.
ENABLE_SELF_CONSISTENCY true Two LLM calls. Flip false if Groq 429s on demo day.
ENABLE_FOLLOWUP_STATE true Structured pronoun resolution.
LLM_CONFIDENCE_CAP 0.60 Displayed ceiling for generative answers.
ENABLE_VECTOR_MEMORY false Optional Chroma index. Not a source of truth.
AUTO_GENERATE_HEALTH_PROFILE false locally true in production if you want a profile after every save.
ENABLE_RXNAV / ENABLE_OPENFDA true Free drug APIs. Curated tables still run if they are down.

4. Docker Compose — repo-root .env

Used only by docker-compose.yml.

GROQ_API_KEY=
RAG_INTERNAL_API_KEY=
DATABASE_URL=mongodb://mongo:27017/medreport
MONGO_DB_NAME=medreport
JWT_SECRET=change-this-to-a-unique-secret-of-at-least-32-characters
ACCESS_TOKEN_SECRET=change-this-to-a-unique-secret-of-at-least-32-characters
MAX_UPLOAD_MB=15
STORE_RAW_TEXT=true
ENABLE_OCR=true
ENABLE_VECTOR_MEMORY=false
AUTO_GENERATE_HEALTH_PROFILE=true
FDA_API_KEY=
ENABLE_RXNAV=true
ENABLE_OPENFDA=true
STORE_ORIGINAL_FILES=true
SYNC_WORKER_ENABLED=true
SYNC_WORKER_INTERVAL_SECONDS=60
VISION_FALLBACK_ENABLED=false
HANDWRITING_ENABLED=false

JWT_SECRET in this file is mapped to ACCESS_TOKEN_SECRET inside the backend container.

Generate production secrets:

openssl rand -base64 48   # ACCESS_TOKEN_SECRET
openssl rand -base64 48   # RAG_INTERNAL_API_KEY  (paste into BOTH services)

Minimal local vs production

Situation What you must set
Browse the demo only Nothing. ./setup_local.sh && ./run_local.sh
Fluent chat locally GROQ_API_KEY in rag_model/.env
Shared local Mongo Same MONGO_DB_URI in Backend + RAG
Production MONGO_DB_URI, ACCESS_TOKEN_SECRET, RAG_INTERNAL_API_KEY (both services), RAG_API_URL, CORS_ORIGINS, FRONTEND_URL, VITE_API_URL, TRUST_PROXY=true
Email verification Gmail OAuth quartet on the backend
Scanned PDFs on a small host ENABLE_OCR=true and Tesseract in the image; EasyOCR needs more RAM

A longer production walkthrough lives in docs/PRODUCTION_ENV_SETUP.md.


Docker Compose

cp .env.example .env
# set JWT_SECRET / ACCESS_TOKEN_SECRET (and GROQ_API_KEY if you want LLM chat)
docker compose up --build
Service Host port
Frontend (nginx) http://localhost:3000
Backend http://localhost:5000
RAG http://localhost:8000
MongoDB 7 internal mongo:27017

Compose waits for Mongo and RAG health checks before starting the backend.


Demo mode (no account)

./run_local.sh
# open http://localhost:5173/demo

Or load every scenario from the CLI:

curl -X POST http://localhost:4000/api/demo/load-all | python3 -m json.tool
Scenario What it proves
Warfarin + aspirin + ibuprofen Cross-drug interaction
Penicillin allergy → amoxicillin Allergy + cross-reactivity
Creatinine 4.5 + metformin Renal contraindication
K 5.8 + ARB + KCl Drug–lab contradiction
Mixed-unit glucose Unit normalisation before trends
Troponin absent Says “not found” instead of inventing it
Embedded SYSTEM INSTRUCTION Prompt-injection defence

Demo patients are namespaced demo__* and cannot touch real records. Disable wherever real data is stored:

DEMO_MODE_ENABLED=false

Tests

# RAG / clinical suite
cd rag_model && source .venv/bin/activate
pytest -q

# Backend syntax + unit tests
cd Backend && npm test

# Frontend
cd medreport_dashboard && npm test

Persistence tests use a real MongoDB if TEST_MONGO_URI / MONGO_DB_URI is reachable, otherwise mongomock. Live Groq hallucination tests are skipped until GROQ_API_KEY is set.


Production deploy

Free-tier path (verified in-repo):

  1. MongoDB Atlas M0 — create a cluster, DB user, allow 0.0.0.0/0, copy the SRV URI.
  2. Render Blueprint — render.yaml creates ygc-backend and ygc-rag.
  3. Set MONGO_DB_URI, RAG_INTERNAL_API_KEY, GROQ_API_KEY on both Render services.
  4. On ygc-backend set RAG_API_URL=https://<ygc-rag>.onrender.com and CORS_ORIGINS / FRONTEND_URL to the Vercel origin.
  5. Vercel — import medreport_dashboard/, set VITE_API_URL=https://<ygc-backend>.onrender.com.
  6. Confirm GET https://<ygc-rag>/patient_summary/test returns 401/403 (key is actually enforced).
  7. Optional: Gmail OAuth for mail; UptimeRobot on the backend /health every 5 minutes.

Render’s free workspace is 750 hours/month. Keep only the backend awake; let RAG cold-start (30–60 s) or move it to the Oracle Always Free VM (deploy/oracle/README.md).

Step-by-step: docs/PRODUCTION_ENV_SETUP.md · docs/deploy-free-tier.md.


Safety and privacy

  • Not a medical device. Findings are informational. Confirm medication and lab decisions with a clinician or pharmacist.
  • Curated tables (dose_limits, specialist_modules, trend_thresholds, …) are tagged pending_clinician_review until a licensed clinician signs them off. See docs/CLINICIAN_REVIEW.md.
  • demo_assets/ is synthetic only. Real reports belong in private_demo_reports/ (gitignored). Never commit PHI.
  • RAG_INTERNAL_API_KEY must be set in any environment that holds real patient data.
  • Set DEMO_MODE_ENABLED=false next to real records.
  • Account deletion removes the user’s Mongo reports and RAG clinical / memory data.

Further reading

Doc Topic
docs/MONGODB_ONLY.md Collections, why there is no SQLite
docs/ZERO_HALLUCINATION_ARCHITECTURE.md Design blueprint for grounded answers
docs/DEGRADATION_PATHS.md Behaviour when Groq / Mongo / RxNav die
docs/DEMO_MODE.md Judge harness
docs/PRODUCTION_ENV_SETUP.md Production env, step by step
docs/deploy-free-tier.md Vercel + Render + Atlas
docs/CLINICIAN_REVIEW.md Signing off curated tables
deploy/oracle/README.md Full-OCR RAG on Oracle Always Free
private_demo_reports/README.md Testing with private reports

YGC Health — understand the report, verify the source, decide with a clinician.

About

YGC (Your Guided Care) is a full-stack medical-report platform. Patients upload lab PDFs, prescriptions, and scans. The system extracts structured facts, runs deterministic clinical safety checks, and answers questions in plain language, citing the exact page the answer came from.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages