| """ |
| AgentFrame 编排层 (Orchestrator) |
| =============================== |
| DeepSeek 决策 ↔ OpenClaw 执行的桥接层 |
| |
| 核心循环: |
| 1. DeepSeek 分析用户意图 → 决定下一步 |
| 2. 调用 OpenClaw 工具 (exec/browser/computer-use) |
| 3. 工具结果 → 分层量化存入 KV 缓存 |
| 4. 循环直到任务完成 |
| |
| 架构: |
| Orchestrator |
| ├── Brain: DeepSeek 客户端 (本地 L40S / API 兜底) |
| ├── Hands: OpenClaw 工具桥 (exec/browser) |
| ├── Memory: 前缀感知缓存池 (复用 agentframe_core.py) |
| └── Loop: Agent 循环控制 |
| |
| 依赖: |
| - agentframe_core.py (前缀缓存池 + KV 量化) |
| - OpenClaw gateway (exec/browser 工具) |
| - DeepSeek 模型 (本地或 API) |
| """ |
|
|
| import json |
| import time |
| import subprocess |
| from typing import Dict, List, Optional, Any, Callable |
|
|
| |
| |
| |
|
|
| class DeepSeekBrain: |
| """ |
| DeepSeek 决策大脑 |
| mode: 'local' (L40S 本地) | 'api' (DeepSeek 官方) |
| """ |
|
|
| def __init__(self, mode: str = "api", model: str = "deepseek-chat", |
| api_key: str = "", base_url: str = "https://api.deepseek.com"): |
| self.mode = mode |
| self.model = model |
| self.api_key = api_key |
| self.base_url = base_url |
| self.system_prompt = "" |
| self.conversation: List[Dict] = [] |
|
|
| def set_system_prompt(self, prompt: str): |
| """设置 Agent 系统提示 (含工具定义)""" |
| self.system_prompt = prompt |
| self.conversation = [{"role": "system", "content": prompt}] |
|
|
| def think(self, user_input: str, tools: List[Dict]) -> Dict: |
| """ |
| DeepSeek 决策: 返回 JSON {action, tool, args} 或 {action: "reply", content} |
| """ |
| if self.mode == "api": |
| return self._think_api(user_input, tools) |
| else: |
| return self._think_local(user_input, tools) |
|
|
| def _think_api(self, user_input: str, tools: List[Dict]) -> Dict: |
| """API 模式 (OpenAI 兼容)""" |
| import urllib.request |
|
|
| self.conversation.append({"role": "user", "content": user_input}) |
| payload = { |
| "model": self.model, |
| "messages": self.conversation, |
| "tools": tools, |
| "tool_choice": "auto", |
| "stream": False, |
| } |
| req = urllib.request.Request( |
| f"{self.base_url}/chat/completions", |
| data=json.dumps(payload).encode(), |
| headers={ |
| "Content-Type": "application/json", |
| "Authorization": f"Bearer {self.api_key}", |
| }, |
| ) |
| with urllib.request.urlopen(req, timeout=60) as resp: |
| data = json.loads(resp.read().decode()) |
|
|
| msg = data["choices"][0]["message"] |
| self.conversation.append(msg) |
|
|
| |
| if msg.get("tool_calls"): |
| tc = msg["tool_calls"][0] |
| return { |
| "action": "tool", |
| "tool": tc["function"]["name"], |
| "args": json.loads(tc["function"]["arguments"] or "{}"), |
| } |
| return {"action": "reply", "content": msg.get("content", "")} |
|
|
| def _think_local(self, user_input: str, tools: List[Dict]) -> Dict: |
| """本地模式 (L40S + V2-Lite, 待实现真实推理)""" |
| |
| |
| return {"action": "reply", "content": "[本地模式待实现 - 需 GPU]"} |
|
|
| def remember_tool_result(self, result: str): |
| """把工具结果追加到对话 (供下轮决策)""" |
| self.conversation.append({"role": "tool", "content": result}) |
|
|
|
|
| |
| |
| |
|
|
| class OpenClawHands: |
| """ |
| OpenClaw 工具执行桥 (调用 gateway 的 exec/browser) |
| 通过 subprocess 调用 openclaw CLI, 或直接调用系统命令 |
| """ |
|
|
| def __init__(self, workspace: str = "/root/.openclaw/workspace"): |
| self.workspace = workspace |
|
|
| def exec(self, command: str, timeout: int = 30) -> Dict: |
| """执行 shell 命令 (OpenClaw exec 能力)""" |
| try: |
| result = subprocess.run( |
| command, |
| shell=True, |
| capture_output=True, |
| text=True, |
| timeout=timeout, |
| cwd=self.workspace, |
| ) |
| return { |
| "success": result.returncode == 0, |
| "stdout": result.stdout[:2000], |
| "stderr": result.stderr[:500], |
| "exit_code": result.returncode, |
| } |
| except subprocess.TimeoutExpired: |
| return {"success": False, "stdout": "", "stderr": "timeout", "exit_code": -1} |
|
|
| def read_file(self, path: str) -> str: |
| """读文件""" |
| return self.exec(f"cat {path}")["stdout"] |
|
|
| def write_file(self, path: str, content: str) -> bool: |
| """写文件""" |
| import base64 |
| b64 = base64.b64encode(content.encode()).decode() |
| result = self.exec(f"echo '{b64}' | base64 -d > {path}") |
| return result["success"] |
|
|
| def browser_open(self, url: str) -> Dict: |
| """浏览器打开网页""" |
| result = self.exec(f"openclaw browser --browser-profile openclaw open {url}") |
| return {"success": result["success"], "note": "browser opened"} |
|
|
| def browser_snapshot(self) -> str: |
| """浏览器快照""" |
| result = self.exec("openclaw browser --browser-profile openclaw snapshot") |
| return result["stdout"] |
|
|
| def list_tools(self) -> List[str]: |
| """可用工具清单""" |
| return ["exec", "read_file", "write_file", "browser_open", "browser_snapshot"] |
|
|
|
|
| |
| |
| |
|
|
| class AgentMemory: |
| """Agent 记忆: 复用 agentframe_core 的前缀池 + 分层量化""" |
|
|
| def __init__(self, system_prompt: str, prompt_tokens: int = 3000): |
| from agentframe_core import PrefixPool, SessionManager, AbsorbedMLAEncoder |
| self.pool = PrefixPool() |
| self.sessions = SessionManager(self.pool) |
| self.encoder = AbsorbedMLAEncoder() |
| self.system_prompt = system_prompt |
| |
| self.session = self.sessions.create_session( |
| "agent-main", system_prompt, prompt_tokens |
| ) |
| self.history: List[Dict] = [] |
|
|
| def record(self, role: str, content: str, layer_idx: int = 0): |
| """记录对话/工具结果到记忆 (分层量化)""" |
| import numpy as np |
| |
| fake_kv = np.random.randn(1, 8, self.encoder.kv_rank) |
| if role == "thought": |
| kv = self.encoder.encode_thought(fake_kv) |
| else: |
| kv = self.encoder.encode_tool_result(fake_kv) |
| self.sessions.append_tool_result(self.session, layer_idx, kv) |
| self.history.append({"role": role, "content": content[:500]}) |
|
|
| def memory_report(self) -> Dict: |
| return self.sessions.session_memory(self.session) |
|
|
| def close(self): |
| self.sessions.close_session("agent-main") |
|
|
|
|
| |
| |
| |
|
|
| class AgentLoop: |
| """Agent 执行循环: 思考 → 行动 → 观察 → 循环""" |
|
|
| def __init__(self, brain: DeepSeekBrain, hands: OpenClawHands, memory: AgentMemory): |
| self.brain = brain |
| self.hands = hands |
| self.memory = memory |
| self.max_steps = 10 |
|
|
| def _tool_schemas(self) -> List[Dict]: |
| """给 DeepSeek 的工具定义 (OpenClaw 能力)""" |
| return [ |
| { |
| "type": "function", |
| "function": { |
| "name": "exec", |
| "description": "执行 shell 命令", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "command": {"type": "string", "description": "要执行的命令"} |
| }, |
| "required": ["command"], |
| }, |
| }, |
| }, |
| { |
| "type": "function", |
| "function": { |
| "name": "browser_open", |
| "description": "打开网页", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "url": {"type": "string", "description": "网页地址"} |
| }, |
| "required": ["url"], |
| }, |
| }, |
| }, |
| ] |
|
|
| def run(self, task: str) -> str: |
| """执行一个任务""" |
| self.brain.set_system_prompt(self.memory.system_prompt) |
| self.memory.record("user", task) |
|
|
| for step in range(self.max_steps): |
| print(f"\n[Step {step+1}] 🧠 DeepSeek 思考中...") |
| self.memory.record("thought", f"step {step+1}") |
|
|
| decision = self.brain.think(task, self._tool_schemas()) |
|
|
| if decision["action"] == "reply": |
| print(f" 💬 Agent: {decision['content']}") |
| return decision["content"] |
|
|
| if decision["action"] == "tool": |
| tool = decision["tool"] |
| args = decision["args"] |
| print(f" 🛠 调用 {tool}({args})") |
|
|
| |
| if tool == "exec": |
| result = self.hands.exec(args.get("command", "")) |
| elif tool == "browser_open": |
| result = self.hands.browser_open(args.get("url", "")) |
| else: |
| result = {"success": False, "stdout": f"未知工具 {tool}"} |
|
|
| |
| result_str = json.dumps(result, ensure_ascii=False)[:500] |
| self.memory.record("tool_result", result_str) |
| self.brain.remember_tool_result(result_str) |
| task = result_str |
|
|
| return "[达到最大步数,任务未完成]" |
|
|
|
|
| |
| |
| |
|
|
| if __name__ == "__main__": |
| print("=" * 60) |
| print("AgentFrame 编排层 演示 (无 GPU 版)") |
| print("=" * 60) |
|
|
| |
| sys_prompt = """你是智能助手,可以操控电脑完成任务。 |
| 你有以下工具: |
| - exec: 执行 shell 命令 |
| - browser_open: 打开网页 |
| 请根据用户需求,一步步完成任务。每次只调用一个工具,观察结果后再决定下一步。""" |
|
|
| brain = DeepSeekBrain(mode="api", model="deepseek-chat", api_key="") |
| hands = OpenClawHands() |
| memory = AgentMemory(sys_prompt, prompt_tokens=3000) |
|
|
| |
| print("\n🖐 测试 OpenClaw 手:") |
| r = hands.exec("echo 'AgentFrame 就绪!' && ls /root/.openclaw/workspace/*.py | head -3") |
| print(f" exec: {'✅' if r['success'] else '❌'}") |
| print(f" → {r['stdout'][:100]}") |
|
|
| |
| print("\n🧠 测试记忆 (前缀缓存池):") |
| memory.record("thought", "分析任务") |
| memory.record("tool_result", "ls 输出: agentframe_core.py, agentframe_orchestrator.py") |
| rep = memory.memory_report() |
| print(f" 前缀引用数: {rep['prefix_refs']}") |
| print(f" 增量内存: {rep['incremental_bytes']/1024:.0f}KB") |
|
|
| |
| print("\n🤖 Agent 循环:") |
| loop = AgentLoop(brain, hands, memory) |
| |
| brain.mode = "local" |
| result = loop.run("查看当前目录有什么文件") |
| print(f" 结果: {result}") |
|
|
| print("\n✅ AgentFrame 编排层骨架验证完成") |
| print(" (真实 DeepSeek 推理需 GPU 开机后接入)") |
|
|