init
This commit is contained in:
53
backend/jsonx.py
Normal file
53
backend/jsonx.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""Robustes JSON-Parsen von LLM-Antworten: Modelle liefern Fences, Prosa drumherum
|
||||
oder Präfixe — wir suchen das erste vollständige JSON-Objekt/-Array."""
|
||||
|
||||
import json
|
||||
import re
|
||||
|
||||
_FENCE = re.compile(r"```(?:json)?\s*(.*?)```", re.DOTALL)
|
||||
|
||||
|
||||
def parse(text: str):
|
||||
"""→ Objekt oder None. Nie werfen — der Aufrufer entscheidet über Retry."""
|
||||
if not text:
|
||||
return None
|
||||
m = _FENCE.search(text)
|
||||
if m:
|
||||
text = m.group(1)
|
||||
text = text.strip()
|
||||
# Das FRÜHESTE Klammerzeichen entscheidet: sonst gewinnt ein {…} im Array-Inneren.
|
||||
erste = sorted((("{", "}"), ("[", "]")),
|
||||
key=lambda p: text.find(p[0]) if p[0] in text else len(text))
|
||||
for start_ch, end_ch in erste:
|
||||
start = text.find(start_ch)
|
||||
if start < 0:
|
||||
continue
|
||||
depth = 0
|
||||
in_str = False
|
||||
esc = False
|
||||
for i in range(start, len(text)):
|
||||
c = text[i]
|
||||
if esc:
|
||||
esc = False
|
||||
continue
|
||||
if c == "\\":
|
||||
esc = in_str
|
||||
continue
|
||||
if c == '"':
|
||||
in_str = not in_str
|
||||
continue
|
||||
if in_str:
|
||||
continue
|
||||
if c == start_ch:
|
||||
depth += 1
|
||||
elif c == end_ch:
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
try:
|
||||
return json.loads(text[start:i + 1])
|
||||
except ValueError:
|
||||
break
|
||||
try:
|
||||
return json.loads(text)
|
||||
except ValueError:
|
||||
return None
|
||||
Reference in New Issue
Block a user