| import os |
|
|
| os.environ["TRANSFORMERS_CACHE"] = "/tmp/huggingface" |
| os.environ["HF_HOME"] = "/tmp/huggingface" |
|
|
| from fastapi import FastAPI, UploadFile, File |
| from fastapi.middleware.cors import CORSMiddleware |
| from transformers import pipeline, AutoTokenizer |
| from PIL import Image |
| import numpy as np |
| import uvicorn |
| from tensorflow.keras.models import load_model |
| import os |
| import hashlib |
| import diskcache |
| import json |
|
|
| |
| app = FastAPI() |
|
|
| |
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=[ |
| "https://agro-lens-web.vercel.app", |
| "http://localhost:3000", |
| ], |
| allow_credentials=True, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| |
| cache = diskcache.Cache("/tmp/cache") |
|
|
| |
| model_path = os.path.join( |
| os.path.dirname(__file__), "saved_model", "multidisease_model.h5" |
| ) |
| if not os.path.exists(model_path): |
| raise FileNotFoundError(f"Model tidak ditemukan di path: {model_path}") |
| image_model = load_model(model_path) |
|
|
| label_map = { |
| 0: "BacterialBlight", |
| 1: "Blast", |
| 2: "Brownspot", |
| 3: "Healthy", |
| 4: "Leaf_Scald", |
| 5: "Tungro", |
| } |
| label_descriptions = { |
| "BacterialBlight": "Penyakit akibat bakteri yang menyebabkan bercak air dan layu.", |
| "Blast": "Penyakit jamur yang menyerang leher malai dan daun.", |
| "Brownspot": "Terdapat bercak coklat bulat di permukaan daun.", |
| "Healthy": "Tanaman padi dalam kondisi sehat tanpa gejala penyakit.", |
| "Leaf_Scald": "Daun mengering dari ujung dan terbakar karena patogen atau cuaca ekstrem.", |
| "Tungro": "Penyakit virus yang membuat daun menguning dan pertumbuhan terhambat.", |
| } |
|
|
| |
| chatbot = pipeline( |
| "text-generation", |
| model="ARusDian/AgroLens-Chatbot", |
| tokenizer="ARusDian/AgroLens-Chatbot", |
| ) |
|
|
|
|
| def preprocess_image(image: Image.Image): |
| image = image.resize((224, 224)) |
| img_array = np.array(image) / 255.0 |
| img_array = np.expand_dims(img_array, axis=0) |
| return img_array |
|
|
|
|
| def hash_image(image: Image.Image) -> str: |
| """Generate hash for image content.""" |
| image_bytes = image.tobytes() |
| return hashlib.md5(image_bytes).hexdigest() |
|
|
|
|
| @app.get("/") |
| def root(): |
| return {"ok": True} |
|
|
|
|
| |
| @app.post("/predict-image") |
| async def predict_image(file: UploadFile = File(...)): |
| image = Image.open(file.file).convert("RGB") |
| image_hash = hash_image(image) |
|
|
| if image_hash in cache: |
| return cache[image_hash] |
|
|
| input_tensor = preprocess_image(image) |
| pred = np.argmax(image_model.predict(input_tensor), axis=1)[0] |
| label = label_map.get(pred, "Tidak dikenal") |
| description = label_descriptions.get(label, "-") |
|
|
| result = {"prediction": label, "description": description} |
| cache[image_hash] = result |
| return result |
|
|
|
|
| |
| @app.post("/chatbot") |
| async def describe(prompt: dict): |
| text = prompt["prompt"] |
| key = hashlib.md5(text.encode()).hexdigest() |
|
|
| if key in cache: |
| return {"response": cache[key]} |
|
|
| tokenizer = AutoTokenizer.from_pretrained("ARusDian/AgroLens-Chatbot") |
| result = chatbot( |
| text, |
| max_new_tokens=120, |
| temperature=0.5, |
| top_p=0.85, |
| repetition_penalty=1.4, |
| no_repeat_ngram_size=5, |
| do_sample=True, |
| eos_token_id=tokenizer.eos_token_id, |
| )[0]["generated_text"] |
|
|
| cache[key] = result |
| return {"response": result} |
|
|
|
|
| |
| if __name__ == "__main__": |
| uvicorn.run("app:app", host="0.0.0.0", port=8000) |
|
|