基于Qwen-VL的手机智能体开发
先上Demo:
vl_agent_demo
代码如下:
0 设置工作目录:
你的工作目录需要如下:
其中utils文件夹和qwenvl_agent.py均参考自
GitHub - QwenLM/Qwen2.5-VL: Qwen2.5-VL is the multimodal large language model series developed by Qwen team, Alibaba Cloud.Qwen2.5-VL is the multimodal large language model series developed by Qwen team, Alibaba Cloud. - QwenLM/Qwen2.5-VL
https://github.com/QwenLM/Qwen2.5-VL
YourProj(文件夹):
utils(文件夹)
agent_function_call.py
mobile_agent.py
qwenvl_agent.py
(1)运行代码mobile_agent.py:
import os
import time
import json
from ppadb.client import Client as AdbClient
import uiautomator2 as u2
import base64
from qwenvl_agent import perform_gui_grounding_with_apiclass Android_VL_Agent:def __init__(self):self.client = AdbClient(host="127.0.0.1", port=5037)self.device_serial = Noneself.u2_device = Noneself.SCREENSHOT_PATH = Noneself.QWEN_MODEL_ID = 'qwen2.5-vl-7b-instruct'self.__set_up()@staticmethoddef check_adb_service():try:result = os.popen("adb devices").read()if "List of devices attached" in result:return Trueelse:os.system("adb start-server")time.sleep(5) # 等待 ADB 服务启动result = os.popen("adb devices").read()if "List of devices attached" in result:return Trueelse:return Falseexcept Exception:print("ADB服务启动失败")return False@staticmethoddef encode_image(image_path):with open(image_path, "rb") as image_file:return base64.b64encode(image_file.read()).decode("utf-8")@staticmethoddef info_parser(info):try:body = info.split("<tool_call>")[1].split("</tool_call>")[0]return json.loads(body)except Exception as e:print(f"解析失败: {str(e)}")return None# 启动def __set_up(self):assert self.check_adb_service()devices = self.client.devices()self.device_serial = devices[0].serial if devices else Noneself.u2_device = u2.connect(self.device_serial)self.SCREENSHOT_PATH = "screenshot.png"# 定义单点事件def __single_point_event(self,x,y):try:self.u2_device.click(x, y)return Trueexcept Exception as e:print(f"单点失败: {str(e)}")return False# 定义输入内容def __input_content(self,content):try:self.u2_device.send_keys(content)return Trueexcept Exception as e:print(f"输入失败: {str(e)}")return False# 截图并保存def __screenshot(self):try:# 清除之前的截图if os.path.exists(self.SCREENSHOT_PATH):os.remove(self.SCREENSHOT_PATH)screenshot = self.u2_device.screenshot()screenshot.save(self.SCREENSHOT_PATH)# screenshot.show()return Trueexcept Exception as e:print(f"截图失败: {str(e)}")return Falsedef __Qwen_vl_agent(self, query):output_info = perform_gui_grounding_with_api(self.SCREENSHOT_PATH, query, self.QWEN_MODEL_ID)# print(output_info)result = self.info_parser(str(output_info))["arguments"]return resultdef __action(self,result):if "click" in result["action"]:coordinate = result["coordinate"]self.__single_point_event(coordinate[0],coordinate[1])elif "type" in result["action"]:self.__input_content(result["text"])def run(self,query):# 重新连接self.u2_device = u2.connect(self.device_serial)# 感知self.__screenshot()# 理解result = self.__Qwen_vl_agent(query)print(result)# 执行self.__action(result)def __call__(self,query):self.run(query)if __name__ == "__main__":agent = Android_VL_Agent()# timesteptimestep = 2name = "名字"message = "信息"agent.run("打开微信")time.sleep(timestep)agent.run(f"点击和{name}聊天框的的顶部区域进入聊天界面")time.sleep(timestep)agent.run("点击屏幕底部的输入框部分进入输入界面")time.sleep(timestep)agent.run(f"在聊天框输入内容:{message}")time.sleep(timestep)agent.run("点击右侧发送按钮中心位置发送消息")
(2)方法代码qwenvl_agent.py
import json
import base64
from openai import OpenAI
from qwen_agent.llm.fncall_prompts.nous_fncall_prompt import (NousFnCallPrompt,Message,ContentItem,
)
from PIL import Image, ImageDraw, ImageColor
from transformers.models.qwen2_vl.image_processing_qwen2_vl_fast import smart_resize
import warnings
warnings.filterwarnings("ignore")
from utils.agent_function_call import ComputerUsedef draw_point(image: Image.Image, point: list, color=None):if isinstance(color, str):try:color = ImageColor.getrgb(color)color = color + (128,)except ValueError:color = (255, 0, 0, 128)else:color = (255, 0, 0, 128)overlay = Image.new('RGBA', image.size, (255, 255, 255, 0))overlay_draw = ImageDraw.Draw(overlay)radius = min(image.size) * 0.05x, y = pointoverlay_draw.ellipse([(x - radius, y - radius), (x + radius, y + radius)],fill=color)center_radius = radius * 0.1overlay_draw.ellipse([(x - center_radius, y - center_radius),(x + center_radius, y + center_radius)],fill=(0, 255, 0, 255))image = image.convert('RGBA')combined = Image.alpha_composite(image, overlay)return combined.convert('RGB')def encode_image(image_path):with open(image_path, "rb") as image_file:return base64.b64encode(image_file.read()).decode("utf-8")def perform_gui_grounding_with_api(screenshot_path, user_query, model_id, min_pixels=3136, max_pixels=12845056):"""Perform GUI grounding using Qwen model to interpret user query on a screenshot.Args:screenshot_path (str): Path to the screenshot imageuser_query (str): User's query/instructionmodel: Preloaded Qwen modelmin_pixels: Minimum pixels for the imagemax_pixels: Maximum pixels for the imageReturns:tuple: (output_text, display_image) - Model's output text and annotated image"""# Open and process imageinput_image = Image.open(screenshot_path)base64_image = encode_image(screenshot_path)client = OpenAI(# If the environment variable is not configured, please replace the following line with the Dashscope API Key: api_key="sk-xxx". Access via https://bailian.console.alibabacloud.com/?apiKey=1 "api_key="xxx",base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",)resized_height, resized_width = smart_resize(input_image.height,input_image.width,min_pixels=min_pixels,max_pixels=max_pixels,)# Initialize computer use functioncomputer_use = ComputerUse(cfg={"display_width_px": resized_width, "display_height_px": resized_height})# Build messagessystem_message = NousFnCallPrompt.preprocess_fncall_messages(messages=[Message(role="system", content=[ContentItem(text="You are a helpful assistant.")]),],functions=[computer_use.function],lang=None,)system_message = system_message[0].model_dump()messages = [{"role": "system","content": [{"type": "text", "text": msg["text"]} for msg in system_message["content"]],},{"role": "user","content": [{"type": "image_url","min_pixels": min_pixels,"max_pixels": max_pixels,# Pass in BASE64 image data. Note that the image format (i.e., image/{format}) must match the Content Type in the list of supported images. "f" is the method for string formatting.# PNG image: f"data:image/png;base64,{base64_image}"# JPEG image: f"data:image/jpeg;base64,{base64_image}"# WEBP image: f"data:image/webp;base64,{base64_image}""image_url": {"url": f"data:image/jpeg;base64,{base64_image}"},},{"type": "text", "text": user_query},],}]# print(json.dumps(messages, indent=4))completion = client.chat.completions.create(model=model_id,messages=messages,)output_text = completion.choices[0].message.content# Parse action and visualize# print(output_text)action = json.loads(output_text.split('<tool_call>\n')[1].split('\n</tool_call>')[0])# display_image = input_image.resize((resized_width, resized_height))# display_image = draw_point(input_image, action['arguments']['coordinate'], color='green')return output_textif __name__ == "__main__":screenshot = "screenshot.png"user_query = '在聊天框输入内容:下午好!'model_id = "qwen2.5-vl-7b-instruct"output_text = perform_gui_grounding_with_api(screenshot, user_query, model_id)print(output_text)
相关文章:
基于Qwen-VL的手机智能体开发
先上Demo: vl_agent_demo 代码如下: 0 设置工作目录: 你的工作目录需要如下: 其中utils文件夹和qwenvl_agent.py均参考自 GitHub - QwenLM/Qwen2.5-VL: Qwen2.5-VL is the multimodal large language model series developed by …...
记录一次Spring事务失效导致的生产问题
一、背景介绍 公司做的是“聚合支付”业务,对接了微信、和包、数字人民币等等多家支付机构,我们提供统一的支付、退款、自动扣款签约、解约等能力给全国的省公司、机构、商户等。 同时,需要做对账功能,即支付机构将对账文件给到…...
深度学习实战:用TensorFlow构建高效CNN的完整指南
一、为什么每个开发者都要掌握CNN? 在自动驾驶汽车识别路标的0.1秒里,在医疗AI诊断肺部CT片的精准分析中,甚至在手机相册自动分类宠物的日常场景里,卷积神经网络(CNN)正悄然改变着我们的世界。本文将以工业…...
算法 之 贪心思维训练!
文章目录 从最大/最小开始贪心2279.装满石头的背包的最大数量2971.找到最大周长的多边形 从最左、最右开始贪心2712.使所有字符相等的最小成本 划分型贪心1221.分割平衡字符串 贪心策略在处理一些题目的时候能够带来意想不到的效果 从最小/最大开始贪心,优先考虑最小…...
从0到1构建AI深度学习视频分析系统--基于YOLO 目标检测的动作序列检查系统:(1)视频信息的获取与转发
文章大纲 基于YOLO的动作序列检查系统架构设计系统架构图实时视频传输协议技术对比视频流 常见协议对比表三、WebSocket内网传输设计方案四、样例程序(Python + JavaScript)五、性能优化建议新兴技术预警参考文献提示词参考基于YOLO的动作序列检查系统架构设计 系统架构图 #…...
大语言模型学习--LangChain
LangChain基本概念 ReAct学习资料 https://zhuanlan.zhihu.com/p/660951271 LangChain官网地址 Introduction | 🦜️🔗 LangChain LangChain是一个基于语言模型开发应用程序的框架。它可以实现以下应用程序: 数据感知:将语言模型…...
【PCIe 总线及设备入门学习专栏 4.5 -- PCIe 中断 MSI 与 MSI-X 机制介绍】
文章目录 PCI 设备中断机制PCIe 设备中断机制PCIe MSI 中断机制MSI CapabilityMSI-X 中断机制MSI-X capabilityMSI-X TablePBAMSI-X capability 解析MSI/MSI-X 操作流程扫描设备配置设备MSI 配置MSI-X 配置中断触发与处理PCI 设备中断机制 以前的PCI 设备是支持 物理上的 INTA…...
wxWidgets GUI 跨平台 入门学习笔记
准备 参考 https://wiki.wxwidgets.org/Microsoft_Visual_C_NuGethttps://wiki.wxwidgets.org/Tools#Rapid_Application_Development_.2F_GUI_Buildershttps://docs.wxwidgets.org/3.2/https://docs.wxwidgets.org/latest/overview_helloworld.htmlhttps://wizardforcel.gitb…...
valgrind 检测多线程 bug,检测 并发 bug concurrent bug parallel bug
valgrind --toolhelgrind ./your_program 如果检测的对象是大型程序,可以设定仅在某些函数中开启 valgrind 的检测: Valgrind 提供了一些客户请求(client requests),可以在代码中插入特定的宏来控制 Valgrind 的行为。…...
OpenMCU(一):STM32F407 FreeRTOS移植
概述 本文主要描述了STM32F407移植FreeRTOS的简要步骤。移植描述过程中,忽略了Keil软件的部分使用技巧。默认读者熟练使用Keil软件。本文的描述是基于OpenMCU_FreeRTOS这个工程,该工程已经下载放好了移植stm32f407 FreeRTOS的所有文件 OpenMCU_FreeRTOS工…...
割平面法的理解
割平面法的理解 1. 简介 割平面法(Cutting Plane Method)用于求解整数规划问题,通过逐步添加线性约束(割平面)逼近整数解。本文以Gomory割平面法为例,结合简单示例拆解核心步骤。 2. 示例详解 问题描述 …...
[自动驾驶-传感器融合] 多激光雷达的外参标定
文章目录 引言外参标定原理ICP匹配示例参考文献 引言 多激光雷达系统通常用于自动驾驶或机器人,每个雷达的位置和姿态不同,需要将它们的数据统一到同一个坐标系下。多激光雷达外参标定的核心目标是通过计算不同雷达坐标系之间的刚性变换关系(…...
C++ 学习(八)(模板,可变参数模板,模板专业化(完整模板专业化,部分模板专业化),类型 Traits,SFINAE(替换失败不是错误),)
C 模板 C 中的模板是一项强大的功能,允许您编写通用代码,这意味着您可以编写可以处理不同数据类型的单个函数或类。这意味着您无需为要使用的每种数据类型编写单独的函数或类。 模板函数 要创建模板函数,请使用 关键字,后跟类型…...
AI---DevOps常备工具(AI-Integrated DevOps Essential Tools)
AI---DevOps常备工具 技术领域正在迅速发展,随着我们步入 2025 年,有一点是明确的:人工智能(AI)不再只是一个流行词,它是每个 DevOps 工程师都需要掌握的工具。随着云环境的复杂性增加、对更快部署的需求以…...
题目梳理2025[长期更新]
题目梳理 组合类题目(2025年3月5日) 组合总数1,组合总数2,组合总数3 -> 递归回溯的思想 组合总数4 -> 爬楼的思想,动态规划,确定递归边界,确定递归入口,最后一步怎么走的思想...
Maven 中 SNAPSHOT 版本与 RELEASE 版本的区别
Maven 仓库分为 Snapshot 快照仓库和 Release 发行仓库两种类型的仓库。Snapshot 快照仓库用于保存 SNAPSHOT 版本,Release 发行仓库用于保存 RELEASE 版本。 SNAPSHOT 是一种特殊的版本标识,主要用于表示项目的不稳定、正在开发中的版本,而…...
JavaScript 知识点整理
1. 什么是AST?它在前端有哪些应用场景? AST Abstract Syntax Tree抽象语法树,用于表达源码的树形结构 应用: Babel:一个广泛使用的 JS 编译器,将ES6 或 JSX 等现代语法转换为兼容性较好的 ES5 代码。Esl…...
迷你世界脚本出生点接口:Spawnport
出生点接口:Spawnport 彼得兔 更新时间: 2023-04-26 10:19:56 具体函数名及描述如下: 序号 函数名 函数描述 1 getSpawnPoint(...) 获取默认出生点 2 setSpawnPoint(...) 设置出生点位置 3 getChunkValidSpawnPos(...) 获取区块有效刷新点…...
鸿蒙与DeepSeek深度整合:构建下一代智能操作系统生态
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/north 目录 技术融合背景与价值鸿蒙分布式架构解析DeepSeek技术体系剖析核心整合架构设计智能调度系统实现…...
利用行波展开法测量横观各向同性生物组织的生物力学特性|文献速递-医学影像人工智能进展
Title 题目 Measurement of biomechanical properties of transversely isotropic biological tissue using traveling wave expansion 利用行波展开法测量横观各向同性生物组织的生物力学特性 01 文献速递介绍 纤维嵌入结构在自然界中普遍存在。从脑白质(罗曼…...
AR配置静态IP双链路负载分担示例
AR配置静态IP双链路负载分担示例 适用于大部分企业网络出口 业务需求: 运营商1分配的接口IP为100.100.1.2,子网掩码为255.255.255.252,网关IP为100.100.1.1。 运营商2分配的接口IP为200.200.1.2,子网掩码为255.255.255.248&am…...
文件操作(详细讲解)(1/2)
你好这里是我说风俗,希望各位客官点点赞,收收藏,关关注,各位对我的支持是我持续更新的动力!!!!第二期会马上更的关注我获得最新消息哦!!!…...
[AI]从零开始的so-vits-svc歌声推理及混音教程
一、前言 在之前的教程中已经为大家讲解了如何安装so-vits-svc以及使用现有的模型进行文本转语音。可能有的小伙伴就要问了,那么我们应该怎么使用so-vits-svc来进行角色歌曲的创作呢?其实歌曲的创作会相对麻烦一些,会使用到好几个软件&#x…...
华为OD机试-停车场最大距离(Java 2024 E卷 100分)
题目描述 停车场有一排车位,用 0 表示空位,1 表示已停车。至少有一辆车停在车位上,也至少有一个空位。为了防剐蹭,需要找到一个空位,使得该空位与最近的车辆之间的距离最大。返回这个最大距离。 输入描述 一个用半角逗号分隔的停车标识字符串,停车标识为 0 或 1,0 表示…...
SpringMVC控制器定义:@Controller注解详解
文章目录 引言一、Controller注解基础二、RequestMapping与请求映射三、参数绑定与数据校验四、RestController与RESTful API五、控制器建议与全局处理六、控制器测试策略总结 引言 在SpringMVC框架中,控制器(Controller)是整个Web应用的核心组件,负责处…...
免费分享一个软件SKUA-GOCAD-2022版本
若有需要,可以下载。 下载地址 通过网盘分享的文件:Paradigm SKUA-GOCAD 22 build 2022.06.20 (x64).rar 链接: https://pan.baidu.com/s/10plenNcMDftzq3V-ClWpBg 提取码: tm3b 安装教程 Paradigm SKUA-GOCAD 2022版本v2022.06.20安装和破解教程-CS…...
学习threejs,使用LineBasicMaterial基础线材质
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.LineBasicMaterial1.…...
python保留字及作用
在 Python 中,保留字(Reserved Keywords)是具有特殊意义和用途的单词,不能用作变量名、函数名或标识符。以下是 Python 的保留字及其作用: Python 保留字列表 保留字作用False布尔值,表示假。None表示空值…...
java面试题(一)基础部分
1.【String】StringBuffer和StringBuilder区别? String对象是final修饰的不可变的。对String对象的任何操作只会生成新对象,不会对原有对象进行操作。 StringBuilder和StringBuffer是可变的。 其中StringBuilder线程不安全,但开销小。 St…...
Mac mini M4安装nvm 和node
先要安装Homebrew(如果尚未安装)。在终端中输入以下命令: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 根据提示操作完成Homebrew的安装。 安装nvm。在终端中输入以下命令…...
