【AI爆点】手搓GUI Agent全攻略!Gemini 3 Flash带你半小时入门自动化操作,代码全奉送!

什么是GUI Agent?简单来说,就是一个能够"看懂"屏幕(mobile/pc/web)并进行自动操作的AI Agent。比如用户发送指令“整理文件”,PC GUI Agent就可以基于纯GUI界面理解页面内容,进行逐步决策&操作,直到完成用户任务。

随着GUI Agent的应用前景逐渐明朗,GUI Agent在25年的发展很迅猛,其中一个比较明显的新趋势是,通用大模型也在训练GUI上的能力:

因此,搭建一个好用的GUI Agent变得越来越简单。本文介绍如何使用通用大模型API,快速从0到1搭建一个可用性强的PC GUI Agent,可以用于自动完成PC任务操作。

前置准备说明: 我使用的是Gemini 3 Flash,先看效果:

一、GUI Agent基础原理介绍

一个GUI Agent通常包含以下几个部分:

  1. 设备环境(Environment):比如手机、电脑这些用来操作的设备,是交互的 “载体“,本文仅以电脑为示例。

  2. 感知系统(Preceptor):负责 “接收信息“,这主要是针对GUI能力较弱的通用大模型。而Gemini 3 Flash这样本身具备较强GUI页面理解能力的大模型通常不再需要单独设计感知系统。

  3. 大模型(决策器):相当于 “大脑”—— 结合知识系统里存的信息,分析感知到的界面内容,决定要完成任务,下一步应该如何操作。

  4. 交互系统(Operator):相当于“手脚” —— 把大模型的决策结果(操作动作+坐标),转化为具体的操作与设备进行交互。

    为了完成一个完整的任务,通常需要进行 “感知->决策->执行” 的多次循环,直到任务完成。下文具体介绍PC GUI Agent的搭建方式。

二、逐步搭建GUI Agent

1. 最简单的模型对话

在开始构建复杂的Agent之前,我们先实现最基础的功能:让AI看懂一张图片。

# utils/model.pyimport osimport base64from openai import OpenAIfrom typing import List, Dict, AnyAPI_KEY = os.getenv("OPENAI_API_KEY")BASE_URL = os.getenv("OPENAI_BASE_URL")class LVMChat: """多模态大模型聊天类""" def __init__(self, api_key: str = API_KEY, base_url: str = BASE_URL, model: str = "gemini-3-flash-preview"): self.client = OpenAI(api_key=api_key, base_url=base_url) self.model = model def _encode_image(self, image_path: str) -> str: """将图片编码为base64""" with open(image_path, "rb") as image_file: return base64.b64encode(image_file.read()).decode('utf-8') def get_multimodal_response(self, text: str, image_paths: str) -> str: """ 最简单的图文对话 Args: text: 你的问题 image_paths: 图片路径 Returns: 模型的回答 """ # 1. 加载图片 base64_image = self._encode_image(image_paths) # 2. 构建消息 messages = [{ "role": "user", "content": [ {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}}, {"type": "text", "text": text} ] }] # 3. 调用API response = self.client.chat.completions.create( model=self.model, messages=messages ) return response.choices[0].message.content

测试一下:

chat = LVMChat()response = chat.get_multimodal_response( text="这张图片里输入框坐标?", image_paths="image.png")print(response)

注意看这里!模型本身是有定位能力的(也就是说可以直接输出操作对象的坐标位置),所以不需要格外的感知器来锚定具体UI元素。

2. 加入记忆 - 让AI记住上下文

上面的代码有个问题:AI每次都是"失忆"的,不记得之前说过什么。对于GUI Agent来说,这是很致命的。举个简单的例子,任务“在输入框输入‘你好’”,如果Agent没有记忆,那么后序执行不记得自己已经决策过输入操作,就会陷入输入的循环,在输入框中多次输入‘你好’而不会停止。相反,有上文记忆的Agent,知道自己前一次已经决策了输入操作,结合当前页面内容,判断本次应为“finish”指令,就不会陷入输入循环。

为此,我们需要升级 LVMChat 类:

class LVMChat: """支持会话记忆的多模态聊天类""" def __init__(self, api_key: str = API_KEY, base_url: str = BASE_URL, model: str = "gemini-3-flash-preview"): self.client = OpenAI(api_key=api_key, base_url=base_url) self.model = model # 🔥 核心改动:添加会话历史记录 self.conversation_history: List[Dict[str, Any]] = [] def get_multimodal_response(self, text: str, image_paths: str, use_history: bool = False) -> str: """ 支持记忆的图文对话 Args: text: 你的问题 image_paths: 图片路径 use_history: 是否使用会话历史(记住之前的对话) """ # 1. 加载图片并构建当前消息 base64_image = self._encode_image(image_paths) current_message = { "role": "user", "content": [ {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}}, {"type": "text", "text": text} ] } # 2. 🔥 关键:如果启用历史,把之前的对话也带上 if use_history: messages = self.conversation_history + [current_message] print(f"📚 使用历史上下文,共 {len(self.conversation_history)} 条") else: messages = [current_message] # 3. 调用API response = self.client.chat.completions.create( model=self.model, messages=messages ) result = response.choices[0].message.content # 4. 🔥 更新历史记录 if use_history: self.conversation_history.append(current_message) self.conversation_history.append({ "role": "assistant", "content": result }) return result def clear_history(self): """清空记忆""" self.conversation_history = []

记忆的原理:

# 第一轮对话conversation_history = [ {"role": "user", "content": [图片1, "在输入框输入‘你好’"]}, {"role": "assistant", "content": "{'Thought': '输入框在页面中间位置,我需要输入文案', 'Action': 'type(content=\'你好\')'}"}]# 第二轮对话时,把历史也带上messages = conversation_history + [ {"role": "user", "content": [图片2, "在输入框输入‘你好’"]}]# 现在AI能看到完整的对话链,知道自己做过什么决策。在第二轮返回:{'Thought': '上一轮已经完成输入操作并且文案已经正确显示在输入框,任务已经完成', 'Action': 'finished'}
3. 搭建Agent框架

现在组装成一个完整的Agent,我们使用LangGraph来构建工作流。

(1)Agent的核心循环

一个GUI Agent的工作流程是这样的:

(2)执行器Operator

首先,我们需要一个能够真正控制鼠标键盘的工具类。在这里强烈推荐pyautogui, 模拟键鼠操作,非常简单易用。但是有一个坑需要注意,输入操作需要用复制粘贴操作而不是打字,因为 pyautogui.write() 不支持中文!而用剪贴板粘贴可以完美支持中英文、特殊字符

# operator/execute.py - import pyautoguiimport pyperclipimport mssimport time# 允许鼠标移动到屏幕角落(默认会触发fail-safe)pyautogui.FAILSAFE = Falseclass Operation: """GUI操作工具类""" def click(self, x: int, y: int): """点击指定坐标""" print(f"🖱️ 点击坐标 ({x}, {y})") pyautogui.click(x=x, y=y) def input(self, text: str): """输入文本(使用粘贴方式,支持中文)""" print(f"⌨️ 输入: {text}") pyperclip.copy(text) # 复制到剪贴板 pyautogui.hotkey('command', 'v') # Mac用command,Windows用ctrl def screenshot(self, save_path: str): """截图并保存""" with mss.mss() as sct: sct.shot(output=save_path) print(f"📸 截图已保存: {save_path}") def hotkey(self, *keys): """按下组合键(如ctrl+c)""" print(f"⌨️ 按下组合键: {' + '.join(keys)}") pyautogui.hotkey(*keys) def wait(self, seconds: float = 1.0): """等待指定时间""" print(f"⏱️ 等待 {seconds} 秒...") time.sleep(seconds)
(3)Prompt

GUI Agent的提示词告诉AI应该如何"思考"和"行动"的规则,需要定义好操作空间和输出格式,我在UI-TARS官方Prompt的基础上做了很小的改动(增加了Output Example,因为我发现Gemini 3 Flash使用UI-TARS的prompt输出格式不是很稳定)。

# utils/prompts.pyCOMPUTER_USE_UITARS = """You are a GUI agent. You are given a task and your action history, with screenshots. You need to perform the next action to complete the task.## Action Spaceclick(point='<point>x1 y1</point>')left_double(point='<point>x1 y1</point>')right_single(point='<point>x1 y1</point>')drag(start_point='<point>x1 y1</point>', end_point='<point>x2 y2</point>')hotkey(key='ctrl c') # Split keys with a space and use lowercase. Also, do not use more than 3 keys in one hotkey action.type(content='xxx') # Use escape characters \\', \\\", and \\n in content part to ensure we can parse the content in normal python string format. If you want to submit your input, use \\n at the end of content. scroll(point='<point>x1 y1</point>', direction='down or up or right or left') # Show more information on the `direction` side.wait() #Sleep for 5s and take a screenshot to check for any changes.finished(content='xxx') # Use escape characters \\', \\", and \\n in content part to ensure we can parse the content in normal python string format.## Note- Use Chinese in `Thought` part.- Write a small plan and finally summarize your next action (with its target element) in one sentence in `Thought` part.- One action per turn.## Output Example{{ "Thought": "...", "Action": "..."}}## User Instruction{instruction}"""
(4)坐标归一化

不同电脑屏幕分辨率不同(1920x1080、2560x1440等),GUI Agent往往会采用千归一化坐标的策略进行处理。因此,拿到大模型的返回之后,需要将归一化坐标 (0-1000范围) 还原成实际像素坐标:

# AI返回归一化坐标: (500, 500) - 表示屏幕中心# 在1920x1080屏幕上: (500, 500) -> (960, 540)# 在2560x1440屏幕上: (500, 500) -> (1280, 720)def normalize_coords(self, x: int, y: int) -> tuple[int, int]: """将归一化坐标(0-1000)转换为实际像素坐标""" actual_x = int(x / 1000.0 * self.screen_width) actual_y = int(y / 1000.0 * self.screen_height) return actual_x, actual_y
(5)LangGraph

LangGraph是一个用于构建Agent工作流的框架,图(Graph)的方式定义Agent的执行逻辑。

# 传统方式(硬编码)def run_agent(): whilenot finished: screenshot() decision = model_decide() execute(decision) if check_finished(): break# LangGraph方式(声明式)workflow = StateGraph(AgentState)workflow.add_node("screenshot", take_screenshot)workflow.add_node("decide", model_decide)workflow.add_node("execute", execute_action)workflow.add_edge("screenshot", "decide")workflow.add_edge("decide", "execute")workflow.add_conditional_edges("execute", should_continue, {...})

优势:✅ 逻辑清晰:可视化工作流 ✅ 易于修改:添加节点/改变流程很简单 ✅ 状态管理:自动在节点间传递状态。

AgentState 是整个工作流的"记忆载体",在各个节点间传递:

# Step 1: 截图节点state = { "instruction": "打开浏览器", "screenshot_path": "s/step_1.png", "step": 1, "finished": False}# Step 2: 决策节点(接收state,更新后返回)state = { **state, # 保留之前的数据 "thought": "需要点击Chrome图标", "action": "click(point='<point>100 200</point>')"}# Step 3: 执行节点state = { **state, # 继续保留 # 执行点击操作...}
(6)Agent主程序

现在把所有模块组装起来:

#!/usr/bin/env python3# -*- coding: utf-8 -*-"""GUI Agent - 自动化GUI测试Agent截图 -> 模型决策 -> 解析Action -> 执行 -> 循环,直到finished"""import reimport jsonfrom datetime import datetimefrom typing import TypedDictfrom pathlib import Pathfrom langgraph.graph import StateGraph, ENDfrom operator.execute import Operationfrom utils.model import LVMChat, Modelfrom utils.prompts import COMPUTER_USE_UITARS# 定义Stateclass AgentState(TypedDict): instruction: str # 用户指令 screenshot_path: str # 当前截图路径 step: int # 当前步骤 thought: str # 模型思考 action: str # 模型输出的动作 finished: bool # 是否完成class GUIAgent: """GUI自动化Agent""" def __init__(self, instruction: str, model_name: str = Model.GOOGLE_GEMINI_3_FLASH_PREVIEW.value): self.instruction = instruction self.operation = Operation() self.lvm_chat = LVMChat(model=model_name) self.s_dir = Path("s") self.s_dir.mkdir(exist_ok=True) # 获取屏幕尺寸用于坐标映射 import pyautogui self.screen_width, self.screen_height = pyautogui.size() print(f"🖥️ 屏幕尺寸: {self.screen_width}x{self.screen_height}") def normalize_coords(self, x: int, y: int) -> tuple[int, int]: """将归一化坐标(0-1000)转换为实际像素坐标""" actual_x = int(x / 1000.0 * self.screen_width) actual_y = int(y / 1000.0 * self.screen_height) print(f" 归一化坐标 ({x}, {y}) -> 实际坐标 ({actual_x}, {actual_y})") return actual_x, actual_y def take_screenshot(self, state: AgentState) -> AgentState: """步骤1: 截图并保存""" step = state.get("step", 0) + 1 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") screenshot_path = str(self.s_dir / f"step_{step}_{timestamp}.png") self.operation.screenshot(screenshot_path) return { **state, "instruction": self.instruction, "screenshot_path": screenshot_path, "step": step, "finished": False } def model_decide(self, state: AgentState) -> AgentState: """步骤2: 模型决策(自动使用会话历史)""" prompt = COMPUTER_USE_UITARS.format(instruction=state["instruction"]) # 调用多模态模型(use_history=True 自动保留上下文) response = self.lvm_chat.get_multimodal_response( text=prompt, image_paths=state["screenshot_path"], res_format="json", use_history=True# 启用会话历史,模型会记住之前的所有交互 ) print(f"\n📸 Step {state['step']} - 模型响应:\n{response}\n") # 解析JSON响应 try: result = json.loads(response) thought = result.get("Thought", "") action = result.get("Action", "") except json.JSONDecodeError: # 如果不是JSON格式,尝试正则提取 thought_match = re.search(r'"Thought":\s*"([^"]*)"', response) action_match = re.search(r'"Action":\s*"([^"]*)"', response) thought = thought_match.group(1) if thought_match else"" action = action_match.group(1) if action_match else"" return { **state, "thought": thought, "action": action } def execute_action(self, state: AgentState) -> AgentState: """步骤3: 解析并执行动作""" action = state["action"] ifnot action: print("⚠️ 没有可执行的动作") return {**state, "finished": True} # 检查是否完成 if action.startswith("finished("): content_match = re.search(r"finished\(content='([^']*)'\)", action) content = content_match.group(1) if content_match else"任务完成" print(f"✅ 任务完成: {content}") return {**state, "finished": True} # 解析并执行动作 try: self._parse_and_execute(action) except Exception as e: print(f"❌ 执行动作失败: {e}") print(f" 动作: {action}") return state def _parse_and_execute(self, action: str): """解析动作字符串并执行""" print(f"🔧 执行动作: {action}") # click(point='<point>x y</point>') 或 click(point='x y') if action.startswith("click("): # 尝试带标签的格式 point_match = re.search(r"<point>(\d+)\s+(\d+)</point>", action) ifnot point_match: # 尝试不带标签的格式 point_match = re.search(r"point=['\"](\d+)\s+(\d+)['\"]", action) if point_match: x, y = int(point_match.group(1)), int(point_match.group(2)) actual_x, actual_y = self.normalize_coords(x, y) self.operation.click(actual_x, actual_y) else: print(f"⚠️ 无法解析点击坐标: {action}") # left_double(point='<point>x y</point>') 或 double_click(point='x y') elif action.startswith("left_double("): # 尝试带标签的格式 point_match = re.search(r"<point>(\d+)\s+(\d+)</point>", action) ifnot point_match: # 尝试不带标签的格式 point_match = re.search(r"point=['\"](\d+)\s+(\d+)['\"]", action) if point_match: x, y = int(point_match.group(1)), int(point_match.group(2)) actual_x, actual_y = self.normalize_coords(x, y) self.operation.double_click(actual_x, actual_y) else: print(f"⚠️ 无法解析双击坐标: {action}") # type(content='xxx') elif action.startswith("type("): content_match = re.search(r"content=['\"]([^'\"]*)['\"]", action) if content_match: text = content_match.group(1) # 处理转义字符 text = text.replace(r"\'", "'").replace(r'\"', '"').replace(r"\n", "\n") self.operation.input(text) # hotkey(key='ctrl c') elif action.startswith("hotkey("): key_match = re.search(r"key=['\"]([^'\"]*)['\"]", action) if key_match: keys = key_match.group(1).split() self.operation.hotkey(*keys) # scroll(point='<point>x y</point>', direction='down') 或 scroll(point='x y', direction='down') elif action.startswith("scroll("): # 尝试带标签的格式 point_match = re.search(r"<point>(\d+)\s+(\d+)</point>", action) ifnot point_match: # 尝试不带标签的格式 point_match = re.search(r"point=['\"](\d+)\s+(\d+)['\"]", action) direction_match = re.search(r"direction=['\"]([^'\"]*)['\"]", action) if point_match and direction_match: x, y = int(point_match.group(1)), int(point_match.group(2)) actual_x, actual_y = self.normalize_coords(x, y) direction = direction_match.group(1) # 移动到位置并滚动 import pyautogui pyautogui.moveTo(actual_x, actual_y) scroll_amount = 3if direction in ["up", "left"] else-3 pyautogui.scroll(scroll_amount) # wait() elif action.startswith("wait("): self.operation.wait(seconds=5) # drag(start_point='<point>x1 y1</point>', end_point='<point>x2 y2</point>') elif action.startswith("drag("): # 尝试带标签的格式 start_match = re.search(r"start_point=['\"]<point>(\d+)\s+(\d+)</point>['\"]", action) end_match = re.search(r"end_point=['\"]<point>(\d+)\s+(\d+)</point>['\"]", action) ifnot start_match: # 尝试不带标签的格式 start_match = re.search(r"start_point=['\"](\d+)\s+(\d+)['\"]", action) end_match = re.search(r"end_point=['\"](\d+)\s+(\d+)['\"]", action) if start_match and end_match: x1, y1 = int(start_match.group(1)), int(start_match.group(2)) x2, y2 = int(end_match.group(1)), int(end_match.group(2)) actual_x1, actual_y1 = self.normalize_coords(x1, y1) actual_x2, actual_y2 = self.normalize_coords(x2, y2) import pyautogui pyautogui.moveTo(actual_x1, actual_y1) pyautogui.drag(actual_x2 - actual_x1, actual_y2 - actual_y1, duration=0.5) # 等待一下让界面响应 self.operation.wait(seconds=1) def should_continue(self, state: AgentState) -> str: """判断是否继续循环""" return"end"if state.get("finished", False) else"continue" def run(self): """运行Agent""" # 构建graph workflow = StateGraph(AgentState) # 添加节点 workflow.add_node("screenshot", self.take_screenshot) workflow.add_node("decide", self.model_decide) workflow.add_node("execute", self.execute_action) # 添加边 workflow.set_entry_point("screenshot") workflow.add_edge("screenshot", "decide") workflow.add_edge("decide", "execute") workflow.add_conditional_edges( "execute", self.should_continue, { "continue": "screenshot", "end": END } ) # 编译并运行 app = workflow.compile() print(f"🚀 开始执行任务: {self.instruction}\n") # 设置递归限制为100步 config = {"recursion_limit": 100} final_state = app.invoke( {"instruction": self.instruction, "step": 0}, config=config ) print(f"\n🎉 任务完成! 共执行 {final_state['step']} 步") return final_stateif __name__ == "__main__": agent = GUIAgent(instruction="""打开浏览器查询GUI, 找到wikipedia的介绍页面进行查看""") agent.run()
4. 执行效果

文章前言部分的demo, 模型的部分决策内容如下:

对于中间步骤,模型会利用到上文的内容,与当前页面状态一起作为决策依据:

最后,如果模型判断任务完成,会输出finished指令,程序停止

三、总结

本文采用简洁易用的方案搭建了一个 PC 端的 GUI Agent,该 Agent 不仅能在 Windows 和 macOS 系统上直接运行,还可操作 Web 应用。得益于以 pyautogui(键鼠模拟)作为核心执行器,该 Agent 能够实现跨应用的操作能力。未来可通过补充滑动、拖拽等更多样的交互方式,并结合知识库的构建,进一步强化其针对特定业务场景的适配性,打造功能更强大的 GUI Agent。

学AI大模型的正确顺序,千万不要搞错了

🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!

有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!

就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇

学习路线:

✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经

以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1184484.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

卫生初中级职称考试直播课推荐——珍藏备考锦囊分享 - 医考机构品牌测评专家

卫生初中级职称考试直播课推荐——珍藏备考锦囊分享对于临床在职医护而言,卫生初中级职称考试绝非简单的证书考核,更是专业能力的官方认证、职业晋升的硬性门槛,承载着个人职业价值的进阶诉求。在三班倒、时间碎片化…

烦死了!测绘工程你能不能不要招女生呀?测绘女生找工作太难了~

2026年悄然而至&#xff0c;春节过后便是金三银四&#xff0c;2026即将迎来第一波求职高峰期。3S专业的求职旺季&#xff0c;几乎每年都会有人来问的问题&#xff1a;测绘外业不招女生怎么办&#xff1f; 事实上这样的现象存在已久&#xff0c;并不是个例&#xff0c;这几乎是每…

2026职场办公视频素材指南:10个素材网站搞定会议场景

根据艾瑞咨询发布的《2025中国数字创意素材产业发展研究报告》显示&#xff0c;2026年我国企业对职场办公及会议场景视频素材的需求同比增长65%&#xff0c;其中免费素材的下载量占比高达72%。这一数据说明&#xff0c;越来越多的职场人在制作PPT、培训视频、企业宣传材料时&am…

学术搜索入口:快速找到权威学术资源的便捷通道

做科研的第一道坎&#xff0c;往往不是做实验&#xff0c;也不是写论文&#xff0c;而是——找文献。 很多新手科研小白会陷入一个怪圈&#xff1a;在知网、Google Scholar 上不断换关键词&#xff0c;结果要么信息过载&#xff0c;要么完全抓不到重点。今天分享几个长期使用的…

uint8_t与int型的区别是什么,为什么嵌入式代码都会用uint8_t而不用int型呢?

uint8_t与int型的区别是什么,为什么嵌入式代码都会用uint8_t而不用int型呢?uint8_t 和 int 的区别是多方面的,嵌入式代码偏爱 uint8_t 的原因也源于这些区别所带来的优势。 下面从多个维度进行详细解释。核心区别对…

2026美食短视频必备:10个精美特写素材网站,免费又好用?

根据《2025抖音美食内容生态报告》显示&#xff0c;2025年美食短视频中特写镜头的使用率同比提升62%&#xff0c;其中食材纹理、烹饪过程、成品摆盘等特写内容成为用户停留时长最长的部分。这一数据说明&#xff0c;高质量的美食短视频精美特写素材是吸引观众、提升视频完播率的…

掌握外科主治医师考试特点与备考重点,方能精进医学素养 - 医考机构品牌测评专家

掌握外科主治医师考试特点与备考重点,方能精进医学素养随着医疗行业专业化程度的不断提升,外科主治医师职称考试作为衡量外科医生临床能力与理论水平的重要标尺,其竞争日趋激烈。近年来,考试内容不断向深度与广度拓…

学霸同款8个AI论文工具,专科生轻松搞定论文格式规范!

学霸同款8个AI论文工具&#xff0c;专科生轻松搞定论文格式规范&#xff01; 论文写作的“秘密武器”&#xff1a;AI 工具如何改变专科生的学习方式 在如今这个信息爆炸的时代&#xff0c;论文写作早已不再是本科以上学生的专属任务。越来越多的专科生也开始面临撰写论文的压力…

知识集锦:分享外科主治医师考试特点与备考重点 - 医考机构品牌测评专家

知识集锦:分享外科主治医师考试特点与备考重点大家好,我是在医院外科部门工作多年的医生,去年外科主治医师考试取得了不错的成绩。近年外科主治医师考试大纲整体变动不大,但难度攀升,专业实践能力的病例分析题占比…

你们在用MySQL还是PostgreSQL?

大家好&#xff0c;我是地鼠哥&#xff0c;最近和我们就业陪跑训练营学员日常答疑的时候聊到一个有趣的话题&#xff0c;就像标题中说的&#xff0c;你们正在用什么DB呢&#xff1f;为什么呢&#xff1f;也欢迎在文末留言区交流。 最近几年&#xff0c;关注国内信创产业或数据…

执业医师考试哪个课程好?六大热门课程实测拆解,按需选对少走弯路 - 医考机构品牌测评专家

执业医师考试哪个课程好?六大热门课程实测拆解,按需选对少走弯路备考执业医师考试,选对课程比盲目跟风报机构更关键。尤其是临床技能部分,既要搞定规范实操,又要培养临床思维,一套适配自身基础、覆盖全备考周期的…

AI Agent yyds!5分钟带你入门智能体开发,小白也能轻松上手

第一章&#xff1a;初识智能体 欢迎来到智能体的世界&#xff01;在人工智能浪潮席卷全球的今天&#xff0c;**智能体&#xff08;Agent&#xff09;**已成为驱动技术变革与应用创新的核心概念之一。无论你的志向是成为AI领域的研究者、工程师&#xff0c;还是希望深刻理解技术…

java+vue+SpringBoot周边游平台(程序+数据库+报告+部署教程+答辩指导)

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿ppt部署教程代码讲解代码时间修改工具 技术实现 开发语言&#xff1a;后端&#xff1a;Java 前端&#xff1a;vue框架&#xff1a;springboot数据库&#xff1a;mysql 开发工具 JDK版本&#xff1a;JDK1.8 数…

AI技术内卷?掌握MCP/RAG/Agent,让你从“调包侠“变身“AI大神“!

前言 最近&#xff0c;AI 圈被三个词刷屏了 ——MCP、RAG、Agent&#xff01;几乎每天都有新的相关工具冒出来&#xff0c;各大技术论坛、行业群聊得热火朝天。但不少朋友一看到这些术语就犯迷糊&#xff1a;它们到底是啥&#xff1f;能干啥&#xff1f;和我们普通人又有啥关系…

java+vue+SpringBoot酒店管理系统(程序+数据库+报告+部署教程+答辩指导)

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿ppt部署教程代码讲解代码时间修改工具 技术实现 开发语言&#xff1a;后端&#xff1a;Java 前端&#xff1a;vue框架&#xff1a;springboot数据库&#xff1a;mysql 开发工具 JDK版本&#xff1a;JDK1.8 数…

德国 EPR 不做,会不会影响其他欧盟国家?

很多卖家在德国 EPR 上犹豫&#xff0c; 真正担心的不是德国&#xff0c; 而是这一句&#xff1a; 德国 EPR 不做&#xff0c; 会不会影响我其他欧盟国家的销售&#xff1f; 这个问题&#xff0c;网上的答案往往非常混乱。 德国 EPR 本身&#xff0c;不会“自动连坐”所有…

3% 获批率 + 权威背书!乐城细胞技术落地一龄,重塑牙周炎精准治疗新范式

2025 年 11 月 1 日&#xff0c;细胞年会 2025 年度盛典在海南博鳌乐城国际医疗旅游先行区顺利举办。作为生物医学领域的重要行业活动&#xff0c;本次盛典正式公布了第四批细胞与基因治疗新技术项目及定价&#xff0c;其中牙髓干细胞治疗牙周炎技术的落地引发广泛关注&#xf…

【程序员救星】AI Agent自动写代码做设计!大模型落地关键,6张图带你秒懂前沿技术,OpenAI盖茨都在打call!

最近AI圈又炸了&#xff01;继大模型之后&#xff0c;AI Agent成了新晋顶流&#xff01;OpenAI CEO山姆奥特曼、比尔盖茨、中国工程院院士邬贺铨都疯狂打call&#xff01; ✓山姆奥特曼说&#xff1a;它将成为下一个重大突破&#xff01; ✓比尔盖茨说&#xff1a;它将颠覆软…

基于AutoGLM-Phone-9B的移动端AI部署方案|支持视觉语音文本融合

基于AutoGLM-Phone-9B的移动端AI部署方案&#xff5c;支持视觉语音文本融合 1. 技术背景与核心价值 随着移动智能设备对多模态交互需求的快速增长&#xff0c;传统大模型因计算资源消耗高、延迟大等问题难以在端侧高效运行。在此背景下&#xff0c;AutoGLM-Phone-9B 应运而生…

PHP下载站开发全攻略

PHP开发下载站的逻辑开发一个基于PHP的下载站需要处理文件上传、存储、下载权限和用户管理等功能。以下是关键逻辑和实现方法&#xff1a;文件上传与存储创建文件上传表单&#xff0c;允许用户或管理员上传文件。文件应存储在服务器非公开目录&#xff0c;避免直接URL访问。$ta…