Wills17 commited on
Commit
c1d85a4
·
verified ·
1 Parent(s): 15e9a5a

Update FastAPI_app.py

Browse files
Files changed (1) hide show
  1. FastAPI_app.py +86 -8
FastAPI_app.py CHANGED
@@ -20,11 +20,11 @@ from fastapi.middleware.cors import CORSMiddleware
20
  import torch
21
  import tensorflow as tf
22
  import google.generativeai as genai
23
- from transformers import AutoTokenizer, AutoModelForCausalLM
24
 
25
 
26
  # Ingredient model (load once)
27
- MODEL_PATH = "models/ingredient_model.h5"
28
  if not os.path.exists(MODEL_PATH):
29
  raise FileNotFoundError(f"Ingredient model not found at {MODEL_PATH}")
30
 
@@ -53,7 +53,38 @@ def timeout_handler(signum, frame):
53
  _lock = threading.Lock()
54
  _tokenizer = None
55
  _model = None
 
 
 
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  def load_Qwen():
58
  global _tokenizer, _model
59
  if _model is not None:
@@ -70,8 +101,7 @@ def load_Qwen():
70
  return _tokenizer, _model
71
 
72
  except TimeoutError:
73
- print("\n🔴 [Fallback] Qwen load timed out.")
74
- raise RuntimeError("\n🔴 Model load failed.")
75
 
76
 
77
  def generate_recipe_qwen(ingredient_names):
@@ -126,7 +156,7 @@ def infer_image(pil_image):
126
  img = pil_image.resize((224, 224))
127
  arr = np.expand_dims(np.array(img) / 255.0, axis=0)
128
  preds = MODEL.predict(arr)[0]
129
- top_idxs = np.argsort(preds)[::-1][:5]
130
  ingredients = []
131
  for i in top_idxs:
132
  ingredients.append({"name": CLASS_NAMES[i].capitalize(), "confidence": float(preds[i])})
@@ -136,12 +166,60 @@ def infer_image(pil_image):
136
 
137
  return ingredients
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
140
  # initialize FastAPI app
141
  app = FastAPI(
142
  title="Fridge2Dish",
143
  description="Upload an image → Detect ingredients → Generate recipes",
144
- version="3.0.0"
145
  )
146
 
147
  # static and templates
@@ -173,9 +251,9 @@ async def detect_ingredients(file: UploadFile = File(...)):
173
  img_bytes = await file.read()
174
  pil_img = Image.open(io.BytesIO(img_bytes)).convert("RGB")
175
 
176
- ingredients = infer_image(pil_img)
177
  end = time.time()
178
- print(f"Detected ingredients: {ingredients} (⌛ Took {end-start:.2f}s)")
179
 
180
  return {"ingredients": ingredients}
181
 
 
20
  import torch
21
  import tensorflow as tf
22
  import google.generativeai as genai
23
+ from transformers import AutoTokenizer, AutoModelForCausalLM, AutoProcessor
24
 
25
 
26
  # Ingredient model (load once)
27
+ MODEL_PATH = "models/ingredient_model_2.h5"
28
  if not os.path.exists(MODEL_PATH):
29
  raise FileNotFoundError(f"Ingredient model not found at {MODEL_PATH}")
30
 
 
53
  _lock = threading.Lock()
54
  _tokenizer = None
55
  _model = None
56
+ _florence_processor = None
57
+ _florence_model = None
58
+ _florence_lock = threading.Lock()
59
 
60
+
61
+ # Florence2 detection first time function
62
+ def load_florence2():
63
+ global _florence_processor, _florence_model
64
+ if _florence_model is not None:
65
+ return _florence_processor, _florence_model
66
+
67
+ with _florence_lock:
68
+ if _florence_model is not None:
69
+ return _florence_processor, _florence_model
70
+
71
+ try:
72
+ print("\n🔵 Loading Florence-2 for accurate detection...")
73
+ _florence_processor = AutoProcessor.from_pretrained("microsoft/Florence-2-base", trust_remote_code=True)
74
+ _florence_model = AutoModelForCausalLM.from_pretrained(
75
+ "microsoft/Florence-2-base",
76
+ torch_dtype=torch.float16,
77
+ device_map="auto",
78
+ trust_remote_code=True)
79
+
80
+ except TimeoutError:
81
+ raise RuntimeError("\n🔴 [Fallback] Florence load timed out.")
82
+
83
+ print("\n🟢 Florence-2 ready!\n")
84
+ return _florence_processor, _florence_model
85
+
86
+
87
+ # Qwen fallback first time function
88
  def load_Qwen():
89
  global _tokenizer, _model
90
  if _model is not None:
 
101
  return _tokenizer, _model
102
 
103
  except TimeoutError:
104
+ raise RuntimeError("\n🔴 [Fallback] Qwen load timed out.")
 
105
 
106
 
107
  def generate_recipe_qwen(ingredient_names):
 
156
  img = pil_image.resize((224, 224))
157
  arr = np.expand_dims(np.array(img) / 255.0, axis=0)
158
  preds = MODEL.predict(arr)[0]
159
+ top_idxs = np.argsort(preds)[::-1][:3]
160
  ingredients = []
161
  for i in top_idxs:
162
  ingredients.append({"name": CLASS_NAMES[i].capitalize(), "confidence": float(preds[i])})
 
166
 
167
  return ingredients
168
 
169
+ # Florence2 infer function
170
+ def infer_image2(pil_image):
171
+ """
172
+ Uses Florence-2 for zero-shot object detection — detects real fridge items accurately.
173
+ Returns: [{"name": "Banana", "confidence": 0.95}, ...] (top 5, confidence estimated from model output)
174
+ """
175
+ processor, model = load_florence2()
176
+
177
+ prompt = "<OD>" # Florence-2's magic prompt for detecting all objects
178
+
179
+ # Process image
180
+ inputs = processor(text=prompt, images=pil_image, return_tensors="pt")
181
+
182
+ # Generate detection
183
+ with torch.no_grad():
184
+ outputs = model.generate(
185
+ input_ids=inputs["input_ids"],
186
+ pixel_values=inputs["pixel_values"],
187
+ max_new_tokens=100,
188
+ do_sample=False,
189
+ num_beams=3
190
+ )
191
+
192
+ # Parse output (Florence-2 returns "<OD> <LOC>object1<LOC> <LOC>object2<LOC>...")
193
+ generated_text = processor.batch_decode(outputs, skip_special_tokens=True)[0]
194
+ parsed = processor.post_process_generation(
195
+ generated_text,
196
+ task=prompt,
197
+ image_size=(pil_image.width, pil_image.height)
198
+ )
199
+
200
+ # Extract detected objects (top 5, with estimated confidence based on parsing)
201
+ detected_objects = parsed.get("<OD>", [])
202
+ ingredients = []
203
+ for obj in detected_objects[:5]:
204
+ name = obj.get("labels", [obj.get("label", "Unknown")])[0] if isinstance(obj.get("labels"), list) else obj.get("label", "Unknown")
205
+
206
+ # Since Florence-2 doesn't output confidence, estimate (0.9+ for strong detections)
207
+ conf = 0.95 if len(detected_objects) > 1 else 0.70 # Simple heuristic
208
+ ingredients.append({"name": name.capitalize(), "confidence": conf})
209
+
210
+ if not ingredients:
211
+ return [{"name": "Unknown", "confidence": 0.0}]
212
+
213
+ return ingredients
214
+
215
+
216
+
217
 
218
  # initialize FastAPI app
219
  app = FastAPI(
220
  title="Fridge2Dish",
221
  description="Upload an image → Detect ingredients → Generate recipes",
222
+ version="4.0.0"
223
  )
224
 
225
  # static and templates
 
251
  img_bytes = await file.read()
252
  pil_img = Image.open(io.BytesIO(img_bytes)).convert("RGB")
253
 
254
+ ingredients = infer_image2(pil_img)
255
  end = time.time()
256
+ print(f"Top 3 Detected ingredients: {ingredients} (⌛ Took {end-start:.2f}s)")
257
 
258
  return {"ingredients": ingredients}
259