跳转到主要内容
在 Stagehand 中缓存操作对于执行成本高昂的操作或当底层 DOM 结构预计不会改变时非常有用。

使用 observe 预览操作

observe 允许您在执行操作前预览它。如果您对操作预览满意,可以直接在 page.act 中运行而无需额外的 LLM 调用。
const [actionPreview] = await page.observe("Click the quickstart link");

/** actionPreview is a JSON-ified version of a Playwright action:
{
	description: "The quickstart link",
	method: "click",
	selector: "/html/body/div[1]/div[1]/a",
	arguments: [],
}
**/

// NO LLM INFERENCE when calling act on the preview
await page.act(actionPreview)

简单缓存

让我们在这个示例中使用基于文件的简单缓存。我们将编写能够读写 JSON 文件的 getter 和 setter 函数:
// Get the cached value (undefined if it doesn't exist)
async function getCache(key: string): Promise<ObserveResult | undefined> {
  try {
    const cache = await readFile("cache.json");
    const parsed = JSON.parse(cache);
    return parsed[key];
  } catch {
    return undefined;
  }
}

// Set the cache value
async function setCache(key: string, value: ObserveResult): Promise<void> {
  const cache = await readFile("cache.json");
  const parsed = JSON.parse(cache);
  parsed[key] = value;
  await writeFile("cache.json", JSON.stringify(parsed));
}

带缓存执行

让我们编写一个函数来检查缓存、获取操作并执行它。如果操作失败,我们将尝试”自我修复”,即直接通过 page.act 重试。
// Check the cache, get the action, and run it
// If selfHeal is true, we'll attempt to self-heal if the action fails
async function actWithCache(page: Page, key: string, prompt: string, selfHeal = false) {
	try {
		const cacheExists = await getCache(key);

		let action: ObserveResult;
		if (cacheExists) {
		// Get the cached action
		action = await getCache(prompt);
		} else {
		// Get the observe result (the action)
		[action] = await page.observe(prompt);

		// Cache the action
		await setCache(prompt, action);
		}

		// Run the action (no LLM inference)
		await page.act(action);
	} catch (e) {
		console.error(e);
		// in selfHeal mode, we'll retry the action
		if (selfHeal) {
			console.log("Attempting to self-heal...");
			await page.act(prompt);
		}
		else {
			throw e;
		}
	}
}
您现在可以使用 actWithCache 来运行带缓存的操作:
const prompt = "Click the quickstart link";
const key = prompt; // Simple cache key
// Attempt cached action or self-heal
await actWithCache(page, key, prompt);

高级缓存

上述示例很简单,但您可能希望基于页面内容来缓存操作。此外,如果有重复的提示,您应该使用更唯一的键。 我们希望将缓存逻辑留给您自己实现,但为您提供实现自定义缓存策略所需的所有工具。 您可以直接从 Playwright 的 page 对象访问 DOM 和无障碍树。以下是访问页面内容的示例:
// Get the page content
const pageContent = await page.content();
您也可以利用无障碍访问树、DOM 或其他信息来生成更具唯一性的键值。参照上述示例的类似逻辑,您可以自由实现这一功能。