随着大模型技术的日益成熟,我们正在见证一场自动化领域的革命。本文将深入探讨如何利用大模型 (LLM) 与 Playwright,构建一个能够自动执行用户指定任务的应用程序,而无需手动编写复杂的网页自动化代码。这种方法能够极大地简化网页交互流程,提高效率,为各种应用场景带来便利。

任务自动化:核心需求与挑战

在日常工作中,我们经常需要重复执行一些网页操作,例如数据抓取、信息填写、测试等等。传统的方法需要编写大量的自动化脚本,不仅耗时费力,而且需要专业的编程知识。任务自动化 的需求日益增长,而传统的解决方案却面临着挑战。

例如,一个电商运营人员需要每天监控竞争对手的价格,并调整自家商品的价格。传统的方法需要编写爬虫程序,定期抓取数据,并进行分析。如果竞争对手的网站结构发生变化,爬虫程序就需要进行修改,维护成本很高。

大模型赋能:理解用户意图

大模型 在自然语言理解方面的强大能力,使得我们能够直接使用自然语言描述任务,而无需编写复杂的代码。大模型能够理解用户的意图,并将任务分解为一系列可执行的步骤。

例如,用户可以说:“点击搜索框,将筛选条件从‘基本’改为‘高级’,在用户名筛选框中输入‘abc’,然后按回车键执行搜索。” 大模型能够理解这段话的含义,并将其转化为一系列具体的网页操作指令。

Playwright:可靠的网页自动化工具

Playwright 是一个强大的网页自动化工具,可以模拟用户的各种操作,例如点击、输入、滚动等等。它支持多种浏览器,具有高度的稳定性和可靠性。Playwright 提供了丰富的 API,可以方便地与大模型进行集成。

Playwright 的优势在于其跨浏览器兼容性、自动等待机制以及强大的选择器支持。自动等待机制能够确保元素加载完成后再进行操作,避免了因元素未加载而导致的错误。强大的选择器支持能够精确定位网页元素,提高自动化脚本的准确性。

构建自动化交互应用:技术实现细节

  1. 网页导航:

    首先,使用 Playwright 打开指定的网页。

    const browser = await chromium.launch({headless: false});
    const page = await browser.newPage();
    page.goto(url);
    

    headless: false 表示以可见模式运行浏览器,方便调试。page.goto(url) 用于导航到指定的网址。

  2. 任务分解与代码生成:

    将用户输入的任务、网页的 DOM 结构、网页截图等信息传递给大模型。大模型会根据这些信息,生成一个子任务列表和相应的 Playwright 代码片段。

    const bodyHTML = await page.evaluate(() => document.body.outerHTML);
    const screenshot = await page.screenshot();
    
    async getTaskList(task: string, taskList: string, commands: string, page_content: string, imageData: string, error?: any) {
        try {
            const userText = { text: `Write or revise subtask list and first task code snippet based on High Level Task:${task}\n current web page content ${page_content}\n, Existing subTask List: ${taskList}\n, Executed Code Snippets:${commands}\n and current page screenshot. ${error ? `Error from last playwright code execution: ${error.message}` : ''}`};
            const msg1Image1 = { inlineData: { mimeType: "image/png", data: imageData } }
            const messages = [userText, msg1Image1]
            const response = await this.chat.sendMessage({ message: messages });
            return response.text;
        } catch (error) {
            return '';
        }
    }
    

    这里使用了 Gemini 的 sendMessage() 方法进行多轮对话。page.evaluate(() => document.body.outerHTML) 获取网页的 DOM 结构。page.screenshot() 获取网页截图。传递网页截图可以帮助大模型更准确地理解网页的当前状态。

  3. 代码执行与结果反馈:

    执行大模型生成的 Playwright 代码片段,并观察执行结果。如果执行失败,将错误信息传递给大模型,让其重新生成代码。

    const command = result.codeSnippet;
    const subTaskList = result.subTaskList;
    await eval(codeSnippet);
    

    eval() 函数用于执行 JavaScript 代码。如果代码执行出错,可以将错误信息反馈给大模型,让其根据错误信息进行调整。

  4. 持续迭代:

    重复执行步骤 2 和 3,直到所有子任务完成。在每次迭代中,大模型都会根据之前的执行结果和错误信息,不断优化子任务列表和代码片段。

系统指令 (System Instruction):引导大模型行为

系统指令是引导大模型行为的关键。通过精心设计的系统指令,我们可以控制大模型的输出格式、风格和逻辑。

const taskListPrompt = `You are an AI assistant for performing web operations for ${url}, the website will be opened beforehand. You will be given a high-level task to be performed in the given website only, you need break it down into smaller subtasks. Each subtask should be simple enough to be executed sequentially by automation tool Playwright without using loops. Write the subtasks as a numbered list. Each step should be actionable and straightforward, and can be used to generate code snippets for playwright to ensure automation progresses sequentially. If existing task list and execute code snippets are empty, it means no action has been performed, you need to generate subtask list based on high level task, initial webpage DOM and webpage screenshot only. If playwright codes have been executed, you need to update subtask list based on the current state of execution in the website include: the original high-level task, existing subtask list, code snippets have been executed, and current webpage DOM, current page screenshot, you need update the subtask list to reflect what still needs to be done or adjust the approach. You need to product playwright code snippet in javascript for the first task in the subtask list. If the previously executed playwright code is not successfully (has error) or UI did not update as expected based on page content and screenshot, you need to generate code snippet (may update subtask list if needed) in a different way. For example, if page.getByRole did not find the element, then try page.locator() with className, ID. Before task execute, a browser will be opened and navigate to ${url}, so do not include those into task. Do not add task about waitfor unless webpage is just redirected or reloaded or if executing search. Playwright Code snippet must not contain new variable declaration and should be in javascript. Avoid using JavaScript decorators, await keyword and expect function in Playwright Code snippet. Use getBy* methods (like getByRole, getByText, etc.) with \`exact: true\` for playwright code snippet. Response should be string Javascript object in strng, follow this format: {"subTaskList": string, "codeSnippet": string} and sample output exactly. Respond **only** with valid JSON on a **single line**. Never use markdown, code blocks, newlines, or explanations. Never wrap the output in \`\`\`json. If All tasks have been completed, Leave the response completely empty, like {"subTaskList": "", "codeSnippet": ""}. \n Screenshot of current web page will also be provided by user. Example sub TaskList: 1. Go to discover Tab. 2. Check for the presence of element ABC. 3. Fill out Adam ID for app adamID filter. 4. Press Enter button. \n Sample Playwright Code snippets: * page.getByRole('button', { name: 'App', exact: true }).click() * page.click('button.search-button') * page.click('a[href="/search/noquery"]'); * page.locator('.profile-username:has-text("abc")').click(); \n Sample Response:'{"subTaskList": "1. Go to discover Tab. 2. Check for the presence of element ABC.", "codeSnippet": "page.getByRole('button', { name: 'App' }).click()"}'`;

这个系统指令告诉大模型:

  • 它的任务是为指定的网站执行网页操作。
  • 它需要将高层次的任务分解为简单的子任务。
  • 每个子任务必须足够简单,能够被 Playwright 依次执行。
  • 它需要根据网页的 DOM 结构和截图,生成 Playwright 代码片段。
  • 如果之前的代码执行失败,它需要根据错误信息,尝试不同的方法。
  • 输出必须是符合 JSON 格式的字符串。

应对 Playwright 执行错误:动态调整策略

Playwright 在执行过程中可能会遇到各种错误,例如找不到指定的元素、元素不可点击等等。为了提高系统的鲁棒性,我们需要设计一些策略来应对这些错误。

一个有效的策略是,当 Playwright 执行出错时,将错误信息传递给大模型,让其重新生成代码。大模型可以根据错误信息,调整选择器、等待时间或其他参数,以解决问题。

例如,如果 page.getByRole 找不到指定的元素,大模型可以尝试使用 page.locator(),并结合元素的 className 或 ID 来定位元素。

实际应用场景:广泛的应用前景

这种基于大模型和 Playwright 的自动化交互技术,具有广泛的应用前景。

  • 自动化测试: 可以自动执行各种测试用例,提高测试效率和覆盖率。
  • 数据抓取: 可以自动抓取网页上的数据,例如商品价格、新闻信息等等。
  • 表单填写: 可以自动填写各种表单,例如注册表单、订单表单等等。
  • RPA (Robotic Process Automation): 可以自动化各种重复性的业务流程,提高工作效率。

例如,一个银行可以使用这种技术来自动处理贷款申请。系统可以自动从多个网站上抓取用户的信用信息,并填写贷款申请表,大大减少了人工操作。

局限性与未来发展方向

尽管基于大模型和 Playwright 的自动化交互技术具有很大的潜力,但也存在一些局限性。

  • 大模型的理解能力有限: 对于一些复杂的任务,大模型可能无法准确理解用户的意图。
  • 网页的动态性: 现代网页越来越动态化,这给自动化带来了挑战。
  • 安全性: 需要注意保护用户的隐私和安全,避免泄露敏感信息。

未来的发展方向包括:

  • 提高大模型的理解能力: 引入更先进的大模型技术,提高其自然语言理解能力。
  • 增强 Playwright 的适应性: 提高 Playwright 对动态网页的适应性,例如支持 Shadow DOM。
  • 加强安全性: 采用更严格的安全措施,保护用户的隐私和安全。
  • 更友好的用户界面: 设计更直观、更易用的用户界面,降低使用门槛。

结论:开启自动化交互的新纪元

利用 大模型Playwright 构建的自动化交互应用,正在开启一个全新的纪元。它极大地简化了 任务自动化 的流程,降低了技术门槛,为各行各业带来了巨大的便利。随着技术的不断发展,我们有理由相信,这种自动化交互技术将会在未来发挥更大的作用。未来,大模型将会更加智能,Playwright也会更加强大,而我们也将迎来一个更加高效、智能的自动化世界。