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)