acne-api / backend /rules.py
ItsFarros's picture
Upload backend/rules.py with huggingface_hub
4b4bc2c verified
Raw
History Blame Contribute Delete
14.2 kB
"""
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
# Setiap jenis jerawat punya rekomendasi produknya sendiri
# ═══════════════════════════════════════════════════════════════════
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",
],
},
}
# ═══════════════════════════════════════════════════════════════════
# SEVERITY-BASED ORAL TREATMENT
# Ditambahkan berdasarkan derajat
# ═══════════════════════════════════════════════════════════════════
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",
],
},
}
# ═══════════════════════════════════════════════════════════════════
# LAYER 2: DAILY SKINCARE
# ═══════════════════════════════════════════════════════════════════
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"},
},
}
# ═══════════════════════════════════════════════════════════════════
# LAYER 3: LIFESTYLE FACTORS
# ═══════════════════════════════════════════════════════════════════
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")
# Kumpulkan treatment untuk setiap jenis jerawat yang terdeteksi
per_lesion = []
has_nodul = False
for cls in detected_classes:
if cls in PER_LESION_TREATMENT:
lesion_info = PER_LESION_TREATMENT[cls]
# Nodul selalu rujuk dokter
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:
# Ambil produk berdasarkan derajat
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 treatment berdasarkan derajat
oral = ORAL_TREATMENT.get(degree, ORAL_TREATMENT["ringan"])
# Daily skincare
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,
}