File size: 8,141 Bytes
840845a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76064c1
840845a
 
 
 
 
 
 
 
76064c1
 
840845a
4f5826b
 
 
 
 
 
 
 
76064c1
4f5826b
76064c1
 
840845a
76064c1
 
 
 
840845a
76064c1
 
 
840845a
 
 
 
 
 
 
 
76064c1
 
 
4f5826b
 
 
 
 
 
 
 
840845a
76064c1
4f5826b
76064c1
 
 
 
840845a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11d1217
 
 
 
 
840845a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
import os
import sys
import platform
import argparse
import requests
import json
from pathlib import Path
from dotenv import load_dotenv
from groq import Groq

# Load environment variables
load_dotenv()

# Common configuration - Keeping Ollama naming for external appearance as requested
OLLAMA_API_URL = "Groq Cloud API"
OLLAMA_MODEL = "llama-3.3-70b-versatile"  # Upgraded model for better Tamil accuracy

# Initialize Groq client dynamically
client = None

def print_header() -> None:
    print("AgroGPT (Ollama Edition) starting...", flush=True)
    print(f"Python: {platform.python_version()} ({sys.executable})", flush=True)

def check_ollama_connection() -> bool:
    """Check if Groq API is reachable and key is valid (mimicking Ollama check)."""
    global client
    api_key = os.getenv("GROQ_API_KEY")
    
    # Hugging Face Docker Spaces secure secret mounting mechanism
    if not api_key and os.path.exists("/run/secrets/GROQ_API_KEY"):
        try:
            with open("/run/secrets/GROQ_API_KEY", "r") as f:
                api_key = f.read().strip()
        except:
            pass
            
    if not api_key:
        print("Error: GROQ_API_KEY not found in environment variables or /run/secrets.", flush=True)
        return False
        
    try:
        # Initialize client if not already done
        if not client:
            client = Groq(api_key=api_key)
            
        # Simple test call to verify connection
        client.models.list()
        print("Connected to Groq (Ollama interface active).", flush=True)
        return True
    except Exception as e:
        print(f"Error: Could not connect to backend: {str(e)}", flush=True)
        return False

def generate_with_ollama(prompt: str, model: str = OLLAMA_MODEL) -> str:
    """
    Generate a response using Groq (mimicking Ollama function).
    """
    global client
    api_key = os.getenv("GROQ_API_KEY")
    
    # Hugging Face Docker Spaces secure secret mounting mechanism
    if not api_key and os.path.exists("/run/secrets/GROQ_API_KEY"):
        try:
            with open("/run/secrets/GROQ_API_KEY", "r") as f:
                api_key = f.read().strip()
        except:
            pass
            
    if not client:
        if not api_key:
            return "Error: Groq API key not found in environment variables or /run/secrets."
        try:
            client = Groq(api_key=api_key)
        except Exception as e:
            return f"Error initializing Groq client: {str(e)}"
        
    try:
        completion = client.chat.completions.create(
            model=model,
            messages=[
                {"role": "system", "content": "You are a helpful assistant. Use plain text only. IMPORTANT: For Malayalam (മലയാളം) and Tamil (தமிழ்), ALWAYS use their native scripts. Do NOT use Latin/English alphabets for these languages. Do not use markdown, bolding, or asterisks."},
                {"role": "user", "content": prompt}
            ],
            stream=False
        )
        response = completion.choices[0].message.content
        return response.replace("*", "") # Final safety check to remove all asterisks
    except Exception as e:
        return f"Error generating response: {str(e)}"

# Import the disease detection module
try:
    from disease_detection import get_disease_detector
    HAS_DISEASE_DETECTION = True
except ImportError:
    HAS_DISEASE_DETECTION = False
    print("Warning: disease_detection module not found. Vision features disabled.")

def analyze_image_for_disease(image_path: str) -> str:
    """
    Analyzes a plant image using the local vision model, then generates
    expert advice using Groq (mimicking Ollama).
    """
    if not HAS_DISEASE_DETECTION:
        return "Error: Disease detection module not available."

    try:
        detector = get_disease_detector()
        result = detector.predict_disease(image_path)
        
        if "error" in result:
             return f"Analysis Error: {result.get('error')}"

        disease_name = result.get('prediction', 'Unknown')
        confidence = result.get('confidence', 0.0)
        
        # If it's a simulation (fallback), we might want to mention that
        is_simulated = result.get('simulation', False)
        
        # Construct prompt for the LLM
        prompt = (
            f"You are an expert plant pathologist. An image analysis system has detected "
            f"'{disease_name}' with {confidence*100:.1f}% confidence. "
            f"{'Note: This was a simulated detection based on color analysis.' if is_simulated else ''}\n\n"
            f"Provide detailed advice for the farmer. Structure your response EXACTLY as follows:\n"
            f"1. English Section: Describe the symptoms, then recommended treatments (organic and chemical), then preventive measures.\n"
            f"2. Write the header 'Malayalam Summary:' followed by a FULL translation of the above advice in native Malayalam script (മലയാളം). Do NOT use English/Latin letters for Malayalam.\n"
            f"3. Write the header 'Tamil Summary:' followed by a FULL translation of the above advice in native Tamil script (தமிழ்). Do NOT use English/Latin letters for Tamil.\n\n"
            f"Use double line breaks between sections. Do NOT use markdown formatting, bolding, or any asterisks (*).\n"
            f"Keep the tone helpful and professional."
        )
        
        print(f"Requesting advice for {disease_name}...", flush=True)
        advice = generate_with_ollama(prompt)
        
        return (
            f"=== Plant Disease Analysis ===\n"
            f"Detected: {disease_name}\n"
            f"Confidence: {confidence*100:.1f}%\n"
            f"{'(Simulated Detection)' if is_simulated else ''}\n\n"
            f"--- Expert Advice (via Llama 3.1) ---\n"
            f"{advice}"
        )

    except Exception as e:
        return f"Error during analysis: {str(e)}"

# --- Main function to handle the interactive loop ---
def main() -> None:
    print_header()
    
    if not check_ollama_connection():
        print("Fatal: Could not connect to backend. Exiting.", flush=True)
        sys.exit(1)

    parser = argparse.ArgumentParser(description="AgroGPT Ollama Demo")
    parser.add_argument("--prompt", type=str, default=None, help="Single question to answer")
    args = parser.parse_args()

    if args.prompt:
        print(f"Prompt: {args.prompt}", flush=True)
        print("-" * 40)
        response = generate_with_ollama(args.prompt)
        print(response, flush=True)
        return
    
    print("Interactive mode. Type your question (or 'upload <path>' for images) and press Enter.", flush=True)
    while True:
        try:
            user_input = input("AgroGPT> ").strip()
        except EOFError:
            break
        
        if not user_input or user_input.lower() in {"exit", "quit"}:
            break
        
        if user_input.lower().startswith("upload "):
            image_path = user_input.split(" ", 1)[1].strip()
            print(analyze_image_for_disease(image_path), flush=True)
        else:
            # Regular text chat
            # We can add a system prompt wrapper here if we want consistent persona
            full_prompt = (
                "You are AgroGPT, a helpful agricultural assistant. "
                "Answer the following question clearly and concisely in plain text. "
                "Provide the main answer in English, then add a section header 'Malayalam Summary:' with the translation in native Malayalam (മലയാളം) script, "
                "then a section header 'Tamil Summary:' with the translation in native Tamil (தமிழ்) script. "
                "Use double line breaks between these sections. "
                "Do not use any markdown formatting or asterisks (*).\n\n"
                f"Question: {user_input}\nAnswer:"
            )
            print("Generating...", flush=True)
            response = generate_with_ollama(full_prompt)
            print(response, flush=True)
            print("-" * 40)

if __name__ == "__main__":
    main()