ripguy Claude Opus 4.8 (1M context) commited on
Commit
6341d31
·
1 Parent(s): 7f5b7cf

fix(vlm): _clean_json returns first complete JSON object, not brace span

Browse files

find('{')..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>

Files changed (1) hide show
  1. app.py +13 -3
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
- start, end = text.find("{"), text.rfind("}")
108
- if start != -1 and end > start:
109
- text = text[start : end + 1]
 
 
 
 
 
 
 
 
 
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