mirror of
https://github.com/GoogleChrome/chrome-extensions-samples.git
synced 2026-03-26 13:19:49 +07:00
add Gemini API sample (#1240)
* add Gemini API sample * Simplify configuration and fix response formatting * Update wording for gemini nano sample
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ node_modules
|
||||
# Temporary directory for debugging extension samples
|
||||
_debug
|
||||
_metadata
|
||||
*.swp # vim temp files
|
||||
|
||||
1
functional-samples/ai.gemini-in-the-cloud/.gitignore
vendored
Normal file
1
functional-samples/ai.gemini-in-the-cloud/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
dist
|
||||
23
functional-samples/ai.gemini-in-the-cloud/README.md
Normal file
23
functional-samples/ai.gemini-in-the-cloud/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# On-device AI with Gemini Nano
|
||||
|
||||
This sample demonstrates how to use the Gemini Cloud API in a Chrome Extension.
|
||||
|
||||
## Overview
|
||||
|
||||
The extension provides a chat interface for the Gemini API. To learn more about the API head over to [https://ai.google.dev/](https://ai.google.dev/).
|
||||
|
||||
## Running this extension
|
||||
|
||||
1. Clone this repository.
|
||||
2. Download the Gemini API client by running:
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
3. [Retrieve an API key](https://ai.google.dev/gemini-api/docs/api-key) and update [functional-samples/ai.gemini-in-the-cloud/sidepanel/index.js](functional-samples/ai.gemini-in-the-cloud/sidepanel/index.js) (only for testing).
|
||||
4. Compile the JS bundle for the sidepanel implementation by running:
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
5. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).
|
||||
6. Click the extension icon.
|
||||
7. Interact with the prompt API in the sidebar.
|
||||
3
functional-samples/ai.gemini-in-the-cloud/background.js
Normal file
3
functional-samples/ai.gemini-in-the-cloud/background.js
Normal file
@@ -0,0 +1,3 @@
|
||||
chrome.sidePanel
|
||||
.setPanelBehavior({ openPanelOnActionClick: true })
|
||||
.catch((error) => console.error(error));
|
||||
BIN
functional-samples/ai.gemini-in-the-cloud/images/icon128.png
Normal file
BIN
functional-samples/ai.gemini-in-the-cloud/images/icon128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
BIN
functional-samples/ai.gemini-in-the-cloud/images/icon16.png
Normal file
BIN
functional-samples/ai.gemini-in-the-cloud/images/icon16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 267 B |
BIN
functional-samples/ai.gemini-in-the-cloud/images/icon32.png
Normal file
BIN
functional-samples/ai.gemini-in-the-cloud/images/icon32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 458 B |
BIN
functional-samples/ai.gemini-in-the-cloud/images/icon48.png
Normal file
BIN
functional-samples/ai.gemini-in-the-cloud/images/icon48.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 890 B |
22
functional-samples/ai.gemini-in-the-cloud/manifest.json
Normal file
22
functional-samples/ai.gemini-in-the-cloud/manifest.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "Google Gemini Demo",
|
||||
"version": "0.1",
|
||||
"manifest_version": 3,
|
||||
"description": "Try the Gemini Models.",
|
||||
"background": {
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"permissions": ["sidePanel"],
|
||||
"side_panel": {
|
||||
"default_path": "sidepanel/index.html"
|
||||
},
|
||||
"action": {
|
||||
"default_icon": {
|
||||
"16": "images/icon16.png",
|
||||
"32": "images/icon32.png",
|
||||
"48": "images/icon48.png",
|
||||
"128": "images/icon128.png"
|
||||
},
|
||||
"default_title": "Open Chat Interface"
|
||||
}
|
||||
}
|
||||
288
functional-samples/ai.gemini-in-the-cloud/package-lock.json
generated
Normal file
288
functional-samples/ai.gemini-in-the-cloud/package-lock.json
generated
Normal file
@@ -0,0 +1,288 @@
|
||||
{
|
||||
"name": "Chrome Extensions Gemini Demo",
|
||||
"version": "1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "Chrome Extensions Gemini Demo",
|
||||
"version": "1.0",
|
||||
"devDependencies": {
|
||||
"@google/generative-ai": "0.15.0",
|
||||
"rollup": "4.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@google/generative-ai": {
|
||||
"version": "0.15.0",
|
||||
"resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.15.0.tgz",
|
||||
"integrity": "sha512-zs37judcTYFJf1U7tnuqnh7gdzF6dcWj9pNRxjA5JTONRoiQ0htrRdbefRFiewOIfXwhun5t9hbd2ray7812eQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.0.tgz",
|
||||
"integrity": "sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.0.tgz",
|
||||
"integrity": "sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.0.tgz",
|
||||
"integrity": "sha512-emvKHL4B15x6nlNTBMtIaC9tLPRpeA5jMvRLXVbl/W9Ie7HhkrE7KQjvgS9uxgatL1HmHWDXk5TTS4IaNJxbAA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.0.tgz",
|
||||
"integrity": "sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.0.tgz",
|
||||
"integrity": "sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.0.tgz",
|
||||
"integrity": "sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.0.tgz",
|
||||
"integrity": "sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.0.tgz",
|
||||
"integrity": "sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.0.tgz",
|
||||
"integrity": "sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.0.tgz",
|
||||
"integrity": "sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.0.tgz",
|
||||
"integrity": "sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.0.tgz",
|
||||
"integrity": "sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.0.tgz",
|
||||
"integrity": "sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.0.tgz",
|
||||
"integrity": "sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.0.tgz",
|
||||
"integrity": "sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.0.tgz",
|
||||
"integrity": "sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.19.0.tgz",
|
||||
"integrity": "sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.5"
|
||||
},
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.19.0",
|
||||
"@rollup/rollup-android-arm64": "4.19.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.19.0",
|
||||
"@rollup/rollup-darwin-x64": "4.19.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.19.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.19.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.19.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.19.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.19.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.19.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.19.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.19.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.19.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.19.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.19.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.19.0",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
functional-samples/ai.gemini-in-the-cloud/package.json
Normal file
12
functional-samples/ai.gemini-in-the-cloud/package.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Chrome Extensions Gemini Demo",
|
||||
"version": "1.0",
|
||||
"scripts": {
|
||||
"build": "rollup sidepanel/index.js --file dist/sidepanel.bundle.js --format iife"
|
||||
},
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@google/generative-ai": "0.15.0",
|
||||
"rollup": "4.19.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica,
|
||||
Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
||||
color: #1f1f1f;
|
||||
background-color: #f2f2f2;
|
||||
font-size: 16px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
textarea,
|
||||
select {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
button {
|
||||
background: #333;
|
||||
color: white;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
min-width: 100px;
|
||||
padding: 8px;
|
||||
margin: 16px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button.primary {
|
||||
background: #333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
button.secondary {
|
||||
background: #ccc;
|
||||
color: black;
|
||||
}
|
||||
|
||||
button[disabled] {
|
||||
background: #ddd;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
input[type='range'] {
|
||||
margin-top: 16px;
|
||||
accent-color: black;
|
||||
}
|
||||
|
||||
textarea {
|
||||
--padding: 32px;
|
||||
width: calc(100% - var(--padding));
|
||||
max-width: calc(100% - var(--padding));
|
||||
}
|
||||
|
||||
.text,
|
||||
textarea {
|
||||
background-color: white;
|
||||
padding: 16px;
|
||||
border-radius: 16px;
|
||||
box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px, rgb(51, 51, 51) 0px 0px 0px 3px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.blink {
|
||||
animation: 1s ease-in-out 1s infinite reverse both running blink;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
25% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="index.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Google Gemini</h1>
|
||||
<textarea
|
||||
id="input-prompt"
|
||||
placeholder='Type something, e.g. "Write a haiku about Chrome Extensions"'
|
||||
cols="30"
|
||||
rows="5"
|
||||
></textarea>
|
||||
<div>
|
||||
<input
|
||||
type="range"
|
||||
id="temperature"
|
||||
name="temperature"
|
||||
min="0"
|
||||
max="2"
|
||||
step="0.01"
|
||||
value="1"
|
||||
/>
|
||||
<label for="temperature"
|
||||
>Temperature: <span id="label-temperature">1</span></label
|
||||
>
|
||||
</div>
|
||||
<button id="button-prompt" class="primary" disabled>Run</button>
|
||||
<div id="response" class="text" hidden></div>
|
||||
<div id="loading" class="text" hidden><span class="blink">...</span></div>
|
||||
<div id="error" class="text" hidden></div>
|
||||
<script src="../dist/sidepanel.bundle.js" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
127
functional-samples/ai.gemini-in-the-cloud/sidepanel/index.js
Normal file
127
functional-samples/ai.gemini-in-the-cloud/sidepanel/index.js
Normal file
@@ -0,0 +1,127 @@
|
||||
import {
|
||||
GoogleGenerativeAI,
|
||||
HarmBlockThreshold,
|
||||
HarmCategory
|
||||
} from '../node_modules/@google/generative-ai/dist/index.mjs';
|
||||
|
||||
// Important! Do not expose your API in your extension code. You have to
|
||||
// options:
|
||||
//
|
||||
// 1. Let users provide their own API key.
|
||||
// 2. Manage API keys in your own server and proxy all calls to the Gemini
|
||||
// API through your own server, where you can implement additional security
|
||||
// measures such as authentification.
|
||||
//
|
||||
// It is only OK to put your API key into this file if you're the only
|
||||
// user of your extension or for testing.
|
||||
const apiKey = '...';
|
||||
|
||||
let genAI = null;
|
||||
let model = null;
|
||||
let generationConfig = {
|
||||
temperature: 1
|
||||
};
|
||||
|
||||
const inputPrompt = document.body.querySelector('#input-prompt');
|
||||
const buttonPrompt = document.body.querySelector('#button-prompt');
|
||||
const elementResponse = document.body.querySelector('#response');
|
||||
const elementLoading = document.body.querySelector('#loading');
|
||||
const elementError = document.body.querySelector('#error');
|
||||
const sliderTemperature = document.body.querySelector('#temperature');
|
||||
const labelTemperature = document.body.querySelector('#label-temperature');
|
||||
|
||||
function initModel(generationConfig) {
|
||||
const safetySettings = [
|
||||
{
|
||||
category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
|
||||
threshold: HarmBlockThreshold.BLOCK_NONE
|
||||
}
|
||||
];
|
||||
genAI = new GoogleGenerativeAI(apiKey);
|
||||
model = genAI.getGenerativeModel({
|
||||
model: 'gemini-1.5-flash',
|
||||
safetySettings,
|
||||
generationConfig
|
||||
});
|
||||
return model;
|
||||
}
|
||||
|
||||
async function runPrompt(prompt) {
|
||||
try {
|
||||
const result = await model.generateContent(prompt);
|
||||
const response = await result.response;
|
||||
return response.text();
|
||||
} catch (e) {
|
||||
console.log('Prompt failed');
|
||||
console.error(e);
|
||||
console.log('Prompt:', prompt);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
sliderTemperature.addEventListener('input', (event) => {
|
||||
labelTemperature.textContent = event.target.value;
|
||||
generationConfig.temperature = event.target.value;
|
||||
});
|
||||
|
||||
inputPrompt.addEventListener('input', () => {
|
||||
if (inputPrompt.value.trim()) {
|
||||
buttonPrompt.removeAttribute('disabled');
|
||||
} else {
|
||||
buttonPrompt.setAttribute('disabled', '');
|
||||
}
|
||||
});
|
||||
|
||||
buttonPrompt.addEventListener('click', async () => {
|
||||
const prompt = inputPrompt.value.trim();
|
||||
showLoading();
|
||||
try {
|
||||
const generationConfig = {
|
||||
temperature: sliderTemperature.value
|
||||
};
|
||||
initModel(generationConfig);
|
||||
const response = await runPrompt(prompt, generationConfig);
|
||||
showResponse(response);
|
||||
} catch (e) {
|
||||
showError(e);
|
||||
}
|
||||
});
|
||||
|
||||
function showLoading() {
|
||||
hide(elementResponse);
|
||||
hide(elementError);
|
||||
show(elementLoading);
|
||||
}
|
||||
|
||||
function showResponse(response) {
|
||||
hide(elementLoading);
|
||||
show(elementResponse);
|
||||
// Make sure to preserve line breaks in the response
|
||||
elementResponse.textContent = '';
|
||||
const paragraphs = response.split(/\r?\n/);
|
||||
for (let i = 0; i < paragraphs.length; i++) {
|
||||
const paragraph = paragraphs[i];
|
||||
if (paragraph) {
|
||||
elementResponse.appendChild(document.createTextNode(paragraph));
|
||||
}
|
||||
// Don't add a new line after the final paragraph
|
||||
if (i < paragraphs.length - 1) {
|
||||
elementResponse.appendChild(document.createElement('BR'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showError(error) {
|
||||
show(elementError);
|
||||
hide(elementResponse);
|
||||
hide(elementLoading);
|
||||
elementError.textContent = error;
|
||||
}
|
||||
|
||||
function show(element) {
|
||||
element.removeAttribute('hidden');
|
||||
}
|
||||
|
||||
function hide(element) {
|
||||
element.setAttribute('hidden', '');
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
# On-device AI with Gemini Nano
|
||||
|
||||
This sample demonstrates how to use the built-in Chrome Prompt API.
|
||||
This sample demonstrates how to use the experimental Gemini Nano API in Chrome. To learn more about the API and how to sign-up for the preview, head over to [Built-in AI on developer.chrome.com](https://developer.chrome.com/docs/ai/built-in).
|
||||
|
||||
## Overview
|
||||
|
||||
The extension provides a chat interface for the built-in Chrome prompt API. To learn more about the API and how to sign-up for the preview, head over to [Built-in AI on developer.chrome.com](https://developer.chrome.com/docs/ai/built-in).
|
||||
The extension provides a chat interface using the prompt API with Chrome's built-in Gemini Nano model.
|
||||
|
||||
## Running this extension
|
||||
|
||||
|
||||
Reference in New Issue
Block a user