Repair truncated LLM proposal JSON
This commit is contained in:
@@ -128,15 +128,50 @@ def validate_proposal(proposal: Proposal, study: StudySpec) -> Proposal:
|
||||
return proposal
|
||||
|
||||
|
||||
def _repair_json_text(text: str) -> str:
|
||||
candidate = text.strip()
|
||||
if not candidate:
|
||||
return candidate
|
||||
stack: list[str] = []
|
||||
in_string = False
|
||||
escape = False
|
||||
for char in candidate:
|
||||
if in_string:
|
||||
if escape:
|
||||
escape = False
|
||||
elif char == "\\":
|
||||
escape = True
|
||||
elif char == '"':
|
||||
in_string = False
|
||||
continue
|
||||
if char == '"':
|
||||
in_string = True
|
||||
elif char == "{":
|
||||
stack.append("}")
|
||||
elif char == "[":
|
||||
stack.append("]")
|
||||
elif char in {"}", "]"} and stack and stack[-1] == char:
|
||||
stack.pop()
|
||||
if in_string:
|
||||
candidate += '"'
|
||||
if stack:
|
||||
candidate += "".join(reversed(stack))
|
||||
return candidate
|
||||
|
||||
|
||||
def _parse_json_object_text(text: str) -> dict[str, Any]:
|
||||
try:
|
||||
payload = json.loads(text)
|
||||
except json.JSONDecodeError:
|
||||
start = text.find("{")
|
||||
end = text.rfind("}")
|
||||
if start < 0 or end < start:
|
||||
if start < 0:
|
||||
raise
|
||||
payload = json.loads(text[start : end + 1])
|
||||
end = text.rfind("}")
|
||||
candidate = text[start:] if end < start else text[start : end + 1]
|
||||
try:
|
||||
payload = json.loads(candidate)
|
||||
except json.JSONDecodeError:
|
||||
payload = json.loads(_repair_json_text(candidate))
|
||||
if not isinstance(payload, dict):
|
||||
raise SpecError("proposal payload must be a JSON object")
|
||||
return payload
|
||||
|
||||
Reference in New Issue
Block a user