midscene/apps/site/docs/zh/blog-programming-practice-using-structured-api.md
yuyutaotao 1589d10f35
docs(core): update blog (#735)
* docs(core): update blog

* docs(blog): update workflow blog

* docs(site): add details and pic

* docs(site): update pic

* docs(site): update pic 2

---------

Co-authored-by: quanruzhuoxiu <quanruzhuoxiu@gmail.com>
2025-05-21 16:49:26 +08:00

189 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 使用 JavaScript 优化 AI 自动化代码
许多开发者喜欢使用 `aiAction` 接口来汇聚自动化任务,甚至将所有复杂逻辑描述在一个自然语言指令中。虽然这看起来很"智能",但实际上会带来一系列问题,甚至困在 Prompt 反复调优的怪圈中。
最常见的典型错误是编写大段逻辑风暴,如:
```javascript
aiAction(`
1. 点击第一个用户
2. 点击主页右侧的聊天气泡
3. 如果我曾经给他发过消息,就返回上一级
4. 如果我没有发过消息,就输入一段打招呼文本,并点击发送
`)
```
另一个常见错误是,企图使用 `aiAction` 方法做复杂的流程控制。和传统的 JavaScript 相比,这些复杂 Prompt 的可靠性可能非常差。例如:
```javascript
aiAction('逐条点击所有记录,如果一个记录包含“已完成”,则跳过')
```
## 使用 JavaScript 和结构化 API 编写自动化脚本
从 v0.16.10 开始Midscene 提供了数据提取方法,如 `aiBoolean` `aiString` `aiNumber`,可以用于控制流程。
结合这些方法和即时操作方法,如 `aiTap` `aiInput` `aiScroll` `aiHover` 等,可以将复杂逻辑拆分为多个步骤,以提升自动化代码的稳定性。
让我们以第一个错误案例为例,将 `.aiAction` 方法转换为结构化 API 调用:
原始提示:
```
逐条点击所有记录,如果一个记录包含“已完成”,则跳过
```
转换后的代码:
```javascript
const recordList = await agent.aiQuery('string[], the record list')
for (const record of recordList) {
const hasCompleted = await agent.aiBoolean(`check if the record contains the text "completed"`)
if (!hasCompleted) {
await agent.aiTap(record)
}
}
```
修改代码风格后,整个过程可以更可靠和易于维护。
## 一个更复杂的例子
以下是修改前的代码:
```javascript
aiAction(`
1. 点击第一个未关注用户,进入用户主页
2. 点击关注按钮
3. 返回上一级
4. 如果所有用户都已关注,则向下滚动一屏
5. 重复上述步骤,直到所有用户都已关注
`)
```
使用结构化 API 后,开发者可以轻松地进行审阅和单步调试:
```javascript
let user = await agent.aiQuery('string[], 列表中所有未关注用户')
let currentUserIndex = 0
while (user.length > 0) {
console.log('当前用户是', user[currentUserIndex])
await agent.aiTap(user[currentUserIndex])
try {
await agent.aiTap('关注按钮')
} catch (e) {
// 忽略错误
}
// 返回上一级
await agent.aiTap('返回按钮')
currentUserIndex++
// 检查是否已经遍历了当前列表中的所有用户
if (currentUserIndex >= user.length) {
// 向下滚动一屏
await agent.aiScroll('向下滚动一屏')
// 获取更新后的用户列表
user = await agent.aiQuery('string[], 列表中所有未关注用户')
currentUserIndex = 0
}
}
```
## 常用的结构化 API 方法
### `aiBoolean` - 条件决策
* 适用场景:条件判断、状态检测
* 优势:将模糊描述转换为明确的布尔值
举例:
```javascript
const hasAlreadyChat = await agent.aiBoolean('当前聊天页面上,我是否给他发过消息');
if (hasAlreadyChat) {
// ...
}
```
### `aiString` - 文本提取
* 适用场景:文本内容获取
* 优势:规避自然语言描述的歧义性
举例:
```javascript
const username = await agent.aiString('用户列表里的第一个用户昵称');
console.log('username is', username);
```
### `aiNumber` - 数值提取
* 适用场景:计数、数值比较、循环控制
* 优势:保证返回标准数字类型
举例:
```javascript
const unreadCount = await agent.aiNumber('消息图标上的未读数字');
for (let i = 0; i < unreadCount; i++) {
// ...
}
```
### `aiQuery` - 通用数据提取
* 适用场景:提取任意数据类型
* 优势:灵活的数据类型处理
举例:
```javascript
const userList = await agent.aiQuery('string[], 用户列表');
```
### 即时操作方法
Midscene 提供了一些即时操作方法,如 `aiTap` `aiInput` `aiScroll` `aiHover` 等,它们也常用于自动化代码中。你可以在 [API](./API) 页面查看。
## 想要轻松编写结构化代码?
如果你觉得上述 javascript 代码很难写,那么现在是时候使用 AI IDE 了。
使用你的 AI IDE 索引以下文档:
- https://midscenejs.com/blog-programming-practice-using-structured-api.md
- https://midscenejs.com/API.md
:::tip
如何将 Midscene 文档添加到 AI IDE
请参考 [这篇文章](./llm-txt.mdx#usage)。
:::
接着使用以下提示词:
```
根据 @Use JavaScript to Optimize the Midscene Al Automation Code 和 @Midscene API 文档中的提示和 API 说明,
请帮我将以下指令转换为结构化 javascript 代码:
<你的提示词>
```
![](/blog/ai-ide-convert-prompt.png)
然后奇迹就会发生。
输入你的提示词后AI IDE 会自动将你的提示词转换为结构化 javascript 代码:
![](/blog/ai-ide-convert-prompt-result.png)
快去试试吧!
## 接下来做什么?
为了获得更好的性能,你可以检查 [Midscene 缓存功能](./caching) 来缓存规划和 xpath 定位结果。
要了解更多关于结构化 API 的信息,请查看 [API 参考](./API)。