Update app.py
Browse files
app.py
CHANGED
|
@@ -435,35 +435,55 @@ def extract_json_from_llm_response(raw_response: str) -> dict:
|
|
| 435 |
logger.error("Sanitized JSON still invalid:\n%s", json_string)
|
| 436 |
raise
|
| 437 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 438 |
def clean_base64_for_model(raw_b64):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
if not raw_b64:
|
| 440 |
return ""
|
| 441 |
-
|
| 442 |
-
# If it
|
| 443 |
if isinstance(raw_b64, list):
|
| 444 |
-
if
|
|
|
|
| 445 |
return ""
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 450 |
if not isinstance(raw_b64, str):
|
| 451 |
-
raise TypeError(f"Expected base64 string, got {type(raw_b64)}")
|
| 452 |
-
|
| 453 |
-
#
|
| 454 |
clean_b64 = re.sub(r"^data:image\/[a-zA-Z]+;base64,", "", raw_b64)
|
| 455 |
clean_b64 = clean_b64.replace("\n", "").replace("\r", "").strip()
|
| 456 |
-
|
| 457 |
-
# Validate
|
| 458 |
try:
|
| 459 |
base64.b64decode(clean_b64)
|
| 460 |
except Exception as e:
|
| 461 |
logger.error(f"Invalid Base64 passed to model: {e}")
|
| 462 |
raise
|
| 463 |
-
|
|
|
|
| 464 |
return f"data:image/png;base64,{clean_b64}"
|
| 465 |
|
| 466 |
|
|
|
|
| 467 |
# Node 1: Logic updating if any issue here
|
| 468 |
def pseudo_generator_node(state: GameState):
|
| 469 |
logger.info("--- Running plan_logic_aligner_node ---")
|
|
|
|
| 435 |
logger.error("Sanitized JSON still invalid:\n%s", json_string)
|
| 436 |
raise
|
| 437 |
|
| 438 |
+
import re
|
| 439 |
+
import io
|
| 440 |
+
import base64
|
| 441 |
+
from PIL import Image
|
| 442 |
+
|
| 443 |
def clean_base64_for_model(raw_b64):
|
| 444 |
+
"""
|
| 445 |
+
Normalize input into a valid data:image/png;base64,<payload> string.
|
| 446 |
+
|
| 447 |
+
Accepts:
|
| 448 |
+
- a list of base64 strings → picks the first element
|
| 449 |
+
- a PIL Image instance → encodes to PNG/base64
|
| 450 |
+
- a raw base64 string → strips whitespace and data URI prefix
|
| 451 |
+
"""
|
| 452 |
if not raw_b64:
|
| 453 |
return ""
|
| 454 |
+
|
| 455 |
+
# 1. If it’s a list, take its first element
|
| 456 |
if isinstance(raw_b64, list):
|
| 457 |
+
raw_b64 = raw_b64[0] if raw_b64 else ""
|
| 458 |
+
if not raw_b64:
|
| 459 |
return ""
|
| 460 |
+
|
| 461 |
+
# 2. If it’s a PIL Image, convert to base64
|
| 462 |
+
if isinstance(raw_b64, Image.Image):
|
| 463 |
+
buf = io.BytesIO()
|
| 464 |
+
raw_b64.save(buf, format="PNG")
|
| 465 |
+
raw_b64 = base64.b64encode(buf.getvalue()).decode()
|
| 466 |
+
|
| 467 |
+
# 3. At this point it must be a string
|
| 468 |
if not isinstance(raw_b64, str):
|
| 469 |
+
raise TypeError(f"Expected base64 string or PIL Image, got {type(raw_b64)}")
|
| 470 |
+
|
| 471 |
+
# 4. Strip any existing data URI prefix, whitespace, or newlines
|
| 472 |
clean_b64 = re.sub(r"^data:image\/[a-zA-Z]+;base64,", "", raw_b64)
|
| 473 |
clean_b64 = clean_b64.replace("\n", "").replace("\r", "").strip()
|
| 474 |
+
|
| 475 |
+
# 5. Validate it’s proper base64
|
| 476 |
try:
|
| 477 |
base64.b64decode(clean_b64)
|
| 478 |
except Exception as e:
|
| 479 |
logger.error(f"Invalid Base64 passed to model: {e}")
|
| 480 |
raise
|
| 481 |
+
|
| 482 |
+
# 6. Return with the correct data URI prefix
|
| 483 |
return f"data:image/png;base64,{clean_b64}"
|
| 484 |
|
| 485 |
|
| 486 |
+
|
| 487 |
# Node 1: Logic updating if any issue here
|
| 488 |
def pseudo_generator_node(state: GameState):
|
| 489 |
logger.info("--- Running plan_logic_aligner_node ---")
|