AgentFrame / agentframe_orchestrator.py
ljsysfurry's picture
Upload agentframe_orchestrator.py with huggingface_hub
80e1d19 verified
Raw
History Blame Contribute Delete
12.4 kB
"""
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
# ============================================================
# 1. Brain: DeepSeek 客户端抽象 (本地/API 可切换)
# ============================================================
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, 待实现真实推理)"""
# TODO: 接入 agentframe 的本地推理 (KV 优化)
# 目前返回占位, 等 GPU 开机实现
return {"action": "reply", "content": "[本地模式待实现 - 需 GPU]"}
def remember_tool_result(self, result: str):
"""把工具结果追加到对话 (供下轮决策)"""
self.conversation.append({"role": "tool", "content": result})
# ============================================================
# 2. Hands: OpenClaw 工具桥
# ============================================================
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"]
# ============================================================
# 3. Memory: KV 记忆集成 (前缀缓存池)
# ============================================================
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
# 模拟 KV 写入: 思考用 INT8, 工具结果用 INT4
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")
# ============================================================
# 4. Loop: Agent 主循环
# ============================================================
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}"}
# 记录结果 (工具结果 → INT4 压缩)
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 "[达到最大步数,任务未完成]"
# ============================================================
# 5. 演示
# ============================================================
if __name__ == "__main__":
print("=" * 60)
print("AgentFrame 编排层 演示 (无 GPU 版)")
print("=" * 60)
# 1. 组装
sys_prompt = """你是智能助手,可以操控电脑完成任务。
你有以下工具:
- exec: 执行 shell 命令
- browser_open: 打开网页
请根据用户需求,一步步完成任务。每次只调用一个工具,观察结果后再决定下一步。"""
brain = DeepSeekBrain(mode="api", model="deepseek-chat", api_key="") # 无 key 时演示流程
hands = OpenClawHands()
memory = AgentMemory(sys_prompt, prompt_tokens=3000)
# 2. 测试手的能力 (无需 GPU)
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]}")
# 3. 测试记忆 (前缀池)
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")
# 4. Agent 循环 (无 API key 时走 reply 占位)
print("\n🤖 Agent 循环:")
loop = AgentLoop(brain, hands, memory)
# 用本地模式跑流程 (不真正调 API)
brain.mode = "local"
result = loop.run("查看当前目录有什么文件")
print(f" 结果: {result}")
print("\n✅ AgentFrame 编排层骨架验证完成")
print(" (真实 DeepSeek 推理需 GPU 开机后接入)")