Spaces:
Running on Zero
Running on Zero
fix(vlm): _clean_json returns first complete JSON object, not brace span
Browse filesfind('{')..rfind('}') spans two emitted objects (e.g. an example then the
answer) and fails the caller's json.loads. Use JSONDecoder().raw_decode to
take the first complete object; fall back to the brace span on decode error.
Takes effect live only after a Space redeploy (scripts/sync_spaces.ps1).
Not CI-unit-testable: the module eager-loads the model at import.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
app.py
CHANGED
|
@@ -25,6 +25,7 @@ clean JSON.
|
|
| 25 |
|
| 26 |
from __future__ import annotations
|
| 27 |
|
|
|
|
| 28 |
import re
|
| 29 |
|
| 30 |
import cv2
|
|
@@ -104,9 +105,18 @@ def _clean_json(text: str) -> str:
|
|
| 104 |
fence = re.search(r"```(?:json)?\s*(.*?)```", text, flags=re.DOTALL)
|
| 105 |
if fence:
|
| 106 |
text = fence.group(1)
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
return text.strip()
|
| 111 |
|
| 112 |
|
|
|
|
| 25 |
|
| 26 |
from __future__ import annotations
|
| 27 |
|
| 28 |
+
import json
|
| 29 |
import re
|
| 30 |
|
| 31 |
import cv2
|
|
|
|
| 105 |
fence = re.search(r"```(?:json)?\s*(.*?)```", text, flags=re.DOTALL)
|
| 106 |
if fence:
|
| 107 |
text = fence.group(1)
|
| 108 |
+
# Return the FIRST complete JSON object. A plain find('{')..rfind('}') span
|
| 109 |
+
# breaks when the model emits two objects (e.g. an example then the answer):
|
| 110 |
+
# the slice would span the gap between them and fail the caller's json.loads.
|
| 111 |
+
start = text.find("{")
|
| 112 |
+
if start != -1:
|
| 113 |
+
try:
|
| 114 |
+
obj, _ = json.JSONDecoder().raw_decode(text[start:])
|
| 115 |
+
return json.dumps(obj)
|
| 116 |
+
except json.JSONDecodeError:
|
| 117 |
+
end = text.rfind("}") # fallback: original brace-span heuristic
|
| 118 |
+
if end > start:
|
| 119 |
+
return text[start : end + 1].strip()
|
| 120 |
return text.strip()
|
| 121 |
|
| 122 |
|