Open-AutoGLM:基于大语言模型的手机自动化智能体架构深度解析
1. 整体介绍
1.1 项目概要
Open-AutoGLM 是一个实验性的开源项目,其核心在于构建一个 “视觉-语言-动作”(Vision-Language-Action, VLA) 闭环系统。项目地址为 zai-org/Open-AutoGLM。根据公开信息,该项目吸引了相当多的关注,其核心价值在于探索一种通过自然语言直接控制移动设备执行复杂任务的新范式,将大语言模型(LLM)的推理规划能力与移动操作系统(Android/iOS)的底层控制能力相结合。
1.2 主要功能与场景
项目旨在解决 “如何让AI像人一样操作手机” 这一核心问题。用户只需下达如“帮我订一份附近评分最高的披萨外卖”或“把刚拍的风景照发到朋友圈并配文‘美景’”这样的自然语言指令,系统便能自动执行从应用启动、屏幕导航、信息搜索到最终确认的完整流程。
对应人群与场景:
- 研究社区:作为VLA智能体、具身智能(Embodied AI)在移动平台上的研究平台。
- 自动化测试工程师:探索基于自然语言的UI自动化测试,替代或补充传统的脚本化测试(如Appium)。
- 个人效率追求者/开发者:构建个性化的手机自动化工作流,例如自动签到、信息聚合、跨应用数据搬运。
- 无障碍辅助:为行动不便的用户提供通过语音指令操控手机的潜在方案。
1.3 面临问题与解决方案对比
传统解决方案的局限:
- 脚本录制/回放工具(如MacroDroid, Tasker):需要用户手动录制操作序列,缺乏灵活性和场景泛化能力。任务逻辑固化,无法处理界面变化或动态内容。
- 基于坐标/控件的自动化框架(如Appium, UI Automator):需要编写和维护大量脚本,开发门槛高。脚本与特定UI布局强绑定,应用UI更新极易导致脚本失效,维护成本巨大。
- 基于图像匹配的RPA工具:同样面临界面变化的挑战,且难以理解和处理复杂的业务逻辑。
Open-AutoGLM的新范式: 项目引入LLM作为“大脑”,其优势在于:
- 自然交互:直接理解人类意图,无需学习脚本语法。
- 强大的推理与规划能力:能够将抽象任务分解为具体步骤序列,并能在执行过程中根据屏幕反馈(视觉信息)进行动态调整。
- 一定的泛化能力:对于未曾见过的UI元素或任务变体,LLM有可能通过理解其语义(如按钮文字、图标含义)做出合理决策,而非依赖固定的坐标或ID。
商业价值逻辑预估: 价值可从成本替代与效率提升两个维度估算:
- 成本侧:替代传统UI自动化脚本开发与维护的人力成本。一个中等复杂度的自动化任务,传统开发可能需要
2-5人日,而基于本框架可能只需描述需求和微调Prompt。长期来看,维护成本(应对UI变更)的降低更为显著。 - 效率与覆盖侧:扩大了自动化任务的边界。许多因逻辑复杂、变化频繁而无法用传统方式自动化的长尾任务(如“从这篇公众号文章里找出所有提到的公司名称并存入表格”),现在变得可能。其效益取决于能成功自动化的任务数量与这些任务本身的价值。
- 初步估算逻辑:
商业价值 ≈ (节约的脚本开发与维护人时成本 × 人力单价) + (新覆盖的高价值自动化任务数量 × 单任务价值)。当前阶段,其价值主要体现在技术探索和特定场景的原型验证上。
2. 详细功能拆解
从产品-技术双视角解构,其核心功能链路由以下模块构成:
| 产品功能视角 | 对应技术模块 | 核心技术组件/原理 |
|---|---|---|
| 1. 意图理解与任务拆解 | 模型推理服务 | 大语言模型(如 autoglm-phone-9b)。接收“用户指令+当前屏幕截图”,输出“思考过程”和“下一个动作指令”。 |
| 2. 手机状态感知 | 屏幕捕捉与上下文构建 | DeviceFactory -> get_screenshot() 获取Base64编码截图;get_current_app() 获取当前应用名,共同构建当前状态上下文。 |
| 3. 动作决策与执行 | 动作解析与执行引擎 | ActionHandler 解析LLM输出的动作字符串(如 do(action=“Tap”, element=[x,y])),调用底层 DeviceFactory (ADB/HDC/iOS) 执行具体操作。 |
| 4. 跨平台设备控制 | 设备抽象层 | DeviceFactory 工厂模式,统一 ADB(Android)、HDC(HarmonyOS)、iOS(WebDriverAgent)的操作接口,实现“编写一次,多端运行”。 |
| 5. 交互式流程管理 | 智能体主循环 | PhoneAgent.run() 与 _execute_step() 构成 “观察(O)-思考(T)-行动(A)” 的ReAct核心循环,直至任务完成或达到最大步数。 |
| 6. 系统健壮性保障 | 预检与配置管理 | check_system_requirements(), check_model_api() 确保环境就绪。ModelConfig, AgentConfig 提供细粒度运行时配置。 |
3. 技术难点挖掘
- 视觉-文本对齐与泛化:LLM如何准确理解截图内容?项目将截图作为视觉信号嵌入对话上下文,依赖VLM能力。难点在于模型对UI元素、图标、非标准布局、弹窗的识别精度,直接影响动作选择的准确性。
- 动作空间的抽象与泛化:如何将无限的屏幕操作抽象为有限、可执行的动作集?项目定义了
Tap,Swipe,Type,Launch等约12个原子动作。难点在于原子动作的组合是否能覆盖所有复杂交互(如多指手势、精确拖拽),以及坐标[x,y]的预测是否精准。 - 长期规划与状态管理:如何让AI记住操作历史,避免循环或重复操作?项目通过维护对话上下文
self._context隐式地保留历史。难点在于长序列任务中的规划能力、对操作是否生效的判断(需模型从下一帧截图推断),以及错误恢复策略。 - 执行可靠性:ADB操作(如点击、输入)本身存在失败可能。项目通过动作执行后的自动截图反馈进行下一轮决策,但缺乏对单步操作失败的即时检测与重试机制。
- 提示工程与规则约束:系统提示词 (
SYSTEM_PROMPT) 极为关键,它定义了动作格式、规则和常识。其设计是项目核心“魔法”之一,编写和维护成本高,且直接影响任务成功率。
4. 详细设计图
4.1 核心架构图
系统采用分层架构,清晰分离了模型、智能体逻辑和设备控制。
4.2 核心链路序列图:执行单步决策
以Android设备为例,展示从接收用户指令到执行一个点击动作的核心流程。
sequenceDiagram
participant U as 用户/调用方
participant A as PhoneAgent
participant DF as DeviceFactory (ADB)
participant MC as ModelClient
participant LLM as LLM服务
participant AH as ActionHandler
U->>A: run("打开微信")
A->>DF: get_screenshot()<br>get_current_app()
DF->>Dev: adb shell screencap
Dev-->>DF: 屏幕截图
DF-->>A: Screenshot对象
A->>MC: request(上下文)
MC->>LLM: Chat Completion Request<br>(含截图Base64)
LLM-->>MC: Stream Response<br>"...<br>当前是桌面,<br/>需启动微信<br>do(action="Launch", app="微信")"
MC-->>A: ModelResponse
A->>AH: execute(action)
AH->>DF: launch_app("微信")
DF->>Dev: adb shell am start ...
Dev-->>DF: (执行结果)
DF-->>AH: True/False
AH-->>A: ActionResult
A->>A: 更新上下文,判断是否继续循环
A-->>U: 返回步骤结果或最终结果
4.3 核心类图
展示项目中最核心的几个类及其关系。
classDiagram
class PhoneAgent {
-ModelConfig model_config
-AgentConfig agent_config
-ModelClient model_client
-ActionHandler action_handler
-List~dict~ _context
-int _step_count
+run(task: str) str
+step(task: str) StepResult
+reset() void
-_execute_step() StepResult
}
class ModelClient {
-ModelConfig config
-OpenAI client
+request(messages) ModelResponse
-_parse_response(content) tuple
}
class ActionHandler {
+execute(action, width, height) ActionResult
}
class DeviceFactory {
-DeviceType device_type
+get_screenshot() Screenshot
+tap(x, y)
+launch_app(app_name) bool
+list_devices()
# 其他原子操作...
}
class ModelConfig {
+base_url: str
+model_name: str
+api_key: str
+lang: str
}
class AgentConfig {
+max_steps: int
+device_id: str
+lang: str
+system_prompt: str
}
PhoneAgent --> ModelClient
PhoneAgent --> ActionHandler
ActionHandler --> DeviceFactory
PhoneAgent --> ModelConfig
PhoneAgent --> AgentConfig
ModelClient --> ModelConfig
4.4 核心函数 _execute_step 拆解图
该函数是 O-T-A循环 的具体实现,是系统运转的心脏。
5. 核心代码解析
5.1 智能体执行循环 (PhoneAgent._execute_step)
此函数完美实现了 ReAct 范式的一次迭代。
def _execute_step(self, user_prompt: str | None = None, is_first: bool = False) -> StepResult:
# 1. 【观察】获取设备当前状态
screenshot = device_factory.get_screenshot(self.agent_config.device_id)
current_app = device_factory.get_current_app(self.agent_config.device_id)
# 2. 构建本次循环的输入消息(包含历史、截图和文本信息)
if is_first:
# 首次步,加入系统提示词和用户任务
self._context.append(MessageBuilder.create_system_message(self.agent_config.system_prompt))
screen_info = MessageBuilder.build_screen_info(current_app)
text_content = f"{user_prompt}\n\n{screen_info}"
self._context.append(
MessageBuilder.create_user_message(text=text_content, image_base64=screenshot.base64_data)
)
else:
# 非首次步,只发送新的屏幕状态
screen_info = MessageBuilder.build_screen_info(current_app)
text_content = f"** Screen Info **\n\n{screen_info}"
self._context.append(
MessageBuilder.create_user_message(text=text_content, image_base64=screenshot.base64_data)
)
# 3. 【思考】请求大模型进行决策
response = self.model_client.request(self._context)
# 4. 解析模型输出的动作指令
try:
action = parse_action(response.action) # 解析为字典,如 {'_metadata': 'do', 'action': 'Tap', 'element': [100, 200]}
except ValueError:
action = finish(message=response.action) # 解析失败,则当作任务结束处理
# 5. 【行动】执行解析出的动作
result = self.action_handler.execute(action, screenshot.width, screenshot.height)
# 6. 为下一轮循环准备:将模型的完整回复加入上下文,并清理图片以减少token消耗
self._context.append(
MessageBuilder.create_assistant_message(
f"<think>{response.thinking}</think><answer>{response.action}</answer>"
)
)
self._context[-2] = MessageBuilder.remove_images_from_message(self._context[-2]) # 移除上轮图片
# 7. 判断本轮是否导致任务结束
finished = action.get("_metadata") == "finish" or result.should_finish
return StepResult(
success=result.success,
finished=finished,
action=action,
thinking=response.thinking,
message=result.message,
)
5.2 模型响应解析器 (ModelClient._parse_response)
此函数负责从LLM返回的非结构化文本中,精确提取出“思考”和“动作”两部分,是连接LLM与动作执行器的关键桥梁。其设计体现了对模型输出格式稳定性的强依赖。
def _parse_response(self, content: str) -> tuple[str, str]:
"""
解析模型响应,支持两种格式:
1. 新格式: `...思考内容... do(action=“Tap”, element=[x,y])`
2. 旧XML格式: `<think>...<think><answer>do(...)</answer>`
"""
# 规则1: 优先匹配‘finish(message=‘
if "finish(message=" in content:
parts = content.split("finish(message=", 1)
thinking = parts[0].strip()
action = "finish(message=" + parts[1] # 保留完整动作字符串
return thinking, action
# 规则2: 匹配‘do(action=‘
if "do(action=" in content:
parts = content.split("do(action=", 1)
thinking = parts[0].strip()
action = "do(action=" + parts[1]
return thinking, action
# 规则3: 回退到旧的XML标签解析(兼容性)
if "<answer>" in content:
parts = content.split("<answer>", 1)
thinking = parts[0].replace("<think>", "").replace("</think>", "").strip()
action = parts[1].replace("</answer>", "").strip()
return thinking, action
# 规则4: 无任何标记,假设整个内容为动作(或错误输出)
return "", content
总结与展望
Open-AutoGLM 项目成功地将大语言模型与移动设备自动化进行了工程化整合,提供了一个清晰、模块化的参考架构。其技术核心在于 DeviceFactory 实现的设备抽象层 与 PhoneAgent 实现的 ReAct 决策循环。
对比同类方案优劣:
- vs 传统自动化脚本:优势在于灵活、自然、开发门槛低;劣势在于单次执行耗时更长(需多次调用LLM)、成本更高(API调用费用)、且当前阶段绝对成功率可能低于精心编写的脚本。
- vs 其他研究型AI智能体(如Android in the Wild):Open-AutoGLM更注重工程落地,提供了完整的CLI、多设备支持和详细的错误检查,易于上手和二次开发。
当前局限与未来方向:
- 依赖强大的VLM:项目效果严重依赖后端模型对手机屏幕的理解能力,通用模型在此垂直领域表现可能不足。
- 提示工程脆弱:复杂的
SYSTEM_PROMPT是双刃剑,既约束了模型,也可能限制其创造性。未来可能需引入微调或强化学习来优化策略。 - 缺乏细粒度状态验证:当前仅依赖下一帧截图进行整体决策,缺乏对“点击是否成功”、“页面是否加载完成”等微观状态的即时判断机制。
- 商业化路径:需解决稳定性、成本、速度等问题。可能的演进方向包括:开发专用轻量化模型、与UI层级信息(可访问性树)结合以提升精度、设计更高效的动作空间等。
总而言之,Open-AutoGLM 是一个极具启发性的项目,它为我们展示了以LLM为中央控制器构建跨平台移动自动化智能体的可行路径,为后续的研究和应用开发奠定了坚实的基础。