| """ |
| Expert System - Treatment Berdasarkan Deteksi YOLO |
| Berdasarkan Tabel 1 PERDOSKI 2024 |
| |
| Prinsip: |
| 1. Tampilkan SEMUA treatment untuk setiap jenis jerawat yang terdeteksi |
| 2. Derajat menentukan intensitas (topikal saja β topikal+oral β oral sistemik) |
| 3. Nodul = selalu rujuk dokter |
| |
| Input: |
| - detected_classes: list jenis jerawat dari YOLO (e.g. ["comedone", "papules"]) |
| - severity_level: "clear" | "mild" | "moderate" | "severe" |
| """ |
|
|
| VALID_SKIN_TYPES = ["berminyak", "kering", "sensitif", "kombinasi"] |
|
|
| SEVERITY_TO_DEGREE = { |
| "clear": "bersih", |
| "mild": "ringan", |
| "moderate": "sedang", |
| "severe": "berat", |
| } |
|
|
| |
| |
| |
| |
|
|
| PER_LESION_TREATMENT = { |
| "comedone": { |
| "lesion": "Komedo", |
| "description": "Penyumbatan pori-pori, belum meradang", |
| "topical": { |
| "mild": { |
| "products": [ |
| "Retinoic Acid / Adapalene 0.1% (malam)", |
| "Salicylic Acid / BHA 2% (pagi atau malam)", |
| "Azelaic Acid 15-20% (alternatif)", |
| ], |
| "usage": "Gunakan salah satu, oleskan tipis pada area komedo", |
| }, |
| "moderate": { |
| "products": [ |
| "Adapalene 0.1% (malam) + Benzoyl Peroxide 2.5% (pagi)", |
| "Salicylic Acid 2% + Niacinamide (pagi)", |
| ], |
| "usage": "Kombinasikan retinoid (malam) dengan BPO/SA (pagi)", |
| }, |
| "severe": { |
| "products": [ |
| "Adapalene 0.3% atau Tretinoin (malam, resep dokter)", |
| "Benzoyl Peroxide 5% (pagi)", |
| ], |
| "usage": "Konsultasi dokter untuk resep yang sesuai", |
| }, |
| }, |
| "contraindications": [ |
| "Retinoid: tidak untuk ibu hamil", |
| "Hindari paparan UV langsung setelah pakai retinoid", |
| ], |
| }, |
| "papules": { |
| "lesion": "Papula", |
| "description": "Jerawat merah, meradang, tanpa nanah", |
| "topical": { |
| "mild": { |
| "products": [ |
| "Niacinamide 4-5% (pagi, anti-inflamasi)", |
| "Benzoyl Peroxide 2.5% (malam, antibakteri)", |
| "Azelaic Acid 15-20% (alternatif)", |
| ], |
| "usage": "Niacinamide pagi untuk menenangkan, BPO malam untuk bakteri", |
| }, |
| "moderate": { |
| "products": [ |
| "Benzoyl Peroxide 2.5-5% (pagi)", |
| "Adapalene 0.1% (malam)", |
| "Clindamycin topikal 1% + BPO (kombinasi)", |
| ], |
| "usage": "BPO pagi, retinoid malam. Antibiotik topikal harus dengan BPO", |
| }, |
| "severe": { |
| "products": [ |
| "Benzoyl Peroxide 5% (pagi)", |
| "Adapalene 0.3% (malam, resep dokter)", |
| "Injeksi triamsinolon acetonide (untuk papul besar)", |
| ], |
| "usage": "Konsultasi dokter untuk injeksi jika perlu", |
| }, |
| }, |
| "contraindications": [ |
| "Jangan gunakan antibiotik topikal sebagai terapi tunggal", |
| "Kombinasikan selalu dengan BPO atau retinoid", |
| ], |
| }, |
| "pustules": { |
| "lesion": "Pustula", |
| "description": "Jerawat bernanah, meradang dengan nanah di puncak", |
| "topical": { |
| "mild": { |
| "products": [ |
| "Benzoyl Peroxide 2.5% (malam, antibakteri)", |
| "Niacinamide 4-5% (pagi, anti-inflamasi)", |
| "Pimple patch / hydrocolloid patch (untuk satu per satu)", |
| ], |
| "usage": "BPO untuk area luas, patch untuk pustula individual", |
| }, |
| "moderate": { |
| "products": [ |
| "Benzoyl Peroxide 2.5-5% (pagi)", |
| "Adapalene 0.1% (malam)", |
| "Clindamycin topikal 1% + BPO (kombinasi)", |
| ], |
| "usage": "Jangan pecahkan pustula sendiri. BPO + retinoid untuk peradangan", |
| }, |
| "severe": { |
| "products": [ |
| "Benzoyl Peroxide 5% (pagi)", |
| "Adapalene 0.3% (malam, resep dokter)", |
| "Injeksi triamsinolon (untuk pustul besar/nyeri)", |
| ], |
| "usage": "Konsultasi dokter, hindari ekstraksi mandiri", |
| }, |
| }, |
| "contraindications": [ |
| "JANGAN pecahkan pustula sendiri β risiko infeksi dan skar", |
| "Hindari produk iritatif pada area pustul", |
| ], |
| }, |
| "nodules": { |
| "lesion": "Nodul", |
| "description": "Jerawat dalam, keras, nyeri, peradangan mendalam", |
| "requires_doctor": True, |
| "doctor_referral": ( |
| "NODUL MEMBUTUHKAN DOKTER:\n" |
| "Jerawat nodul melibatkan peradangan mendalam yang TIDAK bisa diatasi mandiri.\n" |
| "Segera kunjungi dokter spesialis kulit untuk:\n" |
| "1. Injeksi triamsinolon acetonide 2-5 mg/ml\n" |
| "2. Isotretinoin oral 1-2 mg/kg/hari\n" |
| "3. Antibiotik oral (doksisiklin/minosiklin)\n" |
| "4. Ekstraksi/insisi jika terbentuk abses\n\n" |
| "SELAMA MENUNGGU DOKTER:\n" |
| "- Jangan memencet atau mencoba ekstraksi sendiri\n" |
| "- Gunakan kompres dingin untuk meredakan nyeri\n" |
| "- Jaga kebersihan wajah, hindari produk berat" |
| ), |
| "contraindications": [ |
| "JANGAN memencet nodul", |
| "JANGAN mencoba ekstraksi sendiri", |
| "JANGAN menggunakan produk tanpa resep dokter", |
| ], |
| }, |
| } |
|
|
| |
| |
| |
| |
|
|
| ORAL_TREATMENT = { |
| "ringan": { |
| "oral": False, |
| "note": "Tidak perlu antibiotik oral. Fokus pada perawatan topikal.", |
| }, |
| "sedang": { |
| "oral": True, |
| "products": [ |
| "Doxycycline 2x100mg/hari (pilihan utama)", |
| "Eritromisin 2x500mg/hari (alternatif, aman untuk hamil)", |
| ], |
| "note": ( |
| "ANTIBIOTIK ORAL:\n" |
| "- Doxycycline: hindari paparan UV, minum dengan air putih banyak\n" |
| "- Eritromisin: alternatif untuk ibu hamil\n" |
| "- Batasi durasi <12 minggu\n" |
| "- Jangan gunakan sebagai terapi tunggal" |
| ), |
| }, |
| "berat": { |
| "oral": True, |
| "products": [ |
| "Azitromisin 500mg 3x/minggu (alternatif antibiotik)", |
| "Antiandrogen / Cyproterone acetate 50-100mg/hari (perempuan)", |
| "Isotretinoin 0.5-1mg/kg/hari (laki-laki, resep dokter)", |
| ], |
| "note": ( |
| "ORAL SISTEMIK:\n" |
| "- Perempuan: Antiandrogen (butuh kontrasepsi)\n" |
| "- Laki-laki: Isotretinoin (hindari sumbang sperma)\n" |
| "- HARUS dengan pengawasan dokter\n" |
| "- Evaluasi fungsi hati sebelum dan selama terapi" |
| ), |
| "contraindications": [ |
| "Isotretinoin: TERATOGAN", |
| "Antiandrogen: tidak untuk laki-laki", |
| ], |
| }, |
| } |
|
|
| |
| |
| |
|
|
| DAILY_SKINCARE = { |
| "berminyak": { |
| "facial_wash": {"name": "Facial Wash Gel/Foam", "ingredients": "Tea tree, salicylic acid, niacinamide", "usage": "2x sehari"}, |
| "moisturizer": {"name": "Moisturizer Oil-Free", "ingredients": "Hyaluronic acid, niacinamide, aloe vera", "usage": "2x sehari"}, |
| "sunscreen": {"name": "Sunscreen SPF 30+ (Gel/Air)", "ingredients": "SPF 30-50, PA+++", "usage": "Pagi, reapply tiap 2-3 jam"}, |
| }, |
| "kering": { |
| "facial_wash": {"name": "Facial Wash Cream/Milk", "ingredients": "Ceramide, glycerin, centella asiatica", "usage": "2x sehari"}, |
| "moisturizer": {"name": "Moisturizer Hydrating", "ingredients": "Ceramide, hyaluronic acid, squalane", "usage": "2x sehari"}, |
| "sunscreen": {"name": "Sunscreen SPF 30+ (Melembapkan)", "ingredients": "SPF 30-50, PA+++, hyaluronic acid", "usage": "Pagi, reapply tiap 2-3 jam"}, |
| }, |
| "sensitif": { |
| "facial_wash": {"name": "Facial Wash Gentle", "ingredients": "Centella asiatica, panthenol, allantoin", "usage": "2x sehari"}, |
| "moisturizer": {"name": "Moisturizer Calming", "ingredients": "Aloe vera, centella, madecassoside", "usage": "2x sehari"}, |
| "sunscreen": {"name": "Sunscreen SPF 30+ (Mineral)", "ingredients": "Zinc oxide / titanium dioxide", "usage": "Pagi, reapply tiap 2-3 jam"}, |
| }, |
| "kombinasi": { |
| "facial_wash": {"name": "Facial Wash Gentle Foam", "ingredients": "Glycerin, niacinamide ringan, centella", "usage": "2x sehari"}, |
| "moisturizer": {"name": "Moisturizer Gel-Cream", "ingredients": "Hyaluronic acid, niacinamide, aloe vera", "usage": "2x sehari"}, |
| "sunscreen": {"name": "Sunscreen SPF 30+ (Ringan)", "ingredients": "SPF 30-50, PA+++, formula gel", "usage": "Pagi, reapply tiap 2-3 jam"}, |
| }, |
| } |
|
|
| |
| |
| |
|
|
| LIFESTYLE_FACTORS = [ |
| {"factor": "Cuci Wajah", "description": "2x sehari dengan sabun pH balanced, bebas alkohol", "importance": "wajib"}, |
| {"factor": "Kosmetik", "description": "Hindari kosmetik oklusif (menyumbat pori)", "importance": "wajib"}, |
| {"factor": "Pelembap & Sunscreen", "description": "Gunakan sesuai tipe kulit, non-comedogenic", "importance": "wajib"}, |
| {"factor": "Diet Glikemik", "description": "Batasi karbohidrat olahan, makanan berlemak, produk olahan susu", "importance": "disarankan"}, |
| {"factor": "Stres", "description": "Kelola stres, baik pemicu maupun akibat jerawat", "importance": "disarankan"}, |
| {"factor": "Obat-obatan", "description": "Hindari steroid anabolik, kortikosteroid, litium, vit B6/B12 berlebih", "importance": "wajib"}, |
| {"factor": "Pemencetan", "description": "JANGAN memencet jerawat, terutama nodul dan pustul", "importance": "wajib"}, |
| ] |
|
|
|
|
| def get_expert_recommendation( |
| detected_classes: list, |
| summary: dict, |
| skin_type: str, |
| severity_level: str, |
| ) -> dict: |
| """ |
| Kembalikan treatment untuk SETIAP jenis jerawat yang terdeteksi. |
| |
| Returns: |
| dict berisi: |
| - per_lesion: list treatment untuk setiap jenis jerawat |
| - oral_treatment: rekomendasi oral berdasarkan derajat |
| - daily_skincare: perawatan harian berdasarkan tipe kulit |
| - lifestyle_factors: faktor gaya hidup |
| """ |
| if skin_type not in VALID_SKIN_TYPES: |
| skin_type = "berminyak" |
|
|
| degree = SEVERITY_TO_DEGREE.get(severity_level, "ringan") |
|
|
| |
| per_lesion = [] |
| has_nodul = False |
|
|
| for cls in detected_classes: |
| if cls in PER_LESION_TREATMENT: |
| lesion_info = PER_LESION_TREATMENT[cls] |
|
|
| |
| if cls == "nodules": |
| has_nodul = True |
| per_lesion.append({ |
| "class": cls, |
| "lesion": lesion_info["lesion"], |
| "description": lesion_info["description"], |
| "requires_doctor": True, |
| "doctor_referral": lesion_info["doctor_referral"], |
| "contraindications": lesion_info.get("contraindications", []), |
| }) |
| else: |
| |
| topical = lesion_info.get("topical", {}) |
| severity_key = degree if degree in topical else "mild" |
| topical_info = topical.get(severity_key, {}) |
|
|
| per_lesion.append({ |
| "class": cls, |
| "lesion": lesion_info["lesion"], |
| "description": lesion_info["description"], |
| "products": topical_info.get("products", []), |
| "usage": topical_info.get("usage", ""), |
| "contraindications": lesion_info.get("contraindications", []), |
| }) |
|
|
| |
| oral = ORAL_TREATMENT.get(degree, ORAL_TREATMENT["ringan"]) |
|
|
| |
| skincare = DAILY_SKINCARE.get(skin_type, DAILY_SKINCARE["berminyak"]) |
|
|
| return { |
| "degree": degree, |
| "severity_level": severity_level, |
| "per_lesion": per_lesion, |
| "oral_treatment": oral, |
| "daily_skincare": skincare, |
| "lifestyle_factors": LIFESTYLE_FACTORS, |
| "has_nodul": has_nodul, |
| } |
|
|