Avoid ambiguous JSON array extraction
LLM responses can include bracketed prose before the actual JSON array. The old greedy regex spanned from the first '[' to the last ']', causing valid single-array answers to be dropped and making multiple arrays indistinguishable. Constraint: Keep object extraction behavior unchanged. Rejected: Return first parseable array | silently guesses when a response has multiple valid arrays. Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep array extraction conservative when more than one valid top-level array is present. Tested: uv run --with pytest pytest tests/test_json_utils.py -q Tested: uv run --with ruff ruff check skillopt/utils/json_utils.py tests/test_json_utils.py Not-tested: Full benchmark rollouts.
This commit is contained in:
@@ -5,6 +5,7 @@ import pytest
|
||||
|
||||
from skillopt.utils.json_utils import (
|
||||
_top_level_brace_objects,
|
||||
_top_level_bracket_arrays,
|
||||
extract_json,
|
||||
extract_json_array,
|
||||
)
|
||||
@@ -85,6 +86,22 @@ class TestTopLevelBraceObjects:
|
||||
assert _top_level_brace_objects(text) == ['{"edit": "right"}']
|
||||
|
||||
|
||||
class TestTopLevelBracketArrays:
|
||||
"""_top_level_bracket_arrays — string/object-aware top-level array scan."""
|
||||
|
||||
def test_single_clean_array(self) -> None:
|
||||
assert _top_level_bracket_arrays("[1, 2]") == ["[1, 2]"]
|
||||
|
||||
def test_two_top_level_arrays(self) -> None:
|
||||
assert _top_level_bracket_arrays("[1]\n[2]") == ["[1]", "[2]"]
|
||||
|
||||
def test_array_inside_object_is_ignored(self) -> None:
|
||||
assert _top_level_bracket_arrays('{"items": [1, 2]}') == []
|
||||
|
||||
def test_bracket_inside_quoted_prose_is_ignored(self) -> None:
|
||||
assert _top_level_bracket_arrays('label is "set it to [x]" done') == []
|
||||
|
||||
|
||||
class TestExtractJsonTolerantFallback:
|
||||
"""extract_json — json_repair fallback for malformed non-OpenAI output."""
|
||||
|
||||
@@ -186,3 +203,15 @@ class TestExtractJsonArray:
|
||||
"""extract_json_array should not match a bare JSON object."""
|
||||
text = '{"this is an object": true}'
|
||||
assert extract_json_array(text) is None
|
||||
|
||||
def test_ignores_prose_brackets_before_valid_array(self) -> None:
|
||||
text = "Use [not JSON] as prose. Final answer: [1, 2, 3]"
|
||||
assert extract_json_array(text) == [1, 2, 3]
|
||||
|
||||
def test_multiple_valid_arrays_are_ambiguous(self) -> None:
|
||||
text = "First candidate [1], second candidate [2]"
|
||||
assert extract_json_array(text) is None
|
||||
|
||||
def test_nested_object_array_not_confused_with_array_answer(self) -> None:
|
||||
text = '{"items": [1, 2, 3]}'
|
||||
assert extract_json_array(text) is None
|
||||
|
||||
Reference in New Issue
Block a user