語言模型

網頁功能: LanguageModel

開發人員可透過 Prompt API,使用 Gemini Nano 直接在瀏覽器中執行自然語言處理工作。這種內建 AI 的做法可確保使用者隱私、降低伺服器成本,並啟用離線功能。

1. 入門指南和硬體需求

Prompt API 目前適用於 Chrome 148 以上版本 (電腦版),支援 Windows、macOS、Linux 和 Chromebook Plus。

硬體必要條件

  • 儲存空間:22 GB 可用空間 (用於初始設定檔和模型)。
  • 記憶體/CPU:16 GB RAM 和 4 個以上的 CPU 核心。
  • GPU:4 GB VRAM 以上 (音訊輸入必備)。
  • 網路:只有在初次下載模型時才需要。

初始化 API

觸發下載前,請先檢查模型是否可用:

const availability = await LanguageModel.availability();

// Do not call create() when unavailable — the model cannot run on this device.
if (availability !== 'unavailable') {
    const session = await LanguageModel.create({
        monitor(m) {
            // Inform the user while the model downloads so the UI doesn't appear frozen.
            m.addEventListener('downloadprogress', (e) => {
                console.log(`Downloaded ${e.loaded * 100}%`);
            });
        },
    });
}

2. 核心提示功能

為求簡潔,本節的工作階段範例會省略 session.destroy()。不再需要工作階段時,請務必呼叫 session.destroy(),釋出裝置記憶體 (請參閱第 5 節)。

基本和串流輸出

如果是簡短回覆,請使用 prompt()。如要顯示較長的內容,請使用 promptStreaming() 提供回應更快速的使用者介面。

強制:請勿將模型輸出內容指派給 innerHTML。模型輸出內容不受信任,可能含有插入的標記。請一律使用 textContent 或淨化器。

const session = await LanguageModel.create();

// prompt() accumulates the full response before resolving — use for short, one-shot output.
const result = await session.prompt('Write a haiku about coding.');
// textContent, not innerHTML — model output is untrusted and must not be parsed as markup.
outputEl.textContent = result;

// promptStreaming() yields independent chunks that must be concatenated;
// use for longer content so each chunk can be rendered progressively.
const stream = session.promptStreaming('Write a long story about a robot.');
let completeResult = '';
for await (const chunk of stream) {
    completeResult += chunk;
    outputEl.append(chunk);
}
console.log('Full story:', completeResult);

多模態輸入

Prompt API 支援文字、音訊和視覺輸入內容 (圖片、畫布、影片影格)。

const session = await LanguageModel.create({
    // Declaring expected input types lets the browser optimize model loading.
    expectedInputs: [{ type: 'text' }, { type: 'image' }],
    expectedOutputs: [{ type: 'text' }],
});

const response = await session.prompt([
    {
        role: 'user',
        content: [
            { type: 'text', value: 'What is in this image?' },
            { type: 'image', value: document.querySelector('canvas') },
        ],
    },
]);

3. 進階工作階段管理

工作階段可讓模型在多次互動中維持脈絡。

背景資訊和配額

每個工作階段都有權杖數量上限。您可以透過 session.contextUsage 和 session.contextWindow 監控用量。如果視窗溢位,系統會捨棄最舊的訊息 (系統提示除外)。

複製工作階段

複製功能可有效率地啟動平行對話,共用相同的初始情境 (例如「系統」角色),不必重新初始化。

const mainSession = await LanguageModel.create({
    initialPrompts: [{ role: 'system', content: 'You speak like a pirate.' }],
});

const branchA = await mainSession.clone();
const branchB = await mainSession.clone();
// Destroy the base after cloning — the clones own their own context from here.
mainSession.destroy();

還原過往工作階段

原生「還原」功能仍在開發中,但您可以將先前的記錄提供給 initialPrompts,重新建立工作階段。

注意:localStorage 未加密且會永久保存。儲存的對話記錄可能包含使用者 PII,因此在保留即時通訊記錄前,請考量隱私權影響。

// || '[]' ensures JSON.parse never receives null when the key doesn't exist yet.
const history = JSON.parse(localStorage.getItem('chat_history') || '[]');
const session = await LanguageModel.create({
    initialPrompts: history, // Array of {role, content} objects
});

4. 使用 JSON 結構定義輸出結構化內容

為避免模型加入「閒聊」內容 (例如「好的,這是您的 JSON:」),請透過 responseConstraint 欄位使用 JSON 結構定義。這可確保輸出內容是有效的 JSON,能立即剖析。

範例:情緒分類

// Pass the schema as a plain object — do not JSON.stringify() it first.
const schema = {
    type: 'object',
    properties: {
        rating: { type: 'number', minimum: 1, maximum: 5 },
        is_positive: { type: 'boolean' },
    },
    required: ['rating', 'is_positive'],
};

const result = await session.prompt(
    "Rate the following feedback: 'The food was great!'",
    { responseConstraint: schema },
);

const data = JSON.parse(result);
console.log(data.rating); // 5

限制和前置字元

您可以使用 prefix: true 預先填入助理的回覆,進一步引導模型。

const character = await session.prompt([
    { role: 'user', content: 'Create a character sheet' },
    { role: 'assistant', content: '```json\n', prefix: true },
]);

5. 最佳做法和安全

  • 資源清理:對話結束時,請務必呼叫 session.destroy(),釋出記憶體。
  • 輸出內容安全性:模型輸出內容不可信。請一律將結果寫入 textContent,而非 innerHTML,以免惡意模型輸出內容注入 XSS。
  • 如需允許有限的 HTML,請使用原生 Sanitizer API 或 DOMPurify 等淨化工具。
  • 中止工作:使用 AbortController,讓使用者停止長時間執行的生成作業。將 signal 傳遞至 prompt() 或 promptStreaming(),而非 LanguageModel.create()。
  • 安全性:使用權限政策控管 iframe 中的存取權:<iframe src="..." allow="language-model"></iframe>。
  • 設計:詳閱 People + AI Guidebook,確保以負責任的方式導入 AI。

結合結構化輸出內容和強大的工作階段管理功能,開發人員就能建構複雜的有狀態 AI 應用程式,完全在使用者裝置上執行。

建議做法

如需完整的注意事項清單,請參閱 https://developer.chrome.com/docs/ai/built-in-ai-dos-donts.md.txt。以下是重點摘要:

在合理的時間準備模型

適用對象:所有 API,例如 Summarizer、Translator 和 Writer。

建議做法:一旦明確確認使用者有意使用 AI 功能,就立即初始化工作階段。例如,使用者前往相關 AI 工具介面、將滑鼠游標懸停在 AI 工作區上,或與功能周圍的 UI 互動時。預先暖機工作階段可讓模型在使用者設定工作時,在背景安靜地載入記憶體,避免冷啟動延遲。舉例來說,如果功能設計為反覆使用,請在開始算繪目前結果時,立即啟動下一個最可能的 AI 任務,盡可能提前完成。

不建議:除非必要,否則請勿等到使用者點選「生成」才初始化工作階段。這會導致冷啟動延遲,因為模型必須先載入記憶體,並準備執行管道。

在建立時設定初始提示

適用對象:Prompt API。

建議做法:在工作階段初始化期間提供系統指令,加快第一個提示的處理速度。

不建議:從空白工作階段開始,並在第一次 prompt() 呼叫中傳送系統指令。這會迫使模型在最後一刻處理這些指令,因此會增加延遲時間。

複製工作階段,處理重複性工作

適用對象:Prompt API。

在 Prompt API 中,每個工作階段都會追蹤對話的背景資訊,並考量所有先前的互動。由於複製工作階段會繼承父項工作階段的所有內容,包括初始提示和複製前的所有互動記錄,因此請妥善規劃,僅繼承所需內容。

建議做法:

  • 建立基本工作階段:如要有效處理不相關的工作,請建立基本工作階段,其中只包含系統指令,不含先前的對話內容。
  • 複製基準:在新任務中使用 clone() 複製基準工作階段,省去重新剖析系統指令的負擔。這樣就能建立平行對話,或將工作重設為基準。

錯誤做法:

  • 請勿將同一個工作階段重複用於不相關的工作,也避免複製已包含不必要互動記錄的工作階段。這兩種模式都可能導致不相關的先前內容干擾目前的工作。
  • 請勿使用相同的系統指令重複呼叫 create()。請改用複製模式,盡可能提高效能。

刪除未使用的工作階段

適用對象:所有 API。

建議做法:在不再需要的功能工作階段中,明確呼叫 destroy(),釋出記憶體。如果使用複製模式,請保留基本工作階段,並刪除不再需要的複製工作階段。

不建議:同時執行多個大型工作階段。每個工作階段都會耗用記憶體,造成不必要的資源用量,並可能成為問題。工作階段會由垃圾收集器自然清除,但呼叫 destroy() 可更快釋出記憶體。

安全有效率地轉譯串流回應

適用對象:所有支援串流的 API (Prompt、Summarizer、Writer、Rewriter 和 Translator)。

建議做法:將所有 LLM 輸出內容視為不可信內容。請清理完整的合併輸出內容,而非僅清理部分內容,因為惡意程式碼可能會分散在不同更新中。在轉譯前,請盡可能使用 Sanitizer API。為避免效能降低,請使用串流 Markdown 剖析器,例如 streaming-markdown。

不建議:在每次更新區塊時直接設定 innerHTML。這種做法速度緩慢,尤其是語法醒目顯示等複雜格式,而且容易受到插入攻擊。

最佳化輸入速度

適用對象:所有 API。

建議做法:只將絕對必要的資訊傳遞給模型。去除與手邊任務無關的所有內容。如果是大型資料集,請提供簡短總覽和一小部分相關項目。

不建議:將未經處理的原始文字、不必要的中繼資料、HTML 代碼或未經篩選的大型清單傳送至 API。延遲時間會隨著輸入內容大小而大幅增加,這可能會讓 AI 功能在許多裝置上看起來像是故障。

使用結構化輸出內容,取得可預測的結果

適用對象:Prompt API。

建議做法:如需模型以特定格式傳回資料,請提供 responseConstraint 欄位來提供 JSON 結構定義,使用結構化輸出。這可確保輸出內容符合預期,避免需要複雜的後續處理或手動剖析。

不建議:僅仰賴自然語言指令 (例如「僅輸出 JSON」)。模型可能會加入對話填充詞,導致剖析器中斷。

生成內容不受長度限制

適用對象:Prompt API,因為這是唯一支援結構化輸出結構定義的 API。

建議做法:讓模型自然生成回覆,然後使用用戶端邏輯截斷文字,以符合 UI。

不建議:使用結構化輸出結構定義,強制執行 maxLength: 125 等嚴格的字元限制。如果模型的回覆長度超過設定的限制,模型可能會切換至高密度詞元 (例如外語或表情符號) 來壓縮含義,導致輸出內容不合理。

確保使用者知情

適用對象:所有 API。

建議做法:視工作的複雜度和預期時間長度,使用動畫、視覺提示和進度指標,讓使用者瞭解進度。最佳做法取決於您的用途和預期的 API 輸出長度。這裡提供一些想法:

  • 串流長篇內容:如果是摘要或對話,串流預設會建立逐詞打字機效果。這種方式感覺自然,且能立即提供意見回饋。
  • 非串流模式適合短任務 (或長時間非同步任務):如果輸出內容較短 (例如替代文字),非串流模式可提供更精緻的使用者介面。此外,在算繪目前 AI 任務時,也有時間預先準備下一個 AI 任務。這種做法也適用於較長的非同步或背景工作。如果使用者不必等待輸出內容,就能繼續操作,則不必在輸出內容產生時立即提供。在 UI 中顯示程序正在進行。
  • 更新時的視覺轉場效果:翻譯或重寫文字時,請使用動畫,例如文字變形。

不建議:更新 UI 時不提供視覺提示。

符合使用者對時間和工作的心理模型

適用對象:所有 API。

建議做法:如果回覆幾乎是即時,請考慮人工延遲一或兩秒。矛盾的是,如果使用者認為生成過程與他們認知的任務難度相符,可能會覺得結果更值得信賴。使用動畫表示 AI 處理中。

不建議:突然更換 UI,讓使用者措手不及。

允許使用者快速瀏覽及復原 AI 編輯內容

適用對象:所有 API。

建議做法:在 UI 中加入步進器或導覽記錄,讓使用者能放心探索不同結果,並快速復原 AI 編輯內容。這樣一來,您仍可輕鬆取得不同版本。

不建議:覆寫使用者先前的草稿,或他們可能喜歡的 AI 結果,卻無法返回、還原或比較版本。

賦予使用者控制權和覆寫權

適用對象:所有 API。

建議做法:讓使用者成為所有生成內容的最終編輯者。提供直覺式的覆寫功能,讓使用者能完全掌控最終輸出內容。API 可能會產生不正確的結果。

不建議:強制將 AI 生成結果設為唯一選項。

快取週期性工作的結果

適用對象:所有 API。

建議做法:針對重複的輸入內容或查詢,導入本機結果快取 (例如使用 sessionStorage 或 IndexedDB)。修剪空白字元並轉換為小寫,將輸入內容正規化,提高快取命中率。如果是耗用大量資源的輸入內容 (例如圖片),請產生雜湊做為快取鍵。為快取設定保守的存留時間 (TTL),或在背景更新快取結果時提供快取結果。如果結果不盡人意,請讓使用者觸發新的推論。

不建議:針對重複的搜尋查詢或相同的資料輸入,重新執行相同的推論,例如使用者在搜尋結果之間來回瀏覽時。 這能盡量提升回應速度,並有效運用本機運算資源。

6. 備用策略

使用前,請檢查 LanguageModel 物件是否可在全域範圍內使用:

if ('LanguageModel' in self) {
  // The Prompt API is supported.
} else {
  // Execute fallback strategy
}

如果系統不支援 Prompt API,或可用性檢查傳回「無法使用」,請採取適當的備用方案:

  • 遠端 API 備用方案:將偵測要求重新導向至伺服器端點或雲端 API (例如 Vertex AI Gemini API)。
  • 本機 API 備用方案:將偵測要求重新導向至本機端點,例如使用 Transformers.js。