Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Summarizer sample: Format markdown output #1283

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"@mozilla/readability": "0.5.0",
"@rollup/plugin-commonjs": "26.0.1",
"@rollup/plugin-node-resolve": "15.2.3",
"dompurify": "3.1.6",
"marked": "14.1.2",
"rollup": "4.18.1",
"rollup-plugin-copy": "^3.5.0"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,35 @@ import { nodeResolve } from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import copy from 'rollup-plugin-copy';

export default {
input: 'scripts/extract-content.js',
output: {
dir: 'dist/scripts',
format: 'cjs'
export default [
{
input: 'sidepanel/index.js',
output: {
dir: 'dist/sidepanel',
format: 'es',
},
plugins: [
commonjs(),
nodeResolve(),
copy({
targets: [
{
src: ['manifest.json', 'background.js', 'sidepanel', 'images'],
dest: 'dist'
}
]
})
]
},
plugins: [
commonjs(),
nodeResolve(),
copy({
targets: [
{
src: ['manifest.json', 'background.js', 'sidepanel', 'images'],
dest: 'dist'
}
]
})
]
};
{
input: 'scripts/extract-content.js',
output: {
dir: 'dist/scripts',
format: 'es'
},
plugins: [
commonjs(),
nodeResolve(),
]
}
];
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import DOMPurify from '../node_modules/dompurify/dist/purify.es.mjs';
import { marked } from '../node_modules/marked/marked.min';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's quite unusual to import from a relative path like this. Could you look at what setup would be needed so you can just import from "marked"?


// The underlying model has a context of 1,024 tokens, out of which 26 are used by the internal prompt,
// leaving about 998 tokens for the input text. Each token corresponds, roughly, to about 4 characters, so 4,000
// is used as a limit to warn the user the content might be too long to summarize.
Expand Down Expand Up @@ -42,7 +45,7 @@ async function onContentChange(newContent) {

async function generateSummary(text) {
try {
let session = await createSummarizationSession((message, progress) => {
let session = await createSummarizer((message, progress) => {
console.log(`${message} (${progress.loaded}/${progress.total})`);
});
let summary = await session.summarize(text);
Expand All @@ -55,39 +58,32 @@ async function generateSummary(text) {
}
}

async function createSummarizationSession(downloadProgressCallback) {
async function createSummarizer() {
if (!window.ai || !window.ai.summarizer) {
throw new Error('AI Summarization is not supported in this browser');
}
const canSummarize = await window.ai.summarizer.capabilities();
if (canSummarize.available === 'no') {
throw new Error('AI Summarization is not availabe');
}

const summarizationSession = await window.ai.summarizer.create();
if (canSummarize.available === 'after-download') {
if (downloadProgressCallback) {
summarizationSession.addEventListener(
'downloadprogress',
downloadProgressCallback
);
let summarizer;
if (canSummarize && canSummarize.available !== 'no') {
if (canSummarize.available === 'readily') {
// The summarizer can immediately be used.
summarizer = await window.ai.summarizer.create();
} else {
// The summarizer can be used after the model download.
summarizer = await window.ai.summarizer.create();
summarizer.addEventListener('downloadprogress', (e) => {
console.log('Downloading model', e.loaded, e.total);
});
await summarizer.ready;
}
await summarizationSession.ready;
} else {
throw new Error(`AI Summarizer not available (${canSummarize.available})`);
}

return summarizationSession;
return summarizer;
}

async function showSummary(text) {
// Make sure to preserve line breaks in the response
summaryElement.textContent = '';
const paragraphs = text.split(/\r?\n/);
for (const paragraph of paragraphs) {
if (paragraph) {
summaryElement.appendChild(document.createTextNode(paragraph));
}
summaryElement.appendChild(document.createElement('BR'));
}
summaryElement.innerHTML = DOMPurify.sanitize(marked.parse(text));
}

async function updateWarning(warning) {
Expand Down