Skip to content

Commit a326a9c

Browse files
committed
fix(skills): extract first JSON object instead of last from multi-object LLM output
_extract_json_object() always paired each { with the last } in the string. When the LLM emitted multiple JSON objects in one response, the first valid object was silently skipped and the later one was persisted as the skill. Use brace-counting to find the matching } for each {, returning the first complete JSON object. Fixes #3965
1 parent 2a4bba2 commit a326a9c

1 file changed

Lines changed: 15 additions & 4 deletions

File tree

services/memory/skill_extractor.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,23 @@ def _as_dict(candidate):
9393
obj = _as_dict(s)
9494
if obj is not None:
9595
return obj
96-
# Otherwise scan each '{' candidate up to the last '}'.
96+
# Otherwise scan each '{' candidate, using brace counting to find
97+
# the *first* complete JSON object rather than always pairing with
98+
# the last '}' (which silently picks a later object when the LLM
99+
# emits multiple objects in one response).
97100
start = s.find("{")
98101
while 0 <= start < end:
99-
obj = _as_dict(s[start : end + 1])
100-
if obj is not None:
101-
return obj
102+
depth = 0
103+
for i in range(start, len(s)):
104+
if s[i] == "{":
105+
depth += 1
106+
elif s[i] == "}":
107+
depth -= 1
108+
if depth == 0:
109+
obj = _as_dict(s[start : i + 1])
110+
if obj is not None:
111+
return obj
112+
break
102113
start = s.find("{", start + 1)
103114
return None
104115

0 commit comments

Comments
 (0)