Randi-Palguna commited on
Commit
79ab3a4
ยท
1 Parent(s): 20c42f1

feat: backward chaining

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +104 -62
src/streamlit_app.py CHANGED
@@ -46,9 +46,7 @@ PRODUCTION_RULES = [
46
  {"disease": "Bakteri Daun Bergaris (Bacterial Leaf Streak)", "symptoms": ["G4", "G5"], "source": "Literatur 1"},
47
  {"disease": "Blas (Blast)", "symptoms": ["G6", "G7", "G8"], "source": "Literatur 1"},
48
  {"disease": "Tungro", "symptoms": ["G9"], "source": "Literatur 1"},
49
-
50
  {"disease": "Hawar Daun Bakteri (Bacterial Leaf Blight)", "symptoms": ["G10", "G11", "G12", "G13"], "source": "Literatur 2"},
51
-
52
  {"disease": "Bercak Daun Coklat (Brown Spot)", "symptoms": ["G14", "G15", "G16"], "source": "Literatur 3"},
53
  {"disease": "Hawar Pelepah (Sheath Blight)", "symptoms": ["G17", "G18", "G19"], "source": "Literatur 3"},
54
  ]
@@ -63,94 +61,138 @@ def load_model():
63
 
64
  model = load_model()
65
 
66
- st.title("๐ŸŒพ Rice Doctor: Sistem Pakar Penyakit Padi")
67
  st.markdown("""
68
- 1. **Inferensi AI**: Mendeteksi penyakit dari gambar.
69
- 2. **Sistem Pakar**: Memverifikasi diagnosis menggunakan logika Forward Chaining.
 
 
70
  """)
71
 
 
 
72
  if 'prediction' not in st.session_state:
73
- st.session_state['prediction'] = None
74
- if 'priority_codes' not in st.session_state:
75
- st.session_state['priority_codes'] = []
76
- if 'analyzed' not in st.session_state:
77
- st.session_state['analyzed'] = False
78
 
79
- uploaded_file = st.file_uploader("Langkah 1: Unggah Gambar Daun", type=["jpg", "png", "jpeg"])
 
80
 
81
- if uploaded_file is not None:
82
- image = Image.open(uploaded_file)
83
- st.image(image, caption="Gambar yang Diunggah", width=300)
84
-
85
- if st.button("Analisis Penyakit", type="primary"):
86
- if model:
87
- with st.spinner("Menganalisis..."):
88
- results = model.predict(image, imgsz=640)
89
- raw_name = results[0].names[results[0].probs.top1]
90
- top_class_name = raw_name.lower().strip()
91
-
92
- st.session_state['prediction'] = top_class_name
93
- st.session_state['priority_codes'] = YOLO_PROMPTS.get(top_class_name, [])
94
- st.session_state['analyzed'] = True
95
-
96
- st.rerun()
97
 
98
- if st.session_state['analyzed']:
99
  st.divider()
100
- st.subheader("Langkah 2: Verifikasi Gejala")
101
 
102
- pred = st.session_state['prediction']
103
- codes = st.session_state['priority_codes']
104
 
105
- st.info(f"๐Ÿ” **Prediksi AI:** `{pred}`")
 
106
 
107
  if not codes:
108
- st.warning("Tidak ada pertanyaan verifikasi khusus untuk penyakit ini. Silakan periksa **Basis Pengetahuan Lengkap** di bawah ini.")
 
 
 
109
  else:
110
- st.write("Silakan verifikasi diagnosis ini dengan menjawab gejala spesifik di bawah ini:")
111
-
112
- user_answers = {}
113
- for code in codes:
114
- question = SYMPTOM_QUESTIONS.get(code, "Unknown")
115
- ans = st.radio(
116
- f"**({code})** {question}",
117
- options=["Tidak", "Ya"],
118
- index=0,
119
- key=f"q_{code}"
120
- )
121
- if ans == "Ya":
122
- user_answers[code] = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
 
124
  st.divider()
125
- st.markdown("**Apakah ada gejala lain?**")
 
 
126
 
127
  all_symptoms_list = [f"{k}: {v}" for k,v in SYMPTOM_QUESTIONS.items()]
128
- other_checks = st.multiselect("Basis Pengetahuan Lengkap", all_symptoms_list)
129
 
130
- for item in other_checks:
131
- code = item.split(":")[0].strip()
132
- user_answers[code] = True
133
-
134
- if st.button("Langkah 3: Jalankan Forward Chaining", type="primary"):
135
- user_facts = set(user_answers.keys())
 
 
 
 
 
 
 
136
 
137
- if not user_facts:
138
- st.error("**Tidak Meyakinkan:** Anda memilih 'Tidak' untuk semuanya.")
139
  else:
140
  matches = []
141
  for rule in PRODUCTION_RULES:
142
  required = set(rule['symptoms'])
143
- if required.issubset(user_facts):
144
  matches.append(rule)
145
 
146
  if matches:
147
- st.success("**Penyakit Terkonfirmasi!**")
148
  for m in matches:
149
  st.markdown(f"""
 
150
  ### {m['disease']}
151
- - **Source:** {m['source']}
152
- - **Logic:** Found all required symptoms {m['symptoms']}
153
  """)
154
  else:
155
- st.error("**Tidak Ditemukan Kecocokan Pasti**")
156
- st.write("Gejala yang Anda pilih tidak sepenuhnya sesuai dengan aturan ketat mana pun dalam basis pengetahuan.")
 
 
 
 
 
 
46
  {"disease": "Bakteri Daun Bergaris (Bacterial Leaf Streak)", "symptoms": ["G4", "G5"], "source": "Literatur 1"},
47
  {"disease": "Blas (Blast)", "symptoms": ["G6", "G7", "G8"], "source": "Literatur 1"},
48
  {"disease": "Tungro", "symptoms": ["G9"], "source": "Literatur 1"},
 
49
  {"disease": "Hawar Daun Bakteri (Bacterial Leaf Blight)", "symptoms": ["G10", "G11", "G12", "G13"], "source": "Literatur 2"},
 
50
  {"disease": "Bercak Daun Coklat (Brown Spot)", "symptoms": ["G14", "G15", "G16"], "source": "Literatur 3"},
51
  {"disease": "Hawar Pelepah (Sheath Blight)", "symptoms": ["G17", "G18", "G19"], "source": "Literatur 3"},
52
  ]
 
61
 
62
  model = load_model()
63
 
64
+ st.title("๐ŸŒพ Rice Doctor: Sistem Pakar Hibrida")
65
  st.markdown("""
66
+ Sistem ini menggunakan metode **Hybrid AI**:
67
+ 1. **Model AI (YOLO)** untuk memberikan hipotesis awal.
68
+ 2. **Backward Chaining** untuk memverifikasi hipotesis tersebut.
69
+ 3. **Forward Chaining** untuk mencari diagnosis alternatif jika hipotesis salah.
70
  """)
71
 
72
+ if 'step' not in st.session_state:
73
+ st.session_state.step = 1
74
  if 'prediction' not in st.session_state:
75
+ st.session_state.prediction = None
76
+ if 'hypothesis_codes' not in st.session_state:
77
+ st.session_state.hypothesis_codes = []
78
+ if 'user_facts' not in st.session_state:
79
+ st.session_state.user_facts = set()
80
 
81
+ if st.session_state.step == 1:
82
+ uploaded_file = st.file_uploader("Langkah 1: Unggah Gambar Daun", type=["jpg", "png", "jpeg"])
83
 
84
+ if uploaded_file is not None:
85
+ image = Image.open(uploaded_file)
86
+ st.image(image, caption="Gambar yang Diunggah", width=300)
87
+
88
+ if st.button("Analisis Gambar (AI Inference)", type="primary"):
89
+ if model:
90
+ with st.spinner("Model AI sedang menganalisis hipotesis..."):
91
+ results = model.predict(image, imgsz=640)
92
+ raw_name = results[0].names[results[0].probs.top1]
93
+ top_class_name = raw_name.lower().strip()
94
+
95
+ st.session_state.prediction = top_class_name
96
+ st.session_state.hypothesis_codes = YOLO_PROMPTS.get(top_class_name, [])
97
+ st.session_state.step = 2
98
+ st.rerun()
 
99
 
100
+ elif st.session_state.step == 2:
101
  st.divider()
102
+ st.subheader("Langkah 2: Backward Chaining (Verifikasi Hipotesis)")
103
 
104
+ pred = st.session_state.prediction
105
+ codes = st.session_state.hypothesis_codes
106
 
107
+ st.info(f"๐Ÿ” **Hipotesis AI:** `{pred}`")
108
+ st.write("Sistem sedang memverifikasi hipotesis ini menggunakan **Backward Chaining**.")
109
 
110
  if not codes:
111
+ st.warning("Model AI memprediksi kelas yang tidak memiliki aturan verifikasi spesifik atau 'Normal'.")
112
+ if st.button("Lanjut ke Pengecekan Manual (Forward Chaining)"):
113
+ st.session_state.step = 3
114
+ st.rerun()
115
  else:
116
+ st.write("Jawablah pertanyaan berikut untuk memverifikasi hipotesis:")
117
+
118
+ with st.form("backward_chaining_form"):
119
+ bc_answers = {}
120
+ for code in codes:
121
+ question = SYMPTOM_QUESTIONS.get(code, "Unknown")
122
+ ans = st.radio(
123
+ f"**({code})** {question}",
124
+ options=["Tidak", "Ya"],
125
+ index=0,
126
+ key=f"bc_{code}"
127
+ )
128
+ if ans == "Ya":
129
+ bc_answers[code] = True
130
+ else:
131
+ bc_answers[code] = False
132
+
133
+ submitted = st.form_submit_button("Verifikasi Hipotesis")
134
+
135
+ if submitted:
136
+ all_yes = all(bc_answers.values())
137
+
138
+ if all_yes:
139
+ st.success(f"โœ… **Diagnosis Terkonfirmasi: {pred}**")
140
+ st.markdown(f"Hipotesis Backward Chaining bernilai **BENAR**. Semua gejala untuk {pred} terpenuhi.")
141
+ if st.button("Mulai Ulang"):
142
+ st.session_state.step = 1
143
+ st.rerun()
144
+ else:
145
+ st.error("โŒ **Hipotesis Ditolak**")
146
+ st.write("Terdapat gejala yang tidak sesuai dengan hipotesis AI.")
147
+ st.session_state.user_facts = {k for k, v in bc_answers.items() if v}
148
+ st.session_state.step = 3
149
+ st.rerun()
150
 
151
+ elif st.session_state.step == 3:
152
  st.divider()
153
+ st.subheader("Langkah 3: Forward Chaining (Pencarian Fakta)")
154
+
155
+ st.warning("Karena hipotesis awal ditolak, sistem beralih ke **Forward Chaining** untuk mencari diagnosis yang paling cocok berdasarkan fakta-fakta yang ada.")
156
 
157
  all_symptoms_list = [f"{k}: {v}" for k,v in SYMPTOM_QUESTIONS.items()]
 
158
 
159
+ pre_selected = [f"{code}: {SYMPTOM_QUESTIONS[code]}" for code in st.session_state.user_facts if code in SYMPTOM_QUESTIONS]
160
+
161
+ other_checks = st.multiselect(
162
+ "Silakan pilih semua gejala yang terlihat pada tanaman:",
163
+ all_symptoms_list,
164
+ default=pre_selected
165
+ )
166
+
167
+ if st.button("Proses Diagnosis (Forward Chaining)", type="primary"):
168
+ final_facts = set()
169
+ for item in other_checks:
170
+ code = item.split(":")[0].strip()
171
+ final_facts.add(code)
172
 
173
+ if not final_facts:
174
+ st.error("Mohon pilih setidaknya satu gejala.")
175
  else:
176
  matches = []
177
  for rule in PRODUCTION_RULES:
178
  required = set(rule['symptoms'])
179
+ if required.issubset(final_facts):
180
  matches.append(rule)
181
 
182
  if matches:
183
+ st.success("โœ… **Hasil Forward Chaining Ditemukan!**")
184
  for m in matches:
185
  st.markdown(f"""
186
+ ---
187
  ### {m['disease']}
188
+ - **Sumber Aturan:** {m['source']}
189
+ - **Gejala Terpenuhi:** {', '.join(m['symptoms'])}
190
  """)
191
  else:
192
+ st.info("โ„น๏ธ **Tidak Ditemukan Diagnosis Pasti**")
193
+ st.write("Kombinasi gejala yang Anda pilih tidak cocok sepenuhnya dengan aturan penyakit manapun dalam basis pengetahuan.")
194
+
195
+ if st.button("Mulai Ulang Analisis"):
196
+ st.session_state.step = 1
197
+ st.session_state.user_facts = set()
198
+ st.rerun()