Thulth estimates whole‑body and organ biological ages, computes an Aging Rate Index (ARI), and turns insights into a simple weekly plan from three domain agents (General Doctor, Nutrition, Physical Activity). Guidance is non‑diagnostic, privacy‑respectful, and focused on tiny, realistic habits.
TypeScript
0
5 commits
updated Oct 28, 2025
Thulth estimates whole‑body and organ biological ages, computes an Aging Rate Index (ARI), and turns insights into a simple weekly plan from three domain agents (General Doctor, Nutrition, Physical Activity). Guidance is non‑diagnostic, privacy‑respectful, and focused on tiny, realistic habits.
Thulth/
├─ app/ # React Native (Expo) mobile app
│ ├─ package.json # Expo deps + RN navigation
│ └─ src/
│ ├─ App.tsx # Navigation (tabs + stacks)
│ ├─ api/client.ts # Fetchers (predict + agent routing)
│ ├─ i18n/ # i18n provider + strings
│ ├─ components/ # UI components (Meter, OrganCard, etc.)
│ ├─ theme.ts # Theme + color system
│ └─ screens/ # Screens (mobile + flow)
│ ├─ MobileHomeScreen.tsx
│ ├─ WellbeingScreen.tsx
│ ├─ MyFileScreen.tsx
│ ├─ RunOptionsScreen.tsx
│ ├─ ResultsScreen.tsx
│ ├─ PlanScreen.tsx
│ ├─ AgentChatScreen.tsx
│ └─ (EditProfileScreen, etc.)
├─ server/ # FastAPI backend
│ ├─ main.py # Endpoints
│ ├─ models/schemas.py # Pydantic schemas
│ ├─ services/
│ │ ├─ scoring_stub.py # REAL inference (GB models) + mapping
│ │ ├─ coordinator.py # Merge agents into plan (≤5, domain balance)
│ │ ├─ llm.py # Ollama client
│ │ └─ utils.py # DEFAULT_USER, tone, helpers
│ └─ agents/ # Agent runners (GD/NT/PA)
│ ├─ gd.py
│ ├─ nt.py
│ └─ pa.py
├─ model/ # Training artifacts & weights
│ ├─ mpl_model.py # Training script (reference)
│ ├─ weights/ # *.pkl GB models (global/kidney/cardio)
│ ├─ data/ # *healthy_* datasets for scaler fit
│ └─ data_cleaning/ # Data cleaning & population construction scripts
├─ thulth_logo.png # Branding
└─ README.md # This file
Requirements: Python 3.10+, virtualenv
cd server
python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -r <(python - <<'PY'
from tomllib import load
import sys; import pathlib
p = pathlib.Path('pyproject.toml')
print("\n".join(load(p.open('rb'))['project']['dependencies']))
PY
)
# or install manually: fastapi uvicorn pydantic requests pandas numpy scikit-learn joblib scipy
python -m uvicorn main:app --reload --port 8000
Health checks
Requirements: Node 18+, Expo CLI
cd app
npm i
npm run start
# iOS sim: press i | Android: a | Web: w
If running on a device, point the app’s API base (app/src/api/client.ts) to your machine IP instead of localhost.
brew install watchman) or raise ulimit -n 8192.npm i @react-navigation/bottom-tabs @react-navigation/native @react-navigation/native-stack react-native-safe-area-context react-native-screens then npx expo start --clear.python -m pip install uvicorn.The model/data_cleaning/ scripts generate the healthy / nonhealthy populations used for model pre‑fit, fine‑tuning, and testing.
Pipeline (per script comments):
(value − mean) > 3 × sd for each test.Outputs
model/data/*_healthy_non_saudi.txt — used to fit StandardScaler (global/cardio/kidney)model/data/*_healthy_saudi.txt — fine‑tuning splitmodel/data/*_nonhealthy_saudi.txt — held‑out evaluationReproducibility (example)
cd model/data_cleaning
# 1) Merge + clean
python 01_merge_labs.py --input ./raw/ --out ../data/merged.tsv
# 2) Units harmonization
python 02_unit_harmonization.py --in ../data/merged.tsv --out ../data/merged_harmonized.tsv
# 3) Outlier removal (3*sd)
python 03_outlier_filter.py --in ../data/merged_harmonized.tsv --out ../data/filtered.tsv --z 3.0
# 4) Healthy/nonhealthy splits
python 04_define_populations.py --in ../data/filtered.tsv --healthy ../data/*_healthy_*.txt --nonhealthy ../data/*_nonhealthy_*.txt
Notes
Server uses the same feature names from mpl_model.py and maps API payload keys to them.
DISPLAY_NAME_MAP keys used by the model (subset):
M→0, F→1diastolic (from DBP)systolic (from SBP)Triglyceride_result_valueCholesterol..in.Serum.or.Plasma_result_valueCholesterol.in.HDL_result_valueHemoglobin.A1c._result_value (accepts HbA1c/HBA1C/A1C synonyms)Bilirubin.total.[Mass/volume].in.Serum.or.Plasma_result_valueAlbumin.[Mass/volume].in.Serum.or.Plasma_result_valueAspartate.aminotransferase.[Enzymatic.activity/volume].in.Serum.or.Plasma.by.With.P-5-P_result_valueCreatinine..in.Serum.or.Plasma_result_valueUric.acid.in.Serum.or.Plasma_result_valuePotassium.in.Serum.or.Plasma_result_value (K)Sodium.in.Serum.or.Plasma_result_value (Na)Thyroid.Stimulating.Hormone.[TSH]_result_valueWBC_result_valueavg_daily_stepsbmi (computed from height_cm, weight_kg)Models & columns
GLOBAL_COLS (~cardio‑metabolic + BMI)CARDIO_COLS (BP, lipids, A1c)KIDNEY_COLS (creatinine, uric acid, Na/K)Scaling
StandardScaler per system on *_healthy_non_saudi.txt to match training distribution; missing features are filled using the training means.GET /health → { ok: true }GET /logo.png → brandingPOST /predict/run → PredictionOut
whole.bio_age (Global)organs.cardio and organs.kidney values and drivers (top importances)ari (aging rate index) from bio‑age gapPOST /agent/gd | /agent/nt | /agent/pa → AgentResponse (Ollama backed with resilient fallbacks)POST /agent/route → CoordinatorOut (≤5 items, ≥1 per domain, Impact×Ease ordering)Environment (optional)
OLLAMA_HOST (default http://localhost:11434)OLLAMA_MODEL (default llama3.1:8b)Prompts were engineered for empathy, brevity, and transparency; if prediction is missing, agents use DEFAULT_USER + fallbacks.
Internationalization & RTL: AR/EN with I18nProvider and Dubai font
Theming: theme.ts primaryAccent + card style
Persistence: AsyncStorage for last result/plan, BA history, steps, etc.
npm i @react-navigation/bottom-tabs + npx expo start --clearbrew install watchman or ulimit -n 8192source server/.venv/bin/activate then python -m uvicorn main:app --reload --port 8000If you need help wiring a new data source or extending the plan logic, open an issue with sample payloads and desired UX.
Thulth estimates whole‑body and organ biological ages, computes an Aging Rate Index (ARI), and turns insights into a simple weekly plan from three domain agents (General Doctor, Nutrition, Physical Activity). Guidance is non‑diagnostic, privacy‑respectful, and focused on tiny, realistic habits.
TypeScript
0
5 commits
updated Oct 28, 2025
Thulth estimates whole‑body and organ biological ages, computes an Aging Rate Index (ARI), and turns insights into a simple weekly plan from three domain agents (General Doctor, Nutrition, Physical Activity). Guidance is non‑diagnostic, privacy‑respectful, and focused on tiny, realistic habits.
Thulth/
├─ app/ # React Native (Expo) mobile app
│ ├─ package.json # Expo deps + RN navigation
│ └─ src/
│ ├─ App.tsx # Navigation (tabs + stacks)
│ ├─ api/client.ts # Fetchers (predict + agent routing)
│ ├─ i18n/ # i18n provider + strings
│ ├─ components/ # UI components (Meter, OrganCard, etc.)
│ ├─ theme.ts # Theme + color system
│ └─ screens/ # Screens (mobile + flow)
│ ├─ MobileHomeScreen.tsx
│ ├─ WellbeingScreen.tsx
│ ├─ MyFileScreen.tsx
│ ├─ RunOptionsScreen.tsx
│ ├─ ResultsScreen.tsx
│ ├─ PlanScreen.tsx
│ ├─ AgentChatScreen.tsx
│ └─ (EditProfileScreen, etc.)
├─ server/ # FastAPI backend
│ ├─ main.py # Endpoints
│ ├─ models/schemas.py # Pydantic schemas
│ ├─ services/
│ │ ├─ scoring_stub.py # REAL inference (GB models) + mapping
│ │ ├─ coordinator.py # Merge agents into plan (≤5, domain balance)
│ │ ├─ llm.py # Ollama client
│ │ └─ utils.py # DEFAULT_USER, tone, helpers
│ └─ agents/ # Agent runners (GD/NT/PA)
│ ├─ gd.py
│ ├─ nt.py
│ └─ pa.py
├─ model/ # Training artifacts & weights
│ ├─ mpl_model.py # Training script (reference)
│ ├─ weights/ # *.pkl GB models (global/kidney/cardio)
│ ├─ data/ # *healthy_* datasets for scaler fit
│ └─ data_cleaning/ # Data cleaning & population construction scripts
├─ thulth_logo.png # Branding
└─ README.md # This file
Requirements: Python 3.10+, virtualenv
cd server
python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -r <(python - <<'PY'
from tomllib import load
import sys; import pathlib
p = pathlib.Path('pyproject.toml')
print("\n".join(load(p.open('rb'))['project']['dependencies']))
PY
)
# or install manually: fastapi uvicorn pydantic requests pandas numpy scikit-learn joblib scipy
python -m uvicorn main:app --reload --port 8000
Health checks
Requirements: Node 18+, Expo CLI
cd app
npm i
npm run start
# iOS sim: press i | Android: a | Web: w
If running on a device, point the app’s API base (app/src/api/client.ts) to your machine IP instead of localhost.
brew install watchman) or raise ulimit -n 8192.npm i @react-navigation/bottom-tabs @react-navigation/native @react-navigation/native-stack react-native-safe-area-context react-native-screens then npx expo start --clear.python -m pip install uvicorn.The model/data_cleaning/ scripts generate the healthy / nonhealthy populations used for model pre‑fit, fine‑tuning, and testing.
Pipeline (per script comments):
(value − mean) > 3 × sd for each test.Outputs
model/data/*_healthy_non_saudi.txt — used to fit StandardScaler (global/cardio/kidney)model/data/*_healthy_saudi.txt — fine‑tuning splitmodel/data/*_nonhealthy_saudi.txt — held‑out evaluationReproducibility (example)
cd model/data_cleaning
# 1) Merge + clean
python 01_merge_labs.py --input ./raw/ --out ../data/merged.tsv
# 2) Units harmonization
python 02_unit_harmonization.py --in ../data/merged.tsv --out ../data/merged_harmonized.tsv
# 3) Outlier removal (3*sd)
python 03_outlier_filter.py --in ../data/merged_harmonized.tsv --out ../data/filtered.tsv --z 3.0
# 4) Healthy/nonhealthy splits
python 04_define_populations.py --in ../data/filtered.tsv --healthy ../data/*_healthy_*.txt --nonhealthy ../data/*_nonhealthy_*.txt
Notes
Server uses the same feature names from mpl_model.py and maps API payload keys to them.
DISPLAY_NAME_MAP keys used by the model (subset):
M→0, F→1diastolic (from DBP)systolic (from SBP)Triglyceride_result_valueCholesterol..in.Serum.or.Plasma_result_valueCholesterol.in.HDL_result_valueHemoglobin.A1c._result_value (accepts HbA1c/HBA1C/A1C synonyms)Bilirubin.total.[Mass/volume].in.Serum.or.Plasma_result_valueAlbumin.[Mass/volume].in.Serum.or.Plasma_result_valueAspartate.aminotransferase.[Enzymatic.activity/volume].in.Serum.or.Plasma.by.With.P-5-P_result_valueCreatinine..in.Serum.or.Plasma_result_valueUric.acid.in.Serum.or.Plasma_result_valuePotassium.in.Serum.or.Plasma_result_value (K)Sodium.in.Serum.or.Plasma_result_value (Na)Thyroid.Stimulating.Hormone.[TSH]_result_valueWBC_result_valueavg_daily_stepsbmi (computed from height_cm, weight_kg)Models & columns
GLOBAL_COLS (~cardio‑metabolic + BMI)CARDIO_COLS (BP, lipids, A1c)KIDNEY_COLS (creatinine, uric acid, Na/K)Scaling
StandardScaler per system on *_healthy_non_saudi.txt to match training distribution; missing features are filled using the training means.GET /health → { ok: true }GET /logo.png → brandingPOST /predict/run → PredictionOut
whole.bio_age (Global)organs.cardio and organs.kidney values and drivers (top importances)ari (aging rate index) from bio‑age gapPOST /agent/gd | /agent/nt | /agent/pa → AgentResponse (Ollama backed with resilient fallbacks)POST /agent/route → CoordinatorOut (≤5 items, ≥1 per domain, Impact×Ease ordering)Environment (optional)
OLLAMA_HOST (default http://localhost:11434)OLLAMA_MODEL (default llama3.1:8b)Prompts were engineered for empathy, brevity, and transparency; if prediction is missing, agents use DEFAULT_USER + fallbacks.
Internationalization & RTL: AR/EN with I18nProvider and Dubai font
Theming: theme.ts primaryAccent + card style
Persistence: AsyncStorage for last result/plan, BA history, steps, etc.
npm i @react-navigation/bottom-tabs + npx expo start --clearbrew install watchman or ulimit -n 8192source server/.venv/bin/activate then python -m uvicorn main:app --reload --port 8000If you need help wiring a new data source or extending the plan logic, open an issue with sample payloads and desired UX.