Loading...
tansformers.js
to run model locally on client's browser.Summarize Component
- This is a component that takes in the context(in our case element id) and then summarizes it. All of this is done client side on the browser.Sentiment Analysis hook
- This hook takes in the context to analyze and can predict the sentiment of the text on client side.web worker
approach to load the models from hugging face
.transformers.js
library, that is powered to run AI models on the browser.import { pipeline, PipelineType } from "@huggingface/transformers"; type PipelineModel = ReturnType<typeof pipeline>; class PipelineSingleton { static task = "sentiment-analysis" as PipelineType; static model = "Xenova/bert-base-multilingual-uncased-sentiment"; static instance: null | PipelineModel = null; // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type static async getInstance(progress_callback: Function | undefined) { if (this.instance === null) { console.log("Creating Instance"); this.instance = pipeline(this.task, this.model, { progress_callback }); } return this.instance; } }
web workers
eventListeners to pass messages from the web worker to UI and vice versa// Listen for messages from the main thread self.addEventListener("message", async (event) => { console.log("Web worker received", event); (async function () { // Retrieve the classification pipeline. When called for the first time, // this will load the pipeline and save it for future use. const classifier = await PipelineSingleton.getInstance(() => {}); const result = await classifier(event.data.context); // 2. Run model prediction console.log("Service worker result", result); // Send the output back to the main thread self.postMessage({ status: "complete", output: result[0], }); })(); return true; });
worker
and uses the eventListeners.const worker = useRef<Worker | null>(null); useEffect(() => { if (!worker.current) { // Create the worker if it does not yet exist. // worker.current = new MyWorker(); worker.current = new Worker( new URL("./worker/worker.ts", import.meta.url), { name: "worker", type: "module", } ); } // Create a callback function for messages from the worker thread. // eslint-disable-next-line @typescript-eslint/no-explicit-any const onMessageReceived = (event: any) => {}; // Attach the callback function as an event listener. worker.current.addEventListener("message", onMessageReceived); // Define a cleanup function for when the component is unmounted. return () => worker.current?.removeEventListener("message", onMessageReceived); }, []);
export default defineConfig({ // base: ".", plugins: [react(), libInjectCss()], build: { rollupOptions: { external: ["react", "react/jsx-runtime"], }, lib: { entry: { summarize: resolve( __dirname, "./src/components/Summarize/summarize.tsx" ), sentimentAnalysis: resolve( __dirname, "./src/components/SentimentAnalysis/useSentimentAnalysis.ts" ), }, formats: ["es"], }, }, });
exports
in the package.json
"exports": { "./summarize": { "import": "./dist/summarize.js" }, "./sentimentAnalysis": { "import": "./dist/sentimentAnalysis.js" }, "./css": "./dist/style.css" },
For running the components locally:
npm i
npm run dev
for local serverFor testing the components in a separate repo:
package.json
filenpm run build
, this will build the librarysentimentAnalysis.js
and summarize.js
in dist
folder and update the reference import for worker
from "/assets/*********
to "./assets/*****
. So we added the .
in front to make it relative to the file.// example new URL( /* @vite-ignore */ "./assets/worker-2oVLSZZP.js", import.meta.url ),
npm pack
, this will create a tar file which can be installed. The file would be like ai-components-client-0.0.9.tz
npm install ai-components-client-0.0.1.tz
Web Worker
import is manual and no automated way to update is found.