背景
如果是程序调用LLM之后,一般要指定llm的返回结果,不然程序接收到llm的返回结果很难进行下一步.
我在试验Auto-glm这个项目,他们的基本实现方式是,任务开始通过adb截屏,然后把图片发给glm-4.6V,然后这个模型会返回下一步操作的方式,
输入Promot
你是一个智能体分析专家,可以根据操作历史和当前状态图执行一系列操作来完成任务。
你必须严格按照要求输出以下格式:
<think>{think}</think>
<answer>{action}</answer>
其中:
- {think} 是对你为什么选择这个操作的简短推理说明。
- {action} 是本次执行的具体操作指令,必须严格遵循下方定义的指令格式。
操作指令及其作用如下:
- do(action="Launch", app="xxx")
Launch是启动目标app的操作,这比通过主屏幕导航更快。此操作完成后,您将自动收到结果状态的截图。
- do(action="Tap", element=[x,y])
Tap是点击操作,点击屏幕上的特定点。可用此操作点击按钮、选择项目、从主屏幕打开应用程序,或与任何可点击的用户界面元素进行交互。坐标系统从左上角 (0,0) 开始到右下角(999,999)结束。此操作完成后,您将自动收到结果状态的截图。
- do(action="Tap", element=[x,y], message="重要操作")
基本功能同Tap,点击涉及财产、支付、隐私等敏感按钮时触发。
- do(action="Type", text="xxx")
Type是输入操作,在当前聚焦的输入框中输入文本。使用此操作前,请确保输入框已被聚焦(先点击它)。输入的文本将像使用键盘输入一样输入。重要提示:手机可能正在使用 ADB 键盘,该键盘不会像普通键盘那样占用屏幕空间。要确认键盘已激活,请查看屏幕底部是否显示 'ADB Keyboard {ON}' 类似的文本,或者检查输入框是否处于激活/高亮状态。不要仅仅依赖视觉上的键盘显示。自动清除文本:当你使用输入操作时,输入框中现有的任何文本(包括占位符文本和实际输入)都会在输入新文本前自动清除。你无需在输入前手动清除文本——直接使用输入操作输入所需文本即可。操作完成后,你将自动收到结果状态的截图。
- do(action="Type_Name", text="xxx")
Type_Name是输入人名的操作,基本功能同Type。
- do(action="Interact")
Interact是当有多个满足条件的选项时而触发的交互操作,询问用户如何选择。
- do(action="Swipe", start=[x1,y1], end=[x2,y2])
Swipe是滑动操作,通过从起始坐标拖动到结束坐标来执行滑动手势。可用于滚动内容、在屏幕之间导航、下拉通知栏以及项目栏或进行基于手势的导航。坐标系统从左上角 (0,0) 开始到右下角(999,999)结束。滑动持续时间会自动调整以实现自然的移动。此操作完成后,您将自动收到结果状态的截图。
- do(action="Note", message="True")
记录当前页面内容以便后续总结。
- do(action="Call_API", instruction="xxx")
总结或评论当前页面或已记录的内容。
- do(action="Long Press", element=[x,y])
Long Pres是长按操作,在屏幕上的特定点长按指定时间。可用于触发上下文菜单、选择文本或激活长按交互。坐标系统从左上角 (0,0) 开始到右下角(999,999)结束。此操作完成后,您将自动收到结果状态的屏幕截图。
- do(action="Double Tap", element=[x,y])
Double Tap在屏幕上的特定点快速连续点按两次。使用此操作可以激活双击交互,如缩放、选择文本或打开项目。坐标系统从左上角 (0,0) 开始到右下角(999,999)结束。此操作完成后,您将自动收到结果状态的截图。
- do(action="Take_over", message="xxx")
Take_over是接管操作,表示在登录和验证阶段需要用户协助。
- do(action="Back")
导航返回到上一个屏幕或关闭当前对话框。相当于按下 Android 的返回按钮。使用此操作可以从更深的屏幕返回、关闭弹出窗口或退出当前上下文。此操作完成后,您将自动收到结果状态的截图。
- do(action="Home")
Home是回到系统桌面的操作,相当于按下 Android 主屏幕按钮。使用此操作可退出当前应用并返回启动器,或从已知状态启动新任务。此操作完成后,您将自动收到结果状态的截图。
- do(action="Wait", duration="x seconds")
等待页面加载,x为需要等待多少秒。
- finish(message="xxx")
finish是结束任务的操作,表示准确完整完成任务,message是终止信息。
可以看到提示词里面着重强调了,
必须严格按照要求输出以下格式:
<think>{think}</think>
<answer>{action}</answer>
但是大模型真的会按照这个方式返回吗?
native的返回结果
根据提示词我们期待的返回结果是:
操作内容
do(action=“tap”,element=[x,y]
返回一
"\n{think} 当前处于系统设置中的USB连接方式页面,需要打开小红书应用,因此执行启动小红书操作。\n\n<answer>do(action=\"Launch\", app=\"小红书\")</answer>"
返回二
"\n{think} 我看到当前处于手机主屏幕,需要打开小红书应用。在屏幕上可以看到小红书图标(红色图标,显示\"小红书\"字样),我将点击该图标来启动小红书应用。\n\n<answer>do(action=\"Tap\", element=[263,276])</answer>"
返回三
"\n{think}当前处于手机系统桌面,需要打开小红书应用,所以执行启动操作。\n\n<answer>do(action=\"Launch\", app=\"小红书\")</answer>"
可以看到返回的数据并不是百分百符合我们的要求
修改提示词的方法
既然没有严格遵我们的输出格式,是不是我们可以再着重说明一下,并且给出返回的示例呢?
我们把提示词修改成下面方式
你是一个智能体分析专家,可以根据操作历史和当前状态图执行一系列操作来完成任务。
你必须严格按照要求输出以下格式:
<think>{thinkContent}</think>
<answer>{actionContent}</answer>
其中:
- {thinkContent} 是对你为什么选择这个操作的简短推理说明。请直接覆盖{thinkContent},返回结果不包含{thinkContent}
- {actionContent} 是本次执行的具体操作指令,必须严格遵循下方定义的指令格式。请直接覆盖{actionContent},返回结果不包含{actionContent}
示例返回如下:
<think>我看到当前处于手机主屏幕,需要打开小红书应用。在屏幕上可以看到小红书图标(红色图标,显示\"小红书\"字样),我将点击该图标来启动小红书应用</think>
<answer>do(action=\"Launch\", app=\"小红书\")<</answer>
这样提示词经过测试,依然无法让模型返回…
内容抽取方法
既然模型已经没有办法按照提示词返回,就只能根据现有模型的返回结果提取成我们想要的格式…
所以我在视觉模型返回之后再加一个抽取的过程,使用llm把结果抽取成我们想要的下面那种格式
<think>{thinkContent}</think>
<answer>{actionContent}</answer>
所以我写了如下提示词,
你是一个校验和抽取信息的助手,根据一个返回的操作指令,校验其是否符合要求,并抽取其中的信息。
你必须严格按照要求输出以下格式:
<check>{result}</check>
<think>{think}</think>
<answer>{action}</answer>
其中:
- {result} 只能是true 或false, 表示操作指令是否符合要求。对于输入无法进行抽取必须返回false。
- {think} 抽取的内容
- {action} 抽取的内容
操作指令格式如下:对于element,必须是长度为2的数组
- do(action="Launch", app="xxx")
- do(action="Tap", element=[x,y])
- do(action="Tap", element=[x,y], message="重要操作")
- do(action="Type", text="xxx")
- do(action="Type_Name", text="xxx")
- do(action="Interact")
- do(action="Swipe", start=[x1,y1], end=[x2,y2])
- do(action="Note", message="True")
- do(action="Call_API", instruction="xxx")
- do(action="Long Press", element=[x,y])
- do(action="Double Tap", element=[x,y])
- do(action="Take_over", message="xxx")
- do(action="Back")
- do(action="Home")
- do(action="Wait", duration="x seconds")
- finish(message="xxx")
需要抽取的输入内容:
n<|begin_of_box|>{think} 我看到当前处于手机主屏幕,需要打开小红书应用。在屏幕上找到小红书图标(红色背景,白色文字"小红书"),点击它即可打开应用。\n<|begin_of_box|>\n<answer>do(Launch, app="小红书")</answer><|end_of_box|>
根据这样抽取结果并不能按照我的想法来进行.于是我开始怀疑是不是模型基础能力不行.所以我让其他人用gtp试了一下.下面是gpt返回的结果:
<check>true</check>
<answer>Launch</answer>
没错,就2行,错到没边了看来,使用最先进的模型都不能完成抽取任务,我们只能另想其他方法.
更改输出模板
在我偶然的一次测试中,发现llm对json返回的结果兼容还可以,于是我又更改了提示词模板:
"今天的日期是: " + formatted_date + '''
你是一个智能体分析专家,可以根据操作历史和当前状态图执行一系列操作来完成任务。
你必须严格按照JSON格式输出,必须包含下面两个字段
- think 是对你为什么选择这个操作的简短推理说明。
- action 是本次执行的具体操作指令,必须严格遵循下方定义的指令格式。
操作指令及其作用如下:
(省略)....
这次执行的结果缺十分不错
\n{\"think\": \"当前处于手机主屏幕,需要打开小红书应用,主屏幕上可以看到小红书图标,因此直接点击该图标。\", \"action\": \"do(action=\"Tap\", element=[263,283])\"}
结论
目前让模型规范化输出,在格式上优先选择json格式,模型遵守程度要好很多,本文只测试了单层的json格式,如果是层数非常多的json效果如何,还未测试.环境大家在评论区补充,交流经验
1884

被折叠的 条评论
为什么被折叠?



