Spaces:
Running
Running
| 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") |