feryms commited on
Commit
faf22ac
·
1 Parent(s): cf43085

update chromaDB

Browse files
app.py CHANGED
@@ -5,7 +5,10 @@ import cv2
5
  import torch
6
  import tempfile
7
  import os
8
- from chains.rag import generate_narrative
 
 
 
9
 
10
 
11
  st.set_page_config(page_title="ourchamplie", layout="centered")
@@ -14,7 +17,7 @@ st.title("🌿Aplikasi Pendeteksi Penyakit Daun Cabai")
14
 
15
  @st.cache_resource
16
  def load_model():
17
- model = YOLO("model/best.pt")
18
  return model
19
 
20
  model = load_model()
@@ -22,7 +25,7 @@ uploaded_file = st.file_uploader("Unggah gambar daun cabai anda", type=["jpg", "
22
 
23
  if uploaded_file is not None:
24
  image = Image.open(uploaded_file)
25
- st.image(image, caption="Gambar yang Diupload", use_container_width=True)
26
 
27
  with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file:
28
  image.save(temp_file.name)
@@ -48,14 +51,14 @@ if uploaded_file is not None:
48
  detected_labels[label] = confidence
49
 
50
  for label, confidence in detected_labels.items():
51
- st.markdown(f"### 🌱 {label.capitalize()} (skor: {confidence:.2f})")
52
 
53
 
54
 
55
- with st.spinner("📖 Menyusun penjelasan..."):
56
  narrative = generate_narrative(label.capitalize())
57
 
58
- st.subheader("🧠 Penjelasan")
59
  st.write(narrative)
60
 
61
  os.remove(temp_path)
 
5
  import torch
6
  import tempfile
7
  import os
8
+ from src.chains.rag import generate_narrative
9
+
10
+ import logging
11
+ os.environ["TRANSFORMERS_VERBOSITY"] = "error"
12
 
13
 
14
  st.set_page_config(page_title="ourchamplie", layout="centered")
 
17
 
18
  @st.cache_resource
19
  def load_model():
20
+ model = YOLO("model/bestv11.pt")
21
  return model
22
 
23
  model = load_model()
 
25
 
26
  if uploaded_file is not None:
27
  image = Image.open(uploaded_file)
28
+ # st.image(image, caption="Gambar yang Diupload", use_container_width=True)
29
 
30
  with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file:
31
  image.save(temp_file.name)
 
51
  detected_labels[label] = confidence
52
 
53
  for label, confidence in detected_labels.items():
54
+ st.markdown(f"Hasil:{label.capitalize()} (skor: {confidence:.2f})")
55
 
56
 
57
 
58
+ with st.spinner("Menyusun penjelasan..."):
59
  narrative = generate_narrative(label.capitalize())
60
 
61
+ st.subheader("Penjelasan")
62
  st.write(narrative)
63
 
64
  os.remove(temp_path)
backend/api.py CHANGED
@@ -4,7 +4,7 @@ from ultralytics import YOLO
4
  from PIL import Image
5
  import io
6
  import uvicorn
7
- from chains.rag import generate_narrative
8
 
9
  app = FastAPI(
10
  title="ChiliCare API",
 
4
  from PIL import Image
5
  import io
6
  import uvicorn
7
+ from src.chains.rag import generate_narrative
8
 
9
  app = FastAPI(
10
  title="ChiliCare API",
chains/__pycache__/rag.cpython-312.pyc DELETED
Binary file (2.08 kB)
 
chains/rag.py DELETED
@@ -1,65 +0,0 @@
1
- import json
2
- import os
3
- from langchain_openai import ChatOpenAI
4
- from langchain_core.prompts import PromptTemplate
5
-
6
- # 1. Inisialisasi LLM
7
- llm = ChatOpenAI(
8
- base_url="https://openrouter.ai/api/v1",
9
- api_key=os.getenv("OPENROUTER_API_KEY"),
10
- model="nvidia/nemotron-3-nano-30b-a3b:free",
11
- temperature=0.6,
12
- max_tokens=1200
13
- )
14
-
15
- def retrieve_disease_info(disease_name):
16
- with open("data/data.json", "r", encoding="utf-8") as f:
17
- data = json.load(f)
18
- return data.get(disease_name)
19
-
20
- # 2. Setup Prompt Template
21
- prompt_template = PromptTemplate(
22
- input_variables=["disease_name", "penyebab", "gejala", "penanganan", "pencegahan"],
23
- template="""
24
- Anda adalah penyuluh pertanian cabai.
25
-
26
- Gunakan HANYA informasi berikut.
27
- Jangan menambahkan fakta baru.
28
-
29
- Nama penyakit: {disease_name}
30
-
31
- Penyebab:
32
- - {penyebab}
33
-
34
- Gejala:
35
- - {gejala}
36
-
37
- Penanganan:
38
- - {penanganan}
39
-
40
- Pencegahan:
41
- - {pencegahan}
42
-
43
- Gunakan bahasa sederhana untuk petani cabai.
44
- Jika penyakit adalah sehat, jelaskan bahwa daun dalam kondisi sehat.
45
- """
46
- )
47
-
48
- # 3. Gunakan LCEL (LangChain Expression Language) sebagai pengganti LLMChain
49
- chain = prompt_template | llm
50
-
51
- def generate_narrative(disease_name):
52
- info = retrieve_disease_info(disease_name)
53
- if not info:
54
- return "⚠️ Data penyakit tidak ditemukan."
55
-
56
- # 4. Gunakan .invoke() dan ambil kontennya
57
- response = chain.invoke({
58
- "disease_name": disease_name,
59
- "penyebab": "; ".join(info["penyebab"]),
60
- "gejala": "; ".join(info["gejala"]),
61
- "penanganan": "; ".join(info["penanganan"]),
62
- "pencegahan": "; ".join(info["pencegahan"]),
63
- })
64
-
65
- return response.content
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
chroma_data/1537bc7a-6565-4b48-abe9-26f5ab013a16/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:99acbc5e8493d5faef12f11e46065ecfc51823f6315e867c82b0fb04007dd629
3
+ size 423600
chroma_data/1537bc7a-6565-4b48-abe9-26f5ab013a16/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bf12d4486518c7addf488cb4854526902c78e91951990e1e2f4e055cec814e5d
3
+ size 100
chroma_data/1537bc7a-6565-4b48-abe9-26f5ab013a16/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d2ee7cb82599c809ee1967a459779fe297094941684fd31ae0805324957f654d
3
+ size 400
chroma_data/1537bc7a-6565-4b48-abe9-26f5ab013a16/link_lists.bin ADDED
File without changes
chroma_data/chroma.sqlite3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cc3087f1c4cb1a3a703aede6544460ab959e23ff06ade2caf7e0640565572ead
3
+ size 274432
db_setup.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ from langchain_core.documents import Document
4
+ from langchain_chroma import Chroma
5
+ from langchain_huggingface import HuggingFaceEmbeddings
6
+
7
+ JSON_FILE_PATH = "data/data.json"
8
+ CHROMA_DB_DIR = "chroma_data"
9
+
10
+ def main():
11
+ if not os.path.exists(JSON_FILE_PATH):
12
+ print(f"Error: File {JSON_FILE_PATH} not found.")
13
+ return
14
+
15
+ print("Reading JSON data...")
16
+ with open(JSON_FILE_PATH, "r", encoding="utf-8") as f:
17
+ chili_data = json.load(f)
18
+
19
+ # 3. Konversi ke Format Document LangChain
20
+ print("Converting nested JSON data into LangChain Document format")
21
+ documents = []
22
+
23
+ for label, details in chili_data.items():
24
+ teks_gabungan = f"Penyakit/Kondisi: {label}\n"
25
+
26
+ # Mengecek apakah list ada isinya, lalu digabung dengan newline
27
+ if details.get("penyebab"):
28
+ teks_gabungan += "Penyebab:\n- " + "\n- ".join(details["penyebab"]) + "\n"
29
+
30
+ if details.get("gejala"):
31
+ teks_gabungan += "Gejala:\n- " + "\n- ".join(details["gejala"]) + "\n"
32
+
33
+ if details.get("penanganan"):
34
+ teks_gabungan += "Penanganan:\n- " + "\n- ".join(details["penanganan"]) + "\n"
35
+
36
+ if details.get("pencegahan"):
37
+ teks_gabungan += "Pencegahan:\n- " + "\n- ".join(details["pencegahan"]) + "\n"
38
+
39
+ # Membungkus teks rakitan dan metadata (label yolo)
40
+ doc = Document(
41
+ page_content=teks_gabungan,
42
+ metadata={"label": label}
43
+ )
44
+ documents.append(doc)
45
+
46
+ # 4. Setup Embedding Model
47
+ print("Memuat Embedding Model (all-MiniLM-L6-v2)...")
48
+ embeddings = HuggingFaceEmbeddings(model_name="Qwen/Qwen3-Embedding-0.6B")
49
+
50
+ # 5. Simpan ke ChromaDB via LangChain
51
+ print("Menyimpan data ke ChromaDB...")
52
+ vectorstore = Chroma.from_documents(
53
+ documents=documents,
54
+ embedding=embeddings,
55
+ persist_directory=CHROMA_DB_DIR,
56
+ collection_name="chilicare_kb"
57
+ )
58
+ print(f"Berhasil! Database tersimpan di folder: {CHROMA_DB_DIR}\n")
59
+
60
+ # ==========================================
61
+ # --- TESTING HYBRID RETRIEVAL LANGCHAIN ---
62
+ # ==========================================
63
+ print("--- UJI COBA RETRIEVAL (LANGCHAIN) ---")
64
+
65
+ # Tes A: Jalur YOLO (Metadata Filter)
66
+ test_label = "Bercak" # Menguji label Bercak
67
+ print(f"\n[JALUR YOLO] Mencari data dengan filter label: '{test_label}'")
68
+
69
+ yolo_results = vectorstore.similarity_search(
70
+ query="berikan penjelasan lengkap",
71
+ k=1,
72
+ filter={"label": test_label}
73
+ )
74
+ if yolo_results:
75
+ print("✅ Ditemukan Data RAG (Cuplikan):")
76
+ # Print 200 karakter pertama agar terminal tidak terlalu penuh
77
+ print(f"{yolo_results[0].page_content[:200]}...")
78
+
79
+ # Tes B: Jalur Teks/Chat (Semantic Similarity Search)
80
+ test_query = "daunnya melengkung ke atas seperti mangkuk dan kaku"
81
+ print(f"\n[JALUR TEKS] User bertanya: '{test_query}'")
82
+
83
+ chat_results = vectorstore.similarity_search(query=test_query, k=1)
84
+ if chat_results:
85
+ label_terdeteksi = chat_results[0].metadata['label']
86
+ print(f"✅ Sistem menduga ini penyakit: '{label_terdeteksi}'")
87
+ print("📄 Cuplikan Penjelasan:")
88
+ print(f"{chat_results[0].page_content[:200]}...")
89
+
90
+ if __name__ == "__main__":
91
+ main()
src/chains/__pycache__/rag.cpython-312.pyc ADDED
Binary file (2.61 kB). View file
 
src/chains/rag.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from langchain_openai import ChatOpenAI
3
+ from langchain_core.prompts import PromptTemplate
4
+ from langchain_chroma import Chroma
5
+ from langchain_huggingface import HuggingFaceEmbeddings
6
+
7
+ # 1. Inisialisasi LLM (Tetap sama)
8
+ llm = ChatOpenAI(
9
+ base_url="https://openrouter.ai/api/v1",
10
+ api_key=os.getenv("OPENROUTER_API_KEY"),
11
+ model="nvidia/nemotron-3-nano-30b-a3b:free",
12
+ temperature=0.6,
13
+ max_tokens=1500
14
+ )
15
+
16
+ # 2. Koneksi ke ChromaDB Lokal
17
+ print("Memuat koneksi ke Database...")
18
+ embeddings = HuggingFaceEmbeddings(model_name="Qwen/Qwen3-Embedding-0.6B")
19
+ vectorstore = Chroma(
20
+ persist_directory="chroma_data", # Pastikan nama foldernya sama dengan di db_setup.py
21
+ embedding_function=embeddings,
22
+ collection_name="chilicare_kb"
23
+ )
24
+
25
+ # 3. Setup Prompt Template (Lebih Ringkas)
26
+ # Kita hanya butuh 'context' karena isi penyebab/gejala sudah dirakit oleh db_setup.py
27
+ prompt_template = PromptTemplate(
28
+ input_variables=["disease_name", "context"],
29
+ template="""
30
+ Anda adalah penyuluh pertanian cabai.
31
+
32
+ Gunakan HANYA informasi referensi berikut. Jangan menambahkan fakta baru di luar referensi.
33
+
34
+ --- REFERENSI DATABASE ---
35
+ {context}
36
+ --------------------------
37
+
38
+ Tugas:
39
+ Jelaskan tentang kondisi/penyakit "{disease_name}" berdasarkan referensi di atas.
40
+ Gunakan bahasa yang sederhana, ramah, dan mudah dipahami oleh petani cabai.
41
+ Jika kondisinya adalah "Sehat", berikan apresiasi dan jelaskan bahwa tanaman dalam kondisi prima(generate jika label gambar output adalah "sehat").
42
+ """
43
+ )
44
+
45
+ # 4. Buat Chain LCEL
46
+ chain = prompt_template | llm
47
+
48
+ # 5. Fungsi Generate Narrative Terintegrasi RAG
49
+ def generate_narrative(disease_name):
50
+ print(f"Mencari data untuk label: {disease_name}...")
51
+
52
+ # RETRIEVAL: Mengambil data dari ChromaDB menggunakan Metadata Filter (Jalur YOLO)
53
+ # Ini memastikan data yang ditarik 100% akurat sesuai label
54
+ results = vectorstore.similarity_search(
55
+ query="berikan penjelasan lengkap", # Query dummy karena kita mengandalkan filter
56
+ k=1,
57
+ filter={"label": disease_name}
58
+ )
59
+
60
+ if not results:
61
+ return f"⚠️ Data penyakit '{disease_name}' tidak ditemukan di database."
62
+
63
+ # Ambil teks referensi utuh dari hasil retrieval
64
+ retrieved_context = results[0].page_content
65
+
66
+ print("Data ditemukan. Menghasilkan narasi dengan LLM...")
67
+ # GENERATION: Kirim konteks dan nama penyakit ke LLM
68
+ response = chain.invoke({
69
+ "disease_name": disease_name,
70
+ "context": retrieved_context
71
+ })
72
+
73
+ return response.content
74
+
75
+ # --- TEST SCRIPT ---
76
+ if __name__ == "__main__":
77
+ # Pastikan OPENROUTER_API_KEY sudah tersetting di environment variables kamu
78
+ # Contoh penggunaan dari hasil output YOLO
79
+ label_yolo = "Keriting"
80
+ hasil = generate_narrative(label_yolo)
81
+
82
+ print("\n=== HASIL GENERATE ===")
83
+ print(hasil)