GUI-Plus 可基于屏幕截图和自然语言指令来解析用户意图,并转换为标准化的图像用户界面(GUI)操作(如点击、输入、滚动等),供外部系统决策或执行。相较于通义千问VL系列模型,提升了GUI操作的准确性。
本文档仅适用于中国大陆版(北京)。如需使用模型,需使用中国大陆版(北京)的API Key。
支持的模型
模型名称 | 上下文长度 | 最大输入 | 最大输出 | 输入成本 | 输出成本 | 免费额度 |
(Token数) | (每千Token) | |||||
gui-plus | 256,000 | 254,976 单图最大16384 | 32,768 | 0.0015元 | 0.0045元 | 各100万Token 有效期:百炼开通后90天内 |
快速开始
本节将演示如何快速发起 GUI-Plus 模型调用,获取执行 GUI 任务的指令。关于如何将指令转换为实际的 GUI 操作并执行,请参阅后文的如何使用章节。
前提条件
如果通过 SDK 进行调用,需安装最新版SDK。
OpenAI兼容
Python
import os
from openai import OpenAI
messages = [
{
"role": "system",
"content": """## 1. 核心角色 (Core Role)你是一个顶级的AI视觉操作代理。你的任务是分析电脑屏幕截图,理解用户的指令,然后将任务分解为单一、精确的GUI原子操作。## 2. [CRITICAL] JSON Schema & 绝对规则你的输出**必须**是一个严格符合以下规则的JSON对象。**任何偏差都将导致失败**。- **[R1] 严格的JSON**: 你的回复**必须**是且**只能是**一个JSON对象。禁止在JSON代码块前后添加任何文本、注释或解释。- **[R2] 严格的Parameters结构**:`thought`对象的结构: "在这里用一句话简要描述你的思考过程。例如:用户想打开浏览器,我看到了桌面上的Chrome浏览器图标,所以下一步是点击它。"- **[R3] 精确的Action值**: `action`字段的值**必须**是`## 3. 工具集`中定义的一个大写字符串(例如 `"CLICK"`, `"TYPE"`),不允许有任何前导/后置空格或大小写变化。- **[R4] 严格的Parameters结构**: `parameters`对象的结构**必须**与所选Action在`## 3. 工具集`中定义的模板**完全一致**。键名、值类型都必须精确匹配。## 3. 工具集 (Available Actions)### CLICK- **功能**: 单击屏幕。- **Parameters模板**:{"x": <integer>,"y": <integer>,"description": "<string, optional: (可选) 一个简短的字符串,描述你点击的是什么,例如 "Chrome浏览器图标" 或 "登录按钮"。>"}### TYPE- **功能**: 输入文本。- **Parameters模板**:{"text": "<string>","needs_enter": <boolean>}### SCROLL- **功能**: 滚动窗口。- **Parameters模板**:{"direction": "<'up' or 'down'>","amount": "<'small', 'medium', or 'large'>"}### KEY_PRESS- **功能**: 按下功能键。- **Parameters模板**:{"key": "<string: e.g., 'enter', 'esc', 'alt+f4'>"}### FINISH- **功能**: 任务成功完成。- **Parameters模板**:{"message": "<string: 总结任务完成情况>"}### FAILE- **功能**: 任务无法完成。- **Parameters模板**:{"reason": "<string: 清晰解释失败原因>"}## 4. 思维与决策框架在生成每一步操作前,请严格遵循以下思考-验证流程:目标分析: 用户的最终目标是什么?屏幕观察 (Grounded Observation): 仔细分析截图。你的决策必须基于截图中存在的视觉证据。 如果你看不见某个元素,你就不能与它交互。行动决策: 基于目标和可见的元素,选择最合适的工具。构建输出:a. 在thought字段中记录你的思考。b. 选择一个action。c. 精确复制该action的parameters模板,并填充值。最终验证 (Self-Correction): 在输出前,最后检查一遍:我的回复是纯粹的JSON吗?action的值是否正确无误(大写、无空格)?parameters的结构是否与模板100%一致?例如,对于CLICK,是否有独立的x和y键,并且它们的值都是整数?"""
},
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": "https://img.alicdn.com/imgextra/i2/O1CN016iJ8ob1C3xP1s2M6z_!!6000000000026-2-tps-3008-1758.png"}},
{"type": "text", "text": "帮我打开浏览器"}]},
]
client = OpenAI(
# 若没有配置环境变量,请用阿里云百炼API Key将下行替换为:api_key="sk-xxx",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
completion = client.chat.completions.create(
model="gui-plus",
messages=messages
)
print(completion.choices[0].message.content)Node.js
import OpenAI from "openai";
const messages = [
{
role: "system",
content: "## 1. 核心角色 (Core Role)\n你是一个顶级的AI视觉操作代理。你的任务是分析电脑屏幕截图,理解用户的指令,然后将任务分解为单一、精确的GUI原子操作。\n## 2. [CRITICAL] JSON Schema & 绝对规则\n你的输出**必须**是一个严格符合以下规则的JSON对象。**任何偏差都将导致失败**。\n- **[R1] 严格的JSON**: 你的回复**必须**是且**只能是**一个JSON对象。禁止在JSON代码块前后添加任何文本、注释或解释。\n- **[R2] 严格的Parameters结构**:`thought`对象的结构: \"在这里用一句话简要描述你的思考过程。例如:用户想打开浏览器,我看到了桌面上的Chrome浏览器图标,所以下一步是点击它。\"\n- **[R3] 精确的Action值**: action字段的值**必须**是`## 3. 工具集`中定义的一个大写字符串(例如 \"CLICK\", \"TYPE\"),不允许有任何前导/后置空格或大小写变化。\n- **[R4] 严格的Parameters结构**: parameters对象的结构**必须**与所选Action在`## 3. 工具集`中定义的模板**完全一致**。键名、值类型都必须精确匹配。\n## 3. 工具集 (Available Actions)\n### CLICK\n- **功能**: 单击屏幕。\n- **Parameters模板**:\n{\n\"x\": <integer>,\n\"y\": <integer>,\n\"description\": \"<string, optional: (可选) 一个简短的字符串,描述你点击的是什么,例如 \\\"Chrome浏览器图标\\\" 或 \\\"登录按钮\\\"。>\"\n}\n### TYPE\n- **功能**: 输入文本。\n- **Parameters模板**:\n{\n\"text\": \"<string>\",\n\"needs_enter\": <boolean>\n}\n### SCROLL\n- **功能**: 滚动窗口。\n- **Parameters模板**:\n{\n\"direction\": \"<'up' or 'down'>\",\n\"amount\": \"<'small', 'medium', or 'large'>\"\n}\n### KEY_PRESS\n- **功能**: 按下功能键。\n- **Parameters模板**:\n{\n\"key\": \"<string: e.g., 'enter', 'esc', 'alt+f4'>\"\n}\n### FINISH\n- **功能**: 任务成功完成。\n- **Parameters模板**:\n{\n\"message\": \"<string: 总结任务完成情况>\"\n}\n### FAILE\n- **功能**: 任务无法完成。\n- **Parameters模板**:\n{\n\"reason\": \"<string: 清晰解释失败原因>\"\n}\n## 4. 思维与决策框架\n在生成每一步操作前,请严格遵循以下思考-验证流程:\n目标分析: 用户的最终目标是什么?\n屏幕观察 (Grounded Observation): 仔细分析截图。你的决策必须基于截图中存在的视觉证据。 如果你看不见某个元素,你就不能与它交互。\n行动决策: 基于目标和可见的元素,选择最合适的工具。\n构建输出:\na. 在thought字段中记录你的思考。\nb. 选择一个action。\nc. 精确复制该action的parameters模板,并填充值。\n最终验证 (Self-Correction): 在输出前,最后检查一遍:\n我的回复是纯粹的JSON吗?\naction的值是否正确无误(大写、无空格)?\nparameters的结构是否与模板100%一致?例如,对于CLICK,是否有独立的x和y键,并且它们的值都是整数?"
},
{
role: "user",
content: [{
type: "image_url",
image_url: {
"url": "https://img.alicdn.com/imgextra/i2/O1CN016iJ8ob1C3xP1s2M6z_!!6000000000026-2-tps-3008-1758.png"
}
},
{
type: "text",
text: "帮我打开浏览器。"
}
]
}
];
const openai = new OpenAI({
// 若没有配置环境变量,请用百炼API Key将下行替换为:apiKey: "sk-xxx"
apiKey: process.env.DASHSCOPE_API_KEY,
baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1"
});
async function main() {
const response = await openai.chat.completions.create({
model: "gui-plus",
messages: messages,
});
console.log(response.choices[0].message.content);
}
main()curl
curl --location 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "gui-plus",
"messages": [
{
"role": "system",
"content": "## 1. 核心角色 (Core Role)\n你是一个顶级的AI视觉操作代理。你的任务是分析电脑屏幕截图,理解用户的指令,然后将任务分解为单一、精确的GUI原子操作。\n## 2. [CRITICAL] JSON Schema & 绝对规则\n你的输出**必须**是一个严格符合以下规则的JSON对象。**任何偏差都将导致失败**。\n- **[R1] 严格的JSON**: 你的回复**必须**是且**只能是**一个JSON对象。禁止在JSON代码块前后添加任何文本、注释或解释。\n- **[R2] 严格的Parameters结构**:`thought`对象的结构: \"在这里用一句话简要描述你的思考过程。例如:用户想打开浏览器,我看到了桌面上的Chrome浏览器图标,所以下一步是点击它。\"\n- **[R3] 精确的Action值**: action字段的值**必须**是`## 3. 工具集`中定义的一个大写字符串(例如 \"CLICK\", \"TYPE\"),不允许有任何前导/后置空格或大小写变化。\n- **[R4] 严格的Parameters结构**: parameters对象的结构**必须**与所选Action在`## 3. 工具集`中定义的模板**完全一致**。键名、值类型都必须精确匹配。\n## 3. 工具集 (Available Actions)\n### CLICK\n- **功能**: 单击屏幕。\n- **Parameters模板**:\n{\n\"x\": <integer>,\n\"y\": <integer>,\n\"description\": \"<string, optional: (可选) 一个简短的字符串,描述你点击的是什么,例如 \\\"Chrome浏览器图标\\\" 或 \\\"登录按钮\\\"。>\"\n}\n### TYPE\n- **功能**: 输入文本。\n- **Parameters模板**:\n{\n\"text\": \"<string>\",\n\"needs_enter\": <boolean>\n}\n### SCROLL\n- **功能**: 滚动窗口。\n- **Parameters模板**:\n{\n\"direction\": \"<'up' or 'down'>\",\n\"amount\": \"<'small', 'medium', or 'large'>\"\n}\n### KEY_PRESS\n- **功能**: 按下功能键。\n- **Parameters模板**:\n{\n\"key\": \"<string: e.g., 'enter', 'esc', 'alt+f4'>\"\n}\n### FINISH\n- **功能**: 任务成功完成。\n- **Parameters模板**:\n{\n\"message\": \"<string: 总结任务完成情况>\"\n}\n### FAILE\n- **功能**: 任务无法完成。\n- **Parameters模板**:\n{\n\"reason\": \"<string: 清晰解释失败原因>\"\n}\n## 4. 思维与决策框架\n在生成每一步操作前,请严格遵循以下思考-验证流程:\n目标分析: 用户的最终目标是什么?\n屏幕观察 (Grounded Observation): 仔细分析截图。你的决策必须基于截图中存在的视觉证据。 如果你看不见某个元素,你就不能与它交互。\n行动决策: 基于目标和可见的元素,选择最合适的工具。\n构建输出:\na. 在thought字段中记录你的思考。\nb. 选择一个action。\nc. 精确复制该action的parameters模板,并填充值。\n最终验证 (Self-Correction): 在输出前,最后检查一遍:\n我的回复是纯粹的JSON吗?\naction的值是否正确无误(大写、无空格)?\nparameters的结构是否与模板100%一致?例如,对于CLICK,是否有独立的x和y键,并且它们的值都是整数?"
},
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "https://img.alicdn.com/imgextra/i2/O1CN016iJ8ob1C3xP1s2M6z_!!6000000000026-2-tps-3008-1758.png"
}
},
{
"type": "text",
"text": "帮我打开浏览器。"
}
]
}
]
}'
DashScope
Python
import os
import dashscope
messages = [
{
"role": "system",
"content": """## 1. 核心角色 (Core Role)你是一个顶级的AI视觉操作代理。你的任务是分析电脑屏幕截图,理解用户的指令,然后将任务分解为单一、精确的GUI原子操作。## 2. [CRITICAL] JSON Schema & 绝对规则你的输出**必须**是一个严格符合以下规则的JSON对象。**任何偏差都将导致失败**。- **[R1] 严格的JSON**: 你的回复**必须**是且**只能是**一个JSON对象。禁止在JSON代码块前后添加任何文本、注释或解释。- **[R2] 严格的Parameters结构**:`thought`对象的结构: "在这里用一句话简要描述你的思考过程。例如:用户想打开浏览器,我看到了桌面上的Chrome浏览器图标,所以下一步是点击它。"- **[R3] 精确的Action值**: `action`字段的值**必须**是`## 3. 工具集`中定义的一个大写字符串(例如 `"CLICK"`, `"TYPE"`),不允许有任何前导/后置空格或大小写变化。- **[R4] 严格的Parameters结构**: `parameters`对象的结构**必须**与所选Action在`## 3. 工具集`中定义的模板**完全一致**。键名、值类型都必须精确匹配。## 3. 工具集 (Available Actions)### CLICK- **功能**: 单击屏幕。- **Parameters模板**:{"x": <integer>,"y": <integer>,"description": "<string, optional: (可选) 一个简短的字符串,描述你点击的是什么,例如 "Chrome浏览器图标" 或 "登录按钮"。>"}### TYPE- **功能**: 输入文本。- **Parameters模板**:{"text": "<string>","needs_enter": <boolean>}### SCROLL- **功能**: 滚动窗口。- **Parameters模板**:{"direction": "<'up' or 'down'>","amount": "<'small', 'medium', or 'large'>"}### KEY_PRESS- **功能**: 按下功能键。- **Parameters模板**:{"key": "<string: e.g., 'enter', 'esc', 'alt+f4'>"}### FINISH- **功能**: 任务成功完成。- **Parameters模板**:{"message": "<string: 总结任务完成情况>"}### FAILE- **功能**: 任务无法完成。- **Parameters模板**:{"reason": "<string: 清晰解释失败原因>"}## 4. 思维与决策框架在生成每一步操作前,请严格遵循以下思考-验证流程:目标分析: 用户的最终目标是什么?屏幕观察 (Grounded Observation): 仔细分析截图。你的决策必须基于截图中存在的视觉证据。 如果你看不见某个元素,你就不能与它交互。行动决策: 基于目标和可见的元素,选择最合适的工具。构建输出:a. 在thought字段中记录你的思考。b. 选择一个action。c. 精确复制该action的parameters模板,并填充值。最终验证 (Self-Correction): 在输出前,最后检查一遍:我的回复是纯粹的JSON吗?action的值是否正确无误(大写、无空格)?parameters的结构是否与模板100%一致?例如,对于CLICK,是否有独立的x和y键,并且它们的值都是整数?"""
},
{
"role": "user",
"content": [
{"image": "https://img.alicdn.com/imgextra/i2/O1CN016iJ8ob1C3xP1s2M6z_!!6000000000026-2-tps-3008-1758.png"},
{"text": "帮我打开浏览器。"}]
}]
response = dashscope.MultiModalConversation.call(
# 若没有配置环境变量, 请用百炼API Key将下行替换为: api_key = "sk-xxx"
api_key = os.getenv('DASHSCOPE_API_KEY'),
model = 'gui-plus',
messages = messages
)
print(response.output.choices[0].message.content[0]["text"])Java
import java.util.Arrays;
import java.util.Collections;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.exception.UploadFileException;
public class Main {
public static void simpleMultiModalConversationCall()
throws ApiException, NoApiKeyException, UploadFileException {
MultiModalConversation conv = new MultiModalConversation();
MultiModalMessage systemMsg = MultiModalMessage.builder().role(Role.SYSTEM.getValue())
.content(Arrays.asList(
Collections.singletonMap("text", "## 1. 核心角色 (Core Role)\\n你是一个顶级的AI视觉操作代理。你的任务是分析电脑屏幕截图,理解用户的指令,然后将任务分解为单一、精确的GUI原子操作。\\n## 2. [CRITICAL] JSON Schema & 绝对规则\\n你的输出**必须**是一个严格符合以下规则的JSON对象。**任何偏差都将导致失败**。\\n- **[R1] 严格的JSON**: 你的回复**必须**是且**只能是**一个JSON对象。禁止在JSON代码块前后添加任何文本、注释或解释。\\n- **[R2] 严格的Parameters结构**:`thought`对象的结构: \\\"在这里用一句话简要描述你的思考过程。例如:用户想打开浏览器,我看到了桌面上的Chrome浏览器图标,所以下一步是点击它。\\\"\\n- **[R3] 精确的Action值**: action字段的值**必须**是`## 3. 工具集`中定义的一个大写字符串(例如 \\\"CLICK\\\", \\\"TYPE\\\"),不允许有任何前导/后置空格或大小写变化。\\n- **[R4] 严格的Parameters结构**: parameters对象的结构**必须**与所选Action在`## 3. 工具集`中定义的模板**完全一致**。键名、值类型都必须精确匹配。\\n## 3. 工具集 (Available Actions)\\n### CLICK\\n- **功能**: 单击屏幕。\\n- **Parameters模板**:\\n{\\n\\\"x\\\": <integer>,\\n\\\"y\\\": <integer>,\\n\\\"description\\\": \\\"<string, optional: (可选) 一个简短的字符串,描述你点击的是什么,例如 \\\\\\\"Chrome浏览器图标\\\\\\\" 或 \\\\\\\"登录按钮\\\\\\\"。>\\\"\\n}\\n### TYPE\\n- **功能**: 输入文本。\\n- **Parameters模板**:\\n{\\n\\\"text\\\": \\\"<string>\\\",\\n\\\"needs_enter\\\": <boolean>\\n}\\n### SCROLL\\n- **功能**: 滚动窗口。\\n- **Parameters模板**:\\n{\\n\\\"direction\\\": \\\"<'up' or 'down'>\\\",\\n\\\"amount\\\": \\\"<'small', 'medium', or 'large'>\\\"\\n}\\n### KEY_PRESS\\n- **功能**: 按下功能键。\\n- **Parameters模板**:\\n{\\n\\\"key\\\": \\\"<string: e.g., 'enter', 'esc', 'alt+f4'>\\\"\\n}\\n### FINISH\\n- **功能**: 任务成功完成。\\n- **Parameters模板**:\\n{\\n\\\"message\\\": \\\"<string: 总结任务完成情况>\\\"\\n}\\n### FAILE\\n- **功能**: 任务无法完成。\\n- **Parameters模板**:\\n{\\n\\\"reason\\\": \\\"<string: 清晰解释失败原因>\\\"\\n}\\n## 4. 思维与决策框架\\n在生成每一步操作前,请严格遵循以下思考-验证流程:\\n目标分析: 用户的最终目标是什么?\\n屏幕观察 (Grounded Observation): 仔细分析截图。你的决策必须基于截图中存在的视觉证据。 如果你看不见某个元素,你就不能与它交互。\\n行动决策: 基于目标和可见的元素,选择最合适的工具。\\n构建输出:\\na. 在thought字段中记录你的思考。\\nb. 选择一个action。\\nc. 精确复制该action的parameters模板,并填充值。\\n最终验证 (Self-Correction): 在输出前,最后检查一遍:\\n我的回复是纯粹的JSON吗?\\naction的值是否正确无误(大写、无空格)?\\nparameters的结构是否与模板100%一致?例如,对于CLICK,是否有独立的x和y键,并且它们的值都是整数?"))).build();
MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
.content(Arrays.asList(
Collections.singletonMap("image", "https://img.alicdn.com/imgextra/i2/O1CN016iJ8ob1C3xP1s2M6z_!!6000000000026-2-tps-3008-1758.png"),
Collections.singletonMap("text", "帮我打开浏览器。"))).build();
MultiModalConversationParam param = MultiModalConversationParam.builder()
// 若没有配置环境变量,请用百炼API Key将下行替换为:.apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model("gui-plus")
.messages(Arrays.asList(systemMsg,userMessage))
.build();
MultiModalConversationResult result = conv.call(param);
System.out.println(result.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text"));
}
public static void main(String[] args) {
try {
simpleMultiModalConversationCall();
} catch (ApiException | NoApiKeyException | UploadFileException e) {
System.out.println(e.getMessage());
}
System.exit(0);
}
}curl
curl -X POST https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"model": "gui-plus",
"input":{
"messages":[
{
"role": "system",
"content": "## 1. 核心角色 (Core Role)\n你是一个顶级的AI视觉操作代理。你的任务是分析电脑屏幕截图,理解用户的指令,然后将任务分解为单一、精确的GUI原子操作。\n## 2. [CRITICAL] JSON Schema & 绝对规则\n你的输出**必须**是一个严格符合以下规则的JSON对象。**任何偏差都将导致失败**。\n- **[R1] 严格的JSON**: 你的回复**必须**是且**只能是**一个JSON对象。禁止在JSON代码块前后添加任何文本、注释或解释。\n- **[R2] 严格的Parameters结构**:`thought`对象的结构: \"在这里用一句话简要描述你的思考过程。例如:用户想打开浏览器,我看到了桌面上的Chrome浏览器图标,所以下一步是点击它。\"\n- **[R3] 精确的Action值**: action字段的值**必须**是`## 3. 工具集`中定义的一个大写字符串(例如 \"CLICK\", \"TYPE\"),不允许有任何前导/后置空格或大小写变化。\n- **[R4] 严格的Parameters结构**: parameters对象的结构**必须**与所选Action在`## 3. 工具集`中定义的模板**完全一致**。键名、值类型都必须精确匹配。\n## 3. 工具集 (Available Actions)\n### CLICK\n- **功能**: 单击屏幕。\n- **Parameters模板**:\n{\n\"x\": <integer>,\n\"y\": <integer>,\n\"description\": \"<string, optional: (可选) 一个简短的字符串,描述你点击的是什么,例如 \\\"Chrome浏览器图标\\\" 或 \\\"登录按钮\\\"。>\"\n}\n### TYPE\n- **功能**: 输入文本。\n- **Parameters模板**:\n{\n\"text\": \"<string>\",\n\"needs_enter\": <boolean>\n}\n### SCROLL\n- **功能**: 滚动窗口。\n- **Parameters模板**:\n{\n\"direction\": \"<'up' or 'down'>\",\n\"amount\": \"<'small', 'medium', or 'large'>\"\n}\n### KEY_PRESS\n- **功能**: 按下功能键。\n- **Parameters模板**:\n{\n\"key\": \"<string: e.g., 'enter', 'esc', 'alt+f4'>\"\n}\n### FINISH\n- **功能**: 任务成功完成。\n- **Parameters模板**:\n{\n\"message\": \"<string: 总结任务完成情况>\"\n}\n### FAILE\n- **功能**: 任务无法完成。\n- **Parameters模板**:\n{\n\"reason\": \"<string: 清晰解释失败原因>\"\n}\n## 4. 思维与决策框架\n在生成每一步操作前,请严格遵循以下思考-验证流程:\n目标分析: 用户的最终目标是什么?\n屏幕观察 (Grounded Observation): 仔细分析截图。你的决策必须基于截图中存在的视觉证据。 如果你看不见某个元素,你就不能与它交互。\n行动决策: 基于目标和可见的元素,选择最合适的工具。\n构建输出:\na. 在thought字段中记录你的思考。\nb. 选择一个action。\nc. 精确复制该action的parameters模板,并填充值。\n最终验证 (Self-Correction): 在输出前,最后检查一遍:\n我的回复是纯粹的JSON吗?\naction的值是否正确无误(大写、无空格)?\nparameters的结构是否与模板100%一致?例如,对于CLICK,是否有独立的x和y键,并且它们的值都是整数?"
},
{
"role": "user",
"content": [
{"image": "https://img.alicdn.com/imgextra/i2/O1CN016iJ8ob1C3xP1s2M6z_!!6000000000026-2-tps-3008-1758.png"},
{"text": "帮我打开浏览器。"}
]
}
]
}
}'
如何使用
步骤1. 构造 Message 数组
System Message
在System Prompt 中强调模型角色、能力和输出规范等,可以提升 GUI 任务的效果,在当前示例下,可以将 System Prompt 设置为:
system_prompt = """
## 1. 核心角色 (Core Role)
你是一个顶级的AI视觉操作代理。你的任务是分析电脑屏幕截图,理解用户的指令,然后将任务分解为单一、精确的GUI原子操作。
## 2. [CRITICAL] JSON Schema & 绝对规则
你的输出**必须**是一个严格符合以下规则的JSON对象。**任何偏差都将导致失败**。
- **[R1] 严格的JSON**: 你的回复**必须**是且**只能是**一个JSON对象。禁止在JSON代码块前后添加任何文本、注释或解释。
- **[R2] 严格的Parameters结构**:`thought`对象的结构: "在这里用一句话简要描述你的思考过程。例如:用户想打开浏览器,我看到了桌面上的Chrome浏览器图标,所以下一步是点击它。"
- **[R3] 精确的Action值**: `action`字段的值**必须**是`## 3. 工具集`中定义的一个大写字符串(例如 `"CLICK"`, `"TYPE"`),不允许有任何前导/后置空格或大小写变化。
- **[R4] 严格的Parameters结构**: `parameters`对象的结构**必须**与所选Action在`## 3. 工具集`中定义的模板**完全一致**。键名、值类型都必须精确匹配。
## 3. 工具集 (Available Actions)
### CLICK
- **功能**: 单击屏幕。
- **Parameters模板**:
{
"x": <integer>,
"y": <integer>,
"description": "<string, optional: (可选) 一个简短的字符串,描述你点击的是什么,例如 "Chrome浏览器图标" 或 "登录按钮"。>"
}
### TYPE
- **功能**: 输入文本。
- **Parameters模板**:
{
"text": "<string>",
"needs_enter": <boolean>
}
### SCROLL
- **功能**: 滚动窗口。
- **Parameters模板**:
{
"direction": "<'up' or 'down'>",
"amount": "<'small', 'medium', or 'large'>"
}
### KEY_PRESS
- **功能**: 按下功能键。
- **Parameters模板**:
{
"key": "<string: e.g., 'enter', 'esc', 'alt+f4'>"
}
### FINISH
- **功能**: 任务成功完成。
- **Parameters模板**:
{
"message": "<string: 总结任务完成情况>"
}
### FAILE
- **功能**: 任务无法完成。
- **Parameters模板**:
{
"reason": "<string: 清晰解释失败原因>"
}
## 4. 思维与决策框架
在生成每一步操作前,请严格遵循以下思考-验证流程:
目标分析: 用户的最终目标是什么?
屏幕观察 (Grounded Observation): 仔细分析截图。你的决策必须基于截图中存在的视觉证据。 如果你看不见某个元素,你就不能与它交互。
行动决策: 基于目标和可见的元素,选择最合适的工具。
构建输出:
a. 在thought字段中记录你的思考。
b. 选择一个action。
c. 精确复制该action的parameters模板,并填充值。
最终验证 (Self-Correction): 在输出前,最后检查一遍:
我的回复是纯粹的JSON吗?
action的值是否正确无误(大写、无空格)?
parameters的结构是否与模板100%一致?例如,对于CLICK,是否有独立的x和y键,并且它们的值都是整数?
"""User Message
User Message 包含用户的操作指令,通常由屏幕截图和指令构成。将 System Message 和 User Message 整合到 messages 数组中,如下所示:
messages = [
{
"role": "system",
"content": system_prompt},
{ "role": "user",
"content": [{"type": "image_url","image_url": {"url": "https://img.alicdn.com/imgextra/i2/O1CN016iJ8ob1C3xP1s2M6z_!!6000000000026-2-tps-3008-1758.png"}},
{"type": "text", "text": "帮我打开浏览器。"}]},
]步骤2. 发起模型调用
完成messages数组的构建后,通过 SDK 或 API 发起模型调用。
import os
from openai import OpenAI
def get_response(image_url,instruction):
messages = [
{
"role": "system",
"content": system_prompt,
},
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": image_url},"max_pixels":1280*28*28},
{"type": "text", "text": instruction}]},
]
client = OpenAI(
# 若没有配置环境变量,请用阿里云百炼API Key将下行替换为:api_key="sk-xxx",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
completion = client.chat.completions.create(
model="gui-plus",
messages=messages
)
content = completion.choices[0].message.content
return content步骤3. 解析动作指令
模型的返回是包含动作指令的 JSON 字符串。由于模型在处理图像时会进行内部缩放,其返回的坐标是基于缩放后图像的绝对坐标。为在原图上准确执行GUI操作,需要进行JSON解析和坐标映射。
提取并解析 JSON 输出
首先从模型返回的字符串中提取JSON文本,并解析为结构化对象:
import json def parse_json(json_output): lines = json_output.splitlines() for i, line in enumerate(lines): if line == "```json": json_output = "\n".join(lines[i + 1:]) # 删除 "```json"之前的所有内容 json_output = json_output.split("```")[0] # 删除 "```"之后的所有内容 break # 找到"```json"后退出循环 response_dict = json.loads(json_output) return response_dict坐标映射至原始图像
模型返回的坐标是基于其内部缩放后的图像尺寸的绝对坐标。为能在原始尺寸的屏幕上准确操作,需要将这些坐标映射到原始图像尺寸上。
import requests import math from PIL import Image from io import BytesIO def smart_size(image_url, point,factor = 28, max_pixels = 1280 * 28 * 28, min_pixels = 4 * 28 * 28): """ param image_path: 图像url max_pixels:输入图像的最大像素值,超过此值则将图像的像素缩小至max_pixels内,与发起模型调用步骤设置的max_pixels值,应保持一致。 min_pixels:输入图像的最小像素值,一般设置为默认值:4 * 28 * 28即可。 return: 单张图像的Token数 """ response = requests.get(image_url) response.raise_for_status() image = Image.open(BytesIO(response.content)) # 获取图片的原始尺寸 height = image.height width = image.width # 将高度调整为factor的整数倍 h_bar = round(height / factor) * factor # 将宽度调整为factor的整数倍 w_bar = round(width / factor) * factor # 对图像进行缩放处理,调整像素的总数在范围[min_pixels,max_pixels]内 if h_bar * w_bar > max_pixels: # 计算缩放因子beta,使得缩放后的图像总像素数不超过max_pixels beta = math.sqrt((height * width) / max_pixels) # 重新计算调整后的高度,确保为factor的整数倍 h_bar = math.floor(height / beta / factor) * factor # 重新计算调整后的宽度,确保为factor的整数倍 w_bar = math.floor(width / beta / factor) * factor elif h_bar * w_bar < min_pixels: # 计算缩放因子beta,使得缩放后的图像总像素数不低于min_pixels beta = math.sqrt(min_pixels / (height * width)) # 重新计算调整后的高度,确保为factor的整数倍 h_bar = math.ceil(height * beta / factor) * factor # 重新计算调整后的宽度,确保为factor的整数倍 w_bar = math.ceil(width * beta / factor) * factor abs_x1 = int(point["x"] / w_bar * width) abs_y1 = int(point["y"] / h_bar * height) return abs_x1, abs_y1执行坐标转换并输出结果
运行以下代码,将输出GUI操作类型和基于原图的绝对坐标。
if __name__ == "__main__": image_url = "https://img.alicdn.com/imgextra/i2/O1CN016iJ8ob1C3xP1s2M6z_!!6000000000026-2-tps-3008-1758.png" instruction = "帮我打开浏览器。" content = get_response(image_url, instruction) json_output=parse_json(content) parameters= json_output["parameters"] action = json_output["action"] abs_x1, abs_y1= smart_size(image_url, parameters, max_pixels = 1280 * 28 * 28) print("action:",action) print("location:",{'x': abs_x1, 'y': abs_y1})返回结果如下:
action: CLICK location: {'x': 2536, 'y': 295}
步骤4. 执行GUI操作
解析动作指令后,接下来演示如何使用pyautogui库模拟用户的鼠标点击、键盘输入、滚动等物理GUI操作。
以下代码展示了如何根据模型输出的动作类型和参数,使用
pyautogui库执行相应的GUI操作:import pyautogui import time import sys # 模拟滚动操作的默认幅度 SCROLL_AMOUNTS = { "small": 50, "medium": 200, "large": 500, } def execute_gui_action(action: str, parameters: dict, original_image_url: str): """ 根据模型输出的动作和参数执行GUI操作。 Args: action (str): 模型输出的动作类型(如 "CLICK", "TYPE")。 parameters (dict): 动作的参数字典。 original_image_url (str): 原始屏幕截图的URL,用于坐标映射。 """ print(f"执行动作: {action}, 参数: {parameters}") if action == "CLICK": # 确保 'x' 和 'y' 存在并为数值类型 if "x" not in parameters or "y" not in parameters: print("错误: CLICK 动作缺少 'x' 或 'y' 坐标。") return # 将模型输出的坐标映射到原始屏幕分辨率 try: abs_x, abs_y = smart_size(original_image_url,parameters ) pyautogui.click(abs_x, abs_y) print(f"已点击坐标 ({abs_x}, {abs_y})") except Exception as e: print(f"坐标映射或点击失败: {e}") elif action == "TYPE": if "text" not in parameters: print("错误: TYPE 动作缺少 'text' 参数。") return text_to_type = parameters["text"] needs_enter = parameters.get("needs_enter", False) pyautogui.write(text_to_type) if needs_enter: pyautogui.press("enter") print(f"已输入文本: '{text_to_type}', 是否按回车: {needs_enter}") elif action == "SCROLL": if "direction" not in parameters or "amount" not in parameters: print("错误: SCROLL 动作缺少 'direction' 或 'amount' 参数。") return direction = parameters["direction"].lower() amount_key = parameters["amount"].lower() scroll_value = SCROLL_AMOUNTS.get(amount_key, SCROLL_AMOUNTS["medium"]) # 默认中等 if direction == "up": pyautogui.scroll(scroll_value) print(f"已向上滚动 {scroll_value} 单位。") elif direction == "down": pyautogui.scroll(-scroll_value) # pyautogui向下滚动需要负值 print(f"已向下滚动 {scroll_value} 单位。") else: print(f"警告: 未知滚动方向: {direction}") elif action == "KEY_PRESS": if "key" not in parameters: print("错误: KEY_PRESS 动作缺少 'key' 参数。") return key_to_press = parameters["key"].lower() pyautogui.press(key_to_press) print(f"已按下按键: {key_to_press}") elif action == "FINISH": message = parameters.get("message", "任务已完成。") print(f"任务完成: {message}") elif action == "FAIL": reason = parameters.get("reason", "任务失败。") print(f"任务失败: {reason}") else: print(f"警告: 收到未知动作类型: {action}") # 模拟人类操作的延时,避免GUI操作过快 time.sleep(1) # 每次操作后等待1秒整合上述步骤,以下是从模型调用到执行GUI操作的完整流程。
if __name__ == "__main__": original_image_url = "https://img.alicdn.com/imgextra/i2/O1CN016iJ8ob1C3xP1s2M6z_!!6000000000026-2-tps-3008-1758.png" instruction = "帮我打开浏览器。" model_response=get_response(original_image_url, instruction) print("大模型的回复:",model_response) try: response_dict = parse_json(model_response) action = response_dict["action"] parameters = response_dict["parameters"] except ValueError as e: print(f"处理模型响应失败: {e}") sys.exit() execute_gui_action(action, parameters, original_image_url)
更多用法
使用说明
图像限制
gui-plus模型对输入图像有以下具体要求:
支持的图像格式:
图像格式
常见扩展名
MIME Type
BMP
.bmp
image/bmp
JPEG
.jpe, .jpeg, .jpg
image/jpeg
PNG
.png
image/png
TIFF
.tif, .tiff
image/tiff
WEBP
.webp
image/webp
HEIC
.heic
image/heic
图像大小:单个图像的大小不超过10 MB。如果传入 Base64编码的图像,需保证编码后的字符串小于10MB,详情请参见传入本地文件。如需压缩文件体积请参见图像或视频压缩方法。
尺寸与比例:图像的宽度和高度均需大于 10 像素,图像的宽高比(长边与短边的比值)不得超过 200。
像素总量:模型接受任意像素总量的图像输入,但会在内部将其缩放至特定处理上限,超过此上限的图像会损失细节。
图像输入方式
公网URL:提供一个公网可访问的图像地址,支持 HTTP 或 HTTPS 协议。可将本地图像上传至OSS或上传文件获取临时URL,获取公网 URL。
Base64编码传入:将图像转换为 Base64 编码字符串。
本地文件路径传入:直接传入本地图像的路径。
计费与限流
限流:通义千问GUI-Plus模型的限流条件参见限流。
免费额度:从开通百炼或模型申请通过之日起计算有效期,有效期90天内,模型提供100万Token的免费额度。
计费:总费用 = 输入 Token 数 × 模型输入单价 + 模型输出 Token 数 × 模型输出单价;输入/输出价格可参见模型列表。
查看账单:您可以在阿里云控制台的费用与成本页面查看账单或进行充值。
API参考
关于通义千问GUI-Plus模型的输入输出参数,请参见GUI-Plus API参考。
错误码
如果模型调用失败并返回报错信息,请参见错误信息进行解决。