Chrome 137 中的 Gemini Nano:写给 AI 工程师的笔记
原文由 Shawn Wang 于 发布,订阅该博客
总算等到了,Gemini Nano 马上就要面向所有 Chrome 用户开放了(我最早被误导以为是在 Chrome 138——但我自己核实了一下,从 Chrome 137 开始,它已经在部分场景下开始无需 flag 即可使用)。我是被这篇 HN 帖子提醒的。预计到年底就会完全默认开放。
我不太喜欢 Google 写文档的方式,所以这篇博文基本上就是我按自己的思路把他们的文档重写了一遍。
他们提供了几个针对常用场景的 API,但说实话,作为工程师你真正会关心的,主要还是最灵活、最开放的那个——Prompt API。
配置
和当初过度承诺的 window.ai 不同(它还催生了一堆仿制的垫片,比如 xander 和 chromeai,现在都没人维护了),现在正式发布的实现可没那么“优雅”。总之,下面是目前的配置方法。
- 确保你装的是 Chrome 137 及以上版本
- 前往 chrome://flags/#prompt-api-for-gemini-nano 并启用(遗憾的是需要重启 Chrome)
- 然后首次调用
LangaugeModel.create()来下载模型——在家用 Wi-Fi 下大概要几分钟。Gemini 说“下载大小约为 1.5 GB 至 2.4 GB”,这么看大概是个 4 到 60 亿参数、做了 4 到 8 比特量化的模型。
const session = await LanguageModel.create({
monitor(m) {
m.addEventListener("downloadprogress", (e) => {
console.log(`Downloaded ${e.loaded * 100}%`);
});
},
// // uncomment if want multimodal input https://developer.chrome.com/docs/ai/prompt-api#multimodal_capabilities
// expectedInputs: [
// { type: "audio" },
// { type: "image" }
// ]
})需要了解的基础要点
加载后的模型上下文是 6k token(不带任何 initialPrompts 直接查 inputQuota 就能看到):
session.inputQuota
// 6144和 Gemini Nano 团队不同,我恰好是个认为函数调用 / JSON 输出非常重要的人,所以来看看在 Gemini Nano 里怎么实现这个,prompt 示例搬自 Hamel 和 Jason:
const JSONschema = `<schema>
{
"description": "Correctly extracted \`UserDetail\` with all the required parameters with correct types",
"name": "UserDetail",
"parameters": {
"properties": {
"age": {
"title": "Age",
"type": "integer"
},
"name": {
"title": "Name",
"type": "string"
}
},
"required": [
"age",
"name"
],
"type": "object"
}
}
</schema>`
const JSONsession = await LanguageModel.create({
initialPrompts: [
{ role: 'system', content: 'You are a helpful LLM that only responds in valid JSON fitting a schema: ' + JSONschema },
{ role: 'user', content: "Extract Jason is 35 years old" },
{ role: 'assistant', content: '{age: 35, name: Jason}'},
]
});
const result1 = await JSONsession.prompt("Extract sarah is 22 years old");
console.log(result1);
// {age: 22, name: Sarah}坑点
它的指令遵循能力不太好,所以必填字段其实并不会被严格遵守:
const result1 = await JSONsession.prompt("its been a year since vibhu's birthday, he was 28 last year, guess how old he is now");
console.log(result1);
// { "age": 29 }另一点是,session 默认是有状态的,如果忘了这点会很坑。所以一个无状态的版本大概长这样:
const baseSession = await LanguageModel.create({
initialPrompts: // blah blah, as above
})
// you can also implement this as a class if you want to force users to use`new` keyword to make super clear it is stateless
const statelessSession = {
async prompt(str) {
const clonedSession = await session.clone()
return clonedSession.prompt(str)
}
}
// these are all stateless calls now! yay repeatability and predictability!
const result1 = await statelessSession.prompt("Extract sarah is 22 years old");
console.log(result1);
const result2 = await statelessSession.prompt("Extract tanisha is 30 years old");
console.log(result2);正是因为这些坑,你大概会想自己手写一个小的封装库,或者参考 https://github.com/kstonekuan/simple-chromium-ai
最后,给不熟悉 JS 的同学一个小技巧:如何在浏览器环境中(也就是不用 npm install 或打包步骤)用 ESM 语法引入这些封装库(可能需要 <script type="module">——在 localhost 或 CSP 比较宽松的网站上运行):
// alternatively use https://cdn.jsdelivr.net/npm/[email protected]/dist/simple-chromium-ai.mjs
const ChromiumAI = await import('https://unpkg.com/[email protected]/dist/simple-chromium-ai.mjs');
const ai = await ChromiumAI.initialize("You are a friendly assistant");
const response = await ChromiumAI.prompt(ai, "Tell me a joke");
console.log(response);
const ChromiumAI = await import('https://unpkg.com/[email protected]/dist/simple-chromium-ai.mjs');
const ai = await ChromiumAI.initialize("You are a friendly assistant");
const response = await ChromiumAI.prompt(ai, "Tell me a joke");
console.log(response);
// Why don't scientists trust atoms? Because they make up everything!
// and of course... the structured output implementation now works:
const schema = {
type: "object",
properties: {
sentiment: {
type: "string",
enum: ["positive", "negative", "neutral"]
},
confidence: {
type: "number",
minimum: 0,
maximum: 1
},
keywords: {
type: "array",
items: { type: "string" },
maxItems: 5
}
},
required: ["sentiment", "confidence", "keywords"]
};
// Create session with response constraint
const response = await ChromiumAI.prompt(
ai,
"Analyze the sentiment of this text: 'I love this new feature!'",
undefined, // no timeout
{ responseConstraint: schema }
);
// Response will be valid JSON matching the schema
const result = JSON.parse(response);
console.log(result);随机一篇博客
评论
登录后参与讨论