Nkuku commited on
Commit
1346a9b
·
verified ·
1 Parent(s): f7cf5d8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +671 -3
app.py CHANGED
@@ -1,9 +1,677 @@
 
1
  import gradio as gr
2
- import torch
3
- from fastai.learner import load_learner
 
4
  from PIL import Image
5
 
6
- # Load the trained model
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  model_path = "export.pkl" # Change to "grapevine_model.pt" if converted
8
  learner = load_learner(model_path)
9
 
 
1
+ import os
2
  import gradio as gr
3
+ import re
4
+ from fastai.vision.all import *
5
+ from groq import Groq
6
  from PIL import Image
7
 
8
+ # Load the trained model for grapevine disease classification
9
+ learn = load_learner('export.pkl') # Assumes you have a trained model for grapevine diseases
10
+ labels = learn.dls.vocab
11
+
12
+ # Initialize Groq client
13
+ client = Groq(
14
+ api_key=os.environ.get("GROQ_API_KEY"),
15
+ )
16
+
17
+ # Your existing functions remain the same
18
+ def clean_disease_name(name):
19
+ """Clean disease name by removing numbers and special characters, and fix formatting"""
20
+ # Remove numbers and dots at the beginning
21
+ cleaned = re.sub(r'^\d+\.', '', name)
22
+ # Replace underscores with spaces
23
+ cleaned = cleaned.replace('_', ' ')
24
+ # Remove any remaining special characters
25
+ cleaned = re.sub(r'[^\w\s]', '', cleaned)
26
+ # Fix spacing
27
+ cleaned = ' '.join(cleaned.split())
28
+ return cleaned
29
+
30
+ def format_disease_info(raw_info):
31
+ """Improve the formatting of disease information"""
32
+ # Add proper line breaks between sections and ensure consistent heading levels
33
+ formatted = raw_info
34
+
35
+ # Replace markdown headings with HTML headings for better control
36
+ formatted = re.sub(r'#+\s+(.*)', r'<h3>\1</h3>', formatted)
37
+
38
+ # Add paragraph tags for better spacing
39
+ formatted = re.sub(r'\n\*\s+(.*)', r'<p>• \1</p>', formatted)
40
+ formatted = re.sub(r'\n([^<\n].*)', r'<p>\1</p>', formatted)
41
+
42
+ # Remove any duplicate paragraph tags
43
+ formatted = formatted.replace('<p><p>', '<p>')
44
+ formatted = formatted.replace('</p></p>', '</p>')
45
+
46
+ return formatted
47
+
48
+ def get_disease_treatment(disease_name, language="swahili"):
49
+ """Get direct treatment measures for the disease"""
50
+ clean_name = clean_disease_name(disease_name)
51
+
52
+ # Return healthy message if the prediction is healthy
53
+ if clean_name.lower() == "healthy" or "healthy" in clean_name.lower():
54
+ if language.lower() == "swahili":
55
+ return """
56
+ ### Hali ya Jani: Afya nzuri
57
+
58
+ Jani hili liko katika hali nzuri ya afya. Hakuna dalili za magonjwa zinazoonekana. Endelea kutunza mizabibu yako vizuri kwa:
59
+
60
+ • Kumwagilia maji ipasavyo
61
+ • Kuhakikisha rutuba ya udongo
62
+ • Kupunguza matawi kwa usahihi
63
+ • Kufuatilia mara kwa mara kwa dalili za magonjwa
64
+ • Kudumisha hewa nzuri kuzunguka mmea
65
+ """
66
+ else:
67
+ return """
68
+ ### Leaf Status: Healthy
69
+
70
+ This leaf is in a healthy state. No signs of disease are present. Continue to maintain your vines by:
71
+
72
+ • Proper irrigation
73
+ • Ensuring soil fertility
74
+ • Appropriate pruning
75
+ • Regular monitoring for disease symptoms
76
+ • Maintaining good air circulation around the plant
77
+ """
78
+
79
+ prompt = f"""
80
+ Provide a concise, practical list of DIRECT treatment measures for {clean_name} disease in grapevines.
81
+
82
+ Format your response as a bulleted list with 5-7 specific actions a vineyard manager should take IMMEDIATELY to treat the disease.
83
+
84
+ For each treatment measure:
85
+ 1. Start with an action verb
86
+ 2. Be specific about products/techniques to use
87
+ 3. Include application rates/timing when relevant
88
+
89
+ The response should be in {"Swahili" if language.lower() == "swahili" else "English"}.
90
+
91
+ Begin with a short title: "HATUA ZA MATIBABU:" (if Swahili) or "TREATMENT MEASURES:" (if English)
92
+ """
93
+
94
+ try:
95
+ chat_completion = client.chat.completions.create(
96
+ messages=[
97
+ {
98
+ "role": "user",
99
+ "content": prompt,
100
+ }
101
+ ],
102
+ model="llama-3.3-70b-versatile",
103
+ )
104
+ return chat_completion.choices[0].message.content
105
+ except Exception as e:
106
+ error_msg = "Hitilafu kupata taarifa za matibabu" if language.lower() == "swahili" else "Error fetching treatment information"
107
+ return f"{error_msg}: {str(e)}"
108
+
109
+ def get_disease_info(disease_name, language="swahili"):
110
+ """Get detailed information about a grapevine disease using Groq API"""
111
+ clean_name = clean_disease_name(disease_name)
112
+
113
+ # Return healthy message if the prediction is healthy
114
+ if clean_name.lower() == "healthy" or "healthy" in clean_name.lower():
115
+ if language.lower() == "swahili":
116
+ return """
117
+ # Hali ya Jani: Afya nzuri
118
+
119
+ Jani hili liko katika hali nzuri ya afya. Hakuna dalili za magonjwa zinazoonekana. Hii ni ishara nzuri kwamba:
120
+
121
+ - Mizabibu yako inapata virutubisho vya kutosha
122
+ - Umwagiliaji wa maji uko katika kiasi cha kutosha
123
+ - Hali ya hewa katika shamba lako ni nzuri
124
+ - Hakuna mashambulizi ya wadudu waharibifu
125
+
126
+ Endelea kudumisha utunzaji mzuri wa mizabibu yako ili kuhakikisha uzalishaji bora wa zabibu.
127
+ """
128
+ else:
129
+ return """
130
+ # Leaf Status: Healthy
131
+
132
+ This leaf is in a healthy state. No signs of disease are present. This is a good indication that:
133
+
134
+ - Your vines are receiving adequate nutrition
135
+ - Irrigation levels are appropriate
136
+ - Climate conditions in your vineyard are favorable
137
+ - There are no pest invasions
138
+
139
+ Continue to maintain good vineyard practices to ensure optimal grape production.
140
+ """
141
+
142
+ lang = "SWAHILI" if language.lower() == "swahili" else "ENGLISH"
143
+
144
+ prompt = f"""
145
+ Provide detailed information IN {lang} about {clean_name} disease in grapevines.
146
+
147
+ Structure your response like this:
148
+ 1. A brief introduction about what this disease is (1-2 sentences)
149
+ 2. Main symptoms and how to identify the disease (short paragraph)
150
+ 3. FOCUS EXTENSIVELY on the treatment methods and prevention strategies (this should be the longest section)
151
+ 4. Conclusion with practical advice for vineyard managers
152
+
153
+ Format your response in markdown for better readability.
154
+ Make sure the entire response is in {lang}.
155
+ """
156
+
157
+ try:
158
+ chat_completion = client.chat.completions.create(
159
+ messages=[
160
+ {
161
+ "role": "user",
162
+ "content": prompt,
163
+ }
164
+ ],
165
+ model="llama-3.3-70b-versatile",
166
+ )
167
+ return chat_completion.choices[0].message.content
168
+ except Exception as e:
169
+ error_msg = "Hitilafu kupata taarifa" if language.lower() == "swahili" else "Error fetching information"
170
+ return f"{error_msg}: {str(e)}"
171
+
172
+ def predict_and_get_info(img, language="swahili"):
173
+ """Predict grapevine disease and get detailed information"""
174
+ # Process the image
175
+ img = PILImage.create(img)
176
+
177
+ # Get prediction
178
+ pred, pred_idx, probs = learn.predict(img)
179
+
180
+ # Get top 5 predictions (or all if less than 5)
181
+ num_classes = min(5, len(labels))
182
+ top_indices = probs.argsort(descending=True)[:num_classes]
183
+ top_probs = probs[top_indices]
184
+ top_labels = [labels[i] for i in top_indices]
185
+
186
+ # Format as dictionary with cleaned names for display
187
+ prediction_results = {clean_disease_name(top_labels[i]): float(top_probs[i]) for i in range(num_classes)}
188
+
189
+ # Get top prediction (original format for info retrieval)
190
+ top_disease = str(pred)
191
+ # Also keep a clean version for display
192
+ clean_top_disease = clean_disease_name(top_disease)
193
+
194
+ # Check if healthy
195
+ is_healthy = clean_top_disease.lower() == "healthy" or "healthy" in clean_top_disease.lower()
196
+
197
+ # Get detailed information about the top predicted disease
198
+ disease_info = get_disease_info(top_disease, language)
199
+ formatted_info = format_disease_info(disease_info)
200
+
201
+ # Get direct treatment measures
202
+ treatment_measures = get_disease_treatment(top_disease, language)
203
+ formatted_treatment = format_disease_info(treatment_measures)
204
+
205
+ # Create title text based on language and health status
206
+ if language.lower() == "swahili":
207
+ title_text = "Jani Zuri na Afya Njema" if is_healthy else f"Ugonjwa: {clean_top_disease}"
208
+ advice_title = "Ushauri wa Haraka kwa Wakulima"
209
+ advice_text = "Kumbuka: Fuata maelekezo ya kitaalamu na tumia dawa zilizoidhinishwa tu. Wasiliana na mtaalamu wa kilimo kwa ushauri zaidi."
210
+ treatment_title = "Hatua za Matibabu"
211
+ else:
212
+ title_text = "Healthy Leaf" if is_healthy else f"Disease: {clean_top_disease}"
213
+ advice_title = "Quick Advice for Vineyard Managers"
214
+ advice_text = "Remember: Follow professional instructions and use only approved treatments. Contact an agricultural expert for more advice."
215
+ treatment_title = "Treatment Measures"
216
+
217
+ # Create well-formatted display with improved fonts and styling
218
+ custom_css = """
219
+ <style>
220
+ .disease-container {
221
+ font-family: 'Nunito', 'Segoe UI', sans-serif;
222
+ padding: 20px;
223
+ max-width: 100%;
224
+ background-color: #ffffff;
225
+ border-radius: 12px;
226
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
227
+ }
228
+ .disease-title {
229
+ color: #2a633d;
230
+ font-size: 28px;
231
+ font-weight: 700;
232
+ margin-bottom: 20px;
233
+ padding-bottom: 10px;
234
+ border-bottom: 2px solid #e0e0e0;
235
+ }
236
+ .info-container {
237
+ line-height: 1.8;
238
+ font-size: 16px;
239
+ color: #333333;
240
+ }
241
+ .info-container h3 {
242
+ color: #2a633d;
243
+ font-size: 22px;
244
+ font-weight: 600;
245
+ margin-top: 25px;
246
+ margin-bottom: 15px;
247
+ padding-bottom: 8px;
248
+ border-bottom: 1px solid #e0e0e0;
249
+ }
250
+ .info-container p {
251
+ margin-bottom: 15px;
252
+ text-align: justify;
253
+ }
254
+ .treatment-section {
255
+ background-color: #f1f8e9;
256
+ padding: 20px;
257
+ border-radius: 8px;
258
+ margin: 25px 0;
259
+ border-left: 5px solid #558b2f;
260
+ }
261
+ .treatment-section h3 {
262
+ color: #33691e;
263
+ border-bottom: none;
264
+ margin-top: 0;
265
+ }
266
+ .direct-treatment {
267
+ background-color: #e8f5e9;
268
+ padding: 20px;
269
+ border-radius: 8px;
270
+ margin: 25px 0;
271
+ border-left: 5px solid #2e7d32;
272
+ }
273
+ .direct-treatment h3 {
274
+ color: #2e7d32;
275
+ border-bottom: none;
276
+ margin-top: 0;
277
+ }
278
+ .healthy-state {
279
+ background-color: #e8f5e9;
280
+ color: #2e7d32;
281
+ padding: 15px;
282
+ border-radius: 8px;
283
+ text-align: center;
284
+ font-weight: bold;
285
+ font-size: 18px;
286
+ margin: 15px 0;
287
+ }
288
+ /* Ensure good readability for text */
289
+ body {
290
+ font-feature-settings: "kern", "liga", "clig", "calt";
291
+ text-rendering: optimizeLegibility;
292
+ }
293
+ </style>
294
+ """
295
+
296
+ # Healthy banner HTML if needed
297
+ healthy_banner = ""
298
+ if is_healthy:
299
+ if language.lower() == "swahili":
300
+ healthy_banner = '<div class="healthy-state">✓ Jani hili liko katika hali nzuri ya afya</div>'
301
+ else:
302
+ healthy_banner = '<div class="healthy-state">✓ This leaf is in a healthy state</div>'
303
+
304
+ combined_info = f"""
305
+ {custom_css}
306
+ <div class="disease-container">
307
+ <h2 class="disease-title">{title_text}</h2>
308
+ {healthy_banner}
309
+
310
+ <div class="info-container">
311
+ {formatted_info}
312
+ </div>
313
+
314
+ <div class="direct-treatment">
315
+ <h3>{treatment_title}</h3>
316
+ {formatted_treatment}
317
+ </div>
318
+
319
+ <div class="treatment-section">
320
+ <h3>{advice_title}</h3>
321
+ <p>{advice_text}</p>
322
+ </div>
323
+ </div>
324
+ """
325
+
326
+ return prediction_results, combined_info, clean_top_disease
327
+
328
+ def follow_up_question(question, disease_name, language="swahili"):
329
+ """Allow vineyard managers to ask follow-up questions about the identified disease"""
330
+ if not question.strip() or not disease_name:
331
+ return "Tafadhali tambua ugonjwa wa mizabibu kwanza na uulize swali mahususi kuuhusu." if language.lower() == "swahili" else "Please identify a grapevine disease first and ask a specific question about it."
332
+
333
+ lang = "SWAHILI" if language.lower() == "swahili" else "ENGLISH"
334
+
335
+ prompt = f"""
336
+ The vineyard manager is asking about {disease_name} disease: "{question}"
337
+
338
+ Provide a detailed answer IN {lang}, focusing on accurate plant pathology information.
339
+ If the question relates to treatment options, preventive measures, or climate change impacts, emphasize those aspects in your response.
340
+
341
+ IMPORTANT:
342
+ - Do not repeat basic introductory information about the disease that would have already been provided
343
+ - Directly answer the specific question asked
344
+ - The entire response must be in {lang}
345
+ - Focus on practical advice whenever possible
346
+
347
+ Format your response in markdown for better readability.
348
+ """
349
+
350
+ try:
351
+ chat_completion = client.chat.completions.create(
352
+ messages=[
353
+ {
354
+ "role": "user",
355
+ "content": prompt,
356
+ }
357
+ ],
358
+ model="llama-3.3-70b-versatile",
359
+ )
360
+ return chat_completion.choices[0].message.content
361
+ except Exception as e:
362
+ error_msg = "Hitilafu kupata taarifa" if language.lower() == "swahili" else "Error fetching information"
363
+ return f"{error_msg}: {str(e)}"
364
+
365
+ # Enhanced CSS for styling the improved language toggle
366
+ toggle_css = """
367
+ <style>
368
+ /* Main container for language toggle */
369
+ .language-toggle-container {
370
+ display: flex;
371
+ align-items: center;
372
+ justify-content: flex-end;
373
+ margin-bottom: 20px;
374
+ padding: 10px;
375
+ background-color: rgba(255, 255, 255, 0.9);
376
+ border-radius: 8px;
377
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
378
+ }
379
+
380
+ /* Toggle label styling */
381
+ .toggle-label {
382
+ font-size: 16px;
383
+ font-weight: 600;
384
+ margin-right: 10px;
385
+ color: #2a633d;
386
+ }
387
+
388
+ /* Custom styling for the language toggle buttons */
389
+ .language-switcher .gr-form {
390
+ display: flex !important;
391
+ flex-direction: row !important;
392
+ background: #f0f4f1;
393
+ border-radius: 30px;
394
+ padding: 4px;
395
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
396
+ border: 1px solid #dbeadf;
397
+ }
398
+
399
+ .language-switcher .gr-radio {
400
+ display: inline-flex !important;
401
+ gap: 0 !important;
402
+ background: transparent !important;
403
+ border: none !important;
404
+ box-shadow: none !important;
405
+ }
406
+
407
+ .language-switcher .gr-radio-row {
408
+ display: flex !important;
409
+ flex-direction: row !important;
410
+ }
411
+
412
+ .language-switcher .gr-radio label {
413
+ border-radius: 20px !important;
414
+ padding: 8px 16px !important;
415
+ margin: 2px !important;
416
+ font-weight: 600 !important;
417
+ font-size: 14px !important;
418
+ transition: all 0.2s ease !important;
419
+ color: #555 !important;
420
+ }
421
+
422
+ .language-switcher .gr-radio input:checked + label {
423
+ background-color: #2a633d !important;
424
+ color: white !important;
425
+ box-shadow: 0 2px 4px rgba(42, 99, 61, 0.3) !important;
426
+ }
427
+
428
+ .language-switcher .gr-radio input:not(:checked) + label:hover {
429
+ background-color: rgba(42, 99, 61, 0.1) !important;
430
+ }
431
+
432
+ /* Flag icons for visual enhancement */
433
+ .flag-icon {
434
+ display: inline-block;
435
+ width: 18px;
436
+ height: 18px;
437
+ margin-right: 6px;
438
+ vertical-align: middle;
439
+ border-radius: 2px;
440
+ }
441
+
442
+ /* Add animation for language transition */
443
+ .language-transition {
444
+ transition: all 0.3s ease-in-out;
445
+ }
446
+
447
+ /* Responsive adjustments */
448
+ @media (max-width: 768px) {
449
+ .language-toggle-container {
450
+ justify-content: center;
451
+ }
452
+
453
+ .language-switcher .gr-radio label {
454
+ padding: 6px 12px !important;
455
+ font-size: 13px !important;
456
+ }
457
+ }
458
+ </style>
459
+ """
460
+
461
+ # Create the Gradio interface
462
+ with gr.Blocks(theme=gr.themes.Soft(), css=toggle_css) as app:
463
+ # State for current language
464
+ current_language = gr.State("swahili")
465
+
466
+ # Create language-specific text dictionary
467
+ text_dict = {
468
+ "swahili": {
469
+ "title": "# Kitambulisho cha Magonjwa ya Mizabibu",
470
+ "subtitle": "Pakia picha ili kutambua magonjwa ya mizabibu na kupata taarifa za kina kuhusu mikakati ya udhibiti na chaguo za matibabu.",
471
+ "upload_label": "Pakia Picha ya Mizabibu",
472
+ "identify_btn": "Tambua Ugonjwa",
473
+ "prediction_label": "Utabiri wa Juu 5",
474
+ "disease_info_label": "Maelezo ya Ugonjwa",
475
+ "followup_title": "## Maswali ya Ufuatiliaji",
476
+ "question_label": "Uliza swali kuhusu ugonjwa huu",
477
+ "question_placeholder": "Mfano: Je, ni hatua gani bora za kuzuia ugonjwa huu?",
478
+ "submit_btn": "Wasilisha Swali",
479
+ "clear_btn": "Futa Mazungumzo",
480
+ "toggle_label": "Lugha:",
481
+ "error_no_image": "Tafadhali pakia picha",
482
+ "error_processing": "Hitilafu katika kuchakata picha"
483
+ },
484
+ "english": {
485
+ "title": "# Grapevine Disease Identification Tool",
486
+ "subtitle": "Upload an image to identify grapevine diseases and get detailed information on management strategies and treatment options.",
487
+ "upload_label": "Upload Grapevine Image",
488
+ "identify_btn": "Identify Disease",
489
+ "prediction_label": "Top 5 Predictions",
490
+ "disease_info_label": "Disease Information",
491
+ "followup_title": "## Follow-up Questions",
492
+ "question_label": "Ask a question about this disease",
493
+ "question_placeholder": "Example: What are the best preventative measures for this disease?",
494
+ "submit_btn": "Submit Question",
495
+ "clear_btn": "Clear Conversation",
496
+ "toggle_label": "Language:",
497
+ "error_no_image": "Please upload an image",
498
+ "error_processing": "Error processing image"
499
+ }
500
+ }
501
+
502
+ # UI Elements with default language
503
+ title_md = gr.Markdown(text_dict["swahili"]["title"], elem_classes="language-transition")
504
+ subtitle_md = gr.Markdown(text_dict["swahili"]["subtitle"], elem_classes="language-transition")
505
+
506
+ # Store the current disease for context
507
+ current_disease = gr.State("")
508
+
509
+ # Add improved language toggle at the top
510
+ with gr.Row(elem_classes="language-toggle-container"):
511
+ toggle_label = gr.Markdown(text_dict["swahili"]["toggle_label"], elem_classes="toggle-label language-transition")
512
+
513
+ # Custom HTML for flag icons
514
+ flag_html = gr.HTML("""
515
+ <div style="display:none">
516
+ <img id="sw-flag" src="https://flagcdn.com/w20/tz.png" alt="Swahili Flag">
517
+ <img id="en-flag" src="https://flagcdn.com/w20/gb.png" alt="English Flag">
518
+ </div>
519
+ """)
520
+
521
+ with gr.Column(elem_classes="language-switcher", scale=1):
522
+ language_toggle = gr.Radio(
523
+ ["Swahili", "English"],
524
+ value="Swahili",
525
+ label="",
526
+ interactive=True,
527
+ elem_id="language-toggle"
528
+ )
529
+
530
+ # Main identification section
531
+ with gr.Row():
532
+ with gr.Column(scale=1):
533
+ input_image = gr.Image(type="pil", label=text_dict["swahili"]["upload_label"], elem_classes="language-transition")
534
+ submit_btn = gr.Button(text_dict["swahili"]["identify_btn"], variant="primary", elem_classes="language-transition")
535
+
536
+ with gr.Column(scale=2):
537
+ prediction_output = gr.Label(label=text_dict["swahili"]["prediction_label"], num_top_classes=5, elem_classes="language-transition")
538
+ disease_info_output = gr.HTML(label=text_dict["swahili"]["disease_info_label"], elem_classes="language-transition")
539
+
540
+ # Clear divider
541
+ gr.Markdown("---")
542
+
543
+ # Follow-up question section with improved UI
544
+ followup_title_md = gr.Markdown(text_dict["swahili"]["followup_title"], elem_classes="language-transition")
545
+
546
+ conversation_history = gr.Markdown("", elem_classes="language-transition")
547
+
548
+ with gr.Row():
549
+ follow_up_input = gr.Textbox(
550
+ label=text_dict["swahili"]["question_label"],
551
+ placeholder=text_dict["swahili"]["question_placeholder"],
552
+ lines=2,
553
+ elem_classes="language-transition"
554
+ )
555
+
556
+ with gr.Row():
557
+ follow_up_btn = gr.Button(text_dict["swahili"]["submit_btn"], variant="primary", elem_classes="language-transition")
558
+ clear_btn = gr.Button(text_dict["swahili"]["clear_btn"], elem_classes="language-transition")
559
+
560
+ # Enhanced function to switch language based on toggle
561
+ def switch_language(selected_language, current_lang):
562
+ # Map the radio value to our language code
563
+ new_lang = "swahili" if selected_language == "Swahili" else "english"
564
+
565
+ # If language hasn't changed, don't update anything
566
+ if new_lang == current_lang:
567
+ return [current_lang] + [gr.update() for _ in range(11)]
568
+
569
+ # Debug message to verify the language switch
570
+ print(f"Switching language from {current_lang} to {new_lang}")
571
+
572
+ # Add custom JavaScript for smooth transition animation
573
+ js = """
574
+ document.querySelectorAll('.language-transition').forEach(el => {
575
+ el.style.opacity = 0;
576
+ setTimeout(() => { el.style.opacity = 1; }, 300);
577
+ });
578
+ """
579
+
580
+ # Return updated values
581
+ return (
582
+ new_lang,
583
+ text_dict[new_lang]["title"],
584
+ text_dict[new_lang]["subtitle"],
585
+ text_dict[new_lang]["followup_title"],
586
+ gr.update(label=text_dict[new_lang]["upload_label"]),
587
+ text_dict[new_lang]["identify_btn"],
588
+ gr.update(label=text_dict[new_lang]["prediction_label"]),
589
+ gr.update(label=text_dict[new_lang]["disease_info_label"]),
590
+ gr.update(label=text_dict[new_lang]["question_label"], placeholder=text_dict[new_lang]["question_placeholder"]),
591
+ text_dict[new_lang]["submit_btn"],
592
+ text_dict[new_lang]["clear_btn"],
593
+ text_dict[new_lang]["toggle_label"]
594
+ )
595
+
596
+ # Set up event handlers
597
+ def process_image(img, lang):
598
+ if img is None:
599
+ return None, text_dict[lang]["error_no_image"], "", ""
600
+
601
+ try:
602
+ # Print debug message to verify language
603
+ print(f"Processing image with language: {lang}")
604
+
605
+ pred_results, info, clean_disease_name = predict_and_get_info(img, lang)
606
+ return pred_results, info, clean_disease_name, ""
607
+ except Exception as e:
608
+ return None, f"{text_dict[lang]['error_processing']}: {str(e)}", "", ""
609
+
610
+ def update_conversation(question, disease_name, history, lang):
611
+ if not question.strip():
612
+ return history
613
+
614
+ answer = follow_up_question(question, disease_name, lang)
615
+
616
+ # Format the conversation with clear separation
617
+ question_label = "Swali:" if lang == "swahili" else "Question:"
618
+ answer_label = "Jibu:" if lang == "swahili" else "Answer:"
619
+
620
+ new_exchange = f"""
621
+ ### {question_label}
622
+ {question}
623
+ ### {answer_label}
624
+ {answer}
625
+ ---
626
+ """
627
+ updated_history = new_exchange + history
628
+ return updated_history
629
+
630
+ def clear_conversation_history():
631
+ return ""
632
+
633
+ # Connect the language toggle with enhanced functionality
634
+ language_toggle.change(
635
+ switch_language,
636
+ inputs=[language_toggle, current_language],
637
+ outputs=[
638
+ current_language,
639
+ title_md,
640
+ subtitle_md,
641
+ followup_title_md,
642
+ input_image,
643
+ submit_btn,
644
+ prediction_output,
645
+ disease_info_output,
646
+ follow_up_input,
647
+ follow_up_btn,
648
+ clear_btn,
649
+ toggle_label
650
+ ]
651
+ )
652
+
653
+ submit_btn.click(
654
+ process_image,
655
+ inputs=[input_image, current_language],
656
+ outputs=[prediction_output, disease_info_output, current_disease, conversation_history]
657
+ )
658
+
659
+ follow_up_btn.click(
660
+ update_conversation,
661
+ inputs=[follow_up_input, current_disease, conversation_history, current_language],
662
+ outputs=[conversation_history]
663
+ ).then(
664
+ lambda: "",
665
+ outputs=follow_up_input
666
+ )
667
+
668
+ clear_btn.click(
669
+ clear_conversation_history,
670
+ outputs=[conversation_history]
671
+ )
672
+
673
+ # Launch the app
674
+ app.launch(share=True)odel
675
  model_path = "export.pkl" # Change to "grapevine_model.pt" if converted
676
  learner = load_learner(model_path)
677