Open-AutoGLM Python API调用示例,开发更灵活

在手机操作自动化领域,开发者长期面临一个核心矛盾:既要实现精准的界面理解与动作执行,又希望拥有足够的编程自由度来适配复杂业务逻辑。命令行工具虽开箱即用,但难以嵌入现有系统;而真正可编程的接口,往往文档简略、示例匮乏、调试困难。Open-AutoGLM 的 Python API 正是为解决这一痛点而生——它不是简单的封装,而是一套面向工程落地的控制层抽象。本文不讲“怎么连上手机”,而是聚焦于“如何用代码把它变成你系统里一个可调度、可监控、可扩展的智能模块”。我们将从零开始,用真实可运行的 Python 脚本,演示如何连接设备、发送指令、处理响应、捕获中间状态,并构建一个具备错误恢复能力的轻量级任务调度器。

1. 为什么需要 Python API?不只是“能用”,而是“好用”

很多开发者第一次接触 Open-AutoGLM,会直接使用 main.py 命令行方式运行任务。这种方式简单直接,但存在几个实际工程中无法回避的问题:

  • 无法集成:你的业务系统是 Flask 或 FastAPI 服务?命令行脚本无法作为子模块被调用。
  • 状态不可控:你不知道 AI 是在第几步卡住,还是模型返回了模糊指令,还是 ADB 执行失败。所有日志混在一起,排查成本高。
  • 缺乏灵活性:想让 AI 先截图分析当前页面,再决定下一步?想在点击前加个条件判断?命令行模式做不到。
  • 难以测试:没法对单个函数做单元测试,也没法模拟网络延迟或设备断连等异常场景。

Python API 的价值,正在于把整个 Phone Agent 的能力,拆解成一组职责清晰、边界明确、可组合的函数和类。它让你从“使用者”变成“协作者”,可以精确地告诉 AI:“看这张图,告诉我当前页面有没有‘立即支付’按钮”,而不是笼统地说“去支付订单”。

这正是本文要带你深入实践的核心:用 Python API 构建可观察、可干预、可复用的手机自动化工作流

2. 环境准备与依赖安装:轻量起步,拒绝冗余

在开始编码前,我们需要一个干净、最小化的运行环境。与部署完整服务不同,调用 Python API 只需客户端依赖,无需启动 vLLM 或配置 GPU。

2.1 创建独立虚拟环境(推荐)

# 创建并激活虚拟环境
python -m venv autoglm-env
source autoglm-env/bin/activate  # macOS/Linux
# autoglm-env\Scripts\activate  # Windows

2.2 安装核心依赖

Open-AutoGLM 的 Python SDK 并未发布到 PyPI,因此需从源码安装。我们只安装客户端所需部分,跳过服务端和模型推理相关依赖:

# 克隆仓库(仅需最新稳定版)
git clone https://github.com/zai-org/Open-AutoGLM
cd Open-AutoGLM

# 安装核心客户端库(-e 表示可编辑安装,便于后续调试)
pip install -e ".[client]"

说明[client]setup.py 中定义的可选依赖组,它只包含 requests, adbutils, pydantic 等必要库,体积小、安装快,避免了 torch, vllm 等重型依赖的干扰。

2.3 验证安装

运行以下命令,确认 SDK 已正确加载:

# test_install.py
from phone_agent import __version__
print(f"Open-AutoGLM client version: {__version__}")

from phone_agent.adb import ADBConnection
conn = ADBConnection()
print("ADBConnection imported successfully.")

若输出版本号且无报错,则环境准备完成。

3. 核心 API 模块解析:从连接到执行的四层抽象

Open-AutoGLM 的 Python API 并非一个大而全的类,而是遵循“关注点分离”原则,划分为四个逻辑清晰的模块。理解它们的分工,是写出健壮代码的前提。

3.1 phone_agent.adb:设备连接与底层控制

这是整个自动化链条的物理基础。它不关心 AI 在想什么,只负责“让手机动起来”。

  • ADBConnection: 连接管理器,支持 USB 和 WiFi 两种模式,提供 connect(), disconnect(), enable_tcpip() 等方法。
  • list_devices(): 获取当前所有已连接设备列表,返回 Device 对象,包含 device_id, connection_type, state 等属性。
  • get_device_ip(): 自动探测设备在局域网中的 IP 地址,省去手动查找步骤。

关键洞察:这个模块的设计理念是“连接即对象”。一旦 conn.connect("192.168.1.100:5555") 成功,后续所有操作都基于这个 conn 实例,无需反复传参,代码更简洁。

3.2 phone_agent.llm:大模型通信与指令编排

这是 AI 的“大脑”接口。它将复杂的 HTTP 请求、JSON Schema、流式响应等细节封装起来,让你只需关注“我要问什么”和“我想要什么”。

  • LLMClient: 核心客户端,初始化时指定 base_urlmodel_name
  • chat_completion(): 同步调用,接收 messages 列表(符合 OpenAI 格式),返回结构化响应。
  • stream_chat_completion(): 异步流式调用,适用于长任务或需要实时反馈的场景。

关键洞察messages 不是简单的一句字符串。它是一个对话历史数组,你可以预置系统提示词(System Message)来约束 AI 行为,例如:“你是一个严谨的手机操作助手,所有操作前必须确认目标元素是否存在。”

3.3 phone_agent.agent:任务规划与执行引擎

这是最核心、也最具特色的模块。它将 LLM 的“思考”与 ADB 的“行动”串联起来,形成一个闭环。

  • PhoneAgent: 主代理类,初始化时注入 adb_connllm_client
  • run_task(): 主入口方法,接收自然语言指令,自动执行“截图 → 分析 → 规划 → 执行 → 验证”的全流程。
  • step_by_step(): 分步执行模式,返回每一步的详细信息(截图路径、AI 决策、ADB 命令、执行结果),用于深度调试。

关键洞察PhoneAgent 不是黑盒。它的 run_task() 方法内部,就是对 step_by_step() 的循环调用。这意味着,你可以完全绕过 run_task(),自己编写循环逻辑,实现比默认流程更精细的控制。

3.4 phone_agent.utils:实用工具与辅助函数

提供一系列提升开发体验的“胶水”函数。

  • capture_screenshot(): 快速截取当前屏幕并保存为本地文件,方便人工复核。
  • wait_for_element(): 基于 OCR 或 UI 层级等待特定文本或控件出现,解决“页面加载慢导致点击失败”的经典问题。
  • parse_action_response(): 将 LLM 返回的 JSON 字符串,安全地解析为 Action 对象(含 type, x, y, text 等字段)。

关键洞察:这些工具函数的存在,意味着你不必从零开始写轮子。例如,wait_for_element("登录") 一行代码,就替代了手写 while not find_text("登录"): time.sleep(1) 的繁琐逻辑。

4. 实战:构建一个可重试、可监控的任务执行器

现在,我们将综合运用以上模块,编写一个生产环境中真正可用的任务执行器。它将具备三个关键能力:自动重试失败步骤、记录每一步的详细日志、并在关键节点进行人工确认。

4.1 初始化连接与客户端

# task_executor.py
import logging
import time
from pathlib import Path
from phone_agent.adb import ADBConnection, list_devices
from phone_agent.llm import LLMClient
from phone_agent.agent import PhoneAgent
from phone_agent.utils import capture_screenshot, wait_for_element

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    handlers=[logging.StreamHandler()]
)
logger = logging.getLogger(__name__)

# 1. 连接设备
conn = ADBConnection()
# 尝试连接 WiFi 设备(请替换为你的设备IP)
success, msg = conn.connect("192.168.1.100:5555")
if not success:
    logger.error(f"ADB 连接失败: {msg}")
    exit(1)
logger.info(f"ADB 连接成功: {msg}")

# 2. 初始化 LLM 客户端(以 ModelScope 为例)
llm_client = LLMClient(
    base_url="https://api-inference.modelscope.cn/v1",
    model_name="ZhipuAI/AutoGLM-Phone-9B",
    api_key="your_modelscope_api_key_here"  # 请替换为你的实际 API Key
)

# 3. 创建 PhoneAgent 实例
agent = PhoneAgent(adb_conn=conn, llm_client=llm_client)

4.2 编写带重试机制的执行函数

def execute_with_retry(task_desc: str, max_retries: int = 3) -> bool:
    """
    执行一个自然语言任务,并在失败时自动重试
    
    Args:
        task_desc: 自然语言指令,如 "打开微信,给文件传输助手发消息:测试成功"
        max_retries: 最大重试次数
    
    Returns:
        bool: True 表示任务最终成功,False 表示彻底失败
    """
    for attempt in range(1, max_retries + 1):
        logger.info(f"开始第 {attempt} 次尝试执行任务: {task_desc}")
        
        try:
            # 使用分步模式,获取详细过程
            steps = agent.step_by_step(task_desc, max_steps=10)
            
            # 遍历每一步,记录并检查结果
            for i, step in enumerate(steps):
                logger.info(f"  步骤 {i+1}: {step.action.type}")
                logger.debug(f"    决策详情: {step.reasoning}")
                logger.debug(f"    执行命令: {step.action}")
                
                # 如果是截图,保存到本地便于复核
                if step.screenshot_path:
                    screenshot_file = f"screenshots/step_{i+1}_{int(time.time())}.png"
                    Path("screenshots").mkdir(exist_ok=True)
                    Path(step.screenshot_path).rename(screenshot_file)
                    logger.info(f"    截图已保存至: {screenshot_file}")
                
                # 检查该步骤是否成功
                if not step.success:
                    logger.warning(f"    步骤 {i+1} 执行失败: {step.error_message}")
                    # 失败则跳出内层循环,进入下一次重试
                    break
            else:
                # for 循环正常结束,说明所有步骤都成功
                logger.info(f" 任务 '{task_desc}' 执行成功!共 {len(steps)} 步。")
                return True
            
        except Exception as e:
            logger.error(f"    执行过程中发生未预期异常: {e}")
        
        # 如果走到这里,说明本次尝试失败,等待后重试
        if attempt < max_retries:
            logger.info(f"    等待 5 秒后进行第 {attempt + 1} 次重试...")
            time.sleep(5)
    
    logger.error(f" 任务 '{task_desc}' 经过 {max_retries} 次重试后仍失败。")
    return False

# 示例调用
if __name__ == "__main__":
    # 测试一个简单任务
    execute_with_retry("打开设置,搜索并进入'关于手机'页面")

4.3 添加人工确认环节(安全敏感操作)

对于支付、删除、授权等高风险操作,API 提供了 confirm_action() 方法,允许你在 AI 规划出动作后,由人来拍板。

def safe_execute_with_confirmation(task_desc: str) -> bool:
    """执行任务,但在关键操作前要求人工确认"""
    steps = agent.step_by_step(task_desc, max_steps=10)
    
    for i, step in enumerate(steps):
        logger.info(f"步骤 {i+1}: {step.action.type}")
        
        # 检测是否为高风险操作
        if step.action.type in ["click", "long_press"] and "支付" in step.reasoning:
            logger.warning("  检测到潜在支付操作!")
            logger.info(f"   AI 计划点击坐标: ({step.action.x}, {step.action.y})")
            logger.info(f"   当前截图已保存为: {step.screenshot_path}")
            
            # 等待用户输入
            confirm = input("   是否继续执行?(y/N): ").strip().lower()
            if confirm != "y":
                logger.info("   用户取消执行。")
                return False
        
        # 执行动作
        result = agent.execute_action(step.action)
        if not result.success:
            logger.error(f"   执行失败: {result.error_message}")
            return False
    
    return True

# 示例调用
# safe_execute_with_confirmation("打开支付宝,向张三转账100元")

5. 进阶技巧:超越“执行指令”,实现“理解界面”

Python API 的最大魅力,在于它让你能跳出“指令-执行”的线性思维,进入“观察-分析-决策”的智能体范式。下面两个技巧,将展示如何用几行代码,解锁更高级的能力。

5.1 技巧一:主动截图并让 AI 描述当前页面

有时,你不需要 AI 去“做”什么,而是想让它“说”出它看到了什么。这在自动化测试、UI 一致性检查中非常有用。

def describe_current_screen() -> str:
    """截取当前屏幕,并让 AI 用自然语言描述页面内容"""
    # 1. 截图
    screenshot_path = capture_screenshot(conn)
    
    # 2. 构造一个专门的 prompt
    messages = [
        {
            "role": "system",
            "content": "你是一个专业的移动应用界面分析师。请用一段话,准确、简洁地描述这张截图中显示的页面。重点说明:当前应用名称、页面标题、主要功能区域(如顶部导航栏、中部内容区、底部标签栏)、以及页面上最显眼的 3 个可交互元素(按钮、图标、文字链接)及其文字。不要编造不存在的信息。"
        },
        {
            "role": "user",
            "content": [
                {"type": "image_url", "image_url": {"url": f"file://{screenshot_path}"}},
                {"type": "text", "text": "请描述这张截图。"}
            ]
        }
    ]
    
    # 3. 调用 LLM
    response = llm_client.chat_completion(messages=messages)
    return response.choices[0].message.content

# 示例
description = describe_current_screen()
print("当前页面描述:")
print(description)

5.2 技巧二:基于 OCR 的精准文本定位与点击

当 UI 元素没有稳定 ID,但文字内容固定时,wait_for_element() 是你的救星。它结合了设备端的 dumpsys 和客户端的 OCR,比单纯靠坐标点击可靠得多。

def click_text_on_screen(text: str, timeout: int = 10) -> bool:
    """在屏幕上查找指定文本,并点击其所在位置"""
    try:
        # 等待文本出现(最多 timeout 秒)
        x, y = wait_for_element(conn, text, timeout=timeout)
        logger.info(f"找到文本 '{text}',坐标 ({x}, {y})")
        
        # 执行点击
        result = conn.tap(x, y)
        if result:
            logger.info(f" 成功点击文本 '{text}'")
            return True
        else:
            logger.error(" 点击失败")
            return False
    except TimeoutError:
        logger.error(f" 在 {timeout} 秒内未找到文本 '{text}'")
        return False
    except Exception as e:
        logger.error(f" 查找/点击过程出错: {e}")
        return False

# 示例:无论“微信”图标在屏幕哪个位置,都能点开
click_text_on_screen("微信")

6. 总结:API 是桥梁,更是杠杆

通过本文的实践,你应该已经清晰地看到:Open-AutoGLM 的 Python API,远不止是一个“调用模型的快捷方式”。它是一套经过深思熟虑的工程化接口,其设计哲学体现在三个层面:

  • 抽象合理adb, llm, agent, utils 四层分离,让每个模块各司其职,降低了认知负荷。
  • 控制精细:从 step_by_step() 的每一步详情,到 confirm_action() 的人工介入点,再到 wait_for_element() 的智能等待,它赋予你前所未有的掌控力。
  • 扩展友好:所有核心类都采用依赖注入(Dependency Injection)设计,你可以轻松地用自定义的 ADBConnection 子类替换掉默认实现,或者用 Mock 对象进行单元测试。

真正的“开发更灵活”,不在于 API 能写多短的代码,而在于当你面对一个从未见过的 App、一个千奇百怪的 UI、一个必须满足的合规要求时,你能否快速、自信地写出稳定可靠的自动化逻辑。Open-AutoGLM 的 Python API,正是为此而生。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐