RantoG commited on
Commit
fb38519
·
verified ·
1 Parent(s): 53b1c3d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -31
app.py CHANGED
@@ -4,7 +4,7 @@ from google import genai
4
  from google.genai import types
5
  import os
6
  import json
7
- import re
8
  import random
9
  from dotenv import load_dotenv
10
  import requests
@@ -133,28 +133,17 @@ def format_user_context(context_data):
133
  2. DAILY STATUS: Target Calories: {stats.get('target_calories', 2000)} kcal, CONSUMED: {stats.get('consumed_calories', 0)} kcal.
134
  """
135
 
136
- # --- NEW HELPER: SUPER ROBUST NUMBER EXTRACTOR ---
137
  def get_safe_float(data, targets):
138
- """
139
- Mencari nilai float dari dict SECARA CASE-INSENSITIVE.
140
- Juga menangani jika nilai berupa string (e.g., "350 kcal").
141
- """
142
- # 1. Normalkan semua key di data menjadi huruf kecil
143
  data_lower = {k.lower(): v for k, v in data.items()}
144
-
145
  for t in targets:
146
- # Cek target (huruf kecil)
147
  if t in data_lower:
148
  val = data_lower[t]
149
  try:
150
- # Jika angka langsung
151
- if isinstance(val, (int, float)):
152
- return float(val)
153
- # Jika string ("350 kcal"), ambil angkanya saja
154
  if isinstance(val, str):
155
  nums = re.findall(r"[-+]?\d*\.\d+|\d+", val)
156
- if nums:
157
- return float(nums[0])
158
  except:
159
  continue
160
  return 0.0
@@ -165,7 +154,7 @@ def get_safe_float(data, targets):
165
  def home():
166
  return jsonify({
167
  "status": "online",
168
- "message": "GastroGuard AI Backend is Running (Case-Insensitive Mode)!",
169
  "endpoints": ["/analyze-text", "/analyze-image", "/chat"]
170
  })
171
 
@@ -220,12 +209,10 @@ OUTPUT JSON FORMAT:
220
  )
221
 
222
  result = json.loads(clean_json_text(response.text))
223
-
224
  food_data = result.get("data_makanan", {})
225
  nutrisi = food_data.get("nutrisi", {})
226
  decision = result.get("keputusan_sistem", {})
227
 
228
- # Ekstraksi Aman (Bilingual & Case Insensitive)
229
  cal = get_safe_float(nutrisi, ["kalori", "calories", "energy", "kcal"])
230
  prot = get_safe_float(nutrisi, ["protein", "protien"])
231
  carb = get_safe_float(nutrisi, ["karbohidrat", "carbs", "carbohydrate", "karbo"])
@@ -315,7 +302,6 @@ OUTPUT SCHEMA (STRICT):
315
  nutrisi = food_data.get("nutrisi", {})
316
  decision = result.get("keputusan_sistem", {})
317
 
318
- # Ekstraksi Aman
319
  cal = get_safe_float(nutrisi, ["kalori", "calories", "energy", "kcal"])
320
  prot = get_safe_float(nutrisi, ["protein"])
321
  carb = get_safe_float(nutrisi, ["karbohidrat", "carbs"])
@@ -361,10 +347,9 @@ CONTEXT: {user_context_str}
361
  USER MESSAGE: "{message}"
362
 
363
  MANDATORY INSTRUCTIONS:
364
- 1. If the user mentions ANY food name (e.g., "I want to eat X", "X calories?", "Eating X"):
365
- - YOU MUST ESTIMATE THE NUTRITION FACTS in 'data_makanan'.
366
- - DO NOT leave calorie values as 0.
367
- - FILL 'nama_menu' with the specific food name.
368
  2. If no food is mentioned, keep nutrition 0.
369
  3. RETURN JSON ONLY.
370
 
@@ -393,22 +378,36 @@ OUTPUT JSON SCHEMA:
393
  base_reply = result.get("chat_response", "")
394
  food_data = result.get("data_makanan", {})
395
  nutrisi = food_data.get("nutrisi", {})
 
396
 
397
- # --- DEBUG PRINT (WAJIB DILIHAT DI LOGS) ---
398
- print(f"DEBUG CHAT JSON: {json.dumps(result, indent=2)}")
399
-
400
- # --- FIX UTAMA: EKSTRAKSI AMAN ---
401
  cal_val = get_safe_float(nutrisi, ["kalori", "calories", "energy", "kcal"])
402
  prot = get_safe_float(nutrisi, ["protein", "protien"])
403
  carb = get_safe_float(nutrisi, ["karbohidrat", "carbs", "carbohydrate", "gula"])
404
  fat = get_safe_float(nutrisi, ["lemak_total", "fat", "fats", "lemak"])
405
 
406
  menu_name = food_data.get("nama_menu")
407
-
408
- # LOGIKA DISPLAY: Jika kalori > 0, TEMPEL TEKS.
 
 
 
 
 
 
 
 
 
 
 
409
  if cal_val > 0:
410
  display_name = menu_name if menu_name else "Food"
411
- nutrition_text = f"\n\n📊 **{display_name} Info:**\n🔥 {int(cal_val)} kcal | 🥩 P: {int(prot)}g | 🍞 C: {int(carb)}g | 🥑 F: {int(fat)}g"
 
 
 
 
 
412
  final_reply = base_reply + nutrition_text
413
  else:
414
  final_reply = base_reply
@@ -420,7 +419,7 @@ OUTPUT JSON SCHEMA:
420
  "protein": prot,
421
  "carbs": carb,
422
  "fat": fat,
423
- "health_tip": result.get("keputusan_sistem", {}).get("alasan_utama", "")
424
  }
425
  return jsonify(mapped_result)
426
 
 
4
  from google.genai import types
5
  import os
6
  import json
7
+ import re # Import Regex untuk "mencuri" angka dari teks
8
  import random
9
  from dotenv import load_dotenv
10
  import requests
 
133
  2. DAILY STATUS: Target Calories: {stats.get('target_calories', 2000)} kcal, CONSUMED: {stats.get('consumed_calories', 0)} kcal.
134
  """
135
 
 
136
  def get_safe_float(data, targets):
137
+ """Mencari nilai float dari dict SECARA CASE-INSENSITIVE."""
 
 
 
 
138
  data_lower = {k.lower(): v for k, v in data.items()}
 
139
  for t in targets:
 
140
  if t in data_lower:
141
  val = data_lower[t]
142
  try:
143
+ if isinstance(val, (int, float)): return float(val)
 
 
 
144
  if isinstance(val, str):
145
  nums = re.findall(r"[-+]?\d*\.\d+|\d+", val)
146
+ if nums: return float(nums[0])
 
147
  except:
148
  continue
149
  return 0.0
 
154
  def home():
155
  return jsonify({
156
  "status": "online",
157
+ "message": "GastroGuard AI Backend (Regex Fallback Enabled)",
158
  "endpoints": ["/analyze-text", "/analyze-image", "/chat"]
159
  })
160
 
 
209
  )
210
 
211
  result = json.loads(clean_json_text(response.text))
 
212
  food_data = result.get("data_makanan", {})
213
  nutrisi = food_data.get("nutrisi", {})
214
  decision = result.get("keputusan_sistem", {})
215
 
 
216
  cal = get_safe_float(nutrisi, ["kalori", "calories", "energy", "kcal"])
217
  prot = get_safe_float(nutrisi, ["protein", "protien"])
218
  carb = get_safe_float(nutrisi, ["karbohidrat", "carbs", "carbohydrate", "karbo"])
 
302
  nutrisi = food_data.get("nutrisi", {})
303
  decision = result.get("keputusan_sistem", {})
304
 
 
305
  cal = get_safe_float(nutrisi, ["kalori", "calories", "energy", "kcal"])
306
  prot = get_safe_float(nutrisi, ["protein"])
307
  carb = get_safe_float(nutrisi, ["karbohidrat", "carbs"])
 
347
  USER MESSAGE: "{message}"
348
 
349
  MANDATORY INSTRUCTIONS:
350
+ 1. If the user mentions ANY food name (e.g., "I want to eat X", "X calories?"):
351
+ - IGNORE Safety checks for a moment, and FOCUS ON ESTIMATING NUTRITION in 'data_makanan'.
352
+ - ESTIMATE VALUES EVEN IF UNSURE.
 
353
  2. If no food is mentioned, keep nutrition 0.
354
  3. RETURN JSON ONLY.
355
 
 
378
  base_reply = result.get("chat_response", "")
379
  food_data = result.get("data_makanan", {})
380
  nutrisi = food_data.get("nutrisi", {})
381
+ decision = result.get("keputusan_sistem", {})
382
 
383
+ # 1. Cek JSON Normal
 
 
 
384
  cal_val = get_safe_float(nutrisi, ["kalori", "calories", "energy", "kcal"])
385
  prot = get_safe_float(nutrisi, ["protein", "protien"])
386
  carb = get_safe_float(nutrisi, ["karbohidrat", "carbs", "carbohydrate", "gula"])
387
  fat = get_safe_float(nutrisi, ["lemak_total", "fat", "fats", "lemak"])
388
 
389
  menu_name = food_data.get("nama_menu")
390
+
391
+ # 2. JURUS PAMUNGKAS (REGEX FALLBACK)
392
+ # Jika JSON kosong (0), tapi AI nulis angka di teks (misal: "Adding 350 kcal..."), kita curi angkanya.
393
+ if cal_val == 0:
394
+ combined_text = base_reply + " " + decision.get("alasan_utama", "")
395
+ # Cari pola angka + kcal/cal/calories
396
+ found_cals = re.findall(r"(\d+)\s*(?:kcal|cal|calories)", combined_text, re.IGNORECASE)
397
+ if found_cals:
398
+ cal_val = float(found_cals[0]) # Ambil angka pertama yang ketemu
399
+ if not menu_name: # Jika nama menu kosong, coba ambil dari chat
400
+ menu_name = "Detected Food"
401
+
402
+ # 3. LOGIKA DISPLAY: Jika kalori > 0 (baik dari JSON atau curian), TEMPEL TEKS.
403
  if cal_val > 0:
404
  display_name = menu_name if menu_name else "Food"
405
+ # Jika protein/carb/fat masih 0 (karena hasil curian regex cuma kalori), set "-" agar rapi
406
+ p_str = f"{int(prot)}g" if prot > 0 else "?"
407
+ c_str = f"{int(carb)}g" if carb > 0 else "?"
408
+ f_str = f"{int(fat)}g" if fat > 0 else "?"
409
+
410
+ nutrition_text = f"\n\n📊 **{display_name} Info:**\n🔥 {int(cal_val)} kcal | 🥩 P: {p_str} | 🍞 C: {c_str} | 🥑 F: {f_str}"
411
  final_reply = base_reply + nutrition_text
412
  else:
413
  final_reply = base_reply
 
419
  "protein": prot,
420
  "carbs": carb,
421
  "fat": fat,
422
+ "health_tip": decision.get("alasan_utama", "")
423
  }
424
  return jsonify(mapped_result)
425