Create an AI Summarizer Chrome Extension
Building an Chrome Extension that can summarize your webpage with AI
Posted by
HowardRelated reading
Run your own ChatGPT locally with Ollama! (Part 2)
Using LibreChat as UI for Ollama!
Run your own ChatGPT locally with Ollama! (Part 1)
Interested in running ChatGPT locally? Try out Ollama!
Introduction
Ever came across hard texts on the internet and was simply too lazy to google or log on to ChatGPT to ask for explanations? I mean, I still have to create a new tab (adding on to the hundreds i have) google/chatgpt it, navigate back, rinse and repeat. Man, if only I have a chrome extension to do that for me (said no one ever)! Anyways, I thought that would be a fun project so let's get to it.
Prerequisites
Before you begin on this tutorial, make sure that you have your local LLM running. In this tutorial, we will be using Ollama. To learn how to run Ollama, you can visit this article for a guide.
Game Plan
So what exactly are we going to build?
We are going to build a simple chrome extension that allows user to highlight a webpage and subsequently summarize the highlighted content with AI. Let's get started!
Steps
1. Setting up Chrome Extension
Create a local folder first. Next, create a manifest.json file (entry point). Paste the following in your manifest.json file.
{
"name": "AI Summarizer",
"description": "Highlight and Summarize Locally!",
"version": "1.0",
"manifest_version": 3,
"background": {
"service_worker": "service-worker.js"
}
}
Create a service-worker.js file in the same folder. Add a simple print statement for sanity check.
console.log("loaded")
Next, proceed to your Chrome Browser. Go to Manage Extension (chrome://extensions), click on "load unpacked". Select the folder containing your chrome extension files. When successfully loaded, you will see the AI Summarizer in the "All Extensions". Click on the service worker and you should see "loaded" printed in the console. You have successfully loaded your chrome extension!
For our chrome extension, we are going to build a sidepanel UI. To do that, add the following code to service-worker.js (remove the print statement).
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });
Go to your manifest.json, add on the following two configurations.
"permissions": [
"sidePanel"
],
"side_panel": {
"default_path": "index.html"
}
Next, create a index.html in the folder as well. Add in some html codes
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>This is side panel</h1>
</body>
</html>
Head back to Manage Extensions (chrome://extensions) and click the refresh button for AI Summarizer. This is to reload the extension for new changes.
Click on your extension (you can pin it for easier access) and your side panel should show at the side!
2. Highlighting Functionality
Our next step is to create a highlighting functionality and display it on our side panel.
Let's start by creating a script.js file for our logic. In our index.html, import our script.js as well as add in these other changes.
<body>
<h1>AI Summarizer</h1>
<div>
<label>Selected Text:</label>
// Where the selected text will be shown
<textarea id="selected-text" style="width:100%;min-height:250px;resize:none;"></textarea>
// Button to summarize the text
<button id="summarize-btn">Summarize</button>
</div>
<div>
<label>Summarized Explanation:</label>
// Where the summarized text will be shown
<textarea id="summarized-text" style="width:100%;min-height:250px;resize:none;"></textarea>
</div>
// Import the script here. This is a script for the sidepanel logic.
<script src="script.js"></script>
</body>
Next, we need to create a content.js script and use the following code.
document.addEventListener('mouseup', () => {
const selectedText = window.getSelection().toString();
if (selectedText.length > 0) {
chrome.runtime.sendMessage({ selectedText })
}
});
Basically what the code does is on every highlight, send a message. So to receive the message in our side panel, we need to add the following code in script.js
// The element to display the selected tex
const selectedText = document.querySelector("#selected-text")
// Listener to receive the message from content.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
// Fill the textbox with the selected text
selectedText.value = request.selectedText
})
Last but not least, we need to enable content script to run. Go to manifest.json and add the following configurations.
"permissions": [
"sidePanel",
"activeTab"
],
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"content.js"
]
}
]
This is one of the ways to insert content script.
Proceed to reload the extension. And go to any webpage and open up your chrome extension.
Highlight any parts of the page and the selected text should show in the text box in the extension.
3. Linking up with Ollama
For this part, edit the script.js as shown below. Basically what we are just passing the command to summarize + selected text to our ollama.
const selectedText = document.querySelector("#selected-text")
// Add the following new selection for summarize button and summarize text
const summarizeBtn = document.querySelector("#summarize-btn")
const summarizedText = document.querySelector("#summarized-text")
chrome.runtime.onMessage.addListener((request) => {
selectedText.value = request.selectedText
})
// This is the endpoint for ollama when it is running
const ollamaEndpoint = "http://localhost:11434/api/generate"
// Add eventlistener for the summarize button
summarizeBtn.addEventListener('click', async () => {
// You can modify your prompts here according to your wanted result
const prompt = "Summarize this in less than 200 words: " + selectedText.value
// Calling the endpoint of ollama
fetch(ollamaEndpoint, {
method: "POST",
body: JSON.stringify({
"model": "llama3.2",
"prompt": prompt,
"stream": false
}),
mode: 'no-cors',
}).then((res) => {
return res.json();
}).then((data) => {
// Assign the result to the summarized explanation textbox
summarizedText.value = data.response
})
})
And... we are done! You can continue to build on this by implementing other functionalities. Perhaps a simple click to summarize the whole page? Good luck!