feat: subagent SOP, autonomous SOP overhaul, ga.py try-block fix, launch llm_no param, agentmain streamline
This commit is contained in:
105
agentmain.py
105
agentmain.py
@@ -18,11 +18,10 @@ def get_system_prompt():
|
||||
if not os.path.exists('memory/global_mem.txt'):
|
||||
with open('memory/global_mem.txt', 'w', encoding='utf-8') as f: f.write('')
|
||||
if not os.path.exists('memory/global_mem_insight.txt'):
|
||||
content = "## Global Memory Index (Logic)\n\n[CONSTITUTION]\n1. 改我自身源码前必须先问用户\n\n[STORES]\n- global_mem: ../memory/global_mem.txt\n\n[ACCESS]\n- global_mem: 按 TOPIC 检索索引\n\n[TOPICS.GLOBAL_MEM]"
|
||||
if os.path.exists('assets/global_mem_insight_template.txt'):
|
||||
with open('assets/global_mem_insight_template.txt', 'r', encoding='utf-8') as f: content = f.read()
|
||||
with open('memory/global_mem_insight.txt', 'w', encoding='utf-8') as f: f.write(content)
|
||||
t = 'assets/global_mem_insight_template.txt'
|
||||
open('memory/global_mem_insight.txt', 'w', encoding='utf-8').write(open(t, encoding='utf-8').read() if os.path.exists(t) else '')
|
||||
with open('assets/sys_prompt.txt', 'r', encoding='utf-8') as f: prompt = f.read()
|
||||
prompt += f"\nToday: {time.strftime('%Y-%m-%d %a')}\n"
|
||||
prompt += get_global_memory()
|
||||
return prompt
|
||||
|
||||
@@ -37,18 +36,14 @@ class GeneraticAgent:
|
||||
["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'])]
|
||||
if len(llm_sessions) > 0:
|
||||
self.llmclient = ToolClient(llm_sessions, auto_save_tokens=True)
|
||||
else:
|
||||
self.llmclient = None
|
||||
if len(llm_sessions) > 0: self.llmclient = ToolClient(llm_sessions, auto_save_tokens=True)
|
||||
else: self.llmclient = None
|
||||
self.lock = threading.Lock()
|
||||
self.history = []
|
||||
self.task_queue = queue.Queue()
|
||||
self.last_active_time = time.time()
|
||||
self.is_running = False
|
||||
self.is_running, self.stop_sig = False, False
|
||||
self.llm_no = 0
|
||||
self.stop_sig = False
|
||||
self.current_source = 'none'
|
||||
self.inc_out = False
|
||||
self.handler = None
|
||||
self.verbose = True
|
||||
|
||||
@@ -75,9 +70,6 @@ class GeneraticAgent:
|
||||
task = self.task_queue.get()
|
||||
self.is_running = True
|
||||
raw_query, source, display_queue = task["query"], task["source"], task["output"]
|
||||
self.current_source = source
|
||||
self.last_active_time = time.time()
|
||||
|
||||
rquery = smart_format(raw_query.replace('\n', ' '), max_str_len=200)
|
||||
self.history.append(f"[USER]: {rquery}")
|
||||
|
||||
@@ -88,45 +80,74 @@ class GeneraticAgent:
|
||||
gen = agent_runner_loop(self.llmclient, sys_prompt, raw_query,
|
||||
handler, TOOLS_SCHEMA, max_turns=40, verbose=self.verbose)
|
||||
try:
|
||||
full_response = ""; last_pos = 0
|
||||
full_resp = ""; last_pos = 0
|
||||
for chunk in gen:
|
||||
if self.stop_sig: break
|
||||
full_response += chunk
|
||||
if len(full_response) - last_pos > 50:
|
||||
display_queue.put({'next': f'{full_response}', 'source': source})
|
||||
last_pos = len(full_response)
|
||||
if '</summary>' in full_response: full_response = full_response.replace('</summary>', '</summary>\n\n')
|
||||
if '</file_content>' in full_response: full_response = re.sub(r'<file_content>\s*(.*?)\s*</file_content>', r'\n````\n<file_content>\n\1\n</file_content>\n````', full_response, flags=re.DOTALL)
|
||||
display_queue.put({'done': full_response, 'source': source})
|
||||
full_resp += chunk
|
||||
if len(full_resp) - last_pos > 50:
|
||||
display_queue.put({'next': full_resp[last_pos:] if self.inc_out else full_resp, 'source': source})
|
||||
last_pos = len(full_resp)
|
||||
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})
|
||||
self.history = handler.history_info
|
||||
except Exception as e:
|
||||
print(f"Backend Error: {format_error(e)}")
|
||||
display_queue.put({'done': full_response + f'\n```\n{format_error(e)}\n```', 'source': source})
|
||||
display_queue.put({'done': full_resp + f'\n```\n{format_error(e)}\n```', 'source': source})
|
||||
finally:
|
||||
self.is_running = False
|
||||
self.stop_sig = False
|
||||
self.current_source = 'none'
|
||||
self.is_running = self.stop_sig = False
|
||||
self.task_queue.task_done()
|
||||
if self.handler is not None: self.handler.code_stop_signal.append(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--scheduled', action='store_true', help='计划任务轮询模式')
|
||||
parser.add_argument('--task', metavar='IODIR', help='一次性任务模式(文件IO)')
|
||||
parser.add_argument('--llm_no', type=int, default=0, help='LLM编号')
|
||||
args = parser.parse_args()
|
||||
|
||||
agent = GeneraticAgent()
|
||||
agent.llm_no = args.llm_no
|
||||
agent.verbose = False
|
||||
threading.Thread(target=agent.run, daemon=True).start()
|
||||
def drain(dq, tag):
|
||||
|
||||
if args.task:
|
||||
d = f'temp/{args.task}'; rp = f'{d}/reply.txt'
|
||||
with open(f'{d}/input.txt', encoding='utf-8') as f: raw = f.read()
|
||||
while True:
|
||||
item = dq.get(); txt = item.get('done') or item.get('next', '')
|
||||
open('./temp/scheduler_live.log', 'w', encoding='utf-8').write(txt)
|
||||
if 'done' in item: break
|
||||
open('./temp/scheduler.log', 'a', encoding='utf-8').write(f'[{datetime.now():%m-%d %H:%M}] {tag}\n{txt}\n\n')
|
||||
while True:
|
||||
now = datetime.now()
|
||||
for f in os.listdir('./tasks/pending'):
|
||||
m = re.match(r'(\d{4}-\d{2}-\d{2})_(\d{4})_', f)
|
||||
if m and now >= datetime.strptime(f'{m[1]} {m[2]}', '%Y-%m-%d %H%M'):
|
||||
raw = open(f'./tasks/pending/{f}', encoding='utf-8').read()
|
||||
dq = agent.put_task(f'按scheduled_task_sop执行任务文件 ../tasks/pending/{f}(立刻移到running)\n内容:\n{raw}', source='scheduler')
|
||||
threading.Thread(target=drain, args=(dq, f), daemon=True).start()
|
||||
break
|
||||
time.sleep(55 + random.random() * 10)
|
||||
dq = agent.put_task(raw, source='task')
|
||||
while 'done' not in (item := dq.get()): pass
|
||||
with open(f'{d}/output.txt', 'w', encoding='utf-8') as f: f.write(item['done'])
|
||||
for _ in range(300): # 等reply.txt,5分钟超时
|
||||
time.sleep(1)
|
||||
if os.path.exists(rp):
|
||||
with open(rp, encoding='utf-8') as f: raw = f.read()
|
||||
os.remove(rp); break
|
||||
else: break
|
||||
elif args.scheduled:
|
||||
def drain(dq, tag):
|
||||
while 'done' not in (item := dq.get()): pass
|
||||
open('./temp/scheduler.log', 'a', encoding='utf-8').write(f'[{datetime.now():%m-%d %H:%M}] {tag}\n{item["done"]}\n\n')
|
||||
while True:
|
||||
now = datetime.now()
|
||||
for f in os.listdir('./tasks/pending'):
|
||||
m = re.match(r'(\d{4}-\d{2}-\d{2})_(\d{4})_', f)
|
||||
if m and now >= datetime.strptime(f'{m[1]} {m[2]}', '%Y-%m-%d %H%M'):
|
||||
raw = open(f'./tasks/pending/{f}', encoding='utf-8').read()
|
||||
dq = agent.put_task(f'按scheduled_task_sop执行任务文件 ../tasks/pending/{f}(立刻移到running)\n内容:\n{raw}', source='scheduler')
|
||||
threading.Thread(target=drain, args=(dq, f), daemon=True).start()
|
||||
break
|
||||
time.sleep(55 + random.random() * 10)
|
||||
else:
|
||||
agent.inc_out = True
|
||||
while True:
|
||||
q = input('> ').strip()
|
||||
if not q: continue
|
||||
dq = agent.put_task(q, source='user')
|
||||
while True:
|
||||
item = dq.get()
|
||||
if 'next' in item: print(item['next'], end='', flush=True)
|
||||
if 'done' in item: print(); break
|
||||
Reference in New Issue
Block a user