Skip to content

Medical Retrieval-Augmented Generation (Rust + WebAssembly, FHIR)

LuuNa-JD/medical-rag

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 

Repository files navigation

Medical-RAG (Rust + WebAssembly)

Assistant médical francophone (RAG) construit 100 % en Rust :

  • Back-end Actix-web + Tantivy + Candle (LLM)
  • Front-end Yew (WebAssembly)
  • Données FHIR (Patient, Observation, Condition, Encounter, MedicationRequest)

Cas d’usage : poser des questions cliniques en français et obtenir des réponses sourcées uniquement par le contexte FHIR (aucune hallucination volontaire).


Fonctionnalités

  • Ingestion FHIR en lot puis hot-sync toutes les 5 min (_since)
  • Index sémantique Tantivy (+ champs cliniques : LOINC, valeur, unité, dates, patient)
  • Recherche hybride BM25 → filtre patient/année → reclassement embeddings (All-MiniLM-L12-v2)
  • RAG avec Candle (inférence locale, GPU CUDA si dispo) et tokenizer HuggingFace
  • API JSON POST /query
  • UI chat Yew/Trunk, design responsive

Aperçu du dépôt

backend/
  src/        (# fhir.rs, index.rs, rag.rs, rag_doc.rs, main.rs)
  models/     (# modèles Candle: *.safetensors + tokenizer.json)
  index/      (# index Tantivy)
  dummy/      (# index “vide” pour warmup)
  application.yaml
  Cargo.toml
  docker-compose.yml
frontend/
  src/        (# app Yew)
  index.html  (# thème / styles)
  trunk.toml
  Cargo.toml

Prérequis

  • Rust 1.78+ (toolchain stable)
  • Node pas nécessaire (build web via trunk)
  • Trunk pour Yew : cargo install trunk
  • wasm32-unknown-unknown : rustup target add wasm32-unknown-unknown
  • (Optionnel) CUDA pour accélérer Candle
  • Un serveur FHIR R4/R5 accessible (par défaut : http://localhost:8080/fhir)

Configuration

Back-end

  • FHIR_SERVER dans src/fhir.rs (ou via variable d’env si vous préférez)
  • Modèles Candle à placer dans backend/models/ :
    models/
      model-00001-of-00003.safetensors
      model-00002-of-00003.safetensors
      model-00003-of-00003.safetensors
      tokenizer.json
    

    Le projet est configuré pour un petit Mistral-like (voir rag.rsMistralConfig).

  • Le modèle d’embeddings (All-MiniLM-L12-v2) est téléchargé automatiquement au premier run via rust-bert.

Front-end

  • L’UI appelle l’API via API_URL (env compile-time).
    • Dev local : http://localhost:8081 (par défaut)
    • Sinon : exporter à la compilation :
      API_URL=http://localhost:8081 trunk serve

Démarrage rapide (local)

1) Back-end

cd backend
cargo run
  • Démarre l’API sur http://127.0.0.1:8081
  • Étapes au boot :
    1. Chargement embeddings (BGE/All-MiniLM)
    2. Chargement/initialisation du LLM Candle
    3. Ingestion initiale FHIR, mapping Patient ↔ ressources, index Tantivy
    4. Hot-sync toutes les 5 min

2) Front-end

cd frontend
trunk serve --open
# ou API personnalisée :
API_URL=http://127.0.0.1:8081 trunk serve --open
  • Ouvre l’UI chat. Entrez une question, ex. :
    • Quel est l’IMC de John Doe en 2024 ?
    • TA de Jane Smith en juillet 2023
    • patient-123 : HbA1c la plus récente

API

POST /query

Request

{ "query": "TA de John Doe en 2023" }

Response

{ "output": "…réponse concise en français, uniquement basée sur le contexte fourni…" }

Le prompt (rag.rs) force : style concis, aucune invention, dates converties au format humain FR.


Détails techniques

  • Index (index.rs)

    • Schéma Tantivy : id, patientId, patientName, resourceType, summary, loincCode, valueNum, unit, birthDate, date, dateMonth, dateDay, raw
    • Ajout massif en parallèle (rayon), commit par lot
    • Recherche : BM25 (multi-champs) → filtrage patient/année → reclassement cosine embeddings
  • Ingestion FHIR (fhir.rs)

    • Pagination _count=100 + lien next
    • Sync incrémental via _since (horodatage Utc)
  • Préparation des documents (rag_doc.rs)

    • Résumés FR prêts pour le LLM
    • Alias cliniques LOINC : TA, FC, IMC, HbA1c, Cholestérol…
    • Extraction valeurs numériques + unité + dates (YYYY-MM / YYYY-MM-DD)
  • Génération (rag.rs)

    • Budget MAX_PROMPT_TOKENS = 512 (sélection adaptative des chunks)
    • Candle (CPU ou CUDA) avec sampling greedy court (MAX_GENERATION_TOKENS = 128)
    • Tokenizer HuggingFace (tokenizers)
  • Front-end (frontend/src/main.rs)

    • Yew + reqwasm (fetch API)
    • Chat minimal avec auto-scroll, Enter-to-send
    • index.html : thème glassmorphism sombre

Docker (exemple)

Un docker-compose.yml est fourni côté backend (à adapter) :

  • Service API sur 8081
  • Montage ./models et ./index
  • Variable d’env FHIR_SERVER si vous souhaitez la passer par env

Le front peut être servi statiquement (NGINX) après trunk build --release.


Jeu de données de démo

Le dossier backend/ contient des bundles synthétiques FHIR (synthetic_*) pour tester rapidement. Vous pouvez aussi pointer FHIR_SERVER vers un serveur HAPI/FHIR local.


Performance & conseils

  • GPU détecté automatiquement (Device::cuda_if_available(0)), sinon CPU.
  • Gardez les prompts courts et précis ; l’index fait l’essentiel du travail.
  • Ajoutez vos propres synonymes LOINC dans OBS_SYNONYMS.
  • Pour des réponses plus longues, augmentez MAX_GENERATION_TOKENS.

Sécurité & conformité

  • Projet de démonstration. Pour des données réelles : chiffrement au repos, contrôle d’accès, journalisation, cloisonnement réseau, et RGPD (base légale, minimisation, consentement, droits des personnes).
  • Aucune décision médicale ne doit être prise uniquement sur la base de ce prototype.

Dépannage

  • Le téléchargement des embeddings est lent → pré-téléchargez le modèle rust-bert en cache.
  • Pas de résultats → vérifiez FHIR_SERVER, que les bundles contiennent entry[].resource.
  • CUDA non détecté → vérifiez pilotes/NVIDIA, version Candle et compute capability.
  • CORS → le back utilise Cors::permissive() (dev). Durcissez en prod.

Scripts utiles

# Backend
cd backend
RUST_LOG=debug cargo run

# Frontend (dev)
cd frontend
API_URL=http://127.0.0.1:8081 trunk serve --open

# Frontend (build prod)
trunk build --release

Licence

MIT (sauf modèles tiers soumis à leurs licences respectives).


Auteurs & remerciements

  • Stack Rust : Actix-web, Tantivy, Candle, tokenizers, Yew, rust-bert
  • Données : FHIR (HL7®)
  • Design UI : thème custom OrbitNet dans frontend/index.html

About

Medical Retrieval-Augmented Generation (Rust + WebAssembly, FHIR)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published