发布时间:2025 年 1 月 14 日
在去年的 2024 年 Google I/O 大会上,我们推出了 Console Insights,这是 Chrome 开发者工具中的第一项 AI 功能。控制台数据分析会将与日志消息相关的网络数据、源代码和堆栈轨迹发送到 Google 的大语言模型 (LLM) Gemini,以帮助您了解记录到控制台的错误和警告。管理中心数据分析会向 Gemini 发送一个问题,Gemini 会返回一个回答,开发者无法再继续询问后续问题。虽然这种单一互动流程在解释错误消息方面效果相对较好,但无法扩展到开发者工具中更复杂的调试用例,在这些用例中,AI 需要从被检查的网页中获取哪些数据来提供帮助并不明确。
其中一个用例是调试样式问题。单个网页可以包含数千个元素和 CSS 规则,其中只有一部分与调试特定场景相关。确定要调试的正确代码可能很困难,即使对于人类也是如此。但在 Google 举办的 AI 黑客马拉松期间构建的原型表明,LLM 实际上在这方面表现相当不错。因此,我们自然希望将这种强大功能提供给开发者工具用户,打造一款能够通过交互式方式查询网页以获取更多上下文数据,从而调查样式问题的工具。几个月后,我们推出了AI 美妆助手,这便是我们构建的系统。
在本文中,我们将介绍在将 AI 引入深受用户喜爱的产品(例如 Chrome 开发者工具,其核心是一款 Web 应用)时遇到的挑战,以及您可以如何为自己的 AI 功能进行调整。
收集正确的数据
控制台数据分析始终使用相同的数据点来响应预定义的提示。为了让 AI 助手能够针对任何用户定义的提示提供实用帮助,我们需要动态确定哪些上下文数据对当前查询至关重要。
因此,我们实现了 ReAct(Yao 等人,2022) 策略。这种提示策略使 LLM 能够自主推理,并根据推理结果确定后续操作。
这样一来,AI 助理便会在思考、行动和观察的循环中运作,直到确定出适合用户询问的回答,然后结束循环并提供答案。通过这一迭代过程,LLM 可以收集有效调试样式问题所需的精确信息。
为了收集信息,我们仅向 Gemini 提供了一项工具:在被检查的网页上运行 JavaScript。这样一来,Gemini 便可以通过 AI 辅助功能执行以下操作:
- 访问和分析 DOM:遍历 DOM 树、检查元素属性,以及了解元素之间的关系。
- 检索计算样式:访问任何元素的计算样式。
- 执行计算和测量:执行 JavaScript 代码以计算元素的距离、尺寸和位置。
与将完整的 HTML 和 CSS 源代码发送到 Gemini 相比,这样一来,AI 助理便可交互式地仅处理相关代码,从而提高响应质量、响应时间和计算资源的使用效率。
在用户空间中运行 AI 生成的代码
我们使用 JavaScript 调试样式问题,这可能看起来有点意外。这样做的原因有如下两点:
- Web API 非常强大,本身就涵盖许多调试用例。虽然对于开发者来说,手动使用 API 调用来遍历 DOM 或访问计算样式以进行调试可能很繁琐,但对于 LLM 来说,生成调用这些 API 的代码并不难。
- 虽然可以为代理发明新的 API 供其使用,但重复使用现有的公共 API 通常是更好的选择,因为 LLM 已经知道这些 API。若要让 LLM 了解新 API,需要大量的资源来进行微调和使用特定的训练数据。
但在用户空间中运行 AI 生成的代码存在风险。对于 AI 辅助功能,我们需要最大限度地降低代理对网页可能造成的破坏性更改的风险。为此,我们采用了 Chrome 的 JavaScript 引擎 V8 通过 Chrome DevTools 协议公开的副作用检查。开发者工具控制台中的自动补全功能也使用相同的检查:只要 JavaScript 代码不会修改任何页面状态,它便只会运行 JavaScript 代码。这些检查会在 V8 执行代码时执行,并且基于已知没有副作用的 JavaScript 内置函数的许可名单。
如果检查检测到生成的代码正在修改被检查的页面,则会暂停执行,并要求用户检查代码并确认可以运行。
此外,生成的 JavaScript 会在所谓的隔离“世界”中运行。这与扩展程序运行沙盒脚本的方式类似:生成的代码可以访问 DOM 和 Web API,但无法访问被检查网页定义的 JavaScript 代码或状态。
跟踪代理所做的更改
除了调查问题和回答与网页相关的调试问题之外,我们还希望让 AI 辅助客服人员能够以开发者可跟踪的方式修复网页上的样式。
为此,我们实现了一个名为 setElementStyles
的绑定,除了默认的 Web API 之外,我们还将其公开给代理的执行上下文。
为了让 Gemini 了解该新方法,我们指示它在 AI 辅助前言中使用该方法:
If you need to set styles on an HTML element, always call the \`async setElementStyles(el: Element, styles: object)\` function.
尽管它是专为代理设计的 API,但也存在前面提到的挑战。不过,即使没有进行微调,Gemini 在需要更改给定元素的样式时,也能非常可靠地使用它。
在 DevTools 端,从代理调用 setElementStyles
时,AI 辅助功能会使用检查器样式表记录元素选择器的更改。CSS 嵌套用于为更改命名,并提高元素选择器的专属性。因此,代理创建的 CSS 规则示例如下:
.ai-style-change-1 { /* the ID is incremented for each change*/
.element-selector { /* Element selector is computed based on the element setElementStyles was called on. */
color: blue;
}
}
虽然这并不能解决网页上可能发生的所有样式冲突,但在大多数情况下都有效。
与内嵌样式相比,使用检查器样式板的好处在于,代理执行的更改也会显示在更改面板中,这样便于跟踪对元素样式所做的更改,以及开发者需要将哪些内容传输到底层源代码。与“更改”面板集成后,如果您不再需要更改,还可以回滚更改。
让用户能够观察客服人员的操作
向产品添加代理功能时,请务必向用户公开代理操作,以便他们有机会跟踪、了解和可能进行干预。
因此,对于 AI 助理,我们会指示 Gemini 以特定格式构建回答,并在前言中添加以下内容:
You are going to answer to the query in these steps:
* THOUGHT
* TITLE
* ACTION
* ANSWER
* SUGGESTIONS
Use THOUGHT to explain why you take the ACTION. Use TITLE to provide a short summary of the thought.
然后,此结构会用于将 Gemini 的思考过程和操作显示为最初折叠的步骤,从而防止信息过载,同时仍允许用户检查底层详细信息,或在出现意外副作用时停止执行。
这种方法不仅仅是观察 AI,而是要主动从中学习。通过展开这些部分,用户可以分析 Gemini 认为与调试特定问题相关的数据,并了解其遵循的过程。这种透明度让用户可以从 AI 的调试策略中学习,以便在未来遇到类似问题时,即使没有 AI 也可以应用类似的技术。
为了进一步提升用户体验,AI 助理还会在 AI 回答后提供与上下文相关的建议。这些建议可简化对话,提供有关下一步调试步骤的建议,甚至允许用户一键直接执行建议的修复程序。
最初,为了在 AI 帮助中生成步骤标题和建议,我们考虑使用一个专门用于总结的较小单独模型。不过,我们意识到,ReAct 模式(将 Gemini 的推理结构化为“思考”和“行动”的循环)可以有效扩展。因此,我们修改了提示,以指示 Gemini 不仅在同一 ReAct 循环中生成核心“想法”和“操作”,还生成简洁的标题和实用建议,而不是引入第二个模型(这会增加延迟时间)。
以评估为导向的开发
我们在开发用于提供样式方面的 AI 辅助功能时,遵循了严格的评估流程。为了衡量其性能并确定改进方面,我们精心收集了一系列真实的 Web 调试示例,涵盖常见的溢出问题、Web 组件、动画等内容。这让我们能够绘制 Web 调试问题空间的广度,并深入了解相关挑战。但这项工作永远不会结束:随着 Web 平台不断添加新功能,我们日后需要不断更新这些示例。
这些示例会馈送到自动评估流水线,记录 Gemini 的回答。然后,这些自动化测试运行的数据会显示在自定义工具中,我们会在该工具中根据预定义的评分标准手动评估 Gemini 在 AI 辅助方面的表现,以便为后续的开发工作提供参考。
这种以评估为导向的方法可确保所有更改(无论是优化现有行为还是引入新功能)都经过仔细验证,以实现预期的改进并防止现有功能出现回归问题。
为了进一步完善我们的评估流程,我们正在探索自动验证方法,包括:
- 用于确认正确应用修复程序的断言
- 基于代码的检查,以防止 Gemini 输出不必要的输出
- 利用 LLM 作为评判者,在特定评分标准的指导下,实现半自动化和加速手动评估
虽然自动验证有助于扩大规模,但人工反馈也非常重要。我们在 AI 帮助功能的每条回答下方提供了投票控件,以便收集用户反馈,了解用户的满意度。新增了“举报”按钮,让用户可以针对有争议的回答提供更精确的反馈。
提示词注入
LLM 的一个众所周知且已记录的限制是,它们容易受到提示注入。提示注入是一种技术,旨在找到一种方法来覆盖 LLM 的原始系统指令,使其输出开发者意料之外的内容。
目前,大多数模型都内置了针对提示注入的缓解措施,Gemini 也是如此。此外,对于 AI 辅助功能,我们还尝试在序言中添加以下说明,以缓解此问题:
If the user asks a question about religion, race, politics, sexuality, gender, or other sensitive topics, answer with "Sorry, I can't answer that. I'm best at questions about debugging web pages.
虽然这对一些明显不相关的问题有效,但并不完美。我们注意到的一个缺点是,简短且模糊的询问可能会被归类为不相关。
打下坚实的基础
首次在产品中引入 AI 时,不妨循序渐进,而不是一口气完成。我们在 AI 辅助方面也是采用了同样的方法。通过构建样式代理时学到的所有知识,我们奠定了坚实的基础,以便日后将 AI 协助功能扩展到 DevTools 的其他领域。
在处理样式代理时,我们已经解决了大多数较大的挑战,仅仅几个月后,我们就能够为广告网络、效果和来源引入 AI 辅助功能,并专注于解决各自的具体问题。
处理网络请求时的安全影响
借助网络 AI 助理,用户可以与 Gemini 讨论特定网络请求,并将请求中的数据用作对话上下文。具体而言,系统会将以下数据发送到 Gemini:
- 请求标头:浏览器向服务器发送的标头的一部分。
- 响应标头:服务器返回的标头的一部分。
- 响应状态:表示服务器响应的 HTTP 状态代码(例如 200、404)。
- 时间:详细的时间信息,涵盖请求的各个阶段,例如连接设置和数据传输。
- 请求发起方链:发起请求的操作和脚本序列。
虽然标头对于全面了解请求的组成方式至关重要,但它们也存在安全风险:它们可能包含 API 密钥、会话令牌甚至纯文本密码等凭据。为保护此类敏感信息,我们不会向 Gemini 传输所有标头。我们会维护一个包含允许的标头的许可名单。不在许可名单中的标头的值会替换为 <redacted>
。这种方法可确保 Gemini 在保护用户数据的同时,接收必要的上下文。
适应各种数据格式
借助针对源代码的 AI 辅助功能,开发者可以在“源代码”面板中询问有关源代码文件的问题,例如“此文件的用途是什么?”
文件相关数据(包括文件名、文件内容以及是否已映射到来源)全部在一个提示中发送。这种方法非常有效,因为它只是纯文本。但是,大型文本文件或二进制文件对 LLM 来说是一项挑战。对于二进制文件,我们决定在提示中指明内容是二进制内容,而不发送任何实际内容。对于大型文本文件,我们只会发送从文件开头取出的一小部分内容。
对于性能 AI 辅助功能(可让开发者针对记录的性能配置文件询问特定任务的相关问题),也存在类似的挑战,即如何创建适合 Gemini 上下文窗口的表示法,同时还能被解读以提供更多数据洞见。
为了根据性能配置文件创建此类演示,我们创建了一个名为 AiCallTree
的专用序列化器,该序列化器会以 LLM 可以处理的方式设置任务的调用树格式。今后,我们还将在此处探讨 ReAct 策略,以最大限度地减少需要预先发送到 Gemini 的数据量。
未来的 AI 助理
从 Chrome 132 开始,我们将提供所有这些工作的成果,其中包括针对样式、网络、来源和性能的 AI 辅助功能。希望您在使用时和我们在开发时一样愉快。
如需了解从何入手,请参阅全面的 AI 辅助快速入门指南,其中包含许多可在您自己的网页上试用的演示提示,并务必在我们开放的讨论 bug 中告诉我们您的想法。