surfiniaburger commited on
Commit
f24b4d8
Β·
1 Parent(s): e4f78d3
Files changed (7) hide show
  1. agent_setup.py +46 -0
  2. app.py +26 -119
  3. app2.py +0 -247
  4. config.py +13 -0
  5. knowledge_base.md +20 -0
  6. knowledge_base.py +36 -0
  7. vision_model.py +26 -0
agent_setup.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from google.adk import Agent, Runner
2
+ from google.adk.sessions import InMemorySessionService
3
+ from tools import create_plant_diagnosis_tool, create_remedy_retrieval_tool
4
+
5
+ def initialize_adk(vision_model, processor, retriever):
6
+ """
7
+ Initializes the ADK agent, tools, and runner.
8
+
9
+ Args:
10
+ vision_model: The loaded vision model.
11
+ processor: The model's processor.
12
+ retriever: The RAG retriever.
13
+
14
+ Returns:
15
+ A dictionary containing the ADK components, or None on error.
16
+ """
17
+ print("Initializing ADK Tools and Agent...")
18
+ try:
19
+ if vision_model and processor and retriever:
20
+ diagnosis_tool = create_plant_diagnosis_tool(model=vision_model, processor=processor)
21
+ remedy_tool = create_remedy_retrieval_tool(retriever=retriever)
22
+
23
+ agent = Agent(
24
+ name="AuraMindGlowAgent",
25
+ model="gemini-2.5-flash",
26
+ description="A farming assistant that can diagnose plant health and suggest remedies.",
27
+ instruction="You are a friendly farming assistant. Your goal is to help users identify plant health issues and find solutions. Use your tools to diagnose the plant from an image and then find a remedy.",
28
+ tools=[diagnosis_tool, remedy_tool]
29
+ )
30
+
31
+ session_service = InMemorySessionService()
32
+ runner = Runner(agent=agent, app_name="AuraMindGlow", session_service=session_service)
33
+
34
+ print("βœ… ADK Agent and Runner initialized successfully!")
35
+ return {
36
+ "agent": agent,
37
+ "runner": runner,
38
+ "diagnosis_tool": diagnosis_tool,
39
+ "remedy_tool": remedy_tool
40
+ }
41
+ else:
42
+ print("❌ Skipping ADK setup due to errors in model or RAG loading.")
43
+ return None
44
+ except Exception as e:
45
+ print(f"❌ CRITICAL ERROR during ADK setup: {e}")
46
+ return None
app.py CHANGED
@@ -1,150 +1,54 @@
1
  # ==============================================================================
2
- # Aura Mind Glow - Main Application
3
  # ==============================================================================
4
  """
5
  This script launches the Aura Mind Glow application.
6
- It features two modes:
7
- 1. Field Mode (100% Offline): For quick diagnosis and remedy retrieval.
8
- 2. Connected Mode (Online): A conversational agent powered by the Google ADK.
9
  """
10
 
11
  # --- Step 0: Essential Imports ---
12
  import gradio as gr
13
- import torch
14
  from PIL import Image
15
  import os
16
  import warnings
17
  import socket
18
- import asyncio
19
  import tempfile
20
 
21
  # Suppress potential warnings for a cleaner console
22
  warnings.filterwarnings("ignore")
23
- os.environ["TORCH_COMPILE_DISABLE"] = "1" # Ensure torch compile is off
24
 
25
- # Unsloth and Transformers
26
- from unsloth import FastVisionModel
27
- from transformers import AutoProcessor
28
-
29
- # LangChain and RAG components
30
- from langchain_community.vectorstores import FAISS
31
- from langchain_community.document_loaders import TextLoader
32
- from langchain_huggingface import HuggingFaceEmbeddings
33
- from langchain.text_splitter import RecursiveCharacterTextSplitter
34
-
35
- # Google ADK
36
- from google.adk import Agent, Runner
37
- from google.adk.sessions import InMemorySessionService
38
- from google.genai import types
39
-
40
- # Custom Tools
41
- from tools import create_plant_diagnosis_tool, create_remedy_retrieval_tool
42
 
43
  print("βœ… All libraries imported successfully.")
44
 
45
- # --- Step 1: Global Setup - Vision Model and RAG ---
46
  # This expensive setup runs only ONCE when the application starts.
47
 
48
- print("Performing initial setup for Vision Model and RAG...")
49
- VISION_MODEL = None
50
- PROCESSOR = None
51
- RETRIEVER = None
52
- ADAPTER_PATH = "surfiniaburger/maize-health-diagnosis-adapter"
53
-
54
- try:
55
- # Load Vision Model
56
- VISION_MODEL, PROCESSOR = FastVisionModel.from_pretrained(
57
- model_name="unsloth/gemma-3n-E2B-it-unsloth-bnb-4bit",
58
- max_seq_length=2048,
59
- load_in_4bit=True,
60
- dtype=None,
61
- )
62
- FastVisionModel.for_inference(VISION_MODEL)
63
- VISION_MODEL.load_adapter(ADAPTER_PATH)
64
- print(f"βœ… Vision model and adapter '{ADAPTER_PATH}' loaded successfully!")
65
-
66
- # Build RAG Knowledge Base
67
- remedy_knowledge_text = """
68
- # Maize Health Guide
69
- ## Phosphorus Deficiency
70
- **Symptoms:** Plants are often stunted, dark green or purplish. This condition is sometimes called Purple leaf disease. The purplish discoloration is most evident on the tips of leaves of young plants.
71
- **Cause:** Lack of available phosphorus in the soil, often due to incorrect pH or cold soil temperatures.
72
- **Local Remedy:** Apply a high-phosphorus starter fertilizer at planting time. In organic systems, bone meal or rock phosphate are excellent sources. A foliar spray of a water-soluable phosphate fertilizer can be applied directly to the leaves for a quick, short-term fix. Ensure soil pH is between 6.0 and 7.0 for optimal phosphorus uptake.
73
- ## Nitrogen Deficiency
74
- **Symptoms:** General yellowing (chlorosis) of the plant, starting with the lower, older leaves in a distinct "V" shape that progresses up the midrib.
75
- **Cause:** Insufficient nitrogen in the soil, which is a mobile nutrient.
76
- **Local Remedy:** Side-dress with a nitrogen-rich fertilizer like urea, ammonium nitrate, or composted manure whenplants are about knee-high. For organic farming, blood meal or feather meal are effective sources.
77
- ## Leaf Spot
78
- **Symptoms:** Small, circular to oval spots with tan centers and dark borders on the leaves. This is a common fungal disease.
79
- **Cause:** Fungal pathogens that spread via water splash and wind.
80
- **Local Remedy:** Use resistant maize varieties if available. Apply appropriate fungicides if the infection is severe, following label directions. To prevent future outbreaks, improve air circulation by not overcrowding plants and destroy infected crop debris after harvest.
81
- ## Leaf Blight
82
- **Symptoms:** Large, irregular, grayish-green or tan lesions on the leaves, often appearing cigar-shaped. These lesions can grow and merge, leading to significant leaf death.
83
- **Cause:** Fungal pathogens that thrive in warm, humid conditions.
84
- **Local Remedy:** The primary defense is planting resistant hybrids. Fungicide applications may be necessary and should be timed based on disease scouting and weather forecasts. Crop rotation and tilling under infected residue can help reduce the pathogen for the next season.
85
- ## Healthy Plant
86
- **Symptoms:** Vigorous growth with lush, uniformly dark green leaves. No visible spots, lesions, or discoloration.
87
- **Local Remedy:** No remedy needed. Maintain good agricultural practices, including proper watering, fertilization, and pest management to keep the plant healthy.
88
- """
89
- with open("knowledge.txt", "w") as f:
90
- f.write(remedy_knowledge_text)
91
- loader = TextLoader("knowledge.txt")
92
- documents = loader.load()
93
- text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
94
- docs = text_splitter.split_documents(documents)
95
- embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
96
- db = FAISS.from_documents(docs, embeddings)
97
- RETRIEVER = db.as_retriever(search_kwargs={"k": 1})
98
- print("βœ… RAG knowledge base and retriever created successfully!")
99
-
100
- except Exception as e:
101
- print(f"❌ CRITICAL ERROR during global setup: {e}")
102
- pass
103
-
104
- # --- Step 2: Initialize ADK Tools and Agent ---
105
-
106
- print("Initializing ADK Tools and Agent...")
107
- DIAGNOSIS_TOOL = None
108
- REMEDY_TOOL = None
109
- ADK_AGENT = None
110
- ADK_RUNNER = None
111
- SESSION_SERVICE = None
112
-
113
- try:
114
- if VISION_MODEL and PROCESSOR and RETRIEVER:
115
- DIAGNOSIS_TOOL = create_plant_diagnosis_tool(model=VISION_MODEL, processor=PROCESSOR)
116
- REMEDY_TOOL = create_remedy_retrieval_tool(retriever=RETRIEVER)
117
-
118
- ADK_AGENT = Agent(
119
- name="AuraMindGlowAgent",
120
- model="gemini-2.5-flash",
121
- description="A farming assistant that can diagnose plant health and suggest remedies.",
122
- instruction="You are a friendly farming assistant. Your goal is to help users identify plant health issues and find solutions. Use your tools to diagnose the plant from an image and then find a remedy.",
123
- tools=[DIAGNOSIS_TOOL, REMEDY_TOOL]
124
- )
125
-
126
- SESSION_SERVICE = InMemorySessionService()
127
- ADK_RUNNER = Runner(agent=ADK_AGENT, app_name="AuraMindGlow", session_service=SESSION_SERVICE)
128
- print("βœ… ADK Agent and Runner initialized successfully!")
129
- else:
130
- print("❌ Skipping ADK setup due to errors in model or RAG loading.")
131
 
132
- except Exception as e:
133
- print(f"❌ CRITICAL ERROR during ADK setup: {e}")
134
- pass
 
 
135
 
136
 
137
  # --- Step 3: Define Gradio UIs ---
138
 
139
  def create_field_mode_ui():
140
  """Creates the Gradio UI for the offline Field Mode."""
141
-
142
  def get_diagnosis_and_remedy(uploaded_image: Image.Image) -> str:
143
  if uploaded_image is None:
144
  return "Please upload an image of a maize plant first."
145
  if RETRIEVER is None:
146
  raise gr.Error("Knowledge base is not loaded. Cannot find remedy. Check logs.")
147
-
148
  temp_file_path = None
149
  try:
150
  with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as temp_file:
@@ -158,7 +62,7 @@ def create_field_mode_ui():
158
  return f"Sorry, I couldn't identify the condition from the image. Raw output: {diagnosis}"
159
 
160
  remedy = REMEDY_TOOL(diagnosis)
161
-
162
  final_response = f"""
163
  ## Diagnosis Report
164
 
@@ -192,18 +96,19 @@ def create_field_mode_ui():
192
  outputs=gr.Markdown(label="Diagnosis and Remedy Report", value="The report will appear here..."),
193
  title="🌽 Aura Mind Glow: Field Mode (Offline)",
194
  description="**A 100% Offline-Capable Farming Assistant.** Upload an image of a maize plant. The AI will diagnose its condition and retrieve a treatment plan from its local knowledge base.",
195
- article="<p style='text-align: center;'>Built with Unsloth, LangChain, and Gradio. Version 1.3</p>",
196
  allow_flagging="never",
197
  theme=gr.themes.Soft(primary_hue="teal", secondary_hue="orange"),
198
  css=css
199
  )
200
 
 
201
  def create_connected_mode_ui():
202
  """Creates the Gradio UI for the online Connected Mode."""
203
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="green", secondary_hue="lime")) as demo:
204
  gr.Markdown("# 🌽 Aura Mind Glow: Connected Mode πŸ€–")
205
  gr.Markdown("I am an AI farming assistant. Upload an image to get started.")
206
-
207
  chatbot = gr.Chatbot()
208
  msg = gr.MultimodalTextbox(file_types=["image"], label="Upload an image for diagnosis")
209
 
@@ -222,9 +127,10 @@ def create_connected_mode_ui():
222
  return history, gr.MultimodalTextbox(value=None)
223
 
224
  msg.submit(respond, [msg, chatbot], [chatbot, msg])
225
-
226
  return demo
227
 
 
228
  # --- Step 4: App Launcher ---
229
 
230
  def check_internet_connection(host="8.8.8.8", port=53, timeout=3):
@@ -236,6 +142,7 @@ def check_internet_connection(host="8.8.8.8", port=53, timeout=3):
236
  except socket.error:
237
  return False
238
 
 
239
  if __name__ == "__main__":
240
  if check_internet_connection() and ADK_RUNNER:
241
  print("βœ… Internet connection detected. Launching Connected Mode.")
@@ -243,5 +150,5 @@ if __name__ == "__main__":
243
  else:
244
  print("❌ No internet connection or ADK setup failed. Launching Field Mode (Offline).")
245
  ui = create_field_mode_ui()
246
-
247
- ui.launch(share=True, debug=True)
 
1
  # ==============================================================================
2
+ # Aura Mind Glow - Main Application (Refactored)
3
  # ==============================================================================
4
  """
5
  This script launches the Aura Mind Glow application.
 
 
 
6
  """
7
 
8
  # --- Step 0: Essential Imports ---
9
  import gradio as gr
 
10
  from PIL import Image
11
  import os
12
  import warnings
13
  import socket
 
14
  import tempfile
15
 
16
  # Suppress potential warnings for a cleaner console
17
  warnings.filterwarnings("ignore")
18
+ os.environ["TORCH_COMPILE_DISABLE"] = "1" # Ensure torch compile is off
19
 
20
+ # --- Step 1: Import Core Components from Modules ---
21
+ from vision_model import load_vision_model
22
+ from knowledge_base import get_retriever
23
+ from agent_setup import initialize_adk
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  print("βœ… All libraries imported successfully.")
26
 
27
+ # --- Step 2: Global Initialization ---
28
  # This expensive setup runs only ONCE when the application starts.
29
 
30
+ print("Performing initial setup...")
31
+ VISION_MODEL, PROCESSOR = load_vision_model()
32
+ RETRIEVER = get_retriever()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
+ # Initialize ADK components
35
+ adk_components = initialize_adk(VISION_MODEL, PROCESSOR, RETRIEVER)
36
+ ADK_RUNNER = adk_components["runner"] if adk_components else None
37
+ DIAGNOSIS_TOOL = adk_components["diagnosis_tool"] if adk_components else None
38
+ REMEDY_TOOL = adk_components["remedy_tool"] if adk_components else None
39
 
40
 
41
  # --- Step 3: Define Gradio UIs ---
42
 
43
  def create_field_mode_ui():
44
  """Creates the Gradio UI for the offline Field Mode."""
45
+
46
  def get_diagnosis_and_remedy(uploaded_image: Image.Image) -> str:
47
  if uploaded_image is None:
48
  return "Please upload an image of a maize plant first."
49
  if RETRIEVER is None:
50
  raise gr.Error("Knowledge base is not loaded. Cannot find remedy. Check logs.")
51
+
52
  temp_file_path = None
53
  try:
54
  with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as temp_file:
 
62
  return f"Sorry, I couldn't identify the condition from the image. Raw output: {diagnosis}"
63
 
64
  remedy = REMEDY_TOOL(diagnosis)
65
+
66
  final_response = f"""
67
  ## Diagnosis Report
68
 
 
96
  outputs=gr.Markdown(label="Diagnosis and Remedy Report", value="The report will appear here..."),
97
  title="🌽 Aura Mind Glow: Field Mode (Offline)",
98
  description="**A 100% Offline-Capable Farming Assistant.** Upload an image of a maize plant. The AI will diagnose its condition and retrieve a treatment plan from its local knowledge base.",
99
+ article="<p style='text-align: center;'>Built with Unsloth, LangChain, and Gradio. Version 2.0</p>",
100
  allow_flagging="never",
101
  theme=gr.themes.Soft(primary_hue="teal", secondary_hue="orange"),
102
  css=css
103
  )
104
 
105
+
106
  def create_connected_mode_ui():
107
  """Creates the Gradio UI for the online Connected Mode."""
108
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="green", secondary_hue="lime")) as demo:
109
  gr.Markdown("# 🌽 Aura Mind Glow: Connected Mode πŸ€–")
110
  gr.Markdown("I am an AI farming assistant. Upload an image to get started.")
111
+
112
  chatbot = gr.Chatbot()
113
  msg = gr.MultimodalTextbox(file_types=["image"], label="Upload an image for diagnosis")
114
 
 
127
  return history, gr.MultimodalTextbox(value=None)
128
 
129
  msg.submit(respond, [msg, chatbot], [chatbot, msg])
130
+
131
  return demo
132
 
133
+
134
  # --- Step 4: App Launcher ---
135
 
136
  def check_internet_connection(host="8.8.8.8", port=53, timeout=3):
 
142
  except socket.error:
143
  return False
144
 
145
+
146
  if __name__ == "__main__":
147
  if check_internet_connection() and ADK_RUNNER:
148
  print("βœ… Internet connection detected. Launching Connected Mode.")
 
150
  else:
151
  print("❌ No internet connection or ADK setup failed. Launching Field Mode (Offline).")
152
  ui = create_field_mode_ui()
153
+
154
+ ui.launch(share=True, debug=True)
app2.py DELETED
@@ -1,247 +0,0 @@
1
- # ==============================================================================
2
- # Aura Mind Glow - Main Application
3
- # ==============================================================================
4
- """
5
- This script launches the Aura Mind Glow application.
6
- It features two modes:
7
- 1. Field Mode (100% Offline): For quick diagnosis and remedy retrieval.
8
- 2. Connected Mode (Online): A conversational agent powered by the Google ADK.
9
- """
10
-
11
- # --- Step 0: Essential Imports ---
12
- import gradio as gr
13
- import torch
14
- from PIL import Image
15
- import os
16
- import warnings
17
- import socket
18
- import asyncio
19
- import tempfile
20
-
21
- # Suppress potential warnings for a cleaner console
22
- warnings.filterwarnings("ignore")
23
- os.environ["TORCH_COMPILE_DISABLE"] = "1" # Ensure torch compile is off
24
-
25
- # Unsloth and Transformers
26
- from unsloth import FastVisionModel
27
- from transformers import AutoProcessor
28
-
29
- # LangChain and RAG components
30
- from langchain_community.vectorstores import FAISS
31
- from langchain_community.document_loaders import TextLoader
32
- from langchain_huggingface import HuggingFaceEmbeddings
33
- from langchain.text_splitter import RecursiveCharacterTextSplitter
34
-
35
- # Google ADK
36
- from google.adk import Agent, Runner
37
- from google.adk.sessions import InMemorySessionService
38
- from google.genai import types
39
-
40
- # Custom Tools
41
- from tools import create_plant_diagnosis_tool, create_remedy_retrieval_tool
42
-
43
- print("βœ… All libraries imported successfully.")
44
-
45
- # --- Step 1: Global Setup - Vision Model and RAG ---
46
- # This expensive setup runs only ONCE when the application starts.
47
-
48
- print("Performing initial setup for Vision Model and RAG...")
49
- VISION_MODEL = None
50
- PROCESSOR = None
51
- RETRIEVER = None
52
- ADAPTER_PATH = "surfiniaburger/maize-health-diagnosis-adapter"
53
-
54
- try:
55
- # Load Vision Model
56
- VISION_MODEL, PROCESSOR = FastVisionModel.from_pretrained(
57
- model_name="unsloth/gemma-3n-E2B-it-unsloth-bnb-4bit",
58
- max_seq_length=2048,
59
- load_in_4bit=True,
60
- dtype=None,
61
- )
62
- FastVisionModel.for_inference(VISION_MODEL)
63
- VISION_MODEL.load_adapter(ADAPTER_PATH)
64
- print(f"βœ… Vision model and adapter '{ADAPTER_PATH}' loaded successfully!")
65
-
66
- # Build RAG Knowledge Base
67
- remedy_knowledge_text = """
68
- # Maize Health Guide
69
- ## Phosphorus Deficiency
70
- **Symptoms:** Plants are often stunted, dark green or purplish. This condition is sometimes called Purple leaf disease. The purplish discoloration is most evident on the tips of leaves of young plants.
71
- **Cause:** Lack of available phosphorus in the soil, often due to incorrect pH or cold soil temperatures.
72
- **Local Remedy:** Apply a high-phosphorus starter fertilizer at planting time. In organic systems, bone meal or rock phosphate are excellent sources. A foliar spray of a water-soluable phosphate fertilizer can be applied directly to the leaves for a quick, short-term fix. Ensure soil pH is between 6.0 and 7.0 for optimal phosphorus uptake.
73
- ## Nitrogen Deficiency
74
- **Symptoms:** General yellowing (chlorosis) of the plant, starting with the lower, older leaves in a distinct "V" shape that progresses up the midrib.
75
- **Cause:** Insufficient nitrogen in the soil, which is a mobile nutrient.
76
- **Local Remedy:** Side-dress with a nitrogen-rich fertilizer like urea, ammonium nitrate, or composted manure whenplants are about knee-high. For organic farming, blood meal or feather meal are effective sources.
77
- ## Leaf Spot
78
- **Symptoms:** Small, circular to oval spots with tan centers and dark borders on the leaves. This is a common fungal disease.
79
- **Cause:** Fungal pathogens that spread via water splash and wind.
80
- **Local Remedy:** Use resistant maize varieties if available. Apply appropriate fungicides if the infection is severe, following label directions. To prevent future outbreaks, improve air circulation by not overcrowding plants and destroy infected crop debris after harvest.
81
- ## Leaf Blight
82
- **Symptoms:** Large, irregular, grayish-green or tan lesions on the leaves, often appearing cigar-shaped. These lesions can grow and merge, leading to significant leaf death.
83
- **Cause:** Fungal pathogens that thrive in warm, humid conditions.
84
- **Local Remedy:** The primary defense is planting resistant hybrids. Fungicide applications may be necessary and should be timed based on disease scouting and weather forecasts. Crop rotation and tilling under infected residue can help reduce the pathogen for the next season.
85
- ## Healthy Plant
86
- **Symptoms:** Vigorous growth with lush, uniformly dark green leaves. No visible spots, lesions, or discoloration.
87
- **Local Remedy:** No remedy needed. Maintain good agricultural practices, including proper watering, fertilization, and pest management to keep the plant healthy.
88
- """
89
- with open("knowledge.txt", "w") as f:
90
- f.write(remedy_knowledge_text)
91
- loader = TextLoader("knowledge.txt")
92
- documents = loader.load()
93
- text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
94
- docs = text_splitter.split_documents(documents)
95
- embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
96
- db = FAISS.from_documents(docs, embeddings)
97
- RETRIEVER = db.as_retriever(search_kwargs={"k": 1})
98
- print("βœ… RAG knowledge base and retriever created successfully!")
99
-
100
- except Exception as e:
101
- print(f"❌ CRITICAL ERROR during global setup: {e}")
102
- pass
103
-
104
- # --- Step 2: Initialize ADK Tools and Agent ---
105
-
106
- print("Initializing ADK Tools and Agent...")
107
- DIAGNOSIS_TOOL = None
108
- REMEDY_TOOL = None
109
- ADK_AGENT = None
110
- ADK_RUNNER = None
111
- SESSION_SERVICE = None
112
-
113
- try:
114
- if VISION_MODEL and PROCESSOR and RETRIEVER:
115
- DIAGNOSIS_TOOL = create_plant_diagnosis_tool(model=VISION_MODEL, processor=PROCESSOR)
116
- REMEDY_TOOL = create_remedy_retrieval_tool(retriever=RETRIEVER)
117
-
118
- ADK_AGENT = Agent(
119
- name="AuraMindGlowAgent",
120
- model="gemini-2.5-flash",
121
- description="A farming assistant that can diagnose plant health and suggest remedies.",
122
- instruction="You are a friendly farming assistant. Your goal is to help users identify plant health issues and find solutions. Use your tools to diagnose the plant from an image and then find a remedy.",
123
- tools=[DIAGNOSIS_TOOL, REMEDY_TOOL]
124
- )
125
-
126
- SESSION_SERVICE = InMemorySessionService()
127
- ADK_RUNNER = Runner(agent=ADK_AGENT, app_name="AuraMindGlow", session_service=SESSION_SERVICE)
128
- print("βœ… ADK Agent and Runner initialized successfully!")
129
- else:
130
- print("❌ Skipping ADK setup due to errors in model or RAG loading.")
131
-
132
- except Exception as e:
133
- print(f"❌ CRITICAL ERROR during ADK setup: {e}")
134
- pass
135
-
136
-
137
- # --- Step 3: Define Gradio UIs ---
138
-
139
- def create_field_mode_ui():
140
- """Creates the Gradio UI for the offline Field Mode."""
141
-
142
- def get_diagnosis_and_remedy(uploaded_image: Image.Image) -> str:
143
- if uploaded_image is None:
144
- return "Please upload an image of a maize plant first."
145
- if RETRIEVER is None:
146
- raise gr.Error("Knowledge base is not loaded. Cannot find remedy. Check logs.")
147
-
148
- temp_file_path = None
149
- try:
150
- with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as temp_file:
151
- uploaded_image.save(temp_file.name)
152
- temp_file_path = temp_file.name
153
-
154
- diagnosis = DIAGNOSIS_TOOL(temp_file_path)
155
- print(f"Diagnosis received: {diagnosis}")
156
-
157
- if "Could not parse" in diagnosis:
158
- return f"Sorry, I couldn't identify the condition from the image. Raw output: {diagnosis}"
159
-
160
- remedy = REMEDY_TOOL(diagnosis)
161
-
162
- final_response = f"""
163
- ## Diagnosis Report
164
-
165
- **Condition Identified:**
166
- ### {diagnosis}
167
-
168
- ---
169
-
170
- ## Suggested Remedy
171
-
172
- {remedy}
173
- """
174
- print("Workflow complete. Returning response.")
175
- return final_response
176
-
177
- except Exception as e:
178
- print(f"An error occurred during the analysis workflow: {e}")
179
- raise gr.Error(f"An unexpected error occurred: {e}")
180
- finally:
181
- if temp_file_path and os.path.exists(temp_file_path):
182
- os.remove(temp_file_path)
183
-
184
- css = """
185
- footer {visibility: hidden !important;}
186
- .gradio-container {font-family: 'IBM Plex Sans', sans-serif;}
187
- """
188
-
189
- return gr.Interface(
190
- fn=get_diagnosis_and_remedy,
191
- inputs=gr.Image(type="pil", label="Upload Maize Plant Image", sources=["upload", "webcam"]),
192
- outputs=gr.Markdown(label="Diagnosis and Remedy Report", value="The report will appear here..."),
193
- title="🌽 Aura Mind Glow: Field Mode (Offline)",
194
- description="**A 100% Offline-Capable Farming Assistant.** Upload an image of a maize plant. The AI will diagnose its condition and retrieve a treatment plan from its local knowledge base.",
195
- article="<p style='text-align: center;'>Built with Unsloth, LangChain, and Gradio. Version 1.3</p>",
196
- allow_flagging="never",
197
- theme=gr.themes.Soft(primary_hue="teal", secondary_hue="orange"),
198
- css=css
199
- )
200
-
201
- def create_connected_mode_ui():
202
- """Creates the Gradio UI for the online Connected Mode."""
203
- with gr.Blocks(theme=gr.themes.Soft(primary_hue="green", secondary_hue="lime")) as demo:
204
- gr.Markdown("# 🌽 Aura Mind Glow: Connected Mode πŸ€–")
205
- gr.Markdown("I am an AI farming assistant. Upload an image to get started.")
206
-
207
- chatbot = gr.Chatbot()
208
- msg = gr.MultimodalTextbox(file_types=["image"], label="Upload an image for diagnosis")
209
-
210
- async def respond(chat_input, history):
211
- files = chat_input["files"]
212
- if files:
213
- file_path = files[0]
214
- # Directly call the diagnosis tool for testing
215
- diagnosis = DIAGNOSIS_TOOL(file_path)
216
- bot_message = f"**Diagnosis:** {diagnosis}"
217
- history.append([(file_path,), bot_message])
218
- else:
219
- bot_message = "Please upload an image for diagnosis."
220
- history.append([chat_input["text"], bot_message])
221
-
222
- return history, gr.MultimodalTextbox(value=None)
223
-
224
- msg.submit(respond, [msg, chatbot], [chatbot, msg])
225
-
226
- return demo
227
-
228
- # --- Step 4: App Launcher ---
229
-
230
- def check_internet_connection(host="8.8.8.8", port=53, timeout=3):
231
- """Check for internet connectivity."""
232
- try:
233
- socket.setdefaulttimeout(timeout)
234
- socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
235
- return True
236
- except socket.error:
237
- return False
238
-
239
- if __name__ == "__main__":
240
- if check_internet_connection() and ADK_RUNNER:
241
- print("βœ… Internet connection detected. Launching Connected Mode.")
242
- ui = create_connected_mode_ui()
243
- else:
244
- print("❌ No internet connection or ADK setup failed. Launching Field Mode (Offline).")
245
- ui = create_field_mode_ui()
246
-
247
- ui.launch(share=True, debug=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
config.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Configuration for the Aura Mind Glow application
2
+
3
+ # Model and Adapter Paths
4
+ VISION_MODEL_NAME = "unsloth/gemma-3n-E2B-it-unsloth-bnb-4bit"
5
+ ADAPTER_PATH = "surfiniaburger/maize-health-diagnosis-adapter"
6
+ EMBEDDING_MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2"
7
+
8
+ # RAG and Knowledge Base
9
+ KNOWLEDGE_BASE_PATH = "knowledge_base.md"
10
+ FAISS_INDEX_PATH = "faiss_index"
11
+
12
+ # Model Parameters
13
+ MAX_SEQ_LENGTH = 2048
knowledge_base.md ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Maize Health Guide
2
+ ## Phosphorus Deficiency
3
+ **Symptoms:** Plants are often stunted, dark green or purplish. This condition is sometimes called Purple leaf disease. The purplish discoloration is most evident on the tips of leaves of young plants.
4
+ **Cause:** Lack of available phosphorus in the soil, often due to incorrect pH or cold soil temperatures.
5
+ **Local Remedy:** Apply a high-phosphorus starter fertilizer at planting time. In organic systems, bone meal or rock phosphate are excellent sources. A foliar spray of a water-soluable phosphate fertilizer can be applied directly to the leaves for a quick, short-term fix. Ensure soil pH is between 6.0 and 7.0 for optimal phosphorus uptake.
6
+ ## Nitrogen Deficiency
7
+ **Symptoms:** General yellowing (chlorosis) of the plant, starting with the lower, older leaves in a distinct "V" shape that progresses up the midrib.
8
+ **Cause:** Insufficient nitrogen in the soil, which is a mobile nutrient.
9
+ **Local Remedy:** Side-dress with a nitrogen-rich fertilizer like urea, ammonium nitrate, or composted manure whenplants are about knee-high. For organic farming, blood meal or feather meal are effective sources.
10
+ ## Leaf Spot
11
+ **Symptoms:** Small, circular to oval spots with tan centers and dark borders on the leaves. This is a common fungal disease.
12
+ **Cause:** Fungal pathogens that spread via water splash and wind.
13
+ **Local Remedy:** Use resistant maize varieties if available. Apply appropriate fungicides if the infection is severe, following label directions. To prevent future outbreaks, improve air circulation by not overcrowding plants and destroy infected crop debris after harvest.
14
+ ## Leaf Blight
15
+ **Symptoms:** Large, irregular, grayish-green or tan lesions on the leaves, often appearing cigar-shaped. These lesions can grow and merge, leading to significant leaf death.
16
+ **Cause:** Fungal pathogens that thrive in warm, humid conditions.
17
+ **Local Remedy:** The primary defense is planting resistant hybrids. Fungicide applications may be necessary and should be timed based on disease scouting and weather forecasts. Crop rotation and tilling under infected residue can help reduce the pathogen for the next season.
18
+ ## Healthy Plant
19
+ **Symptoms:** Vigorous growth with lush, uniformly dark green leaves. No visible spots, lesions, or discoloration.
20
+ **Local Remedy:** No remedy needed. Maintain good agricultural practices, including proper watering, fertilization, and pest management to keep the plant healthy.
knowledge_base.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from langchain_community.vectorstores import FAISS
3
+ from langchain_community.document_loaders import TextLoader
4
+ from langchain_huggingface import HuggingFaceEmbeddings
5
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
6
+ import config
7
+
8
+ def get_retriever():
9
+ """
10
+ Creates or loads a FAISS vector store and returns a retriever.
11
+
12
+ Returns:
13
+ A FAISS retriever object, or None on error.
14
+ """
15
+ try:
16
+ embeddings = HuggingFaceEmbeddings(model_name=config.EMBEDDING_MODEL_NAME)
17
+
18
+ if os.path.exists(config.FAISS_INDEX_PATH):
19
+ print(f"βœ… Loading existing FAISS index from {config.FAISS_INDEX_PATH}...")
20
+ db = FAISS.load_local(config.FAISS_INDEX_PATH, embeddings, allow_dangerous_deserialization=True)
21
+ else:
22
+ print(f"⚠️ FAISS index not found. Building a new one from {config.KNOWLEDGE_BASE_PATH}...")
23
+ loader = TextLoader(config.KNOWLEDGE_BASE_PATH)
24
+ documents = loader.load()
25
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
26
+ docs = text_splitter.split_documents(documents)
27
+ db = FAISS.from_documents(docs, embeddings)
28
+ db.save_local(config.FAISS_INDEX_PATH)
29
+ print(f"βœ… New FAISS index built and saved to {config.FAISS_INDEX_PATH}.")
30
+
31
+ retriever = db.as_retriever(search_kwargs={"k": 1})
32
+ print("βœ… RAG knowledge base and retriever created successfully!")
33
+ return retriever
34
+ except Exception as e:
35
+ print(f"❌ CRITICAL ERROR during RAG setup: {e}")
36
+ return None
vision_model.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from unsloth import FastVisionModel
3
+ from transformers import AutoProcessor
4
+ import config
5
+
6
+ def load_vision_model():
7
+ """
8
+ Loads the FastVisionModel and its adapter for inference.
9
+
10
+ Returns:
11
+ A tuple containing the loaded model and processor, or (None, None) on error.
12
+ """
13
+ try:
14
+ model, processor = FastVisionModel.from_pretrained(
15
+ model_name=config.VISION_MODEL_NAME,
16
+ max_seq_length=config.MAX_SEQ_LENGTH,
17
+ load_in_4bit=True,
18
+ dtype=None,
19
+ )
20
+ FastVisionModel.for_inference(model)
21
+ model.load_adapter(config.ADAPTER_PATH)
22
+ print(f"βœ… Vision model and adapter '{config.ADAPTER_PATH}' loaded successfully!")
23
+ return model, processor
24
+ except Exception as e:
25
+ print(f"❌ CRITICAL ERROR during vision model loading: {e}")
26
+ return None, None