🌏
Google Chrome内蔵のAI Gemini Nanoを試してみる
Chrome 内蔵の Gemini Nano を試してみる
Gemini Nano は Chrome に内蔵された AI で簡易的な AI 機能をオフラインで利用できるので試してみました。
Gemini Nano を有効化する
Chrome Ver.126 から内蔵されていますが、デフォルトでは無効化されているので有効化する必要があります。
Experimental flag を変更
chrome://flags/#optimization-guide-on-device-model
Default
から Enabled BypassPerfRequirement
に変更
chrome://flags/#prompt-api-for-gemini-nano
Default
から Enabled
に変更
コンポーネントをインストール
chrome://componentsを開いて、 Optimization Guide On Device Model
をアップデートする。
Optimization Guide On Device Model が無い場合
F12 を押して開発者ツールを開いて、コンソールに以下のコマンドを入力
await ai.languageModel.create();
エラーが出て来るけど、これでコンポーネントに Optimization Guide On Device Model
の項目が追加された。
Uncaught InvalidStateError: The session cannot be created.
翻訳 AI サンプルコード
日本語から英語への翻訳をしながらチャットみたいにログが表示されるサンプルコードを作ってみました。
コピペして HTML ファイルに保存して Chrome で開いたら使えます。もちろんオフライン環境でも。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Translate</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 min-h-screen flex flex-col items-center py-6">
<h1 class="text-2xl font-bold text-gray-800 mb-4">
Gemini Nano Chrome内蔵AIテスト
</h1>
<!-- 設定手順エリア -->
<div id="setupInstructions" class="w-full max-w-3xl mb-6 hidden">
<div
class="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4 rounded-lg shadow-md"
>
<h3 class="font-bold mb-2">
Gemini Nanoの準備ができていません。以下の手順を実行してください。
</h3>
<ul class="list-disc pl-5 space-y-2">
<li>
<a
href="chrome://flags/#optimization-guide-on-device-model"
target="_blank"
class="text-blue-600 underline"
>chrome://flags/#optimization-guide-on-device-model</a
>
を開き、<code>Default</code> から
<code>Enabled BypassPerfRequirement</code> に変更。
</li>
<li>
<a
href="chrome://flags/#prompt-api-for-gemini-nano"
target="_blank"
class="text-blue-600 underline"
>chrome://flags/#prompt-api-for-gemini-nano</a
>
を開き、<code>Default</code> から <code>Enabled</code> に変更。
</li>
<li>
<a
href="chrome://components"
target="_blank"
class="text-blue-600 underline"
>chrome://components</a
>
を開き、<strong>Optimization Guide On Device Model</strong>
をアップデートする。
</li>
</ul>
</div>
</div>
<div class="w-full max-w-3xl bg-white shadow-md rounded-lg p-6">
<!-- 開閉可能なシステムプロンプト設定 -->
<div class="mb-6">
<button
id="togglePromptButton"
class="w-full text-left px-4 py-2 bg-gray-100 text-gray-700 font-medium rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500"
>
システムプロンプト設定を表示
</button>
<div id="systemPromptContainer" class="mt-4 hidden">
<textarea
id="systemPrompt"
class="w-full p-3 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"
rows="4"
></textarea>
<button
id="updatePromptButton"
class="mt-3 px-4 py-2 bg-indigo-600 text-white text-sm font-medium rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500"
>
システムプロンプトを更新
</button>
</div>
</div>
<!-- 入力フィールド -->
<div class="mb-6">
<label for="input" class="block text-sm font-medium text-gray-700 mb-2">
翻訳するテキスト
</label>
<div class="flex">
<input
type="text"
id="input"
placeholder="テキストを入力してください"
class="flex-grow p-3 border border-gray-300 rounded-l-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"
/>
<button
id="translateButton"
class="px-4 py-2 bg-indigo-600 text-white text-sm font-medium rounded-r-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500"
>
送信
</button>
</div>
</div>
<!-- ログエリア -->
<div
id="log"
class="bg-gray-50 p-4 border border-gray-300 rounded-md shadow-sm overflow-y-auto max-h-96"
>
<p id="emptyLogMessage" class="text-sm text-gray-500">
ここに翻訳結果が表示されます。
</p>
</div>
</div>
<script>
let aiSession = null;
const translationQueue = [];
let isProcessing = false;
const defaultSystemPrompt =
"Translate the following Japanese text into English without adding any explanation or context. Only provide the translated text.";
async function initializeAI() {
const systemPrompt = document.getElementById("systemPrompt").value;
try {
const capabilities = await window.ai.languageModel.capabilities();
console.log("Capabilities:", capabilities);
if (!capabilities.available) {
displaySetupInstructions();
return;
}
aiSession = await window.ai.languageModel.create({
systemPrompt,
});
} catch (error) {
console.error("AI Initialization Error:", error);
displaySetupInstructions();
}
}
function displaySetupInstructions() {
const setupInstructions = document.getElementById("setupInstructions");
setupInstructions.classList.remove("hidden");
}
function updateSystemPrompt() {
aiSession = null;
initializeAI();
alert("システムプロンプトを更新しました。");
}
function toggleSystemPrompt() {
const container = document.getElementById("systemPromptContainer");
const button = document.getElementById("togglePromptButton");
if (container.classList.contains("hidden")) {
container.classList.remove("hidden");
button.textContent = "システムプロンプト設定を隠す";
} else {
container.classList.add("hidden");
button.textContent = "システムプロンプト設定を表示";
}
}
function toggleEmptyLogMessage() {
const log = document.getElementById("log");
const emptyLogMessage = document.getElementById("emptyLogMessage");
if (log.children.length > 1) {
emptyLogMessage.style.display = "none";
} else {
emptyLogMessage.style.display = "block";
}
}
function queueTranslation(inputText) {
const log = document.getElementById("log");
const logEntry = document.createElement("div");
logEntry.innerHTML = ``;
log.prepend(logEntry);
toggleEmptyLogMessage();
translationQueue.push({ inputText, logEntry });
processQueue();
}
async function processQueue() {
if (isProcessing || translationQueue.length === 0) return;
isProcessing = true;
const { inputText, logEntry } = translationQueue.shift();
try {
const result = await aiSession.prompt(inputText);
logEntry.innerHTML = ``;
} catch (error) {
console.error("Translation Error:", error);
logEntry.innerHTML = ``;
} finally {
isProcessing = false;
processQueue();
}
}
document.addEventListener("DOMContentLoaded", () => {
document.getElementById("systemPrompt").value = defaultSystemPrompt;
initializeAI();
document
.getElementById("updatePromptButton")
.addEventListener("click", updateSystemPrompt);
document
.getElementById("togglePromptButton")
.addEventListener("click", toggleSystemPrompt);
document
.getElementById("translateButton")
.addEventListener("click", () => {
const input = document.getElementById("input").value.trim();
if (input) {
queueTranslation(input);
document.getElementById("input").value = "";
}
});
document
.getElementById("input")
.addEventListener("keydown", (event) => {
if (event.key === "Enter") {
const input = document.getElementById("input").value.trim();
if (input) {
queueTranslation(input);
document.getElementById("input").value = "";
}
}
});
toggleEmptyLogMessage();
});
</script>
</body>
</html>
Discussion