目录

一、整体实现思路:把手机当作一个“可视 GUI 环境”的 Agent 闭环

二、底层交互原理:一个“观察–思考–行动”的循环

状态感知(Perception):从设备抓取屏幕和上下文

思考与规划(Thinking / Planning):由模型驱动

动作解析(Action Parsing):把模型输出映射为结构化指令

动作执行(Action Execution):从抽象动作到真实 ADB/HDC 调用

三、用的是什么技术栈?AI 交互是如何“装配”上去的?

编程语言 & 运行环境

设备控制技术栈

模型服务栈:OpenAI 兼容 API + vLLM/SG‑lang

四、与 AI 交互的具体实现细节

通信协议:OpenAI Chat Completions(流式)

响应分段:从原始文本中分离 thinking 与 action

上下文管理:如何维持“有记忆”的多轮操作

五、从“底层交互原理”的角度再总结一遍

六、如果你要“参考 AutoGLM 自己实现一套”:可以怎么抄架构?

References


小总览:

  1. 这个开源项目是怎样实现的?(整体架构与代码逻辑)

  2. 底层交互原理是什么?(Agent ⇄ 模型 ⇄ 设备 的闭环机制)

  3. 用的是什么技术栈,在这个栈上如何“加上”AI 交互?

  4. 与 AI 交互的具体实现细节是什么?(消息格式、模型 API、解析逻辑等)


一、整体实现思路:把手机当作一个“可视 GUI 环境”的 Agent 闭环

AutoGLM 的开源实现叫 Open‑AutoGLM,本质上是一个 “手机 GUI Agent 框架 + 多模态模型服务” 的组合:

  • 两大部分架构(README 明确说明)[1]:

    • Agent Code(本仓库)

      1. 跑在你的电脑/服务器上

      2. 负责:

        • 连接手机(ADB/HDC/WDA)

        • 截图 + 识别当前前台 App

        • 构造发给模型的多模态消息(文字 + 截图)

        • 解析模型返回的 do(...) / finish(...) 动作

        • 把动作转换成实际的点击、滑动、输入等操作

    • Vision Model Service(视觉语言模型服务)

      1. 可以是云端 API(z.ai / Novita / Parasail)

      2. 也可以是你自己用 vLLM / SG‑lang 在本地部署的服务

      3. 提供一个 OpenAI 兼容的 Chat Completions HTTP 接口

核心理念: Agent 只做“观察 + 执行”,不自己做复杂规划;复杂推理/规划全交给多模态大模型。


二、底层交互原理:一个“观察–思考–行动”的循环

用更工程化的语言,AutoGLM 的底层是一个典型的 perception–planning–action loop,每一步都非常清晰。

  1. 状态感知(Perception):从设备抓取屏幕和上下文

在每个 step 中,Agent 先获取当前手机状态:

device_factory = get_device_factory() screenshot = device_factory.get_screenshot(device_id) current_app = device_factory.get_current_app(device_id)

  • get_screenshot

    • Android:通过 ADB 把 screencap 的结果拉过来,转成 base64

    • HarmonyOS:通过 HDC 抓图

  • get_current_app

    • 通过 adb shell dumpsys window 等方式解析当前前台 Activity / 包名,抽象成 current_app

再用 MessageBuilder.build_screen_info(current_app, ...) 组装成一个 JSON 风格的 “屏幕信息摘要字符串”,写进 prompt 里给模型看:

python复制

screen_info = MessageBuilder.build_screen_info(current_app) # 返回 JSON 字符串,例如 {"current_app": "com.tencent.mm"}

  1. 思考与规划(Thinking / Planning):由模型驱动

整个“该干什么”的决策完全交给模型:

  1. 构造一个 system 提示(系统角色,用于约束输出格式和行为):

    1. 中文系统提示(极长):详细定义了可用动作,如 do(action="Launch", app="xxx")do(action="Tap", element=[x,y])finish(message="xxx"),以及一堆操作策略规则(比如网络错误重试策略、搜索策略、各种 App 运营规则等)[2]。

    2. 英文系统提示:结构更简洁,但同样要求输出 <think>...</think><answer>do(...)</answer> 格式[3]。

  2. 构造 user message(多模态):

  3. 第一步:

  4. text_content = f"{user_task}\n\n{screen_info}" user_msg = MessageBuilder.create_user_message( text=text_content, image_base64=screenshot.base64_data # 图像用 data:image/png;base64,... 形式 )

  5. 后续步骤不再附加用户指令,只上传当前屏幕信息:

  6. text_content = f"** Screen Info **\n\n{screen_info}" user_msg = MessageBuilder.create_user_message(text=text_content)

  7. 把所有历史 system + user + assistant 消息(self._context)送入模型:

  8. stream = client.chat.completions.create( messages=self._context, model=model_name, stream=True, ... )

  9. 模型按照系统提示要求输出:

  10. <think>...内部思考...</think> <answer>do(action="Tap", element=[x,y])</answer>

  11. 或最终:

  12. <answer>finish(message="任务完成")</answer>

  13. 动作解析(Action Parsing):把模型输出映射为结构化指令

模型输出中真正要执行的部分统一是一个 Python 风格的伪代码:

do(action="Launch", app="WeChat") do(action="Tap", element=[523, 312]) do(action="Type", text="Hello") finish(message="Done")

在 Agent 中:

from phone_agent.actions.handler import do, finish, parse_action action = parse_action(response.action)

parse_action 的逻辑非常关键[4]:

  • 对 Type/Type_Name 这种特例,用字符串操作直接提取 text=...

  • 对一般的 do(...) 调用:

    • 使用 ast.parse(response, mode="eval")

      • 避免直接 eval,安全性高得多

    • 遍历 ast.Call.keywords,用 ast.literal_eval 读取参数值:

    • python复制

    • action = {"_metadata": "do"} for kw in call.keywords: action[kw.arg] = ast.literal_eval(kw.value)

  • finish(message=...),生成:

  • {"_metadata": "finish", "message": "..."}

所以:模型的“代码输出”本质上是一个 DSL,被安全地解析为结构化 dict。

  1. 动作执行(Action Execution):从抽象动作到真实 ADB/HDC 调用

ActionHandler.execute(action, screen_width, screen_height) 做了两件事:

  1. 根据 _metadata 判断是否结束:

    1. _metadata == "finish"should_finish=True,不再操作设备,只返回消息。

    2. 否则 _metadata == "do" → 交给具体 handler 执行。

  2. 按 action 名分发到各个 handler[5]:

  3. 支持的动作包括:

    1. Launch

    2. Tap

    3. Type / Type_Name

    4. Swipe

    5. Back

    6. Home

    7. Double Tap

    8. Long Press

    9. Wait

    10. Take_over

    11. Note

    12. Call_API

    13. Interact

  4. 示例:Tap 的执行大致是:

  5. def _handle_tap(action, width, height): rel_x, rel_y = action["element"] # 0~1000 相对坐标 x = int(rel_x / 1000 * width) y = int(rel_y / 1000 * height) device_factory.tap(x, y, device_id)

  6. 其中 device_factory.tap 内部再去组装 adb shell input tap x y 或 HDC 对应命令。

到这里,一个完整 step 的行为闭环就走完了。


三、用的是什么技术栈?AI 交互是如何“装配”上去的?

  1. 编程语言 & 运行环境

  • 语言:Python 3.10+

  • 依赖通过 requirements.txtpip install -e . 安装[1]。

  • 框架方面没有重度用到 web 框架,全是命令行/脚本式的结构。

  1. 设备控制技术栈

表格 还在加载中,请等待加载完成后再尝试复制

ADB/HDC 的实现都是用 Python 包一层 subprocess.run 调用系统 adb/hdc 命令,解析 stdout/stderr,抽象为:

  • get_screenshot(device_id)

  • tap(x, y, device_id)

  • swipe(start, end, device_id)

  • launch_app(app_name, device_id)

  • get_current_app(device_id)

  1. 模型服务栈:OpenAI 兼容 API + vLLM/SG‑lang

核心选型是:不自己发明协议,直接用 OpenAI Chat Completions 协议。

  • 使用 openai Python SDK(from openai import OpenAI)[11]:

  • self.client = OpenAI(base_url=config.base_url, api_key=config.api_key)

  • 默认配置:

  • base_url="http://localhost:8000/v1" model_name="autoglm-phone-9b" max_tokens=3000 temperature=0.0 top_p=0.85 frequency_penalty=0.2

  • 本地部署模型(vLLM 示例)[1]:

  • python3 -m vllm.entrypoints.openai.api_server \ --served-model-name autoglm-phone-9b-multilingual \ --model zai-org/AutoGLM-Phone-9B-Multilingual \ --port 8000 \ ... # 一堆多模态参数 # 服务地址即 http://localhost:8000/v1

  • AutoGLM 模型本身的架构:

    • Hugging Face 说明:AutoGLM-Phone-9B(-Multilingual) 的架构 与 GLM‑4.1V‑9B‑Thinking 相同[12],本质是一个多模态 VLM(能看图)。

因此 AI 交互并不是绑定某家云服务,而是通过“OpenAI API 兼容协议”这层抽象,你可以用:

  • 智谱官方 API (https://api.z.ai/api/paas/v4)

  • Novita AI / Parasail 提供的 OpenAI 兼容端点

  • 或者你自己用 vLLM/SG‑lang 跑在本地 GPU 上


四、与 AI 交互的具体实现细节

  1. 通信协议:OpenAI Chat Completions(流式)

模型客户端 ModelClientrequest(messages) 做的事是:

stream = client.chat.completions.create( messages=messages, # 标准 OpenAI messages 格式 model=config.model_name, max_tokens=config.max_tokens, temperature=config.temperature, top_p=config.top_p, frequency_penalty=config.frequency_penalty, extra_body=config.extra_body, stream=True, )

  • messages 的结构示例:

  • [ {"role": "system", "content": SYSTEM_PROMPT_ZH}, { "role": "user", "content": [ {"type": "image_url", "image_url": { "url": "data:image/png;base64,...." }}, {"type": "text", "text": "用户任务 + 屏幕信息 JSON"} ] }, # 历史 assistant 消息: "<think>...</think><answer>do(...)</answer>" ... ]

  • 通过 stream=True 实现 令牌级流式输出:

    • 一边接收 token,一边在控制台打印模型的 “thinking” 部分;

    • 一旦检测到 finish(message=do(action= 这样的标记,就认为进入 action 阶段,停止在控制台继续打印 thinking,将剩余内容保留在 raw_content 中。

  1. 响应分段:从原始文本中分离 thinking 与 action

ModelClient 内部维护:

  • raw_content:把所有 token 串起来

  • buffer:用于查找 action 标记

  • action_markers = ["finish(message=", "do(action="]

流处理过程大概是:

  1. 每次拿到 chunk.choices[0].delta.content

    1. 累加到 raw_content

    2. 若尚未进入 action 阶段,则累加到 buffer,并尝试:

      • 如果某个 marker 出现在 buffer 中:

        • thinking_part = buffer.split(marker, 1)[0] → 打印出来

        • 标记 in_action_phase=True,记录 time_to_thinking_end

      • 如果 buffer 的结尾可能只是 marker 的前缀(例如 do(act),则暂不打印,等待更多 token。

      • 否则,就把 buffer 打印并清空

  2. 全部结束后,用 _parse_response(raw_content) 分出:

    1. thinking:完整 <think>...</think> 部分

    2. actiondo(...)finish(...) 部分字符串

_parse_response 源码没完全展示,但从使用方式和系统提示内容可推断大致逻辑。)

  1. 上下文管理:如何维持“有记忆”的多轮操作

PhoneAgent 维护一个 _context: list[dict]

  • 第一步:

    • append system message

    • append user message(任务 + 首屏截图)

  • 每一步执行完后:

    • 将刚刚那轮的 <think>...</think><answer>...</answer> 作为 assistant 消息塞回 _context

    • self._context.append( MessageBuilder.create_assistant_message( f"<think>{response.thinking}</think><answer>{response.action}</answer>" ) )

    • 同时把上一条 user 消息中的图片内容删掉(只保留文字),节省上下文长度:

    • self._context[-1] = MessageBuilder.remove_images_from_message(self._context[-1])

下一轮再追加新的 user 消息(当前屏幕信息),如此往复,形成一个 多轮 GUI 操作对话记录。


五、从“底层交互原理”的角度再总结一遍

用一句话概括 AutoGLM 的底层交互原理:

把手机屏幕抽象成“多模态上下文”,把点击/输入抽象成“ DSL 指令”,用 OpenAI 兼容 Chat API 做“视觉—规划—动作生成”,再用 ADB/HDC 把这些 DSL 指令落成真实操作。

更细一点分层看:

  1. 模型层:

    1. AutoGLM‑Phone‑9B(-Multilingual) = 一个 GLM‑4.1V‑9B‑Thinking 架构的 VLM,接受文本 + 图像输入;

    2. 通过系统 prompt 把输出空间限制为 do(...)/finish(...) 风格的动作代码。

  2. 协议层:

    1. 完全复用 OpenAI Chat Completions 协议(包含多模态 image_url);

    2. 本地可由 vLLM/SG‑lang 提供服务,云端可由各类兼容 API 提供。

  3. Agent 层:

    1. 负责构造 messages、调用模型、解析模型输出、管理对话历史;

    2. 通过 AST 安全解析将模型输出变为结构化动作。

  4. 设备层:

    1. ADB/HDC/WDA 负责真实世界的 GUI 操作;

    2. 对 Agent 暴露的是逻辑函数:tapswipelaunch_appget_screenshot 等。


六、如果你要“参考 AutoGLM 自己实现一套”:可以怎么抄架构?

按照 AutoGLM 的思路,你可以最小化复刻一个类似系统,关键步骤是:

  1. 先选一个多模态模型 + OpenAI 兼容推理框架(如 vLLM)

    1. 保证支持 image_url 输入;

    2. 用类似 AutoGLM 的 system prompt 约束输出为 do(...) / finish(...)

  2. 实现一个最小的 ModelClient

    1. openai SDK 或直接 HTTP 请求;

    2. 支持 messages(system + user + assistant 历史);

    3. 输出一段文本,内部再拆出 thinkingaction

  3. 设计一套简单的 DSL + 解析器

    1. 比如就支持:LaunchTapTypeBackHome

    2. 仿照 AutoGLM 用 ast.parse 做安全解析。

  4. 封装设备控制

    1. 对 Android 包一层 ADB:tap(x,y), swipe, screencap 等;

    2. 用一个 DeviceFactory 来屏蔽 ADB/HDC/WDA 差异。

  5. 写一个 Agent Loop

    1. 输入:自然语言任务;

    2. 循环: 1)截图 + 当前 App → 拼成 user message 2)调用模型 → 得到 do(...) 3)解析动作并执行 4)直到 finish(...) 或步数上限。

这套设计就是 AutoGLM 的核心精髓,Open‑AutoGLM 已经把每一层都拆得很清晰,可以直接按模块借鉴。

References

[1] README_en – Open‑AutoGLM 架构与部署说明. https://github.com/zai-org/Open-AutoGLM/blob/main/README_en.md [2] prompts_zh.py – 中文系统提示与规则. https://github.com/zai-org/Open-AutoGLM/blob/main/phone_agent/config/prompts_zh.py [3] prompts_en.py – 英文系统提示与输出格式约束. https://github.com/zai-org/Open-AutoGLM/blob/main/phone_agent/config/prompts_en.py [4] handler.py – parse_action 实现与动作分发接口. https://github.com/zai-org/Open-AutoGLM/blob/main/phone_agent/actions/handler.py [5] handler.py – ActionHandler 支持的动作类型与执行逻辑. https://github.com/zai-org/Open-AutoGLM/blob/main/phone_agent/actions/handler.py [6] adb/init.py – Android 设备控制函数导出. https://github.com/zai-org/Open-AutoGLM/blob/main/phone_agent/adb/__init__.py [7] adb/connection.py – ADB 连接、列设备与 server 管理实现. https://github.com/zai-org/Open-AutoGLM/blob/main/phone_agent/adb/connection.py [8] hdc/init.py – HarmonyOS 设备控制接口导出. https://github.com/zai-org/Open-AutoGLM/blob/main/phone_agent/hdc/__init__.py [9] hdc/connection.py – HDC 连接、列设备与 server 管理实现. https://github.com/zai-org/Open-AutoGLM/blob/main/phone_agent/hdc/connection.py [10] main.py – CLI 入口与 Agent/ModelConfig 组装逻辑. https://github.com/zai-org/Open-AutoGLM/blob/main/main.py [11] model/client.py – ModelClient 与消息构造、流式响应处理. https://github.com/zai-org/Open-AutoGLM/blob/main/phone_agent/model/client.py [12] AutoGLM-Phone-9B-Multilingual 模型卡 – 模型架构与能力说明. https://huggingface.co/zai-org/AutoGLM-Phone-9B-Multilingual

Logo

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

更多推荐