Skip to content

Hetnet

API do grafowej bazy wiedzy medycznej (Hetionet na Neo4j). PoC łączący choroby, symptomy, leki i anatomię – z wizualizacją, testbenchem i RAG na Cloudflare Workers.

Tech Stack

  • Backend: Node.js ≥18, Express, Neo4j 5 (graph database)
  • Frontend: Vanilla JS (D3.js visualization)
  • RAG/Chat: Cloudflare Workers + Vectorize
  • Translation: DeepL / LibreTranslate / MyMemory
  • Deployment: Railway (Neo4j remote), Cloudflare (chat worker)
  • Data: Hetionet TSV, Mendeley datasets, Infermedica docs (scraped)

Szybki start

bash
npm install
cp .env.example .env   # ustaw NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD

# uruchom Neo4j + (opcjonalnie) LibreTranslate lokalnie
docker compose up -d neo4j libretranslate
# Neo4j: ~10s start, UI http://localhost:7474
# LibreTranslate: host :5010 (5000→5010 z uwagi na macOS AirPlay), pierwszy start pobiera modele en↔pl (~kilka minut)

npm run pipeline       # load → neo4j → translate → export-rag (pełny pipeline)
npm start              # uruchom API na :3000

Dostępne interfejsy:


Struktura projektu

├── src/              # Express API (Neo4j driver)
├── public/           # Frontend (graf D3.js, testbench UI)
├── pipeline/         # ETL pipeline (load→parse→import→translate→export)
│   ├── parsers/      # Parsery źródeł danych (hetionet, sider, disease-ontology, etc.)
│   ├── steps/        # Kroki pipeline (1-load, 2-neo4j, 3-translate, 4-export-rag)
│   └── run.js        # Runner pipeline
├── data/
│   ├── raw/          # Surowe dane (hetionet TSV, mendeley, etc.)
│   └── translations/ # Persystentny store tłumaczeń (pl.json, meta.json)
├── chat/             # Cloudflare Worker RAG (Vectorize + LLM)
├── scripts/          # Utility scripts (count-remaining, translate-and-update)
└── symptomate/       # Scraped docs Infermedica API (conditions, symptoms, risk factors)

Pipeline

Główny flow ETL: źródła → parsing → Neo4j → tłumaczenia → eksport RAG chunks.

Komendy pipeline

bash
npm run pipeline           # pełny przebieg (wszystkie kroki)
npm run pipeline:load      # krok 1: ściągnięcie danych do data/raw/
npm run pipeline:neo4j     # krok 2: import parsed data do Neo4j
npm run pipeline:translate # krok 3: tłumaczenia (DeepL/LibreTranslate/MyMemory)
npm run pipeline:rag       # krok 4: eksport chunków do chat/export/

Źródła danych (parsowane w pipeline/parsers/):

  • Hetionet (nodes.tsv, edges.sif.gz) – główny graph
  • SIDER, Disease Ontology, SymbiPredict, NeonatalADR, Health-KG, Mendeley datasets, HuggingFace, inne (sprawdź pipeline/parsers/index.js)

Po imporcie do Neo4j masz ~138k węzłów i ~5.2M krawędzi (unverified — zależy od aktualnych źródeł).

Tłumaczenia

Pipeline krok 3 (npm run pipeline:translate) oraz standalone npm run translate używają persystentnego store data/translations/pl.json.

Backendy tłumaczeń:

  • DeepL (domyślny): wymaga DEEPL_API_KEY w .env. Przy przekroczeniu limitu quota → błąd Quota Exceeded.
  • LibreTranslate lokalny: npm run translate:libre:docker (Neo4j z .env) lub npm run translate:libre:docker:railway (Neo4j z Railway). Wymaga Docker Desktop, kontener libretranslate musi być up (:5010).
  • LibreTranslate publiczny: ustaw LIBRETRANSLATE_API_KEY + LIBRETRANSLATE_URL.
  • MyMemory: darmowy, ale z rate limit (429). Testowo: npm run translate:mymemory (tylko Disease+Symptom, max 500 nodes).

Filtrowanie (przyspiesza na start):

bash
TRANSLATE_KINDS=Disease,Symptom npm run translate

Railway remote (tłumaczenie na zdalnym Neo4j):

bash
railway run --service hetnet node scripts/translate-and-update.js

Nowe języki: dodaj plik store w data/translations/, rozszerz pipeline/config.js (krok translate obecnie wspiera tylko PL przez standalone skrypt).


Railway Deployment

Pipeline działa lokalnie, łączy się z Neo4j na Railway i importuje dane (nie potrzebujesz Docker lokalnie dla remote setup).

Setup projektu Railway (unverified — confirm steps with team)

  1. Projekt: Deploy from GitHub → Wellysa/hetnet
  2. Dodaj Neo4j service:
    • Image: neo4j:5-community
    • Variables: NEO4J_AUTH=neo4j/hasło
    • Volume: /data
    • Expose TCP Proxy na port 7687
  3. Neo4j Variables: dodaj BOLT_URI = bolt://${{TCP_PROXY_DOMAIN}}:${{TCP_PROXY_PORT}}
  4. API Service Variables:
    • NEO4J_URI = ${{Neo4j.BOLT_URI}}
    • NEO4J_USER = neo4j
    • NEO4J_PASSWORD = hasło z kroku 2
  5. Railway CLI:
    bash
    npm i -g @railway/cli
    railway link   # wybierz projekt

Import danych na remote

bash
railway run npm run pipeline

Uruchamia pełny pipeline (load → parse → import do Neo4j na Railway). Trwa kilka minut.

Opcjonalnie NeoDash (unverified): Image neo4jlabs/neodash, te same zmienne Neo4j co główny service.


API (endpoints unverified — verify in src/index.js)

MetodaEndpointOpis
GET/healthHealth check
GET/api/statsLiczba węzłów i krawędzi
GET/api/labelsTypy węzłów (labels)
GET/api/search?q=aspirin&limit=20Full-text search
GET/api/node/:idWęzeł + bezpośrednie relacje
GET/api/neighbors/:id?depth=1&limit=100Sąsiedzi do głębokości N
GET/api/diseasesLista chorób
GET/api/symptomsLista symptomów
GET/api/disease/:id/symptomsSymptomy dla choroby
POST/api/diseases-by-symptomsChoroby pasujące do symptomów (koniunkcja)

Query param ?lang=pl: zwraca name_pl gdzie dostępne (po uruchomieniu tłumaczeń).

OpenAPI: /docs (Swagger UI), /openapi.json


Testbench

/testbench – interaktywny UI do testowania:

  • Wybierz chorobę → pokaż symptomy
  • Wybierz symptomy → znajdź choroby (koniunkcja)
  • Przełącznik PL/EN

Chat (RAG)

Czat z bazą wiedzy na Cloudflare Workers (Vectorize + embedding bge-m3 + Llama 3.1).

Setup (unverified — see chat/README.md):

  1. Uruchom pipeline (lub npm run export:rag po imporcie do Neo4j) – eksportuje chunki do chat/export/
  2. Ingest do Vectorize:
    bash
    CHAT_URL=https://your-worker.workers.dev node chat/ingest-from-export.js
  3. Deploy workera:
    bash
    cd chat
    npx wrangler deploy

Szczegóły konfiguracji Vectorize, bindings, secrets → chat/README.md.


Symptomate

Folder symptomate/ zawiera scraped dokumentację Infermedica API (platform-api, engine-api, intake-api, overview). Tylko listy encji (conditions, symptoms, risk factors) – bez relacji choroba↔symptom (te są w Hetionet).

Ponowne scrapowanie (unverified): node symptomate/scrape-docs.js


Development

bash
npm install
# ustaw .env: NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD, (opcjonalnie) DEEPL_API_KEY

npm run dev    # --watch mode (Node 18+)
npm start      # produkcja

Inne komendy:

bash
npm run count:remaining   # policz pozostałe do przetłumaczenia
npm run export:rag        # eksport RAG chunków (bez pełnego pipeline)

Status

PoC – proof of concept dla grafowej bazy wiedzy medycznej. Produkcyjne deployment wymaga:

  • Rate limiting, auth dla API
  • Walidacja źródeł danych (licencje, aktualność)
  • Monitoring tłumaczeń (quality check)
  • CI/CD dla Railway + Cloudflare deploy

License & Data Sources

Hetionet: CC0 (public domain). Pozostałe źródła: sprawdź data/raw/MANUAL_SOURCES.md i licencje poszczególnych datasets.

Wellysa Consigliere — internal use only.