fix(common): more robust JSON string loading#1350
fix(common): more robust JSON string loading#1350opposj wants to merge 2 commits intoagentscope-ai:mainfrom
Conversation
| if isinstance(result, dict): | ||
| return result | ||
| result = repair_json(json_str, stream_stable=True) | ||
| while not isinstance(result := json.loads(result), dict): |
There was a problem hiding this comment.
@opposj This introduces an infinite loop — the loop body is ... (no-op), so if json.loads(result) never returns a dict, it will loop forever. What's the intention here?
There was a problem hiding this comment.
Actually, an infinite loop is technically impossible due to the "reduction" behavior of json.loads. Given any object, json.loads will never return itself unchanged. A possible type from dict[str, Any] | list[Any] | str | float | int | bool | None is always guaranteed, or an exception is raised. For any return type that is not a dict or str, when fed into json.loads again, an exception occurs, and we have captured it correctly. For str, as mentioned before, json.loads will never infinitely resolve a string; every time a string is fed, the output is shortened until an exception is hit. Overall, as our goal is to return a valid dict, iteratively checking for a potentially "nested" string is a more robust method with no risk introduced :)
I have added a simple example that demonstrates this "nested" case in the comment of the changed code.
AgentScope Version
1.0.17
Description
I encountered a JSON parsing issue while working with a locally deployed vLLM model fine-tuned on the Qwen-3 series. With tool calls resolved by Hermes, I obtained the following function argument (take an example):
Currently, the JSON parsing in
agentscope/src/agentscope/_utils/_common.py
Line 31 in c19b8bc
Still a string and fails the
isinstancecheck. However, it can actually be parsed viajson.loadsagain:Based on this observation, it is more robust to iteratively parse the raw string until a
dictcheck is satisfied, and that's all about this commit. This commit is fully backward compatible and does not affect any other components, just providing a more robust JSON string parsing.Checklist
Please check the following items before code is ready to be reviewed.
pre-commit run --all-filescommand