Leyang 5a1a3ba18a
feat(web-integration): support disable cache for a single api call (#740)
* feat(web-integration): support disable cache for a single api call

* feat(workflow): version mismatch

* feat(web-integration): cache rename to cacheable

* feat(web-integration): add cacheable option to multiple API methods and update caching documentation

* docs(site): update cacheable option descriptions to reference caching feature documentation

* docs(core): update caching doc

---------

Co-authored-by: yutao <yutao.tao@bytedance.com>
2025-05-21 16:46:20 +08:00

586 lines
17 KiB
Plaintext
Raw Permalink 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.

# API 参考
> 在以下文档中,你可能会看到带有 `agent.` 前缀的函数调用。如果你在 Playwright 中,这些调用是不带 `agent.` 前缀的,如 `async ({ ai, aiQuery }) => { /* ... */}`。这只是解构语法的区别。
## 构造器
Midscene 中每个 Agent 都有自己的构造函数。
* 在 Puppeteer 中,使用 [PuppeteerAgent](./integrate-with-puppeteer)
* 在桥接模式Bridge Mode使用 [AgentOverChromeBridge](./bridge-mode-by-chrome-extension#constructor)
这些 Agent 有一些相同的构造参数:
* `generateReport: boolean`: 如果为 true则生成报告文件。默认值为 true。
* `autoPrintReportMsg: boolean`: 如果为 true则打印报告消息。默认值为 true。
* `cacheId: string | undefined`: 如果配置,则使用此 cacheId 保存或匹配缓存。默认值为 undefined也就是不启用缓存。
* `actionContext: string`: 调用 `agent.aiAction()` 时,发送给 AI 模型的背景知识,比如 '有 cookie 对话框时先关闭它',默认值为空。
在 puppeteer 中,还有三个额外的参数:
* `forceSameTabNavigation: boolean`: 如果为 true则限制页面在当前 tab 打开。默认值为 true。
* `waitForNetworkIdleTimeout: number`: 在执行每个操作后等待网络空闲的超时时间,默认值为 2000ms设置为 0 则禁用超时。
* `waitForNavigationTimeout: number`: 在页面跳转后等待页面加载完成的超时时间,默认值为 5000ms设置为 0 则禁用超时。
## 交互方法
这些是 Midscene 中各类 Agent 的主要 API。
:::info 自动规划 v.s. 即时操作
在 Midscene 中你可以选择使用自动规划Auto Planning或即时操作Instant Action
* `agent.ai()` 是自动规划Auto PlanningMidscene 会自动规划操作步骤并执行。它更智能,更像流行的 AI Agent 风格,但可能较慢,且效果依赖于 AI 模型的质量。
* `agent.aiTap()`, `agent.aiHover()`, `agent.aiInput()`, `agent.aiKeyboardPress()`, `agent.aiScroll()` 是即时操作Instant ActionMidscene 会直接执行指定的操作,而 AI 模型只负责底层任务,如定位元素等。这种接口形式更快、更可靠。当你完全确定自己想要执行的操作时,推荐使用这种接口形式。
:::
### `agent.aiAction()` 或 `.ai()`
这个方法允许你通过自然语言描述一系列 UI 操作步骤。Midscene 会自动规划这些步骤并执行。
* 类型
```typescript
function aiAction(prompt: string, opt?: {
cacheable?: boolean;
}): Promise<void>;
function ai(prompt: string): Promise<void>; // 简写形式
```
* 参数:
* `prompt: string` - 用自然语言描述的操作内容
* `opt?: Object` - 可选,一个配置对象,包含:
* `cacheable?: boolean` - 当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
* 返回值:
* 返回一个 Promise。当所有步骤执行完成时解析为 void若执行失败则抛出错误。
* 示例:
```typescript
// 基本用法
await agent.aiAction('在搜索框中输入 "JavaScript",然后点击搜索按钮');
// 使用 .ai 简写形式
await agent.ai('点击页面顶部的登录按钮,然后在用户名输入框中输入 "test@example.com"');
// 使用 ui-tars 模型时,可以使用更高维度的提示词
await agent.aiAction('发布一条微博,内容为 "Hello World"');
```
:::tip
在实际运行时Midscene 会将用户指令规划Planning成多个步骤然后逐步执行。如果 Midscene 认为无法执行,将抛出一个错误。
为了获得最佳效果,请尽可能提供清晰、详细的步骤描述。具体可以参考这篇文档:[编写提示词的技巧](./prompting-tips)
关联文档:
* [选择 AI 模型](./choose-a-model)
:::
### `agent.aiTap()`
点击某个元素。
* 类型
```typescript
function aiTap(locate: string, options?: Object): Promise<void>;
```
* 参数:
* `locate: string` - 用自然语言描述的元素定位。
* `options?: Object` - 可选,一个配置对象,包含:
* `deepThink?: boolean` - 是否开启深度思考。如果为 trueMidscene 会调用 AI 模型两次以精确定位元素。
* `cacheable?: boolean` - 当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
* 返回值:
* `Promise<void>`
* 示例:
```typescript
await agent.aiTap('页面顶部的登录按钮');
// 使用 deepThink 功能精确定位元素
await agent.aiTap('页面顶部的登录按钮', { deepThink: true });
```
### `agent.aiHover()`
鼠标悬停某个元素上。
* 类型
```typescript
function aiHover(locate: string, options?: Object): Promise<void>;
```
* 参数:
* `locate: string` - 用自然语言描述的元素定位。
* `options?: Object` - 可选,一个配置对象,包含:
* `deepThink?: boolean` - 是否开启深度思考。如果为 trueMidscene 会调用 AI 模型两次以精确定位元素。
* `cacheable?: boolean` - 当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
* 返回值:
* `Promise<void>`
* 示例:
```typescript
await agent.aiHover('页面顶部的登录按钮');
```
### `agent.aiInput()`
在某个元素中输入文本。
* 类型
```typescript
function aiInput(text: string, locate: string, options?: Object): Promise<void>;
```
* 参数:
* `text: string` - 要输入的文本内容。使用空字符串可以清空输入框。
* `locate: string` - 用自然语言描述的元素定位。
* `options?: Object` - 可选,一个配置对象,包含:
* `deepThink?: boolean` - 是否开启深度思考。如果为 trueMidscene 会调用 AI 模型两次以精确定位元素。
* `cacheable?: boolean` - 当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
* 返回值:
* `Promise<void>`
* 示例:
```typescript
await agent.aiInput('Hello World', '搜索框');
```
### `agent.aiKeyboardPress()`
按下键盘上的某个键。
* 类型
```typescript
function aiKeyboardPress(key: string, locate?: string, options?: Object): Promise<void>;
```
* 参数:
* `key: string` - 要按下的键,如 `Enter`、`Tab`、`Escape` 等。不支持组合键。
* `locate?: string` - 用自然语言描述的元素定位。
* `options?: Object` - 可选,一个配置对象,包含:
* `deepThink?: boolean` - 是否开启深度思考。如果为 trueMidscene 会调用 AI 模型两次以精确定位元素。
* `cacheable?: boolean` - 当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
* 返回值:
* `Promise<void>`
* 示例:
```typescript
await agent.aiKeyboardPress('Enter', '搜索框');
```
### `agent.aiScroll()`
滚动页面或某个元素。
* 类型
```typescript
function aiScroll(scrollParam: PlanningActionParamScroll, locate?: string, options?: Object): Promise<void>;
```
* 参数:
* `scrollParam: PlanningActionParamScroll` - 滚动参数
* `direction: 'up' | 'down' | 'left' | 'right'` - 滚动方向
* `scrollType: 'once' | 'untilBottom' | 'untilTop' | 'untilRight' | 'untilLeft'` - 滚动类型
* `distance: number` - 滚动距离,单位为像素。
* `locate?: string` - 用自然语言描述的元素定位。如果未传入Midscene 会在当前鼠标位置滚动。
* `options?: Object` - 可选,一个配置对象,包含:
* `deepThink?: boolean` - 是否开启深度思考。如果为 trueMidscene 会调用 AI 模型两次以精确定位元素。
* `cacheable?: boolean` - 当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
* 返回值:
* `Promise<void>`
* 示例:
```typescript
await agent.aiScroll({ direction: 'up', distance: 100, scrollType: 'once' }, '表单区域');
```
:::tip 关于 `deepThink` (深度思考)特性
`deepThink` 是一个强大的特性,它允许 Midscene 调用 AI 模型两次以精确定位元素。这在目标元素面积较小、难以和周围元素区分时非常有用。
:::
## 数据提取
### `agent.aiQuery()`
使用此方法,你可以直接从 UI 提取数据,并借助多模态 AI 的推理能力,实现智能提取。只需在 `dataDemand` 中定义期望格式如字符串、数字、JSON、数组等Midscene 即返回相应结果。
* 类型
```typescript
function aiQuery<T>(dataShape: string | Object): Promise<T>;
```
* 参数:
* `dataShape: T`: 描述预期的返回值格式。
* 返回值:
* 返回值可以是任何合法的基本类型比如字符串、数字、JSON、数组等。
* 你只需在 `dataDemand` 中描述它Midscene 就会给你满足格式的返回。
* 示例:
```typescript
const dataA = await agent.aiQuery({
time: '左上角展示的日期和时间string',
userInfo: '用户信息,{name: string}',
tableFields: '表格的字段名string[]',
tableDataRecord: '表格中的数据记录,{id: string, [fieldName]: string}[]',
});
// 你也可以用纯字符串描述预期的返回值格式:
// dataB 将是一个字符串数组
const dataB = await agent.aiQuery('string[],列表中的任务名称');
// dataC 将是一个包含对象的数组
const dataC = await agent.aiQuery('{name: string, age: string}[], 表格中的数据记录');
```
此外,我们还提供了 `aiBoolean()`, `aiNumber()`, `aiString()` 三个便捷方法,用于直接提取布尔值、数字和字符串。
### `agent.aiBoolean()`
从 UI 中提取一个布尔值。
* 类型
```typescript
function aiBoolean(prompt: string): Promise<boolean>;
```
* 参数:
* `prompt: string` - 用自然语言描述的期望值。
* 返回值:
* 返回一个 Promise。当 AI 返回结果时解析为布尔值。
* 示例:
```typescript
const bool = await agent.aiBoolean('是否存在登录对话框');
```
### `agent.aiNumber()`
从 UI 中提取一个数字。
* 类型
```typescript
function aiNumber(prompt: string): Promise<number>;
```
* 参数:
* `prompt: string` - 用自然语言描述的期望值。
* 返回值:
* 返回一个 Promise。当 AI 返回结果时解析为数字。
* 示例:
```typescript
const number = await agent.aiNumber('账户剩余的积分');
```
### `agent.aiString()`
从 UI 中提取一个字符串。
* 类型
```typescript
function aiString(prompt: string): Promise<string>;
```
* 参数:
* `prompt: string` - 用自然语言描述的期望值。
* 返回值:
* 返回一个 Promise。当 AI 返回结果时解析为字符串。
* 示例:
```typescript
const string = await agent.aiString('当前列表的第一条记录的名称');
```
## 更多方法
### `agent.aiAssert()`
通过自然语言描述一个断言条件,让 AI 判断该条件是否为真。当条件不满足时SDK 会抛出错误,并在错误信息中追加 AI 返回的详细原因。
* 类型
```typescript
function aiAssert(assertion: string, errorMsg?: string): Promise<void>;
```
* 参数:
* assertion: string - 用自然语言描述的断言条件。
* errorMsg?: string - 当断言失败时附加的可选错误提示信息。
* 返回值:
* 返回一个 Promise。当断言成功时解析为 void若断言失败则抛出一个错误错误信息包含 `errorMsg` 以及 AI 生成的原因。
* 示例:
```typescript
await agent.aiAssert('"Sauce Labs Onesie" 的价格是 7.99');
```
:::tip
断言在测试脚本中非常重要。为了降低因 AI 幻觉导致错误断言的风险(例如遗漏错误),你也可以使用 `.aiQuery` 加上常规的 JavaScript 断言来替代 `.aiAssert`。
例如,你可以这样替代上面的断言代码:
```typescript
const items = await agent.aiQuery(
'"{name: string, price: number}[], 返回商品名称和价格列表'
);
const onesieItem = items.find(item => item.name === 'Sauce Labs Onesie');
expect(onesieItem).toBeTruthy();
expect(onesieItem.price).toBe(7.99);
```
:::
### `agent.aiLocate()`
通过自然语言描述一个元素的定位。
* 类型
```typescript
function aiLocate(locate: string, options?: {
cacheable?: boolean;
}): Promise<{
rect: {
left: number;
top: number;
width: number;
height: number;
};
center: [number, number];
}>;
```
* 参数:
* `locate: string` - 用自然语言描述的元素定位。
* `options?: Object` - 可选,一个配置对象,包含:
* `deepThink?: boolean` - 是否开启深度思考。如果为 trueMidscene 会调用 AI 模型两次以精确定位元素。
* `cacheable?: boolean` - 当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
* 返回值:
* 返回一个 Promise。当元素定位成功时解析为元素定位信息。
* 示例:
```typescript
const locateInfo = await agent.aiLocate('页面顶部的登录按钮');
console.log(locateInfo);
```
### `agent.aiWaitFor()`
等待某个条件达成。考虑到 AI 服务的成本,检查间隔不会超过 `checkIntervalMs` 毫秒。
* 类型
```typescript
function aiWaitFor(
assertion: string,
options?: {
timeoutMs?: number;
checkIntervalMs?: number;
}
): Promise<void>;
```
* 参数:
* `assertion: string` - 用自然语言描述的断言条件
* `options?: object` - 可选的配置对象
* `timeoutMs?: number` - 超时时间(毫秒),默认为 15000
* `checkIntervalMs?: number` - 检查间隔(毫秒),默认为 3000
* 返回值:
* 返回一个 Promise。当断言成功时解析为 void若超时则抛出错误。
* 示例:
```typescript
// 基本用法
await agent.aiWaitFor("界面上至少有一个耳机的信息");
// 使用自定义配置
await agent.aiWaitFor("购物车图标显示数量为 2", {
timeoutMs: 30000, // 等待 30 秒
checkIntervalMs: 5000 // 每 5 秒检查一次
});
```
:::tip
考虑到 AI 服务的时间消耗,`.aiWaitFor` 并不是一个特别高效的方法。使用一个普通的 `sleep` 可能是替代 `waitFor` 的另一种方式。
:::
### `agent.runYaml()`
执行一个 YAML 格式的自动化脚本。脚本中的 `tasks` 部分会被执行,并返回所有 `.aiQuery` 调用的结果。
* 类型
```typescript
function runYaml(yamlScriptContent: string): Promise<{ result: any }>;
```
* 参数:
* `yamlScriptContent: string` - YAML 格式的脚本内容
* 返回值:
* 返回一个包含 `result` 属性的对象,其中包含所有 `aiQuery` 调用的结果
* 示例:
```typescript
const { result } = await agent.runYaml(`
tasks:
- name: search weather
flow:
- ai: input 'weather today' in input box, click search button
- sleep: 3000
- name: query weather
flow:
- aiQuery: "the result shows the weather info, {description: string}"
`);
console.log(result);
```
:::tip
更多关于 YAML 脚本的信息,请参考 [Automate with Scripts in YAML](./automate-with-scripts-in-yaml)。
:::
### `agent.setAIActionContext()`
设置在调用 `agent.aiAction()` 时,发送给 AI 模型的背景知识。
* 类型
```typescript
function setAIActionContext(actionContext: string): void;
```
* 参数:
* `actionContext: string` - 要发送给 AI 模型的背景知识。
* 示例:
```typescript
await agent.setAIActionContext('如果 “使用cookie” 对话框存在,先关闭它');
```
### `agent.evaluateJavaScript()`
这个方法允许你在 web 页面上下文中执行一段 JavaScript 代码,并返回执行结果。
* 类型
```typescript
function evaluateJavaScript(script: string): Promise<any>;
```
* 参数:
* `script: string` - 要执行的 JavaScript 代码。
* 返回值:
* 返回执行结果。
* 示例:
```typescript
const result = await agent.evaluateJavaScript('document.title');
console.log(result);
```
## 属性
### `.reportFile`
报告文件的路径。
## 更多配置
### 在运行时设置环境变量
你可以通过 `overrideAIConfig` 方法在运行时设置环境变量。
```typescript
import { overrideAIConfig } from '@midscene/web/puppeteer'; // 或其他的 Agent
overrideAIConfig({
OPENAI_BASE_URL: "...",
OPENAI_API_KEY: "...",
MIDSCENE_MODEL_NAME: "..."
});
```
### 打印 AI 性能信息
设置 `DEBUG=midscene:ai:profile:stats` 环境变量,你可以看到每次调用 AI 的时间和 token 数量。
```bash
export DEBUG=midscene:ai:profile:stats
```
### 自定义运行产物目录
设置 `MIDSCENE_RUN_DIR` 变量,你可以自定义运行产物目录。
```bash
export MIDSCENE_RUN_DIR=midscene_run # 默认值为当前运行目录下的 midscene_run 目录,支持设置为绝对路径或者相对于当前目录的相对路径
```
### 使用 LangSmith
LangSmith 是一个用于调试大语言模型的平台。想要集成 LangSmith请按以下步骤操作
```bash
# 设置环境变量
# 启用调试标志
export MIDSCENE_LANGSMITH_DEBUG=1
# LangSmith 配置
export LANGSMITH_TRACING_V2=true
export LANGSMITH_ENDPOINT="https://api.smith.langchain.com"
export LANGSMITH_API_KEY="your_key_here"
export LANGSMITH_PROJECT="your_project_name_here"
```
启动 Midscene 后,你应该会看到类似如下的日志:
```log
DEBUGGING MODE: langsmith wrapper enabled
```