fix(llm): fall back when a prefilled answer is too deeply nested to parse

json.loads raises RecursionError on deeply nested input, which escaped the
complete-JSON check and failed the request. Treat it like any other input
that is not a complete JSON document.

Signed-off-by: FenjuFu <fufenjupku@gmail.com>
This commit is contained in:
FenjuFu
2026-10-04 16:31:47 +08:00
parent af325fbb85
commit d351fc5502
2 changed files with 11 additions and 2 deletions
+4 -2
View File
@@ -54,13 +54,15 @@ def _is_json_document(content: str) -> bool:
"""Whether ``content`` is one complete JSON object or array.
Reasoning followed by a closing tag is never valid JSON, so a structured
answer that carries the tag inside a string value is left whole.
answer that carries the tag inside a string value is left whole. Input
nested too deeply to parse is not treated as JSON rather than failing the
request.
"""
stripped = content.strip()
if not stripped.startswith(("{", "[")):
return False
try:
json.loads(stripped)
except ValueError:
except (ValueError, RecursionError):
return False
return True
+7
View File
@@ -66,6 +66,13 @@ def test_strip_reasoning_prefilled(content: str, expected: str) -> None:
assert strip_reasoning(content, prefilled=True) == expected
def test_strip_reasoning_prefilled_survives_deeply_nested_json() -> None:
# Deep enough for json.loads to raise RecursionError on every supported Python.
depth = 100_000
content = "[" * depth + '"</think>"' + "]" * depth
assert strip_reasoning(content, prefilled=True) == '"' + "]" * depth
def _openai_provider(content: str, **kwargs: Any) -> OpenAIProvider:
provider = OpenAIProvider(api_key="test", **kwargs)
message = SimpleNamespace(content=content, tool_calls=None)