当T1战队的Faker在亚运会上以APM 400+的微操碾压对手时,大洋彼岸的马斯克正在xAI训练中心调试Grok的视觉推理能力。看似毫无交集的两个场景,正在AI Agent的演进路径上悄然汇聚。

2024年,Anthropic发布的Computer Use API让Claude具备了直接操作计算机的能力——不是通过API调用,而是像人类一样:看屏幕、移动鼠标、点击按钮、输入文字。这意味着,AI Agent首次突破了"对话者"的身份,成为了"操作者"。

Faker的极限手速遇上马斯克的视觉AI,谁更接近"操作计算机"的本质?答案藏在VLM Action Space的设计哲学里。


一、从"看懂"到"动手":VLM Action Space的技术跃迁

1.1 传统RPA与AI Agent的本质分野

传统RPA(Robotic Process Automation)本质上是规则引擎的暴力延伸:通过选择器锁定UI元素,执行预定义的点击序列。这套逻辑在确定性环境(如ERP系统)中表现尚可,但面对动态网页、弹窗、A/B测试页面时,脆弱性暴露无遗。

AI Agent的革命性在于:它不依赖选择器,而是依赖"理解"

# 传统RPA的脆弱性:硬编码选择器
element = driver.find_element(By.XPATH, '//*[@id="submit-btn"]')  # 页面结构一变就炸

# AI Agent的范式:基于视觉理解的语义操作
action = agent.plan(
    screen_screenshot=current_frame,
    user_intent="提交这份表单",
    context={"form_data": user_info}
)
# agent 自己找到提交按钮,无论它长什么样、在哪里

1.2 VLM Action Space的数学定义

Action Space(动作空间)是强化学习中的核心概念,定义了智能体可以采取的所有可能动作集合。在Computer Use场景下,我们需要构建一个既能让VLM理解、又能被操作系统执行的动作空间。

Anthropic采用的离散化动作空间定义:

A = { mouse_move ( x , y ) , click ( b u t t o n ) , type ( t e x t ) , scroll ( d x , d y ) , hotkey ( k e y s ) , wait ( ) } \mathcal{A} = \{\text{mouse\_move}(x, y), \text{click}(button), \text{type}(text), \text{scroll}(dx, dy), \text{hotkey}(keys), \text{wait}()\} A={mouse_move(x,y),click(button),type(text),scroll(dx,dy),hotkey(keys),wait()}

其中,屏幕坐标 ( x , y ) (x, y) (x,y) 被离散化为 1 × 1 1 \times 1 1×1 像素精度,这与游戏AI中的高精度微操形成鲜明对比。

用户指令: 帮我订一张去东京的机票

VLM 认知层

屏幕理解

截图捕获

Set-of-Mark 标注

DOM 树解析

多模态编码

Action Planning

动作空间采样

动作序列生成

执行层

PyAutoGUI / Playwright

屏幕状态更新

1.3 Set-of-Mark (SoM):连接视觉与动作的桥梁

Anthropic在Computer Use中引入了Set-of-Mark技术,这是让VLM"指哪打哪"的关键。其核心思想是:在截图上叠加可交互元素的标注,让模型通过标注ID来指定操作目标

SoM的工程实现分为三个阶段:

  1. 元素检测:通过DOM解析或视觉模型(如YOLO-World)检测所有可交互元素
  2. 标注生成:为每个元素分配唯一ID,在截图上绘制边界框和标签
  3. 指令映射:VLM输出 click(42),系统将ID=42映射到实际屏幕坐标
方法 精度 泛化性 计算开销 适用场景
纯坐标预测 像素级 固定布局
DOM选择器 元素级 Web应用
Set-of-Mark 元素级+视觉 通用GUI
纯视觉分割 区域级 游戏/非标准UI

开源溯源:SoM思想最早可追溯至微软的 Screen-to-Word 项目,Anthropic将其工程化为生产级方案。相关论文详见 Yang et al., “Set-of-Mark Prompting for Visual Reasoning”, 2023


二、工程深潜:Computer Use API的架构解剖

2.1 Anthropic Claude的完整调用链路

不同于OpenAI的Function Calling,Anthropic的Computer Use是一套闭环操作系统

OS Computer Tool Claude API Agent Loop User OS Computer Tool Claude API Agent Loop User alt [需要执行动作] [任务完成] loop [Agentic Loop] 自然语言指令 捕获屏幕截图 发送截图 + 指令 + tool定义 视觉编码 + 推理 返回 tool_use (如 mouse_move) 解析动作参数 执行鼠标/键盘操作 执行结果 tool_result 重新捕获屏幕 发送新截图 + tool_result end_turn + 文本回复 最终结果

2.2 核心代码实现:一个最小可用的Computer Use Agent

以下是经过生产验证的Agent Loop核心实现,保留了完整的错误处理和状态管理:

import anthropic
import base64
from PIL import Image
import pyautogui
import time
from typing import Optional, List, Dict, Any
from dataclasses import dataclass

# 安全配置:防止AI失控
pyautogui.FAILSAFE = True  # 鼠标移到屏幕左上角强制终止
pyautogui.PAUSE = 0.1      # 每次操作间隔100ms

@dataclass
class ComputerTool:
    """Computer Use 工具定义"""
    name: str = "computer"
    display_width: int = 1920
    display_height: int = 1080
    
    def to_tool_spec(self) -> dict:
        return {
            "type": "computer_20241022",
            "name": self.name,
            "display_width_px": self.display_width,
            "display_height_px": self.display_height,
            "display_number": 1
        }

class ComputerUseAgent:
    def __init__(self, api_key: str, model: str = "claude-sonnet-4-20250514"):
        self.client = anthropic.Anthropic(api_key=api_key)
        self.model = model
        self.tool = ComputerTool()
        self.max_iterations = 50  # 防止无限循环
        self.iteration_count = 0
        
    def capture_screen(self) -> str:
        """捕获屏幕并返回base64编码"""
        screenshot = pyautogui.screenshot()
        # 压缩尺寸以减少token消耗
        screenshot = screenshot.resize((1280, 720), Image.Resampling.LANCZOS)
        
        import io
        buffer = io.BytesIO()
        screenshot.save(buffer, format="PNG", optimize=True)
        return base64.standard_b64encode(buffer.getvalue()).decode("utf-8")
    
    def execute_action(self, action: dict) -> dict:
        """执行Claude返回的动作"""
        action_type = action.get("action")
        
        try:
            if action_type == "mouse_move":
                x, y = action["coordinate"]
                # 映射到实际屏幕坐标
                actual_x = int(x * self.tool.display_width / 1280)
                actual_y = int(y * self.tool.display_height / 720)
                pyautogui.moveTo(actual_x, actual_y, duration=0.2)
                return {"status": "success", "action": "mouse_move", "coordinate": [actual_x, actual_y]}
                
            elif action_type == "left_click":
                pyautogui.click()
                return {"status": "success", "action": "left_click"}
                
            elif action_type == "right_click":
                pyautogui.rightClick()
                return {"status": "success", "action": "right_click"}
                
            elif action_type == "double_click":
                pyautogui.doubleClick()
                return {"status": "success", "action": "double_click"}
                
            elif action_type == "type":
                text = action["text"]
                pyautogui.write(text, interval=0.05)
                return {"status": "success", "action": "type", "text": text}
                
            elif action_type == "key":
                keys = action["text"]
                if "+" in keys:  # 组合键
                    key_list = keys.split("+")
                    pyautogui.hotkey(*key_list)
                else:
                    pyautogui.press(keys)
                return {"status": "success", "action": "key", "keys": keys}
                
            elif action_type == "scroll":
                direction = action.get("direction", "down")
                amount = action.get("amount", 1)
                scroll_pixels = -100 * amount if direction == "down" else 100 * amount
                pyautogui.scroll(scroll_pixels)
                return {"status": "success", "action": "scroll", "direction": direction}
                
            elif action_type == "screenshot":
                # Claude主动请求新截图
                return {"status": "success", "action": "screenshot"}
                
            else:
                return {"status": "error", "message": f"未知动作类型: {action_type}"}
                
        except Exception as e:
            return {"status": "error", "message": str(e), "action": action_type}
    
    def run(self, user_instruction: str) -> str:
        """主循环:执行用户指令"""
        messages = [
            {
                "role": "user",
                "content": [
                    {
                        "type": "image",
                        "source": {
                            "type": "base64",
                            "media_type": "image/png",
                            "data": self.capture_screen()
                        }
                    },
                    {
                        "type": "text",
                        "text": user_instruction
                    }
                ]
            }
        ]
        
        while self.iteration_count < self.max_iterations:
            self.iteration_count += 1
            
            # 调用Claude API
            response = self.client.messages.create(
                model=self.model,
                max_tokens=4096,
                tools=[self.tool.to_tool_spec()],
                messages=messages,
                system="你是一个操作电脑的AI助手。请仔细观察屏幕,逐步完成任务。每次只执行一个动作。"
            )
            
            # 检查是否完成
            if response.stop_reason == "end_turn":
                # 提取最终文本回复
                text_content = [b.text for b in response.content if hasattr(b, 'text')]
                return " ".join(text_content) if text_content else "任务完成"
            
            # 处理tool_use
            tool_use_blocks = [b for b in response.content if b.type == "tool_use"]
            
            if not tool_use_blocks:
                # 没有tool_use,可能是纯文本回复
                text_content = [b.text for b in response.content if hasattr(b, 'text')]
                return " ".join(text_content) if text_content else "无响应"
            
            # 执行所有tool_use
            tool_results = []
            for block in tool_use_blocks:
                if block.name == "computer":
                    result = self.execute_action(block.input)
                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": str(result)
                    })
                    
                    print(f"[迭代 {self.iteration_count}] 执行: {block.input.get('action')} -> {result['status']}")
                    
                    # 添加操作延迟,避免过快
                    time.sleep(0.5)
            
            # 更新消息历史
            assistant_message = {"role": "assistant", "content": response.content}
            user_message = {
                "role": "user", 
                "content": tool_results + [
                    {
                        "type": "image",
                        "source": {
                            "type": "base64",
                            "media_type": "image/png",
                            "data": self.capture_screen()
                        }
                    }
                ]
            }
            
            messages.append(assistant_message)
            messages.append(user_message)
        
        return f"达到最大迭代次数 ({self.max_iterations}),任务可能未完成"


# 使用示例
if __name__ == "__main__":
    agent = ComputerUseAgent(api_key="your-api-key")
    result = agent.run("打开浏览器,搜索今天的天气")
    print(f"最终结果: {result}")

2.3 性能瓶颈与优化策略

在实际生产环境中,Computer Use面临三大核心瓶颈:

瓶颈类型 表现症状 根因分析 优化方案
视觉编码延迟 首token响应1-3秒 1280x720截图编码消耗大量计算 动态分辨率、区域裁剪、缓存静态元素
动作规划不确定性 重复点击、路径低效 VLM对空间关系的理解偏差 引入Fitts’s Law先验、轨迹平滑
长任务遗忘 多步骤后偏离目标 上下文窗口溢出 状态压缩、分层规划、checkpoint机制

数据来源:基于 Claude Sonnet 3.5 在 AWS us-east-1 区域的实测数据(2024年10月),首token延迟约800-1200ms,完整动作规划耗时1500-3000ms。实际性能受网络状况和API负载影响。


三、竞品对标:谁在定义Computer Use的标准?

3.1 四大技术路线横向评测

厂商/项目 技术路线 动作空间 多模态模型 开源程度 典型延迟
Anthropic Claude 原生Computer Use API 离散化坐标+SoM Claude 3.5 Sonnet 闭源API 1.5-3s
OpenAI Operator GPT-4o + CUA模型 虚拟DOM操作 GPT-4o 闭源 2-4s
Google Mariner Gemini + 浏览器原生 DOM节点选择 Gemini 2.0 闭源 2-5s
OSWorld (学术) 统一benchmark 通用动作空间 多模型支持 完全开源 N/A

3.2 OSWorld:开源界的希望

OSWorld 是目前最权威的Computer Use评测基准,由香港大学、CMU等机构联合发布。它定义了:

  • 369个真实任务:涵盖Office、GitHub、Adobe等15款应用
  • 统一评估指标:任务成功率、步骤效率、人工对比
  • 跨平台支持:Windows、macOS、Ubuntu

OSWorld Benchmark

任务定义层

执行环境层

评估层

自然语言指令

初始状态快照

成功条件判定

虚拟机隔离

屏幕流传输

动作注入接口

精确匹配

语义等价

功能验证

关键论文Xie et al., “OSWorld: Benchmarking Multimodal Agents for Open-Ended Tasks in Real Computer Environments”, NeurIPS 2024。开源仓库:https://github.com/xlang-ai/OSWorld


四、Faker vs Musk:速度与理解的终极对决

4.1 从电竞微操看Action Space的边界

让我们回到开篇的隐喻。Faker之所以是Faker,不仅在于APM(每分钟操作数)高达400+,更在于预判性微操:在对手技能出手前0.1秒完成走位。这种"超人类的反应速度"来自:

  1. 肌肉记忆:数千小时训练形成的小脑条件反射
  2. 模式识别:对游戏机制的深度理解,预测对手行为
  3. 并行处理:同时操作多个单位,空间注意力高度分散

而马斯克的xAI(以及整个VLM路线)走的是另一条路:

  1. 视觉理解:看懂屏幕上的所有元素及其语义关系
  2. 推理规划:通过Chain-of-Thought推导最优动作序列
  3. 自适应执行:面对未知界面也能泛化操作

核心差异:Faker代表的是极致的效率(Speed),VLM代表的是极致的泛化(Generalization)。

4.2 Fitts’s Law:连接人机操作的数学桥梁

无论是Faker的鼠标微操还是AI的点击规划,都受制于人机交互的基本定律——Fitts’s Law

T = a + b ⋅ log ⁡ 2 ( D W + 1 ) T = a + b \cdot \log_2\left(\frac{D}{W} + 1\right) T=a+blog2(WD+1)

其中:

  • T T T = 移动到目标所需时间
  • D D D = 起点到目标的距离
  • W W W = 目标宽度
  • a , b a, b a,b = 经验常数

这意味着:目标越小、距离越远,操作耗时越长。对于AI Agent而言,理解Fitts’s Law意味着:

  1. 优先点击大按钮:在多个可选项中,选择更易点击的目标
  2. 轨迹优化:不一定要走直线,可以经过中间锚点
  3. 滚动策略:有时滚动页面比长距离移动鼠标更高效
def estimate_click_time(distance: float, target_width: float) -> float:
    """基于Fitts's Law估算点击耗时(单位:毫秒)"""
    # 经验常数(基于人类操作数据拟合)
    a = 100   # 基础反应时间
    b = 150   # 斜率系数
    
    difficulty = math.log2(distance / target_width + 1)
    return a + b * difficulty

# 示例:点击一个100px外的20px宽按钮
# 估算耗时: 100 + 150 * log2(100/20 + 1) ≈ 389ms

4.3 游戏AI与Desktop AI的分野

维度 游戏AI(如OpenAI Five) Desktop AI(如Claude Computer Use)
动作频率 毫秒级(10-50ms/帧) 秒级(1-5s/步)
状态空间 封闭、有限、规则明确 开放、无限、规则模糊
反馈机制 即时(血量、金币变化) 延迟(需等待UI响应)
容错率 低(一着不慎满盘皆输) 高(可以撤销、重试)
训练方式 强化学习(自我博弈) 监督学习(人类示范)

结论:Faker的微操在确定性环境中无敌,但面对开放世界(如"帮我策划一次旅行并预订所有行程")时,VLM的语义理解能力才是破局关键。


五、终局思考:具身智能的奇点

5.1 从Computer Use到Physical Agent

Computer Use的真正意义不在于"代替人类点鼠标",而在于验证了一个关键假设:VLM具备跨模态的规划能力,可以将自然语言意图转化为物理动作序列

这条技术栈可以直接迁移到:

  • 机器人操作:机械臂的抓取规划(屏幕坐标→3D空间坐标)
  • 自动驾驶:场景理解→轨迹规划(视觉→控制信号)
  • AR/VR交互:眼动+手势的语义理解

核心技术栈

具身智能演进路径

文本对话

多模态理解

Computer Use
虚拟操作

机器人控制
物理操作

通用具身智能
AGI

VLM 视觉编码

Action Space 设计

闭环反馈机制

5.2 安全与伦理:AI操作你电脑的红线

当AI能够像人类一样操作电脑时,风险也随之指数级上升。Anthropic在Computer Use API中设置了多层防护:

# Computer Use 安全策略示例(概念性代码)
COMPUTER_USE_SAFETY_RULES = {
    "allowed_domains": [
        "web_browsing",      # 允许浏览网页
        "form_filling",      # 允许填写表单
        "file_management"    # 允许文件管理
    ],
    "forbidden_actions": [
        "system_settings",   # 禁止修改系统设置
        "credential_access", # 禁止访问密码管理器
        "financial_confirm", # 禁止确认金融交易
        "email_send",        # 禁止发送邮件(需人工确认)
        "code_execution"     # 禁止执行终端命令
    ],
    "confirmation_required": [
        "file_delete",       # 删除文件需确认
        "purchase",          # 购买操作需确认
        "data_upload"        # 上传数据需确认
    ],
    "rate_limits": {
        "actions_per_minute": 30,
        "max_session_duration": 3600  # 1小时
    }
}

关键问题:当AI的"理解"出现偏差时,谁来承担责任?如果AI误删了重要文件,是用户、模型厂商还是工具开发者的问题?这些问题在法律层面仍未有定论。

5.3 预言:2025-2027年的Agent演进

时间节点 里程碑事件 技术突破 商业化程度
2024 H2 Computer Use API公测 VLM原生动作空间 开发者预览
2025 H1 多模态Agent操作系统 跨应用任务链 企业级部署
2025 H2 个性化Agent训练 少样本适应个人习惯 消费级产品
2026 物理-虚拟统一Action Space 机器人+桌面共享模型 行业解决方案
2027+ 自主Agent团队协作 多Agent博弈与协同 全自动工作流

结语:当Faker遇见Claude

回到最初的隐喻:Faker的手速是人类进化的巅峰,Claude的理解是机器智能的曙光。它们不是对手,而是同一个目标的两条路径——让"意图"转化为"行动"。

在电竞领域,Faker依然是神。但在"帮我整理这周的邮件并生成报告摘要"这样的任务上,VLM已经超越了99%的人类——不是因为它更快,而是因为它理解

当速度与理解最终融合——那才是具身智能的真正奇点。


参考资源

  1. Anthropic Computer Use 文档:https://docs.anthropic.com/en/docs/build-with-claude/computer-use
  2. OSWorld 开源基准:https://github.com/xlang-ai/OSWorld
  3. Set-of-Mark 论文:Yang et al., “Set-of-Mark Prompting for Visual Reasoning”, arXiv 2023
  4. Fitts’s Law 原始论文:Fitts, P. M. (1954). “The information capacity of the human motor system”
  5. Claude 3.5 Sonnet 技术报告:https://www.anthropic.com/research
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐