chilicareAI / app.py
feryms's picture
update docker
1e384db
import streamlit as st
import requests
from PIL import Image
import io
import base64
# URL untuk kedua endpoint FastAPI
# API_DETECT_URL = "http://localhost:8000/detect"
# API_ASK_URL = "http://localhost:8000/ask"
API_DETECT_URL = "http://backend:8000/detect"
API_ASK_URL = "http://backend:8000/ask"
st.set_page_config(page_title="ChiliCare AI", page_icon="🌶️", layout="centered")
# === MEMBUAT SIDEBAR NAVIGASI ===
st.sidebar.title("🌶️ Menu ChiliCare")
st.sidebar.markdown("Pilih fitur yang ingin Anda gunakan:")
menu = st.sidebar.radio(
"====",
["📷 Deteksi Penyakit (Gambar)", "🤖 Chatbot (Teks)"]
)
# === HALAMAN 1: DETEKSI PENYAKIT (GAMBAR) ===
if menu == "📷 Deteksi Penyakit (Gambar)":
st.title("🌶️🌿 Deteksi Penyakit Daun Cabai")
st.write("Unggah foto daun cabai yang sakit untuk mendapatkan diagnosis dan solusinya.")
uploaded_file = st.file_uploader("Unggah gambar daun cabai anda", type=["jpg", "jpeg", "png"])
if uploaded_file is not None:
original_image = Image.open(uploaded_file)
# st.image(original_image, caption="Gambar yang Diupload", use_container_width=True)
files = {"file": (uploaded_file.name, uploaded_file.getvalue(), uploaded_file.type)}
try:
with st.spinner("Memproses gambar dengan YOLOv11..."):
response = requests.post(API_DETECT_URL, files=files)
if response.status_code == 200:
data = response.json()
if "image_base64" in data:
image_bytes = base64.b64decode(data["image_base64"])
annotated_image = Image.open(io.BytesIO(image_bytes))
st.image(annotated_image, caption="Hasil Analisis YOLO", use_container_width=True)
st.subheader("📋 Hasil Diagnosis: ")
if data.get("total_detections", 0) > 0:
for item in data["results"]:
st.markdown(f"### 🦠 {item['class']} (Keyakinan: {item['confidence']:.0%})")
st.info(f"**Saran Penanganan:**\n\n{item['narrative']}")
else:
st.success("Tidak ada penyakit yang terdeteksi. Daun tampak sehat!")
else:
st.error(f"Gagal memproses gambar. Error: {response.status_code}")
except requests.exceptions.ConnectionError:
st.error("Gagal terhubung ke server FastAPI. Pastikan backend sudah berjalan.")
# === HALAMAN 2: TANYA AHLI (TEKS) ===
elif menu == "🤖 Chatbot (Teks)":
st.title("🤖 Chatbot Ahli Cabai")
st.write("Tanyakan seputar perawatan, penyakit, atau pupuk cabai. Saya siap membantu!")
# 1. Inisialisasi memori obrolan (session state)
if "messages" not in st.session_state:
st.session_state.messages = []
# 2. Tampilkan riwayat chat sebelumnya agar tidak hilang saat halaman direfresh
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# 3. Kolom input untuk user menggunakan gaya chat
if prompt := st.chat_input("Tulis pertanyaan Anda di sini... (misal: Kapan waktu panen cabai?)"):
# Tampilkan pesan user di layar
with st.chat_message("user"):
st.markdown(prompt)
# Simpan pesan user ke memori
st.session_state.messages.append({"role": "user", "content": prompt})
# Siapkan tempat untuk jawaban AI
with st.chat_message("assistant"):
with st.spinner("Berpikir dan mencari referensi..."):
try:
# KITA KIRIM REQUEST KE FASTAPI (Bukan panggil chain lokal)
payload = {"question": prompt}
response = requests.post(API_ASK_URL, json=payload)
if response.status_code == 200:
data = response.json()
jawaban = data["answer"]
# Tampilkan jawaban dari FastAPI/LLM
st.markdown(jawaban)
# Simpan jawaban ke memori
st.session_state.messages.append({"role": "assistant", "content": jawaban})
else:
error_msg = f"Gagal mendapatkan jawaban. Error: {response.status_code}"
st.error(error_msg)
st.session_state.messages.append({"role": "assistant", "content": error_msg})
except requests.exceptions.ConnectionError:
error_msg = "Gagal terhubung ke server FastAPI. Pastikan backend sudah berjalan."
st.error(error_msg)
st.session_state.messages.append({"role": "assistant", "content": error_msg})
st.sidebar.markdown("---")
st.sidebar.markdown("""
# Spesifikasi Model AI
**1. Vision (Deteksi Penyakit)**
* Model: `YOLOv11s` (Small)
* Framework: `Ultralytics`
**2. Retrieval-Augmented Generation (RAG)**
* Vector Database: `ChromaDB`
* Embedding: `Qwen3-Embedding-0.6B`
**3. Large Language Model (LLM)**
* Model: `Nvidia Nemotron-3 120B`
* Provider: `OpenRouter`
""")
st.sidebar.markdown("---")
st.sidebar.caption("© 2026 ChiliCare AI Engineer Portfolio")