谷歌开发者

招募活动投稿展示|就算大雨让整座城市断网,我还有浏览器内置 AI

Image

活动介绍

谷歌开发者招募活动是专为 Google 技术的爱好者及开发者们开展的活动,旨在鼓励大家通过多种形式 (文章/视频/coding 等) 创作与 Google 技术相关的讲解分享、实践案例或活动感受等内容,展示代码、框架、平台在真实世界中的生动表现,以及分享您应用 AI 技术的故事经历与成果。

作者简介

本文作者 Jax,从事 Web 开发工作已有 7 年,也从中获得了很多乐趣。

文章导读

本文作者将带您了解 Chrome 内置 AI 的最新进展,手把手解锁 Web 端侧智能,并借助 Prompt API 实现几个小应用,为您落地 AI 灵感提供指导。

*以下为投稿原文

相信你已经知道了,Chrome 浏览器内置了 Gemini Nano* 这个大语言模型,这可以算作是 Web 端侧智能的里程碑事件了。如今,Chrome 内置 AI 又有了什么新动向呢?如果你也对 Web AI 感兴趣,那么这篇文章正是为你而写的,读下去吧。
这一次,我们来了解 Chrome 内置 AI 的最新进展,帮助你构建低成本、可扩缩,并能更好保护隐私安全的 Web 应用,在 AI 赋能的情形下探索更多出海场景。我会手把手带你解锁 Web 端侧智能,并借助 Prompt API 实现几个小应用,让你切实感受到浏览器级别的智能能力带给开发者和用户的便利性。

先配齐运行环境

一个好消息是,不像之前那样需要额外安装 Chrome Canary,现在我们已经可以在 Chrome 最新的正式版 (131.0.6778.140) 中使用内置 AI 了。但因为功能更新和 Bug 修复总是会最先、最及时地更新到 Canary 版本上,所以我们还是用最新版 Canary 来进行本文的实操。

由于内置 AI 仍然是作为实验功能装载进浏览器的,所以还需要手动解锁一下。简单来说是以下几步:
1.  在 chrome://flags 中搜索「optimization guide on device」和「Gemini」,把搜到的设置项通通开启。
Image
Image
2.  重启 Chrome
3.  在 chrome://components 中找到「Optimization Guide On Device Model」并点击按钮下载模型

Image

4.  最后,在 Console 中打印 ai 这个全局对象,如果一切顺利,你将会看到如下结果:

Image

再看看整体变化

我们刚刚测试解锁时,打印了全局对象 `ai`,可以看到,它的成员已经是四个新对象了:

```JavaScript{    languageModel,    writer,    rewriter,    summarizer,}```
Chrome 取消了 `window.model` 这个冗余成员,并且把原有的 `createTextSession` 等方法整合进了 `languageModel` 子对象的其他方法实现中。可以说,现在的 Prompt API 和之前完全不一样了。
这代表着,浏览器内置 AI 目前还在厂商的积极尝试中,远没有达到 W3C 标准的阶段,其功能实现还不稳定,处于频繁变动的状态中。所以我们目前还没办法让内置 AI 功能投产。但这也带给我们一种见证历史的感觉 —— 能目睹内置 AI 的诞生和发展,并且能参与到它的进化过程中去,是可遇不可求的视角和体验。
Prompt,意为提示词,狭义上指的是我们用自然语言向大模型传达的指令。而 Prompt API 则是浏览器为 Web 开发者提供的与内置大模型交互的接口。
`writer`,`rewriter`,`summarizer` 都是用于文本处理的 API,而 `languageModel` 就是我们本次要重新认识的 Prompt API。

新的模型入口: languageModel 对象

检测可用性

由于 API 还不稳定,所以我们在使用时,应该总是先检测其可用性。

`languageModel` 对象具有一个 `capabilities` 方法,可以提供给我们一些内置 AI 的状态信息:

Image

在返回结果中,`topK` 和 `temperature` 是用于调控生成结果的参数;而 `available` 则标识了当前环境下是否可用内置 AI 能力,它的取值范围如下:
  • `no`: 当前设备或浏览器不支持
  • `after-download`: 需要等模型下载完成后才可用
  • `readily`: 可用

所以我们可以用这样的逻辑来检测可用性:

```JavaScriptconst capabilities = window.ai?.languageModel?.capabilitiesif (!capabilities) return falseconst { available } = await capabilities()return available === 'readily'```

创建对话

确定可用之后,我们就可以和内置模型来一次对话了。
开启对话的方式沿用了之前的风格: 先创建 `session`,然后进行 prompt 交互。
```JavaScriptconst session = await window.ai.languageModel.create()const result = await session.prompt('Who are you and what can you do?')console.log(result)```

执行上面的代码后,你可能会等上一小会儿,才会看见一整段文字被一次性打印出来。其实模型并不是吭哧瘪肚半天才憋出来一段话。文本生成的原理是根据上文递归推断下一个字 (或者说 token),所以在我们等待的过程中,模型实际上每秒都在生成一定字数的内容。只不过 `prompt()` 就是这种不到火候不揭锅的调性,会等全部生成完成才肯吐口。

为了减轻等待的感觉,API 提供了另一个方法 `promptStreaming`,让模型能够对答如流。

```JavaScriptconst stream = await session.promptStreaming('Can you tell me a joke?')
for await (const chunk of stream) { console.log(chunk)}```

这一次,你会在浏览器 Console 里看到一条信息流倾泻而出,行云流水、从上至下:

Image

因为目前返回的 `stream` 并不真的是流式数据,而是每个 `chunk` 都是最新的完整回答。但好在我们已经可以在提问后立即得到反馈了。

你一定觉得这样在 Console 运行代码的对话形式太不方便了,肯定想要更流畅地领略端侧大语言模型的魅力。我就猜到你是有品味的程序员,所以写了一个对话界面 —— https://rejax.fun/chrome-ai/prompt/#/chat-bot,你可以直接和内置 AI 聊天,而且聊天记录还会保存在 localStorage 里哦~

Image

设置系统提示词

在提示词工程中有这样一个技巧: 你可以给大模型设定一个角色,比如「你是一个 Web 开发专家」、「你是一个数据分析师」或者「你是一个乐于点赞、收藏的读者 ❤️」…… 其作用在于让具备通用泛化能力的大模型在生成内容时,专注于某一块特定的领域,以便于更好地处理我们提出的特定问题,忽略无关的信息。这个技巧能够大幅提升生成内容的质量和相关度,从而提高体验和效率。

而 Prompt API 也为这个技巧提供了接口: 在创建 `session` 时,我们可以给 `create()` 传入配置参数:

```JavaScriptconst session = await ai.languageModel.create({    systemPrompt: 'You are a web development expert……'})```

由此创建出来的 `session`,在后续对话中,会牢牢记住自己的使命,按照 `systemPrompt` 中的指令来推理。

还有一种更通用、更易扩展的配置方法:

```JavaScriptconst session = await ai.languageModel.create({    initialPrompts: [        {            role: 'system',            content: 'You are a web development expert……'        }    ]})```

这种 `role: 'system'` 的方式能起到相同的效果,只不过更符合提示词工程的通用范式,Open AI、LangChain 等提示词的组织形式都是如此。

配置系统提示词的时候,有几点需要注意:
  • `systemPrompt` 和 `role: 'system'` 不能混用

  • `role: 'system'` 只能有一组,且必须放在 `initialPrompts` 的首位

在提示词中附带示例

现在假设要开发一个对联机器人,我们的系统提示词可能会是「你是一个语言学家,你对给定的上联返回下联……」。实测中可能会发现,大模型不是很能理解「上下联」是什么意思。在这种情况下,你当然可以选择整理一批对联数据集,然后对模型进行训练、微调或者蒸馏。但还有一个更简洁、更经济的方法能迅速带来优化效果,那就是 N-Shot 提示词。

N-Shot 也是提示词工程中的一个技巧,N 代表非负整数,Shot 代表样本或者示例。二者合在一起的意思就是在提示词中带上 N 个示例。比如在上文的几个对话中,提示词只给出了指令,那这就属于 0-Shot 提示词。

示例能帮助模型更好地「理解」指令要求中的含义。仍以对联机器人为例,我们把提示词改为「你是一个语言学家,你对给定的上联返回下联。下面是几个例子: 上联: 大江东流去,下联: 小河西淌来。……」,可以以最低的成本获得效果的提升。

回到 Prompt API,`initialPrompts` 参数是一个数组,除了系统提示词,我们还可以预先传入几轮对话,作为 `session` 的背景上文,就像这样:

```JavaScriptinitialPrompts: [    {        role: 'system',        content: '你是一个语言学家,你对给定的上联返回下联'    },    {        role: 'user',        content: '大江东流去'    },    {        role: 'assistant',        content: '小河西淌来',    }]```
其中 `role: ‘user’` 代表用户输入,`role: ‘assistant’` 代表用户输出。这样组织提示词,可以让大模型的生成内容更合我们心意。

Token 计算

Token 数量一般是商业大模型服务的收费指标之一。用户输入的内容越多,大模型需要处理的 token 就越多。虽说 Chrome 内置的 Gemini Nano 是本地模型,咱们开发者可以不用担心计费问题。但每个大模型都有其上下文窗口极限,具体表现就是如果一次性输入几百万字进去,大模型可能无法全部消化;或者经过几百轮对话后,它无法「回忆」起最初几轮对话里的信息。
这种情况下,就需要开发者进行干预了。比如,我们可以计算每轮对话消耗的 token 数量,预计快要接近极限之前,就把早期内容的关键信息提炼出来,在腾出空间的同时保留一定程度的上文。

内置 AI 也同样为开发者提供了一套计量 token 的工具:

  • `session` 实例上有一个 `countPromptTokens` 方法,可以计算传入的字符串参数相当于多少 token
  • `session` 还有三个可读属性:
    1. `maxTokens`: 数量上限
    2. `tokensSoFar`: 目前消耗了多少 token
    3. `tokensLeft`: 还剩多少 token 可用

这样,开发者就能在对话过程中对 token 消耗程度进行把控,从而能够及时处理信息丢失的问题了。

ShowCase: 三分钟写一个小玩具

通过上面的介绍,你会发现 Prompt API 是如此简单易用,不知道它有没有激发你的灵感呢?总之先来看看我写的一个: https://rejax.fun/chrome-ai/prompt/#/prompt

这个脑洞来自那句歌词「What does the fox say?」

Image

在这个小玩具里,用户输入动物名称,大模型返回这种动物的叫声。如果用户输入的不是动物,就会返回「走开」。

核心代码如下:

```JavaScriptconst session = await window.ai.languageModel.create({    initialPrompts: [        {            role: 'system',            content: 'You are a animal expert, user will give you a name of animal, you return the sound of the animal. If the name is not an animal, you return "go away". Return less than 3 words.'        },        {            role: 'user',            content: 'dog'        },        {            role: 'assistant',            content: 'woof',        },        {            role: 'user',            content: 'table'        },        {            role: 'assistant',            content: 'go away',        }    ],})
const sound = await session.prompt(userPrompt)```

结语

这次,我们「复习」了全新的 Prompt API,它是我们实践提示词工程的绝佳帮手,能帮我们几乎无成本地落地 AI 应用灵感。
Prompt API 已经进化出了新的形态,来适应新的环境和需求。在我观察到的一些 W3C 标准和社区草稿的编纂过程里,浏览器内置 AI 草稿绝对可以算是更新最积极的一个。相信再过一段时间,它会变得更加强大、更加易用。
如果你也对 Web 端侧智能充满信心和希冀,那就和我一起关注 Web AI,见证端侧智能的崛起!Witness!
*部分 Google AI 技术适用于出海开发者

写在最后

感谢 Jax 的创作分享,我们也期待更多 Web 开发者能够借助内置 AI 落地应用灵感。如果您也想将自己的实践案例与更多开发者分享,欢迎报名参与谷歌开发者招募活动,积累资源和开发经验,收获灵感和惊喜,探索技术的无限可能!

Image

扫描二维码提交报名

和伙伴们一起探索 Google 技术


Image 点击屏末| 阅读原文 |即刻报名谷歌开发者招募活动

Image

Image

Image