当前位置: 首页 > article >正文

阶跃星辰 GUI-MCP 解读---(2)---决策层

本文是第二篇主要是介绍决策层本层在任何情况下是/非MCP都会用到。因为是反推解读而且时间有限所以可能会有各种错误还请大家不吝指出。0x01 LocalServerLocalServer 是本地 GUI Agent 服务器实现作为系统核心组件之一负责协调模型推理、环境管理和任务执行。总的来说LocalServer 是 GUI Agent 系统的大脑负责将高层任务请求转化为具体的模型推理和设备操作序列。1.1 核心功能概述会话管理模型推理调度即负责与 LLM 交互解析模型输出为可执行动作环境状态跟踪日志记录与持久化1.2 详细功能说明会话管理get_session 方法创建新的任务会话并分配唯一 session_idUUID 保证唯一性初始化会话配置任务描述、任务类型、模型配置等记录会话开始日志自动化步骤执行automate_step 方法这是 LocalServer 的核心方法负责执行单步自动化操作① 环境状态读取读取历史日志获取之前的环境和动作记录解析当前观察主要是屏幕截图支持图像缩放预处理② 消息构建使用 Parser 将任务、环境和历史动作转换为模型输入消息支持图像缩放预处理③ 模型调用调用 ask_llm_anything 函数与 LLM 交互并记录模型推理时间和响应④ 动作解析使用 Parser 将模型响应解析为可执行动作⑤ 日志记录保存完整的交互日志环境、动作、模型输入输出等支持调试模式下的详细输出日志管理系统使用 LocalServerLogger 管理会话日志提供日志与图像文件分离存储支持日志读取和图像保存1.3 在系统架构中的位置LocalServer 在整个系统中起到承上启下的协调作用MCP 接口 / 命令行工具 ↓ [LocalServer]协调层 ↓ ↓ Parser环境转换 LLM 模型推理决策 ↓ 设备执行层act_on_device 等1.4 实现automate_stepautomate_step 将 GUI 交互的观测信息截图 文本转换为可执行的动作指令是 GUI-Agent 决策的核心环节。通过解析器适配不同任务类型图片预处理适配不同模型日志全流程记录保证可溯源流程图数据预处理阶段核心是将用户的截图 查询转换为 LLM 可识别的格式同时通过日志器保存原始数据保证可溯源适配优化阶段通过图片预处理缩放适配不同 LLM 的输入要求深拷贝原始消息避免预处理修改日志数据LLM 交互阶段封装模型调用参数记录调用全生命周期耗时便于性能监控和调优结果输出阶段将 LLM 的文本响应解析为结构化动作同时返回步骤数适配 Copilot 服务的多步执行逻辑代码automate_step 的代码如下def automate_step(self, payload: dict) - dict: Automate a step in the Copilot service. 核心功能执行Copilot服务的单步自动化逻辑输入观测信息截图查询输出下一步操作指令 # 从请求载荷中提取会话ID用于日志隔离和溯源 session_id payload[session_id] # 初始化本地服务器日志器指定日志目录、图片目录、会话ID用于保存步骤截图和日志 logger LocalServerLogger({ log_dir: self.server_config[log_dir], image_dir: self.server_config[image_dir], session_id: session_id }) # 计算当前步骤数日志列表长度-1logs为全局/类内维护的历史日志0号为配置日志 current_ste len(logs) - 1 # 读取0号日志配置日志解析核心配置信息 config_log logs[0] config_dict config_log[message] # 提取任务类型、模型配置、核心任务描述 task_type config_dict[task_type] model_config config_dict[model_config] task config_dict[task] # 从观测信息中获取当前步骤的核心输入截图用户查询 observation payload[observation] # 提取截图的URL并读取图片数据 image_url observation[screenshot][image_url][url] image read_from_url(image_url) # 保存图片到本地生成内部可访问的图片URL用于日志和LLM输入 image_inner_url logger.save_image(image, fstep_{current_ste1}) # 提取用户查询无则为空字符串 query observation.get(query, ) # 定义内部函数从历史日志中提取环境信息和动作序列logs[1:]为非配置日志 def get_envs_acts_from_logs(logs): environments [] # 存储历史环境信息截图用户输入 actions [] # 存储历史动作指令 for log in logs[1:]: msg log[message] environments.append(msg[environment]) actions.append(msg[action]) return environments, actions # 提取历史环境和动作构建上下文 environments, actions get_envs_acts_from_logs(logs) # 构建当前步骤的环境信息本地图片URL用户查询 current_env { image: image_inner_url, user_comment: query } # 将当前环境加入历史列表用于LLM上下文构建 environments.append(current_env) # 根据任务类型获取对应的解析器适配不同任务的消息构建/动作解析逻辑 parser get_parser(task_type) # 调用解析器将任务、历史环境/动作转换为LLM可识别的消息格式 messages_to_ask parser.env2messages4ask( task task, environments environments, actions actions, ) # 深拷贝原始消息用于日志记录避免后续图片预处理修改原始数据 asked_messages deepcopy(messages_to_ask) # 提取模型配置模型名称、提供商默认eval model_name model_config[model_name] model_provider model_config.get(model_provider, eval) # 提取LLM调用参数设置默认值保证参数完整性 args model_config.get(args, { temperature: 0.1, # 低温度保证输出稳定 top_p: 1.0, # 采样策略 frequency_penalty: 0.0, # 重复惩罚 max_tokens: 512, # 最大生成令牌数 }) # 提取图片预处理配置None则不处理 image_preprocess model_config.get(image_preprocess, None) # 图片预处理若指定目标尺寸缩放消息中的图片 if image_preprocess is not None: if target_image_size in image_preprocess: target_image_size image_preprocess[target_image_size] # 定义内部函数遍历消息缩放所有图片URL def resize_image_in_messages(messages, target_size): for msg in messages: # 跳过纯文本消息 if type(msg[content]) str: continue # 遍历消息内容处理图片URL for content in msg[content]: if content[type] text: continue # 提取图片URL并生成缩放后的Base64 URL image_url content[image_url][url] image_resize_url make_b64_url(image_url, resize_config{ is_resize: True, target_image_size: target_size }) # 替换为缩放后的URL适配LLM的图片输入要求 content[image_url][url] image_resize_url # 执行图片缩放修改待发送给LLM的消息中的图片URL resize_image_in_messages(messages_to_ask, target_image_size) # 记录LLM调用开始时间监控耗时 llm_start_time time.time() # 调用LLM传入提供商、模型名、消息、参数获取响应 response ask_llm_anything( model_providermodel_provider, model_namemodel_name, messagesmessages_to_ask, argsargs ) # 记录LLM调用结束时间 llm_end_time time.time() # 调用解析器将LLM文本响应解析为结构化的动作指令 action parser.str2action(response) # 构建当前步骤的日志消息完整记录上下文、模型响应、耗时等 log_message { environment: current_env, # 当前环境信息 action: action, # 解析后的动作指令 asked_messages: asked_messages, # 原始LLM请求消息未预处理 model_response: response, # LLM原始响应 model_config: model_config, # 模型配置 llm_cost: { # LLM调用耗时统计 llm_time: llm_end_time - llm_start_time, llm_start_time: llm_start_time, llm_end_time: llm_end_time }, } # 返回核心结果下一步动作指令、当前步骤数 return { action: action, current_step: current_ste 1 }ask_llm_anythingask_llm_anything 是阶跃星辰 GUI-Agent 中通用的 LLM 调用核心函数专门负责将 GUI 场景下的多模态消息文本 图片标准化处理后调用指定 LLM 并返回结果其核心特色包括① 多源图片适配自动将 URL 形式的图片转换为 Base64 编码兼容 PNG/JPEG 格式同时支持image_b64格式自动转换为image_url格式统一 LLM 输入规范② 灵活的图片预处理能力支持按指定尺寸缩放图片且缩放后统一转换为 JPEG 格式并压缩质量适配不同 LLM 的图片输入限制③ 模型配置解耦通过读取model_config.yaml文件动态加载不同提供商的 API 地址和密钥无需硬编码④ 完整的调用监控记录 LLM 推理耗时和请求 ID便于性能分析和问题排查⑤ 兼容推理过程返回若 LLM 返回reasoning_content则拼接至结果前保留模型思考过程提升 GUI-Agent 决策的可解释性⑥ 鲁棒的参数处理为温度、最大令牌数等核心参数设置默认值避免调用异常流程图流程图核心说明初始化阶段优先加载模型配置文件校验提供商合法性避免无效 API 调用消息预处理核心统一图片格式将image_urlURL/Base64、image_b64全部转换为标准image_urlBase64 格式将图片按需缩放至目标尺寸统一转换为 JPEG 格式压缩适配 LLM 输入限制LLM 交互阶段记录调用全生命周期耗时打印关键监控信息耗时 / 请求 ID便于问题排查结果处理兼容reasoning_content模型思考过程拼接后返回提升 GUI-Agent 决策的可解释性代码ask_llm_anything 的代码如下def ask_llm_anything(model_provider, model_name, messages, args { max_tokens: 256, temperature: 0.5, top_p: 1.0, frequency_penalty: 0.0, }, resize_configNone): 通用LLM调用函数处理多模态消息文本图片调用指定LLM并返回结果 :param model_provider: 模型提供商如openai/self-host等 :param model_name: 模型名称如gpt-4v/llama3-vision等 :param messages: 待发送的多模态消息列表 :param args: LLM调用参数温度、最大令牌数等 :param resize_config: 图片缩放配置是否缩放、目标尺寸 :return: LLM返回的文本结果含可选的推理过程 # 读取模型配置文件加载不同提供商的API地址和密钥 with smart_open(model_config.yaml, r) as f: model_config yaml.safe_load(f) # 配置当前提供商的API基础地址和密钥 if model_provider in model_config: openai.api_base model_config[model_provider][api_base] openai.api_key model_config[model_provider][api_key] else: # 未知提供商则抛出异常避免无效调用 raise ValueError(fUnknown model provider: {model_provider}) # 定义内部函数预处理消息中的图片统一转换为Base64格式的image_url def preprocess_messages(messages): # 遍历每条消息 for msg in messages: # 跳过纯文本消息content为字符串 if type(msg[content]) str: continue # 断言content为列表多模态内容格式 assert type(msg[content]) list # 遍历消息内的每个内容块文本/图片 for content in msg[content]: # 跳过文本内容块 if content[type] text: continue # 处理image_url类型的图片 if content[type] image_url: url content[image_url][url] # 已为Base64格式则跳过 if url.startswith(data:image/): continue else: # 从URL读取图片字节数据 image_bytes smart_open(url, moderb).read() # 转换为Base64编码 b64 base64.b64encode(image_bytes).decode(utf-8) # 判断图片格式设置对应的Base64前缀 if image_bytes[0:4] b\x89PNG: content[image_url][url] data:image/png;base64, b64 elif image_bytes[0:2] b\xff\xd8: content[image_url][url] data:image/jpeg;base64, b64 else: # 未知格式默认按PNG处理 content[image_url][url] data:image/png;base64, b64 else: # 处理image_b64类型转换为统一的image_url格式 assert content[type] image_b64 b64 content[image_b64][b64_json] # 删除原image_b64字段 del content[image_b64] # 新增image_url字段统一格式 content[image_url] {url: data:image/png;base64, b64} content[type] image_url # 图片缩放处理若配置了缩放且开启 if resize_config is not None and resize_config.get(is_resize, False) True: # 提取Base64编码部分去掉前缀 image_url content[image_url][url] image_b64_url image_url.split(,, 1)[1] # 解码Base64为图片字节数据 image_data base64.b64decode(image_b64_url) # 打开图片并缩放至目标尺寸 image Image.open(io.BytesIO(image_data)) image image.resize(size resize_config[target_image_size]) # 转换为RGB并保存为JPEG格式压缩质量85 image_data io.BytesIO() image image.convert(RGB) image.save(image_data, formatJPEG, quality85) image_data image_data.getvalue() # 重新编码为Base64并更新URL b64_image base64.b64encode(image_data).decode(utf-8) content[image_url][url] fdata:image/jpeg;base64,{b64_image} return messages # 执行消息预处理统一图片格式和尺寸 messages preprocess_messages(messages) # 记录LLM调用开始时间 start_time time.time() # 调用OpenAI兼容的ChatCompletion接口 completion openai.ChatCompletion.create( api_keyopenai.api_key, # 传入API密钥 api_base openai.api_base, # 传入API基础地址 modelmodel_name, # 指定模型名称 messagesmessages, # 预处理后的多模态消息 temperatureargs.get(temperature, 0.5), # 采样温度默认0.5 top_pargs.get(top_p, 1.0), # 核采样默认1.0 frequency_penaltyargs.get(frequency_penalty, 0.0), # 重复惩罚默认0.0 max_tokensargs.get(max_tokens, 100), # 最大生成令牌数默认100 ) # 记录LLM调用结束时间 end_time time.time() # 打印推理耗时便于性能监控 print(fLLM {model_name} inference time: {end_time - start_time:.2f} seconds) # 提取LLM返回的核心结果 result completion.choices[0].message[content] # 打印请求ID便于问题排查 print(llm ask id:, completion[id]) # 提取可选的推理过程内容reasoning_content reasoning completion.choices[0].message.get(reasoning_content, ) # 若有推理过程拼接至结果前格式推理内容\n结果 if reasoning is not None and len(reasoning) 0: result reasoning |FunctionCallEnd|0x02 Parser0920Summary 的功能如上一篇所言GUI-MCP 提供一套跨平台的标准协议将设备能力抽象为少量原子级和复合级工具。其分层双栈架构把“低层 MCP”与“高层 MCP”结合起来前者提供细粒度操作如点击、滑动、文本输入后者则把整个任务委派给本地部署的 GUI 专家模型如 Step-GUI-4B。该设计让主 LLM 只需关注高层规划而将常规 GUI 操作卸载给本地模型。尤为关键的是GUI-MCP 支持高隐私执行模式原始截图与敏感状态始终留在设备端仅将语义摘要发送给外部 LLM从而在利用云端推理能力的同时有效保护用户隐私。因此图像摘要/文本摘要/任务描述 是一个及其重要的功能。Parser0920Summary 是一个专用于 GUI Agent 交互的解析器类 在 GUI Agent 体系中充当关键桥梁负责把自然语言任务和环境信息转换成模型可理解的消息并将模型输出解析为可执行的动作。2.1 核心功能概览Parser0920Summary 的核心功能如下。构造提供给 LLM 的提示信息环境信息 → 消息格式即 环境信息 任务描述 → [Parser0920Summary] → 模型输入消息解析 LLM 返回的动作指令模型输出 → 结构化动作即 模型输出字符串 → [Parser0920Summary] → 结构化动作 → 设备执行动作格式标准化历史交互摘要维护通过上述双向转换Parser0920Summary 实现自然语言与设备操作之间的无缝衔接是 GUI Agent 理解并执行复杂任务的核心组件。2.2 详细功能说明构建提示词make_status_prompt 该函数是整个 GUI Agent 系统中人机交互的关键环节确保模型能够获得足够的上下文信息来做出正确的操作决策。整合任务上下文信息当前用户任务描述历史操作摘要summary_history用户评论/指令user_comment当前屏幕截图格式化提示内容将所有信息组织成结构化的文本格式添加必要的引导说明指导模型如何响应包含动作空间定义和输出格式要求处理历史对话整合之前的问答历史historical_qa特别强调用户的最新指令环境转消息env2messages4ask将任务描述、历史环境和动作转换为可供模型理解的消息格式整合任务描述与用户指令添加历史操作摘要包含当前屏幕截图处理用户与 Agent 的问答历史生成符合模型输入要求的多模态消息字符串到动作解析str2action将模型输出的字符串解析为结构化的动作对象解析提取动作类型和参数兼容多种动作格式标准化坐标点容错错误格式动作到字符串转换action2str将结构化动作转换为标准化字符串格式生成含思考过程的完整输出格式化各类动作参数添加动作摘要信息动作标准化action2action确保动作对象符合标准格式根据动作类型CLICK、TYPE、AWAKE、INFO、WAIT、COMPLETE、ABORT、SLIDE、LONGPRESS验证特定字段统一不同动作类型的参数处理字段命名兼容性问题2.3 重点函数分析我们要把几个函数单独拿出来分析。2.3.1 str2actionstr2action 函数负责把模型生成的原始字符串解析成可执行的结构化指令使系统能够理解并执行模型的决策。核心步骤核心步骤如下提取思考过程CoT捕获 内容容错修正标签拼写如 解析动作参数按制表符分隔提取键值对获取 action、explain、point/point1/point2 等关键字段处理制表符分隔的键值对格式。数据类型转换将坐标字符串 100,200 转为整数列表 [100, 200]对其他参数执行相应类型转换。容错处理应对模型输出格式不规范返回错误信息便于调试解析失败。使用场景在 LocalServer 的 automate_step 方法中调用response ask_llm_anything(...) # 获取模型响应 action parser.str2action(response) # 解析为结构化动作输入模型字符串THINK我需要点击搜索按钮来查找相关信息/THINK explain点击搜索按钮以开始搜索|tactionCLICK|tpoint:500,320|tsummary:已点击搜索按钮输出结构化字典OrderedDict([ (cot, 我需要点击搜索按钮来查找相关信息), (explain, 点击搜索按钮以开始搜索), (action, CLICK), (point, [500, 320]), (summary, 已点击搜索按钮) ])代码def str2action(self, command_str): command_str command_str.strip() # Normalize THINK tags: fix typos, case, and spacing command_str ( command_str .replace(TINK, THINK).replace(/TINK, /THINK) .replace(think, THINK).replace(/think, /THINK) ) command_str re.sub(r\s*/?THINK\s*, lambda m: THINK if / not in m.group() else /THINK, command_str, flagsre.IGNORECASE) # Extract CoT and key-value parts # Expected format: THINK cot /THINK\nexplain:xxx\taction:xx\tvalue:xxx\tsummary:xxx try: cot_part command_str.split(THINK)[1].split(/THINK)[0].strip() kv_part command_str.split(/THINK)[1].strip() except IndexError: print(f[Parser Warning] Missing THINK tags, treating entire response as kv) kv_part command_str cot_part action OrderedDict() action[cot] cot_part # Error split by \n, should split by tab separator kvs [kv.strip() for kv in kv_part.split(\t) if kv.strip()] for kv in kvs: if : not in kv: continue key kv.split(:, 1)[0].strip() value kv.split(:, 1)[1].strip() if key action: action[action] value elif key summary: action[summary] value elif point in key: # Parse point format: x,y or x y try: # Replace comma with space for unified processing coords value.replace(,, ).split() if len(coords) 2: raise ValueError(fExpected 2 coordinates, got {len(coords)}) x, y int(coords[0]), int(coords[1]) action[key] [x, y] except (ValueError, IndexError) as e: raise ValueError( f[Parser Error] Failed to parse point {value} for key {key}: {str(e)}. fExpected format: x,y or x y with integer values ) from e else: action[key] value return action2.3.2 make_status_prompt该函数在 Parser0920Summary 类的 env2messages4ask 方法中被调用用于生成发送给 LLM 的消息内容# 在 parser_0920_summary.py 中 conversations [ { type: text, text: task_define_prompt # 任务定义和动作空间说明 make_status_prompt( # 当前状态信息 task, current_env[image], hints, summary_history, qa_prompt ) } ]函数返回一个包含以下元素的列表任务描述和历史操作用户任务与已完成操作的文本描述当前截图以图像 URL 形式提供的当前屏幕截图操作指导指导模型如何思考和回应的说明文本代码如下def make_status_prompt(task, current_image, hints, summary_history, user_comment): if len(hints) 0: hint_str else: hint_str \n.join([f- {hint} for hint in hints]) hint_str f### HINT\n{hint_str}\n if user_comment : history_display summary_history if summary_history.strip() else 暂无历史操作 else: history_display summary_history user_comment if summary_history.strip() else 暂无历史操作 user_instruction f\n\n{user_comment}\n\n if user_comment ! else task task user_instruction 指令结束\n\n status_conversation [ { type: text, text: f 已知用户指令为{task} 已知已经执行过的历史动作如下{history_display} 当前手机屏幕截图如下 }, { type: image_url, image_url: {url: current_image} }, { type: text, text: f 在执行操作之前请务必回顾你的历史操作记录和限定的动作空间先进行思考和解释然后输出动作空间和对应的参数 1. 思考THINK在 THINK 和 /THINK 标签之间。 2. 解释explain在动作格式中使用 explain: 开头简要说明当前动作的目的和执行方式。 在执行完操作后请输出执行完当前步骤后的新历史总结。 输出格式示例 THINK 思考的内容 /THINK explain:解释的内容\taction:动作空间和对应的参数\tsummary:执行完当前步骤后的新历史总结 } ] return status_conversation2.4 THINK 标签既然上面代码中提到了THINK 标签我们本小节就进行分析。定义和结构在Parser0920Summary类中定义了 THINK 标签的使用方式THINK 标签用于封装 Agent 的思维过程格式为THINK 思考的内容 /THINK在make_status_prompt函数中明确要求 Agent 在执行操作前进行思考解析在str2action方法中解析包含 THINK 标签的响应使用正则表达式提取 THINK 标签中的内容作为COTChain of Thought字段str2action方法中包含错误处理逻辑处理标签格式不规范的情况在 LLM 交互中的应用在ask_llm_v2.py中当 LLM 响应包含 THINK 标签时会提取 之后的内容ask_llm_anything函数会处理reasoning_content字段将其包装在 THINK 标签中在 Agent 决策中的作用在gui_agent_loop中每个步骤的action都包含cot字段即 THINK 标签内容COT内容在日志中输出便于调试和理解 Agent 的决策过程在 INFO 动作中的应用当 Agent 执行 INFO 动作时auto_reply 函数会分析 THINK 标签内容来理解 Agent 的问题auto_reply 使用 THINK 标签中的内容作为上下文生成合适的回复2.5 COT 输出与执行流程GUI-Agent 不是将 COT 输出作为具体执行流程。COT 输出主要作用为COT 不直接参与设备操作的执行实际执行的动作由 action 字段定义如 CLICK、TYPE 等COT 记录并展示 Agent 的思考过程让用户了解 Agent 如何分析界面元素和决策点击位置COT 可以协助任务规划Agent 需要分析当前屏幕截图和任务COT 可以帮助 Agent 系统化地分析视觉信息和任务需求Agent 需要将复杂任务分解为一系列动作COT 可以帮助 Agent 规划执行路径Agent 需要将视觉信息转换为具体操作COT 可以帮助 Agent 理解界面元素与目标之间的关系有助于精确定位点击坐标x,y 为 0-1000 范围有助于处理复杂的界面布局和交互场景COT 提供决策的可解释性开源辅助调试和分析当 Agent 做出错误决策时可以通过 THINK 内容追踪错误原因便于调试和改进 Agent 的决策逻辑在需要时辅助生成对用户问题的回复即在 INFO 动作中COT 信息可用于生成对用户的回复具体如下COT 是在 标签中生成的用于解释 Agent 的决策逻辑在 str2action 方法中COT 从 LLM 响应中提取并存储为 COT 字段在 execute_task 的返回结果中中间日志会包含 COT 信息intermediate_logs 中包含每个步骤的 COT 字段在最终结果中final_action 也包含 COT 信息2.6 支持的动作类型动作空间定义Parser0920Summary 支持完整的 Android GUI 操作集合例如CLICK点击屏幕坐标OTYPE输入文本COMPLETE标记任务完成WAIT等待指定时间AWAKE唤醒指定应用INFO向用户询问信息ABORT终止任务SLIDE滑动操作LONGPRESS长按操作提示词引导在task_define_prompt中明确定义了可用的动作空间和参数格式。task_define_prompt 你是一个手机 GUI-Agent 操作专家你需要根据用户下发的任务、手机屏幕截图和交互操作的历史记录借助既定的动作空间与手机进行交互从而完成用户的任务。 请牢记手机屏幕坐标系以左上角为原点x轴向右y轴向下取值范围均为 0-1000。 # 行动原则 1. 你需要明确记录自己上一次的action如果是滑动不能超过5次。 2. 你需要严格遵循用户的指令如果你和用户进行过对话需要更遵守最后一轮的指令 # Action Space: 在 Android 手机的场景下你的动作空间包含以下9类操作所有输出都必须遵守对应的参数要求 1. CLICK点击手机屏幕坐标需包含点击的坐标位置 point。 例如action:CLICK\tpoint:x,y 2. TYPE在手机输入框中输入文字需包含输入内容 value、输入框的位置 point。 例如action:TYPE\tvalue:输入内容\tpoint:x,y 3. COMPLETE任务完成后向用户报告结果需包含报告的内容 value。 例如action:COMPLETE\treturn:完成任务后向用户报告的内容 4. WAIT等待指定时长需包含等待时间 value秒。 例如action:WAIT\tvalue:等待时间 5. AWAKE唤醒指定应用需包含唤醒的应用名称 value。 例如action:AWAKE\tvalue:应用名称 6. INFO询问用户问题或详细信息需包含提问内容 value。 例如action:INFO\tvalue:提问内容 7. ABORT终止当前任务仅在当前任务无法继续执行时使用需包含 value 说明原因。 例如action:ABORT\tvalue:终止任务的原因 8. SLIDE在手机屏幕上滑动滑动的方向不限需包含起点 point1 和终点 point2。 例如action:SLIDE\tpoint1:x1,y1\tpoint2:x2,y2 9. LONGPRESS长按手机屏幕坐标需包含长按的坐标位置 point。 例如action:LONGPRESS\tpoint:x,y 动作解析通过str2action方法解析模型输出的动作该方法会从模型响应中提取 action 类型、参数等信息解析时会验证动作类型是否在预定义的动作空间内动作验证使用action_assertion函数验证动作格式验证每个动作是否包含必需的字段如CLICK 动作必须包含 point 参数TYPE 动作必须包含 value 参数SLIDE 动作必须包含 point1 和 point2 参数实际执行流程实际生成动作的流程如下LocalServer 的 automate_step 方法接收 observation 并生成动作gui_agent_loop 调用 automate_step 获取动作动作通过 uiTars_to_frontend_action 转换为前端动作act_on_device 执行具体的设备操作0x03 交互LocalServer.automate_step 与 Parsero920Summary 之间的逻辑关系如下LocalServer.automate_step 负责协调整个流程从日志读取历史环境和动作通过 get_parser 获取 Parsero920Summary 实例调用 env2messages4ask 构建模型输入消息Parsero920Summary 内部函数协作env2messages4ask 接收任务、环境和动作参数整合历史动作和当前状态通过 make_status_prompt 构建状态提示包含任务描述、历史动作和当前截图str2action 解析模型输出action2action 验证动作格式模型交互流程env2messages4ask 返回构建好的消息格式LocalServer 通过 ask_llm_anything 调用模型模型返回字符串后str2action 解析成动作对象处理LocalServer 将动作和当前步骤信息记录到日志数据流向环境数据从 LocalServer 传递给 Parsero920SummaryParsero920Summary 构建消息并返回给 LocalServerLocalServer 调用模型并接收响应Parsero920Summary 解析模型响应并返回动作给 LocalServerLocalServer 记录结果并返回给调用者Parser0920Summary 与 LocalServer 交互流程图如下

相关文章:

阶跃星辰 GUI-MCP 解读---(2)---决策层

本文是第二篇,主要是介绍决策层,本层在任何情况下(是/非MCP)都会用到。因为是反推解读,而且时间有限,所以可能会有各种错误,还请大家不吝指出。0x01 LocalServerLocalServer 是本地 GUI Agent 服…...

Odoo 19 AI功能实战:不用写代码,用自然语言就能自动化你的业务流程

Odoo 19 AI功能实战:不用写代码,用自然语言就能自动化你的业务流程 想象一下,早晨打开电脑,你只需要对系统说"把昨天所有未处理的客户咨询按优先级排序,并生成回复草稿",30秒后就能收到整理好的列…...

MongoDB EF Core 提供程序中的可查询加密和向量搜索

ngoDB Entity Framework (EF) Core 提供程序自 2024 年 5 月起正式发布。自发布以来,我们欣喜地看到 .NET 开发人员社区给予了积极的反馈,并且该提供程序在各种应用程序中得到了越来越广泛的采用。 该提供商使开发人员能够利用 LINQ 查询、更改跟踪和乐…...

Topit:5倍提升多任务效率的macOS窗口置顶神器

Topit:5倍提升多任务效率的macOS窗口置顶神器 【免费下载链接】Topit Pin any window to the top of your screen / 在Mac上将你的任何窗口强制置顶 项目地址: https://gitcode.com/gh_mirrors/to/Topit Topit是一款专为macOS用户设计的开源窗口管理工具&…...

Unity VideoPlayer常见报错解析:First video frame not zero与Color Standard问题实战

1. 解析"First video frame not zero"报错 遇到Unity VideoPlayer报出"First video frame not zero"时,很多开发者会一头雾水。这个错误直译过来就是"第一帧视频不是从零开始的",听起来有点抽象。我用个生活中的例子解释&…...

Pine Script交易策略开发实战指南:从零基础到自动化交易的完整路径

Pine Script交易策略开发实战指南:从零基础到自动化交易的完整路径 【免费下载链接】awesome-pinescript A Comprehensive Collection of Everything Related to Tradingview Pine Script. 项目地址: https://gitcode.com/gh_mirrors/aw/awesome-pinescript …...

面试:synchronized用过吗,其原理是什么

一、基础回答 1. 用过吗?用来做什么? 用过。synchronized 是 Java 内置的悲观锁关键字,用来解决多线程并发安全问题,保证同一时刻只有一个线程执行被锁定的代码,避免线程安全问题(如原子性、可见性、有序性…...

electron+ruoyi-vue深度整合指南:从web到桌面的完整改造方案

ElectronRuoYi-Vue企业级桌面应用深度整合实战 企业级应用从Web向桌面端迁移已成为提升用户体验的重要路径。作为国内广泛使用的开源后台管理系统,RuoYi-Vue与Electron的结合能够快速构建跨平台桌面应用。但真正实现企业级稳定运行,需要解决主进程通信、…...

BiliTools:5分钟学会高效管理你的B站学习资源

BiliTools:5分钟学会高效管理你的B站学习资源 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools 你是否曾经…...

保姆级教程:手把手教你配置英飞凌TC38x的Overlay功能(附寄存器详解)

保姆级教程:手把手教你配置英飞凌TC38x的Overlay功能(附寄存器详解) 在汽车电子控制单元(ECU)开发中,实时标定参数是开发调试过程中不可或缺的环节。英飞凌TC38x系列微控制器提供的Overlay功能,…...

LCD1602自定义字符显示实战:从取模到屏幕显示的完整指南

1. LCD1602显示模块基础入门 第一次接触LCD1602时,我完全被它简单的接口和强大的功能吸引了。这块2行16字符的小屏幕,几乎成了所有嵌入式初学者的"Hello World"实验标配。但很多人可能不知道,它内置的字符生成器(CGROM&…...

STEP3-VL-10B私有化部署指南:Apache 2.0许可下的完整教程

STEP3-VL-10B私有化部署指南:Apache 2.0许可下的完整教程 1. 认识STEP3-VL-10B:轻量级多模态模型 STEP3-VL-10B是阶跃星辰开源的一款10B参数量的多模态视觉语言模型。虽然参数规模不算庞大,但在多个专业评测中表现优异,甚至能与…...

Node-RED 4.0.2连接Oracle数据库避坑指南:从模组选择到环境变量配置全流程

Node-RED 4.0.2连接Oracle数据库全流程实战:从环境搭建到高效查询 在物联网和自动化流程开发领域,Node-RED因其可视化编程特性而广受欢迎。当需要将Node-RED与Oracle数据库集成时,许多开发者会遇到各种环境配置和连接问题。本文将详细介绍如何…...

intv_ai_mk11新手教程:3步完成提示词输入→参数调整→结果查看

intv_ai_mk11新手教程:3步完成提示词输入→参数调整→结果查看 1. 快速了解intv_ai_mk11 intv_ai_mk11是一个基于Llama架构的文本生成模型,特别适合日常的问答、内容改写和简短创作。它就像一位随时待命的文字助手,能帮你快速完成各种文字工…...

AGI能力边界与安全约束

AGI能力边界与安全约束📝 本章学习目标:通过本章学习,你将全面掌握"AGI能力边界与安全约束"这一核心主题,建立系统性认知。一、引言:为什么这个话题如此重要 在人工智能快速发展的今天,AGI能力边…...

Godot引擎PCK文件解析与资源提取指南:从入门到专家

Godot引擎PCK文件解析与资源提取指南:从入门到专家 【免费下载链接】godot-unpacker godot .pck unpacker 项目地址: https://gitcode.com/gh_mirrors/go/godot-unpacker 一、基础认知:PCK文件的数字档案馆架构 Godot引擎的PCK文件(P…...

手把手教你用Verilog实现一个带权重的轮询仲裁器(附Testbench与仿真波形)

手把手教你用Verilog实现带权重的轮询仲裁器 在数字电路设计中,仲裁器(Arbiter)是一个常见但至关重要的模块。想象一下,当多个主设备(比如CPU、DMA控制器等)需要访问同一个从设备(比如内存)时,仲…...

电路分析不求人:手把手教你用戴维南定理搞定复杂电路(附Multisim仿真验证)

电路分析实战:用戴维南定理拆解复杂电路的全流程指南 当你面对一个布满电阻、电源和交叉连线的复杂电路图时,是否感到无从下手?戴维南定理就像一把瑞士军刀,能将这些看似棘手的电路简化为一个电压源和一个电阻的串联组合。但理论归…...

凸优化问题中严格凸函数与最优解唯一性的关系

1. 为什么我们需要严格凸函数? 在优化问题中,我们常常会遇到多个局部最优解的情况,这就像在山地徒步时发现多个山谷,每个山谷看起来都很深,但只有一个是真正的最低点。严格凸函数就像是一个设计精良的漏斗&#xff0c…...

技术赋能旧设备:OpenCore Legacy Patcher让Mac重获新生

技术赋能旧设备:OpenCore Legacy Patcher让Mac重获新生 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 当您的Mac设备被苹果官方系统升级列表排除…...

突破魔兽争霸3帧率限制:WarcraftHelper实现180fps流畅游戏体验全攻略

突破魔兽争霸3帧率限制:WarcraftHelper实现180fps流畅游戏体验全攻略 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 在现代高性能电脑上运…...

Win11 23H2任务栏Copilot图标消失?别慌,一个注册表文件+两步设置帮你永久找回

Win11 23H2任务栏Copilot图标长效修复指南:从临时解决到永久生效 最近不少升级到Windows 11 23H2版本的用户发现,原本出现在任务栏右侧的Copilot图标突然消失了。这个问题看似小,却让依赖Copilot快速访问AI助手的用户感到不便。更令人困扰的是…...

[具身智能-250]:吾生也有涯,而知也无涯:深度学习的“模糊”智慧与泛化本质

“吾生也有涯,而知也无涯。”模糊的智慧。深度神经网络泛化能力强的本质是,通过数学公式构建最小神经元单元,然后进一步构建庞大的神经网络模型,该模型仅仅依赖历史经验,依赖过往数据的相似性、可能性,即概…...

AutoCAD二次开发避坑指南:手把手教你选对.NET、VS和CAD版本(2025版)

AutoCAD二次开发避坑指南:手把手教你选对.NET、VS和CAD版本(2025版) 刚接触AutoCAD二次开发时,最让人头疼的莫过于版本匹配问题。我曾在一个旧项目改造中,因为没注意Visual Studio版本与AutoCAD 2023的兼容性&#xff…...

避坑指南:海康RGBD工业相机Python开发那些事儿——从环境配置到实时显示

避坑指南:海康RGBD工业相机Python开发全流程实战 第一次接触海康RGBD相机时,我被它强大的深度感知能力吸引,但随之而来的是一连串的环境配置和开发难题。记得那个深夜,我对着报错的OpenCV界面发呆,才意识到工业级设备的…...

3个步骤实现Windows直接运行安卓应用:开发者与玩家的跨平台解决方案

3个步骤实现Windows直接运行安卓应用:开发者与玩家的跨平台解决方案 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 还在为手机应用无法在电脑上运行而困扰…...

matlab(Octave) 绘图

1. ezplot plot , [plɒt] ,vt. 绘图。 ezplot,easy to plot。用于绘制一元函数。 ezplot(expression,[左区间,右区间]) %语法 ezplot(1/x,[-10,10]); %例子,y1/x的图像图 1-1 ezplot作图,octave 2.mesh(x,y,z) 用于作…...

推荐系统中的特征工程

有这么一句话在业界广泛流传:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。所以特征工程的目的是最大限度地从原始数据中提取特征, 以供算法和模型使用。 特征类型 普通离散特征 职业, 婚姻状态等, 同常枚举值不超过100个.id类特…...

RN 0.63 双端冷启动线程流转

RN 0.63 旧架构下,Android 和 iOS 的冷启动都经历了相同的思路:主线程入口 → 后台线程做重活(创建引擎、加载 Bundle)→ JS Thread 接管 → Shadow 计算布局 → 主线程渲染首帧。两端实现细节不同,但线程模型一致。一…...

别再手动画码了!C#搭配ZXing.Net库,5分钟搞定商品标签一维码与会员卡二维码生成

企业级条码生成实战:用C#和ZXing.Net实现高效标签与会员卡管理 在仓储物流和会员管理的数字化浪潮中,条码技术早已从简单的商品标识进化为企业数据流转的核心枢纽。想象一下这样的场景:当仓库管理系统(WMS)收到订单时,系统自动生成…...