agentloop yield turn dict marker; agentmain intercepts and tracks per-turn outputs

This commit is contained in:
Liang Jiaqing committed 2026-05-16 17:13:42 +08:00
1 parent 1e9ed9bc38
commit cebd6a37c9
4 files changed
+24 -21

No files matched your search

+4 -2
View File
@@ -39,7 +39,8 @@ def get_pretty_json(data):
data = data.copy(); data["script"] = data["script"].replace("; ", ";\n ")
return json.dumps(data, indent=2, ensure_ascii=False).replace('\\n', '\n')
def agent_runner_loop(client, system_prompt, user_input, handler, tools_schema, max_turns=40, verbose=True, initial_user_content=None):
def agent_runner_loop(client, system_prompt, user_input, handler, tools_schema,
max_turns=40, verbose=True, initial_user_content=None, yield_info=False):
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": initial_user_content if initial_user_content is not None else user_input}
@@ -49,8 +50,9 @@ def agent_runner_loop(client, system_prompt, user_input, handler, tools_schema,
turn += 1; turnstr = f'LLM Running (Turn {turn}) ...'
if handler.parent.task_dir: turnstr = f'Turn {turn} ...'
if verbose: turnstr = f'**{turnstr}**'
if yield_info: yield {'turn': turn}
yield f"\n\n{turnstr}\n\n"
if turn%10 == 0: client.last_tools = '' # 每10轮重置一次工具描述,避免上下文过大导致的模型性能下降
if turn%10 == 0: client.last_tools = '' # 每10轮重置一次工具描述
response_gen = client.chat(messages=messages, tools=tools_schema)
if verbose:
response = yield from response_gen
+16 -12
View File
@@ -46,8 +46,8 @@ class GenericAgent:
self.task_dir = None
self.history = []; self.handler = None;
self.task_queue = queue.Queue()
self.is_running = False; self.stop_sig = False
self.llm_no = 0; self.inc_out = False; self.verbose = True
self.is_running = False; self.stop_sig = False; self.llm_no = 0;
self.inc_out = False; self.verbose = True; self.show_mode = 'text'
self.peer_hint = True
self.log_path = os.path.join(script_dir, f'temp/model_responses/model_responses_{int(time.time()*1e6)%1000000:06d}.txt')
self.load_llm_sessions()
@@ -143,21 +143,25 @@ class GenericAgent:
if ps > 0: handler.working['key_info'] += f'\n[SYSTEM] 此为 {ps} 个对话前设置的key_info,若已在新任务,先更新或清除工作记忆。\n'
self.handler = handler # although new handler, the **full** history is in llmclient, so it is full history!
self.llmclient.log_path = self.log_path
gen = agent_runner_loop(self.llmclient, sys_prompt, raw_query,
handler, TOOLS_SCHEMA, max_turns=70, verbose=self.verbose)
gen = agent_runner_loop(self.llmclient, sys_prompt, raw_query, handler, TOOLS_SCHEMA,
max_turns=80, verbose=self.verbose, yield_info=True)
try:
full_resp = ""; last_pos = 0
full_resp = ""; last_pos = 0; curr_turn = 0; turn_resps = []
for chunk in gen:
if consume_file(self.task_dir, '_stop'): self.abort()
if self.stop_sig: break
full_resp += chunk
if len(full_resp) - last_pos > 50 or 'LLM Running' in chunk:
display_queue.put({'next': full_resp[last_pos:] if self.inc_out else full_resp, 'source': source})
if isinstance(chunk, dict) and 'turn' in chunk:
curr_turn = chunk['turn']; turn_resps.append(''); continue
full_resp += chunk; turn_resps[-1] += chunk
if len(full_resp) - last_pos > 30 or 'LLM Running' in chunk:
display_queue.put({'next': full_resp[last_pos:] if self.inc_out else full_resp,
'source': source, 'turn': curr_turn, 'outputs': turn_resps[-1:]})
last_pos = len(full_resp)
if self.inc_out and last_pos < len(full_resp): display_queue.put({'next': full_resp[last_pos:], 'source': source})
if '</summary>' in full_resp: full_resp = full_resp.replace('</summary>', '</summary>\n\n')
if '</file_content>' in full_resp: full_resp = re.sub(r'<file_content>\s*(.*?)\s*</file_content>', r'\n````\n<file_content>\n\1\n</file_content>\n````', full_resp, flags=re.DOTALL)
display_queue.put({'done': full_resp, 'source': source})
if self.inc_out and last_pos < len(full_resp): display_queue.put({'next': full_resp[last_pos:], 'source': source,
'turn': curr_turn, 'outputs': turn_resps[-1:]})
#if '</summary>' in full_resp: full_resp = full_resp.replace('</summary>', '</summary>\n\n')
#if '</file_content>' in full_resp: full_resp = re.sub(r'<file_content>\s*(.*?)\s*</file_content>', r'\n````\n<file_content>\n\1\n</file_content>\n````', full_resp, flags=re.DOTALL)
display_queue.put({'done': full_resp, 'source': source, 'turn': curr_turn, 'outputs': turn_resps.copy()})
self.history = handler.history_info
except Exception as e:
print(f"Backend Error: {format_error(e)}")
+2 -5
View File
@@ -281,11 +281,8 @@ if prompt := st.chat_input("any task?"):
result = handle_frontend_command(agent, cmd)
history = extract_ui_messages(target) if target and result.startswith('✅') else None
tail = [{"role": "assistant", "content": result, "time": ts}]
if history:
st.session_state.messages = history + tail
else:
st.session_state.messages = list(st.session_state.messages) + \
[{"role": "user", "content": cmd, "time": ts}] + tail
if history: st.session_state.messages = history + tail
else: st.session_state.messages = list(st.session_state.messages)+[{"role": "user", "content": cmd, "time": ts}]+tail
_reset_and_rerun()
if cmd.startswith("/btw"):
answer = btw_handle_frontend(agent, cmd) # sync; bypasses put_task → main agent.run() untouched
+2 -2
View File
@@ -558,7 +558,7 @@ class GenericAgentHandler(BaseHandler):
self.history_info.append(f'[Agent] {summary}')
_plan = self._in_plan_mode()
if turn % 65 == 0 and (not _plan):
if turn % 75 == 0 and (not _plan):
next_prompt += f"\n\n[DANGER] 已连续执行第 {turn} 轮。必须总结情况进行ask_user,不允许继续重试。"
elif turn % 7 == 0:
next_prompt += f"\n\n[DANGER] 已连续执行第 {turn} 轮。禁止无效重试。若无有效进展,必须切换策略:1. 探测物理边界 2. 请求用户协助。如有需要,可调用 update_working_checkpoint 保存关键上下文。"
@@ -566,7 +566,7 @@ class GenericAgentHandler(BaseHandler):
if _plan and turn >= 10 and turn % 5 == 0:
next_prompt = f"[Plan Hint] 正在计划模式。必须 file_read({_plan}) 确认当前步骤,回复开头引用:📌 当前步骤:...\n\n" + next_prompt
if _plan and turn >= 90: next_prompt += f"\n\n[DANGER] Plan模式已运行 {turn} 轮,已达上限。必须 ask_user 汇报进度并确认是否继续。"
if _plan and turn >= 120: next_prompt += f"\n\n[DANGER] Plan模式已运行 {turn} 轮,已达上限。必须 ask_user 汇报进度并确认是否继续。"
injkeyinfo = consume_file(self.parent.task_dir, '_keyinfo')
injprompt = consume_file(self.parent.task_dir, '_intervene')