Spaces:
Sleeping
Sleeping
Upload app.py
Browse files
app.py
CHANGED
|
@@ -325,13 +325,36 @@ Now return a NEW JSON different from the example.
|
|
| 325 |
|
| 326 |
|
| 327 |
def try_parse_json(text: str) -> Optional[Dict[str, Any]]:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 328 |
if not text:
|
| 329 |
return None
|
| 330 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 331 |
if not match:
|
| 332 |
return None
|
|
|
|
|
|
|
| 333 |
try:
|
| 334 |
-
return json.loads(
|
| 335 |
except Exception:
|
| 336 |
return None
|
| 337 |
|
|
@@ -403,26 +426,66 @@ def model_call(prompt: str) -> str:
|
|
| 403 |
|
| 404 |
|
| 405 |
def normalize_output(
|
| 406 |
-
data: Dict[str, Any],
|
|
|
|
|
|
|
|
|
|
| 407 |
) -> Dict[str, Any]:
|
| 408 |
-
|
| 409 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 410 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 411 |
q = (q + [""] * 4)[:4]
|
|
|
|
|
|
|
|
|
|
| 412 |
m = (m + [""] * 2)[:2]
|
| 413 |
|
|
|
|
| 414 |
if not data.get("tone"):
|
| 415 |
if lang == "fr":
|
| 416 |
tone = "ludique" if variant == "best" else "sincère"
|
| 417 |
else:
|
| 418 |
tone = "playful" if variant == "best" else "sincere"
|
| 419 |
else:
|
| 420 |
-
tone = str(data
|
| 421 |
|
|
|
|
| 422 |
safety_notes = str(data.get("safety_notes", ""))
|
| 423 |
|
| 424 |
return {
|
| 425 |
-
"category":
|
| 426 |
"language": lang,
|
| 427 |
"questions": q,
|
| 428 |
"micro_actions": m,
|
|
|
|
| 325 |
|
| 326 |
|
| 327 |
def try_parse_json(text: str) -> Optional[Dict[str, Any]]:
|
| 328 |
+
"""
|
| 329 |
+
Try to extract a JSON object from the model output.
|
| 330 |
+
Handles cases where the model wraps JSON in ``` or ```json fences.
|
| 331 |
+
"""
|
| 332 |
if not text:
|
| 333 |
return None
|
| 334 |
+
|
| 335 |
+
stripped = text.strip()
|
| 336 |
+
|
| 337 |
+
# If the model wrapped the JSON in ``` or ```json fences, strip them.
|
| 338 |
+
if stripped.startswith("```"):
|
| 339 |
+
lines = stripped.splitlines()
|
| 340 |
+
|
| 341 |
+
# Drop the first line (``` or ```json)
|
| 342 |
+
lines = lines[1:]
|
| 343 |
+
|
| 344 |
+
# Drop final line if it's a closing fence
|
| 345 |
+
if lines and lines[-1].strip().startswith("```"):
|
| 346 |
+
lines = lines[:-1]
|
| 347 |
+
|
| 348 |
+
stripped = "\n".join(lines).strip()
|
| 349 |
+
|
| 350 |
+
# Now look for the first {...} block
|
| 351 |
+
match = re.search(r"\{[\s\S]*\}", stripped)
|
| 352 |
if not match:
|
| 353 |
return None
|
| 354 |
+
|
| 355 |
+
candidate = match.group(0)
|
| 356 |
try:
|
| 357 |
+
return json.loads(candidate)
|
| 358 |
except Exception:
|
| 359 |
return None
|
| 360 |
|
|
|
|
| 426 |
|
| 427 |
|
| 428 |
def normalize_output(
|
| 429 |
+
data: Dict[str, Any],
|
| 430 |
+
lang: str,
|
| 431 |
+
category_key: str,
|
| 432 |
+
variant: str
|
| 433 |
) -> Dict[str, Any]:
|
| 434 |
+
"""
|
| 435 |
+
Make model output always valid, even if the model returns emojis, wrong category labels,
|
| 436 |
+
capitalized names, or unexpected keys.
|
| 437 |
+
"""
|
| 438 |
+
|
| 439 |
+
# --- FIX CATEGORY ---
|
| 440 |
+
raw_cat = str(data.get("category", "")).strip()
|
| 441 |
+
|
| 442 |
+
# Strip emojis
|
| 443 |
+
raw_cat = re.sub(r"[^\w\- ]+", "", raw_cat)
|
| 444 |
|
| 445 |
+
# Lowercase
|
| 446 |
+
raw_cat = raw_cat.lower()
|
| 447 |
+
|
| 448 |
+
# Map likely variants to internal keys
|
| 449 |
+
mapping = {
|
| 450 |
+
"alimentation": "alimentation",
|
| 451 |
+
"nutrition": "alimentation",
|
| 452 |
+
"mouvement": "mouvement",
|
| 453 |
+
"movement": "mouvement",
|
| 454 |
+
"cerveau": "cerveau",
|
| 455 |
+
"brain": "cerveau",
|
| 456 |
+
"liens": "liens",
|
| 457 |
+
"links": "liens",
|
| 458 |
+
"bienetre": "bien-etre",
|
| 459 |
+
"bien-etre": "bien-etre",
|
| 460 |
+
"wellbeing": "bien-etre",
|
| 461 |
+
"well being": "bien-etre",
|
| 462 |
+
}
|
| 463 |
+
|
| 464 |
+
# Choose corrected category
|
| 465 |
+
clean_cat = mapping.get(raw_cat, category_key)
|
| 466 |
+
|
| 467 |
+
# --- FIX QUESTIONS ---
|
| 468 |
+
q = [str(x).strip() for x in data.get("questions", []) if str(x).strip()]
|
| 469 |
q = (q + [""] * 4)[:4]
|
| 470 |
+
|
| 471 |
+
# --- FIX MICRO-ACTIONS ---
|
| 472 |
+
m = [str(x).strip() for x in data.get("micro_actions", []) if str(x).strip()]
|
| 473 |
m = (m + [""] * 2)[:2]
|
| 474 |
|
| 475 |
+
# --- FIX TONE ---
|
| 476 |
if not data.get("tone"):
|
| 477 |
if lang == "fr":
|
| 478 |
tone = "ludique" if variant == "best" else "sincère"
|
| 479 |
else:
|
| 480 |
tone = "playful" if variant == "best" else "sincere"
|
| 481 |
else:
|
| 482 |
+
tone = str(data.get("tone")).strip().lower()
|
| 483 |
|
| 484 |
+
# --- SAFETY NOTES ---
|
| 485 |
safety_notes = str(data.get("safety_notes", ""))
|
| 486 |
|
| 487 |
return {
|
| 488 |
+
"category": clean_cat,
|
| 489 |
"language": lang,
|
| 490 |
"questions": q,
|
| 491 |
"micro_actions": m,
|