File size: 3,642 Bytes
8733d64 fb4b43b 8733d64 4418b9b dda7755 4418b9b dda7755 4418b9b dda7755 4418b9b bd002c5 4418b9b dda7755 4418b9b dda7755 4418b9b dda7755 4418b9b dda7755 31dca8d a747b47 31dca8d a747b47 dda7755 4418b9b dda7755 4418b9b dda7755 4418b9b dda7755 4418b9b dda7755 4418b9b dda7755 4418b9b dda7755 4418b9b dda7755 4418b9b f8340db | 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 | 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
# === Inisialisasi FastAPI ===
app = FastAPI()
# === CORS ===
app.add_middleware(
CORSMiddleware,
allow_origins=[
"https://agro-lens-web.vercel.app", # ini penting!
"http://localhost:3000", # opsional untuk dev lokal
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# === Inisialisasi Cache ===
cache = diskcache.Cache("/tmp/cache")
# === Load Model Gambar ===
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.",
}
# === Load Chatbot ===
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}
# === Endpoint: Prediksi Gambar ===
@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
# === Endpoint: Chatbot ===
@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}
# === Run lokal (tidak dipakai di Spaces) ===
if __name__ == "__main__":
uvicorn.run("app:app", host="0.0.0.0", port=8000)
|