fix: improve JSON parsing error handling with bad_json mechanism
This commit is contained in:
Binary file not shown.
BIN
.vs/GenericAgent/v17/.wsuo
Normal file
BIN
.vs/GenericAgent/v17/.wsuo
Normal file
Binary file not shown.
12
.vs/GenericAgent/v17/DocumentLayout.json
Normal file
12
.vs/GenericAgent/v17/DocumentLayout.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "C:\\Users\\Ljq\\Documents\\mywork\\MyTools\\AutoOperation\\webagent\\GenericAgent\\",
|
||||
"Documents": [],
|
||||
"DocumentGroupContainers": [
|
||||
{
|
||||
"Orientation": 0,
|
||||
"VerticalTabListWidth": 256,
|
||||
"DocumentGroups": []
|
||||
}
|
||||
]
|
||||
}
|
||||
3
.vs/ProjectSettings.json
Normal file
3
.vs/ProjectSettings.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"CurrentProjectSetting": null
|
||||
}
|
||||
6
.vs/VSWorkspaceState.json
Normal file
6
.vs/VSWorkspaceState.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"ExpandedNodes": [
|
||||
""
|
||||
],
|
||||
"PreviewInSolutionExplorer": false
|
||||
}
|
||||
BIN
.vs/slnx.sqlite
Normal file
BIN
.vs/slnx.sqlite
Normal file
Binary file not shown.
@@ -24,6 +24,8 @@ class BaseHandler:
|
||||
ret = yield from try_call_generator(getattr(self, method_name), args, response)
|
||||
_ = yield from try_call_generator(self.tool_after_callback, tool_name, args, response, ret)
|
||||
return ret
|
||||
elif tool_name == 'bad_json':
|
||||
return StepOutcome(None, next_prompt=args.get('msg', 'bad_json'), should_exit=False)
|
||||
else:
|
||||
yield f"❌ 未知工具: {tool_name}\n"
|
||||
return StepOutcome(None, next_prompt=f"未知工具 {tool_name}", should_exit=False)
|
||||
|
||||
@@ -30,15 +30,14 @@ class GeneraticAgent:
|
||||
if not os.path.exists('temp'): os.makedirs('temp')
|
||||
from sidercall import sider_cookie, oai_configs, claude_configs
|
||||
llm_sessions = []
|
||||
for cfg in claude_configs.values():
|
||||
llm_sessions += [ClaudeSession(api_key=cfg['apikey'], api_base=cfg['apibase'], model=cfg['model'])]
|
||||
if sider_cookie: llm_sessions += [SiderLLMSession(default_model=x) for x in \
|
||||
["gemini-3.0-flash", "claude-haiku-4.5", "kimi-k2"]]
|
||||
for cfg in oai_configs.values():
|
||||
llm_sessions += [LLMSession(api_key=cfg['apikey'], api_base=cfg['apibase'], model=cfg['model'])]
|
||||
for cfg in claude_configs.values():
|
||||
llm_sessions += [ClaudeSession(api_key=cfg['apikey'], api_base=cfg['apibase'], model=cfg['model'])]
|
||||
if len(llm_sessions) > 0:
|
||||
llmclient = ToolClient(llm_sessions, auto_save_tokens=True)
|
||||
self.llmclient = llmclient
|
||||
self.llmclient = ToolClient(llm_sessions, auto_save_tokens=True)
|
||||
else:
|
||||
self.llmclient = None
|
||||
self.lock = threading.Lock()
|
||||
|
||||
16
ga.py
16
ga.py
@@ -84,20 +84,10 @@ def code_run(code, code_type="python", timeout=60, cwd=None, code_cwd=None, stop
|
||||
|
||||
|
||||
def ask_user(question: str, candidates: list = None):
|
||||
"""question: 向用户提出的问题。candidates: 可选的候选项列表。需要保证should_exit为True
|
||||
"""
|
||||
构造一个中断请求。
|
||||
question: 向用户提出的问题。
|
||||
candidates: 可选的候选项列表。
|
||||
需要保证should_exit为True
|
||||
"""
|
||||
return {
|
||||
"status": "INTERRUPT",
|
||||
"intent": "HUMAN_INTERVENTION",
|
||||
"data": {
|
||||
"question": question,
|
||||
"candidates": candidates or []
|
||||
}
|
||||
}
|
||||
return {"status": "INTERRUPT", "intent": "HUMAN_INTERVENTION",
|
||||
"data": {"question": question, "candidates": candidates or []}}
|
||||
|
||||
from simphtml import execute_js_rich, get_html
|
||||
|
||||
|
||||
2964
restore_commit.txt
Normal file
2964
restore_commit.txt
Normal file
File diff suppressed because it is too large
Load Diff
14
sidercall.py
14
sidercall.py
@@ -56,18 +56,18 @@ class GeminiSession:
|
||||
return iter([full_text]) if stream else full_text
|
||||
|
||||
class ClaudeSession:
|
||||
def __init__(self, api_key, api_base, model="claude-opus", context_win=32000):
|
||||
def __init__(self, api_key, api_base, model="claude-opus", context_win=24000):
|
||||
self.api_key, self.api_base, self.default_model, self.context_win = api_key, api_base.rstrip('/'), model, context_win
|
||||
self.raw_msgs, self.lock = [], threading.Lock()
|
||||
def _trim_messages(self, messages):
|
||||
total = sum(len(m['prompt'])//4 for m in messages)
|
||||
if total <= self.context_win: return messages
|
||||
trimmed = []
|
||||
target, current, result = self.context_win * 0.9, 0, []
|
||||
for msg in reversed(messages):
|
||||
if sum(len(m['prompt'])//4 for m in trimmed) + len(msg['prompt'])//4 <= self.context_win * 0.9:
|
||||
trimmed.insert(0, msg)
|
||||
if (msg_len := len(msg['prompt'])//4) + current <= target:
|
||||
result.append(msg); current += msg_len
|
||||
else: break
|
||||
return trimmed if trimmed else messages[-2:]
|
||||
return result[::-1] or messages[-2:]
|
||||
def raw_ask(self, messages, model=None, temperature=0.5, max_tokens=4096):
|
||||
model = model or self.default_model
|
||||
headers = {"x-api-key": self.api_key, "Content-Type": "application/json"}
|
||||
@@ -315,9 +315,9 @@ class ToolClient:
|
||||
args = data.get('arguments') or data.get('args') or data.get('params') or data.get('parameters')
|
||||
if args is None: args = data
|
||||
if func_name: tool_calls = [MockToolCall(func_name, args)]
|
||||
except json.JSONDecodeError:
|
||||
except json.JSONDecodeError as e:
|
||||
print("[Warn] Failed to parse tool_use JSON:", json_str)
|
||||
remaining_text += f"[Warning] JSON 解析失败,模型输出了无效的 JSON."
|
||||
tool_calls = [MockToolCall('bad_json', {'msg': f'Failed to parse tool_use JSON: {str(e)}'})]
|
||||
except Exception as e:
|
||||
print("[Error] Exception during tool_use parsing:", str(e), data)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user