mirror of
https://github.com/GoogleChrome/chrome-extensions-samples.git
synced 2026-03-27 13:29:34 +07:00
Improve prompt API sample (#1344)
* Improve prompt API sample * Render response as markdown * Fix initial maxK and temperature values * Add privacy statement (for webstore submission) * Regenerate key and trial token * fix formatting errors * Update functional-samples/ai.gemini-on-device/sidepanel/index.js Update maxTemperature Co-authored-by: Thomas Steiner <tomac@google.com> * Update functional-samples/ai.gemini-on-device/sidepanel/index.js Better string comparison Co-authored-by: Thomas Steiner <tomac@google.com> --------- Co-authored-by: Thomas Steiner <tomac@google.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,4 +4,5 @@ node_modules
|
|||||||
# Temporary directory for debugging extension samples
|
# Temporary directory for debugging extension samples
|
||||||
_debug
|
_debug
|
||||||
_metadata
|
_metadata
|
||||||
|
dist
|
||||||
*.swp # vim temp files
|
*.swp # vim temp files
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
_archive
|
_archive
|
||||||
third-party
|
third-party
|
||||||
node_modules
|
node_modules
|
||||||
|
dist
|
||||||
|
|||||||
3
functional-samples/ai.gemini-on-device/.gitignore
vendored
Normal file
3
functional-samples/ai.gemini-on-device/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
dist
|
||||||
|
node_modules
|
||||||
|
*.swp
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "Chrome Built-in AI Demo",
|
"name": "Chrome Prompt AI Demo",
|
||||||
"version": "0.1",
|
"version": "0.1",
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"description": "Try the built-in AI preview in Chrome.",
|
"description": "Try Chrome's built-in prompt API.",
|
||||||
"background": {
|
"background": {
|
||||||
"service_worker": "background.js"
|
"service_worker": "background.js"
|
||||||
},
|
},
|
||||||
"permissions": ["sidePanel", "aiLanguageModelOriginTrial"],
|
"permissions": ["sidePanel", "aiLanguageModelOriginTrial"],
|
||||||
"trial_tokens": ["A6hC1yvazc5QTqSESgEo3uwIUs1KBM4VB93yiTdtgFlFlYNJjf18zmzScpaCepaYpNLaMJ4dNkDps+vbrk7oEw8AAAB9eyJvcmlnaW4iOiAiY2hyb21lLWV4dGVuc2lvbjovL2lkZm1qYmJqY21qamtoYWlvZmltbWNtY29qYmlnbmpmIiwgImZlYXR1cmUiOiAiQUlQcm9tcHRBUElGb3JFeHRlbnNpb24iLCAiZXhwaXJ5IjogMTk4OTQwNzUwMH0="],
|
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvf0O/bR3JULoj6dOpG7sDif4BNVgootUIfSybh2a7jX47BglfZFNH/aRUgDjNtcTBPinXdGbljMVIudQ7w6LiwVq9b1Ht6ZXFVtHTKOsDWtVh/rVKE/AGue9eQ7xCncHFl4zLJUaDRUIRqe5zvjHtaMr8p92I3c/6k43LmTUp1QHz0NooDJRYKRPLS77YVDX8hZc2yopIH5NIY25Ned3wxZ/NWV70GZkYqFRN+UzvMS8bJUEY23L1AMSX7YQjMThY0BCZ/MBLo8UBLs8vN11EphMpLxnBhF2Zwwj2sCPR0jn0ev8HYCtKmGx8nzOl79oK24RFIsW8YWFB2fd28fBLwIDAQAB",
|
||||||
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi99ZKuRYfZMQ80XryBYKNA4DJTHPMEiNkiF6TLqTXMp4Cb23I/DTblxlEELWyM1vDuXeFI7jqXDuM6YVHd7zTtA1hGbGgLm9w9+d763x2wCRbxud+dXIXW4IoD4CqXpCLscDD7Vrar/I5XbcmdA9jjlCXMGS2OKNRhYMjNpaVhFCi2jzWid+92DZSpPbdM9iBODGfwnFNp16tFX8/dDx3w23FneeOVHV3JjNIWO3uT60AhZWOtcQlERuMBJmEkKAgqE8T3ZjoZe4ALupfvDxI7khP29+gBXhgF/r6T0RAbB1LfxubhyLk/X7aC/sw3umCemqvc+knvKRBLHMVl1nHQIDAQAB",
|
"trial_tokens": ["Aozzz6KfHYqh8q5x+Khse27nSp8YM7Tftv6XZhNO7lgYcP5uQxxBEpMfRhiFbYJV+yJl1fDNzvtao7FswtZGIgQAAAB4eyJvcmlnaW4iOiJjaHJvbWUtZXh0ZW5zaW9uOi8vYWhpaWZrb2RnbWlmcGNnbmRja3BwaW1lY25wa3BkbGwiLCJmZWF0dXJlIjoiQUlQcm9tcHRBUElGb3JFeHRlbnNpb24iLCJleHBpcnkiOjE3NjA0ODYzOTl9"],
|
||||||
"minimum_chrome_version": "131",
|
"minimum_chrome_version": "131",
|
||||||
"side_panel": {
|
"side_panel": {
|
||||||
"default_path": "sidepanel/index.html"
|
"default_path": "sidepanel/index.html"
|
||||||
|
|||||||
1500
functional-samples/ai.gemini-on-device/package-lock.json
generated
Normal file
1500
functional-samples/ai.gemini-on-device/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
20
functional-samples/ai.gemini-on-device/package.json
Normal file
20
functional-samples/ai.gemini-on-device/package.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "Chrome Prompt API Example",
|
||||||
|
"private": true,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "background.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "rollup -c rollup.config.mjs"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"license": "Apache 2.0",
|
||||||
|
"devDependencies": {
|
||||||
|
"dompurify": "3.1.6",
|
||||||
|
"marked": "14.1.2",
|
||||||
|
"@rollup/plugin-commonjs": "26.0.1",
|
||||||
|
"@rollup/plugin-node-resolve": "15.2.3",
|
||||||
|
"rollup": "4.22.4",
|
||||||
|
"rollup-plugin-copy": "3.5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
functional-samples/ai.gemini-on-device/privacy,txt
Normal file
1
functional-samples/ai.gemini-on-device/privacy,txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
This extension does not collect, use or share any user data.
|
||||||
29
functional-samples/ai.gemini-on-device/rollup.config.mjs
Normal file
29
functional-samples/ai.gemini-on-device/rollup.config.mjs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
||||||
|
import commonjs from '@rollup/plugin-commonjs';
|
||||||
|
import copy from 'rollup-plugin-copy';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
input: 'sidepanel/index.js',
|
||||||
|
output: {
|
||||||
|
dir: 'dist/sidepanel',
|
||||||
|
format: 'iife',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
nodeResolve({
|
||||||
|
jsnext: true,
|
||||||
|
main: true,
|
||||||
|
browser: true
|
||||||
|
}),
|
||||||
|
commonjs(),
|
||||||
|
copy({
|
||||||
|
targets: [
|
||||||
|
{
|
||||||
|
src: ['manifest.json', 'background.js', 'sidepanel', 'images'],
|
||||||
|
dest: 'dist'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="index.css" />
|
<link rel="stylesheet" type="text/css" href="index.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Chrome built-in AI</h1>
|
|
||||||
<textarea
|
<textarea
|
||||||
id="input-prompt"
|
id="input-prompt"
|
||||||
placeholder='Type something, e.g. "Write a haiku about Chrome Extensions"'
|
placeholder='Type something, e.g. "Write a haiku about Chrome Extensions"'
|
||||||
@@ -25,7 +24,7 @@
|
|||||||
></label>
|
></label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="range" id="top-k" name="top-k" min="1" max="50" step="1" />
|
<input type="range" id="top-k" name="top-k" min="1" max="8" step="1" />
|
||||||
<label for="top-k">Top-k: <span id="label-top-k"></span></label>
|
<label for="top-k">Top-k: <span id="label-top-k"></span></label>
|
||||||
</div>
|
</div>
|
||||||
<button id="button-prompt" class="primary" disabled>Run</button>
|
<button id="button-prompt" class="primary" disabled>Run</button>
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import DOMPurify from 'dompurify';
|
||||||
|
import { marked } from 'marked';
|
||||||
|
|
||||||
const inputPrompt = document.body.querySelector('#input-prompt');
|
const inputPrompt = document.body.querySelector('#input-prompt');
|
||||||
const buttonPrompt = document.body.querySelector('#button-prompt');
|
const buttonPrompt = document.body.querySelector('#button-prompt');
|
||||||
const buttonReset = document.body.querySelector('#button-reset');
|
const buttonReset = document.body.querySelector('#button-reset');
|
||||||
@@ -41,11 +44,19 @@ async function initDefaults() {
|
|||||||
}
|
}
|
||||||
const defaults = await chrome.aiOriginTrial.languageModel.capabilities();
|
const defaults = await chrome.aiOriginTrial.languageModel.capabilities();
|
||||||
console.log('Model default:', defaults);
|
console.log('Model default:', defaults);
|
||||||
sliderTemperature.value = defaults.temperature;
|
if (defaults.available !== 'readily') {
|
||||||
sliderTopK.value = defaults.topK;
|
showResponse(
|
||||||
labelTopK.textContent = defaults.topK;
|
`Model not yet available (current state: "${defaults.available}")`
|
||||||
labelTemperature.textContent = defaults.temperature;
|
);
|
||||||
labelTemperature.value = defaults.temperature;
|
return;
|
||||||
|
}
|
||||||
|
sliderTemperature.value = defaults.defaultTemperature;
|
||||||
|
// sliderTemperature.max = defaults.maxTemperature;
|
||||||
|
// Pending https://issues.chromium.org/issues/367771112.
|
||||||
|
sliderTopK.value = defaults.defaultTopK;
|
||||||
|
sliderTopK.max = defaults.maxTopK;
|
||||||
|
labelTopK.textContent = defaults.defaultTopK;
|
||||||
|
labelTemperature.textContent = defaults.defaultTemperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
initDefaults();
|
initDefaults();
|
||||||
@@ -101,15 +112,7 @@ function showLoading() {
|
|||||||
function showResponse(response) {
|
function showResponse(response) {
|
||||||
hide(elementLoading);
|
hide(elementLoading);
|
||||||
show(elementResponse);
|
show(elementResponse);
|
||||||
// Make sure to preserve line breaks in the response
|
elementResponse.innerHTML = DOMPurify.sanitize(marked.parse(response));
|
||||||
elementResponse.textContent = '';
|
|
||||||
const paragraphs = response.split(/\r?\n/);
|
|
||||||
for (const paragraph of paragraphs) {
|
|
||||||
if (paragraph) {
|
|
||||||
elementResponse.appendChild(document.createTextNode(paragraph));
|
|
||||||
}
|
|
||||||
elementResponse.appendChild(document.createElement('BR'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showError(error) {
|
function showError(error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user