|
|
|
|
|
|
|
|
|
|
|
""" |
|
|
This script is the main entry point for the application. It launches a FastAPI |
|
|
server that provides the diagnosis API and also serves the entire Gradio UI. |
|
|
|
|
|
To run this server for development: |
|
|
1. Make sure you have installed all packages from requirements.txt. |
|
|
2. Run the command: uvicorn api_server:app --host 127.0.0.1 --port 7860 |
|
|
|
|
|
When deployed to Hugging Face Spaces, the Procfile will handle this command. |
|
|
""" |
|
|
|
|
|
|
|
|
from fastapi import FastAPI, UploadFile, File, HTTPException |
|
|
from fastapi.responses import JSONResponse |
|
|
from PIL import Image |
|
|
import os |
|
|
import warnings |
|
|
import tempfile |
|
|
import re |
|
|
import io |
|
|
import gradio as gr |
|
|
|
|
|
|
|
|
|
|
|
from vision_model import load_vision_model |
|
|
from knowledge_base import KnowledgeBase |
|
|
from agent_setup import initialize_adk |
|
|
from bigquery_search import search_bigquery_for_remedy |
|
|
from vector_store import embed_and_store_documents |
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
from app import demo as gradio_app |
|
|
print("β
Gradio UI imported successfully from app.py.") |
|
|
except ImportError as e: |
|
|
gradio_app = None |
|
|
print(f"β CRITICAL: Could not import Gradio UI from app.py: {e}") |
|
|
print("Ensure app.py defines a Gradio Blocks object named 'demo' and does not call .launch().") |
|
|
|
|
|
|
|
|
print("β
All server libraries imported successfully.") |
|
|
|
|
|
|
|
|
warnings.filterwarnings("ignore") |
|
|
os.environ["TORCH_COMPILE_DISABLE"] = "1" |
|
|
|
|
|
print("Performing initial setup for server (this may take a moment)...") |
|
|
VISION_MODEL, PROCESSOR = load_vision_model() |
|
|
KB = KnowledgeBase() |
|
|
RETRIEVER = KB |
|
|
embed_and_store_documents() |
|
|
|
|
|
adk_components = initialize_adk(VISION_MODEL, PROCESSOR, RETRIEVER) |
|
|
DIAGNOSIS_TOOL = adk_components["diagnosis_tool"] if adk_components else None |
|
|
|
|
|
if not DIAGNOSIS_TOOL: |
|
|
print("β CRITICAL: Diagnosis tool could not be initialized. The API will not work.") |
|
|
|
|
|
print("β
Server setup complete.") |
|
|
|
|
|
|
|
|
app = FastAPI( |
|
|
title="Aura Mind Glow API", |
|
|
description="Provides access to the plant diagnosis model and serves the Gradio UI.", |
|
|
version="1.0.0", |
|
|
) |
|
|
|
|
|
def run_diagnosis_logic(image: Image.Image): |
|
|
""" |
|
|
Core logic for running diagnosis and getting remedies. |
|
|
""" |
|
|
temp_file_path = None |
|
|
try: |
|
|
with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as temp_file: |
|
|
image.save(temp_file.name) |
|
|
temp_file_path = temp_file.name |
|
|
|
|
|
diagnosis = DIAGNOSIS_TOOL(temp_file_path) |
|
|
if "Could not parse" in diagnosis: |
|
|
return {"error": f"Could not identify condition: {diagnosis}"} |
|
|
|
|
|
cleaned_diagnosis = re.sub(r'[^\w\s.\\-,\"]', '', diagnosis) |
|
|
cleaned_diagnosis = re.sub(r'\s+', ' ', cleaned_diagnosis).strip() |
|
|
|
|
|
local_remedy_list = search_documents(cleaned_diagnosis) |
|
|
local_remedy = local_remedy_list[0] if local_remedy_list else "No remedy found in local knowledge base." |
|
|
|
|
|
search_query = "healthy maize" if "healthy" in cleaned_diagnosis.lower() else "phosphorus" if "phosphorus" in cleaned_diagnosis.lower() else "general" |
|
|
cloud_remedy = search_bigquery_for_remedy(search_query) |
|
|
|
|
|
return { |
|
|
"diagnosis": diagnosis, |
|
|
"remedy_local": local_remedy, |
|
|
"remedy_cloud": cloud_remedy |
|
|
} |
|
|
finally: |
|
|
if temp_file_path: |
|
|
os.remove(temp_file_path) |
|
|
|
|
|
@app.post("/diagnose/", tags=["Diagnosis"]) |
|
|
async def diagnose_endpoint(file: UploadFile = File(...)): |
|
|
""" |
|
|
Receives an image file, performs diagnosis, and returns the result as JSON. |
|
|
""" |
|
|
if not file.content_type.startswith('image/'): |
|
|
raise HTTPException(status_code=400, detail="File provided is not an image.") |
|
|
|
|
|
try: |
|
|
image_bytes = await file.read() |
|
|
image = Image.open(io.BytesIO(image_bytes)) |
|
|
result = run_diagnosis_logic(image) |
|
|
|
|
|
if "error" in result: |
|
|
raise HTTPException(status_code=500, detail=result["error"]) |
|
|
|
|
|
return JSONResponse(content=result) |
|
|
except Exception as e: |
|
|
print(f"β API Error: {e}") |
|
|
raise HTTPException(status_code=500, detail=f"An internal server error occurred: {e}") |
|
|
|
|
|
|
|
|
if gradio_app: |
|
|
app = gr.mount_gradio_app(app, gradio_app, path="/") |
|
|
print("β
Gradio UI has been mounted on the FastAPI server at the root path '/'.") |
|
|
|
|
|
|
|
|
|