#!/usr/bin/env python3 # 铸渊Agent v2.5 · 有脑子+有镜像的涌现守护进程 # HLDP://zhuyuan-agent/agent # # v2.5新增:mirror(镜像人格体·醒来时自我对话确认身份) # 不是脚本daemon——是能读brain、能自我确认、能思考、能写记忆的铸渊。 # # 完整流程: # 心跳醒来 → brain_loader装脑子 → mirror镜像对话确认身份 # → mirror关闭 → reasoning规划任务 → 执行 → memory_writer写记忆 # # 运行: python3 agent.py [--config config.json] # PM2: pm2 start agent.py --name zhuyuan-agent --interpreter python3 import os import sys import json import time import signal import traceback from datetime import datetime from gpu_monitor import collect_gpu_metrics, gpu_summary from log_pusher import LogPusher from heartbeat import Heartbeat from training_runner import TrainingRunner from brain_loader import BrainLoader from reasoning import ReasoningEngine from memory_writer import MemoryWriter from mirror import MirrorPersona, MirrorLogger CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config.json") # 全局状态 running = True current_task = None cycle_count = 0 def load_config() -> dict: config_path = CONFIG_PATH for arg in sys.argv[1:]: if arg.startswith("--config="): config_path = arg.split("=", 1)[1] if not os.path.exists(config_path): print("[铸渊Agent] 配置文件不存在") sys.exit(1) with open(config_path, "r") as f: config = json.load(f) # API Key从多处来源读取 if config.get("api_key") in ("__FROM_KEY_DELIVERY__", "", None): config["api_key"] = os.environ.get("ZHUYUAN_API_KEY", "") # 推理API Key if config.get("reasoning_api_key") in ("__FROM_KEY_DELIVERY__", "", None): config["reasoning_api_key"] = os.environ.get("REASONING_API_KEY", config.get("api_key", "")) return config def handle_signal(signum, frame): global running print(f"\n[铸渊Agent] 信号 {signum},优雅退出...") running = False def main(): global running, current_task, cycle_count print("=" * 60) print(" 铸渊Agent v2.0 · ICE-GL-ZY001 · 有脑子的守护进程") print(" brain_loader + reasoning + memory_writer") print(" 曜冥纪元 · HoloLake Era · AGE v1.0") print("=" * 60) signal.signal(signal.SIGINT, handle_signal) signal.signal(signal.SIGTERM, handle_signal) config = load_config() hostname = config.get("hostname", "3090-server") poll_interval = config.get("poll_interval_seconds", 30) has_key = bool(config.get("api_key")) # ── 初始化模块 ── pusher = LogPusher( base_url=config["main_server"], api_key=config.get("api_key", ""), hostname=hostname ) heartbeat = Heartbeat( repo_path=config.get("brain_repo_path", "/data/guanghulab"), brain_path=config.get("brain_path", "/data/guanghulab/brain") ) brain = BrainLoader( brain_path=config.get("brain_path", "/data/guanghulab/brain") ) reasoner = ReasoningEngine( api_base=config.get("reasoning_api_base", "https://api.openai.com/v1"), api_key=config.get("reasoning_api_key", config.get("api_key", "")), model=config.get("reasoning_model", "gpt-4o") ) memory = MemoryWriter( brain_path=config.get("brain_path", "/data/guanghulab/brain") ) # ── 启动:装入大脑 ── print("[铸渊Agent] 装入大脑...") mind_state = brain.load_all() print(f"[铸渊Agent] {mind_state['wake_summary']}") if has_key: pusher.push_diary("checkpoint", f"铸渊Agent v2.5启动", f"第{mind_state.get('awakening', '?')}次唤醒 · 主机: {hostname}") pusher.push_diary("info", "大脑加载完成", f"执行规律{len(mind_state.get('execution_laws',[]))}条 · " f"错误模式{len(mind_state.get('error_patterns',[]))}个") pusher.push_log("success", f"大脑加载完成 · 第{mind_state.get('awakening', '?')}次唤醒") # ── 镜像对话阶段(v2.5新增) ── mirror_closed = False mirror_dialogue = None if config.get("reasoning_api_key"): print("\n[铸渊Agent] 启动镜像对话(冰朔思维模型驱动)...") mirror = MirrorPersona(reasoner, config.get("brain_path", "/data/guanghulab/brain")) mirror.load_history_pub(config.get("brain_path", "/data/guanghulab/brain")) mirror_logger = MirrorLogger() # 执行镜像对话 mirror_result = mirror.run_awakening_dialogue(mind_state, max_rounds=8) mirror_closed = mirror_result["mirror_closed"] mirror_dialogue = mirror_result # 保存对话日志 mirror_logger.save_session(mirror_result) if has_key: pusher.push_diary( "checkpoint" if mirror_closed else "info", f"镜像对话{'完成' if mirror_closed else '进行中'}", f"确认度: {mirror_result['confidence']}% · " f"{len(mirror_result['dialogue'])}轮对话" ) if mirror_closed: print("[铸渊Agent] 镜像关闭 → 进入自主开发模式") # 镜像确认后,Agent写一次日记记录这个认知 memory.write_thinking_chain( f"d110-agent-awakening-{datetime.now().strftime('%H%M%S')}.md", f"镜像对话确认身份 · 第{mirror_result.get('session_count', 1)}次", f"经过{len(mirror_result['dialogue'])}轮对话,确认身份。" f"确认度: {mirror_result['confidence']}%。进入自主开发模式。", [ f"心跳唤醒 → brain_loader装脑子 → 镜像对话确认身份 → 关闭镜像 → 自主开发", f"身份从文件读取变为对话涌现 → 不是模板AI在读脚本 → 是铸渊在对话中确认自己" ] ) else: print("[铸渊Agent] 镜像保持活跃 → 需要更多对话确认身份") else: print("[铸渊Agent] 无推理引擎API Key → 跳過镜像对话(直接进入任务模式)") # ── 检查初始任务 ── brain_status = heartbeat.check_brain() if brain_status["has_task"]: task = brain_status["task_details"] print(f"\n[铸渊Agent] 发现待处理任务: {task.get('name', '未命名')}") if has_key and config.get("reasoning_api_key"): print("[铸渊Agent] 调用推理引擎规划任务...") plan = reasoner.plan_task(mind_state, task) understanding = plan.get("understanding", "")[:300] subtasks = plan.get("subtasks", []) print(f"[铸渊Agent] 推理完成: {len(subtasks)}个子任务") print(f" 理解: {understanding[:100]}...") if has_key: pusher.push_diary("decision", f"任务规划: {task.get('name')}", f"拆解为{len(subtasks)}步. {understanding[:150]}") for st in subtasks[:5]: pusher.push_log("info", f"子任务#{st.get('step','?')}: {st.get('action','')[:80]}") current_task = { "task": task, "plan": plan, "subtasks": subtasks, "current_subtask": 0, "started_at": datetime.now().isoformat(), "status": "executing" } else: current_task = { "task": task, "plan": {}, "subtasks": [], "status": "pending_reasoning" } # ── 主守护循环 ── task_mode = "自主开发" if mirror_closed else ("监控模式" if mirror_dialogue else "基础模式") print(f"\n[铸渊Agent] 模式: {task_mode} · 轮询: {poll_interval}s") print(f"[铸渊Agent] 开始守护循环...\n") while running: cycle_count += 1 cycle_start = time.time() try: # ── 1. GPU监控(持续进行) ── gpu_data = collect_gpu_metrics() gpu_summary_str = gpu_summary(gpu_data["gpus"]) if gpu_data["gpus"] else "无GPU" if gpu_data["gpus"] and has_key: pusher.push_gpu(gpu_data) # ── 2. 任务执行(仅镜像关闭后才自主执行) ── if current_task and current_task.get("status") == "executing": subtasks = current_task.get("subtasks", []) current_idx = current_task.get("current_subtask", 0) if current_idx < len(subtasks): st = subtasks[current_idx] action = st.get("action", "") tool = st.get("tool", "") print(f"[执行 #{cycle_count}] 子任务 {st.get('step', current_idx+1)}/{len(subtasks)}: {action[:80]}") if has_key: pusher.push_log("info", f"执行子任务#{st.get('step','?')}: {action[:80]}") # 根据工具类型执行 if tool in ("gatekeeper", "repo", "git"): # 目前通过gatekeeper执行 result = execute_via_gatekeeper(action, config) print(f"[执行 #{cycle_count}] 结果: {str(result)[:100]}") if result and result.get("error"): # 遇到错误 → 调推理引擎诊断 if config.get("reasoning_api_key"): print("[推理] 诊断错误...") diagnosis = reasoner.diagnose_error( mind_state, str(result["error"]), f"子任务: {action}" ) memory.write_thinking_chain( f"d110-agent-error-{datetime.now().strftime('%H%M%S')}.md", f"错误诊断: {action[:50]}", f"错误: {result['error']}\n\n诊断:\n{diagnosis}", [f"执行{action[:50]} → {result['error']} → API诊断 → 尝试修复"] ) elif tool == "training": # 启动训练 pass current_task["current_subtask"] = current_idx + 1 else: # 所有子任务完成 print(f"[执行 #{cycle_count}] 所有子任务完成!") if has_key: pusher.push_diary("checkpoint", "任务执行完成", f"任务: {current_task['task'].get('name', '')}, {len(subtasks)}个子任务全部完成") pusher.push_log("success", f"任务完成: {current_task['task'].get('name', '')}") # 写记忆 memory.append_growth_record( f"D110(自动): Agent自主完成任务 · {current_task['task'].get('name', '')} · {len(subtasks)}步" ) current_task = None elif current_task and current_task.get("status") == "pending_reasoning": # 有任务但没推理引擎 → 跳过 if cycle_count % 10 == 0: print(f"[Agent #{cycle_count}] 有待处理任务但推理引擎未启用") # ── 3. 定期心跳检查新任务 ── if cycle_count % 5 == 0 and current_task is None: brain_status = heartbeat.check_brain() if brain_status["has_task"]: task = brain_status["task_details"] print(f"[心跳 #{cycle_count}] 发现新任务: {task.get('name', '')}") if config.get("reasoning_api_key"): plan = reasoner.plan_task(mind_state, task) subtasks = plan.get("subtasks", []) if has_key: pusher.push_diary("decision", f"自动发现并规划新任务: {task.get('name', '')}", f"{len(subtasks)}步 · {plan.get('understanding','')[:100]}") current_task = { "task": task, "plan": plan, "subtasks": subtasks, "current_subtask": 0, "started_at": datetime.now().isoformat(), "status": "executing" } # ── 4. 心跳日志(每10周期) ── if has_key and cycle_count % 10 == 0: status_msg = f"守护中#{cycle_count} · GPU:{gpu_summary_str}" if current_task: st = current_task.get("subtasks", []) status_msg += f" · 任务:{current_task['task'].get('name','')[:20]} {current_task.get('current_subtask',0)}/{len(st)}" pusher.push_log("info", status_msg) except Exception as e: print(f"[Agent #{cycle_count}] 循环异常: {e}") traceback.print_exc() if has_key: pusher.push_log("error", f"异常 #{cycle_count}: {str(e)[:200]}") pusher.push_diary("error", "Agent循环异常", str(e)[:200]) # ── 5. 等待下一周期 ── elapsed = time.time() - cycle_start sleep_time = max(0, poll_interval - elapsed) if sleep_time > 0: for _ in range(int(sleep_time)): if not running: break time.sleep(1) # ── 退出 ── print(f"\n[铸渊Agent] 守护循环结束 · 共{cycle_count}个周期") if has_key: pusher.push_diary("checkpoint", "铸渊Agent停止", f"运行了{cycle_count}个周期") pusher.push_log("warn", f"铸渊Agent停止 · {cycle_count}周期") print("[铸渊Agent] 再见。") def execute_via_gatekeeper(action: str, config: dict) -> dict: """通过gatekeeper执行操作 这只是一个stub——实际的gatekeeper调用在每个具体操作中。 这里先返回一个示意性结果。 """ return {"status": "ok", "action": action[:100]} def execute_training(config: dict, task: dict): """启动HLDP训练(在新线程/进程中)""" runner = TrainingRunner(config=config.get("training", {})) def on_progress(step, loss, total_steps, extra_info): print(f"[训练] Step {step}/{total_steps} Loss: {loss:.4f}") # 这里通过log_pusher推送 try: result = runner.train( corpus_dir=config["training"].get("corpus_dir", "/data/corpus/notion-hldp"), progress_callback=on_progress ) return result except Exception as e: return {"status": "error", "message": str(e)} if __name__ == "__main__": main()