Spaces:
Sleeping
Sleeping
| import os | |
| import sys | |
| import platform | |
| import argparse | |
| import json | |
| from dotenv import load_dotenv | |
| from groq import Groq | |
| # Import the new prompts | |
| from prompts import SYSTEM_PROMPT | |
| # Load environment variables | |
| load_dotenv() | |
| # Common configuration | |
| OLLAMA_MODEL = "llama-3.3-70b-versatile" # Upgraded model for better Tamil accuracy | |
| # Initialize Groq client | |
| GROQ_API_KEY = os.getenv("GROQ_API_KEY") | |
| client = None | |
| if GROQ_API_KEY: | |
| client = Groq(api_key=GROQ_API_KEY) | |
| def print_header() -> None: | |
| print("AgroGPT (Mobile Backend) 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.""" | |
| if not GROQ_API_KEY: | |
| print("Error: GROQ_API_KEY not found in .env file.", flush=True) | |
| return False | |
| try: | |
| if client: | |
| client.models.list() | |
| print("Connected to Groq (JSON Mode Ready).", flush=True) | |
| return True | |
| return False | |
| except Exception as e: | |
| print(f"Error: Could not connect to backend: {str(e)}", flush=True) | |
| return False | |
| def generate_with_ollama(user_prompt: str, system_prompt: str = SYSTEM_PROMPT, model: str = OLLAMA_MODEL) -> dict: | |
| """ | |
| Generate a JSON response using Groq. | |
| Returns a dictionary parsed from the JSON response. | |
| """ | |
| if not client: | |
| return {"error": "Groq client not initialized. Check your API key."} | |
| try: | |
| completion = client.chat.completions.create( | |
| model=model, | |
| messages=[ | |
| {"role": "system", "content": system_prompt}, | |
| {"role": "user", "content": user_prompt} | |
| ], | |
| response_format={"type": "json_object"}, | |
| stream=False | |
| ) | |
| response_text = completion.choices[0].message.content | |
| return json.loads(response_text) | |
| except json.JSONDecodeError: | |
| return {"error": "Failed to parse JSON response from LLM", "raw_response": response_text} | |
| except Exception as e: | |
| return {"error": 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) -> dict: | |
| """ | |
| Analyzes a plant image using the local vision model, then generates | |
| expert advice using Groq (returning JSON). | |
| """ | |
| 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 {"error": result.get('error')} | |
| disease_name = result.get('prediction', 'Unknown') | |
| confidence = result.get('confidence', 0.0) | |
| is_simulated = result.get('simulation', False) | |
| # Construct prompt for the LLM to get structured advice | |
| # We reuse the same system prompt structure but adapt the user input | |
| input_data = { | |
| "task": "disease_analysis", | |
| "disease_name": disease_name, | |
| "confidence_score": confidence, | |
| "is_simulated": is_simulated, | |
| "user_query": "Provide detailed treatment and prevention advice for this disease." | |
| } | |
| prompt = f"Analyze this disease detection result and provide structured advice:\n{json.dumps(input_data, indent=2)}" | |
| print(f"Requesting advice for {disease_name}...", flush=True) | |
| advice_json = generate_with_ollama(prompt) | |
| # Merge vision results with LLM advice | |
| return { | |
| "disease_detection": { | |
| "name": disease_name, | |
| "confidence": confidence, | |
| "is_simulated": is_simulated | |
| }, | |
| "advice": advice_json | |
| } | |
| except Exception as e: | |
| return {"error": 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 Mobile Backend CLI") | |
| 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(json.dumps(response, indent=2), flush=True) | |
| return | |
| print("Interactive mode (JSON). Type your question 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 | |
| # Simple wrapper for CLI testing | |
| response = generate_with_ollama(user_input) | |
| print(json.dumps(response, indent=2), flush=True) | |
| print("-" * 40) | |
| if __name__ == "__main__": | |
| main() | |