Files
praxis/background.js
2025-07-06 06:14:06 -04:00

124 lines
4.4 KiB
JavaScript

import { pipeline, env } from './transformers/transformers.min.js';
env.allowLocalModels = true;
env.backends.onnx.wasm.wasmPaths = {
'default': './transformers/',
'threaded': './transformers/',
'simd': './transformers/',
'simd-threaded': './transformers/',
};
env.allowRemoteModels = false;
let classifier = null;
let llmInitializationPromise = null;
async function initializeLLM() {
if (classifier) {
return;
}
if (llmInitializationPromise) {
return llmInitializationPromise;
}
llmInitializationPromise = (async () => {
try {
classifier = await pipeline(
'zero-shot-classification',
'nli-deberta-v3-small',
{
local_files_only: true,
model_file_name: "model.onnx",
}
);
llmInitializationPromise = null;
} catch (error) {
classifier = null;
llmInitializationPromise = null;
throw error;
}
})();
return llmInitializationPromise;
}
initializeLLM();
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
(async () => {
if (!classifier) {
try {
await initializeLLM();
} catch (error) {
sendResponse({ type: "LLM_ERROR", error: "LLM initialization failed: " + error.message });
return;
}
}
try {
switch (message.type) {
case 'ANALYZE_SENTIMENT':
const headlineForSentiment = message.payload.headline;
const sentimentLabels = ['negative', 'positive', 'neutral', 'depressing', 'worrying'];
const sentimentOutput = await classifier(headlineForSentiment, sentimentLabels);
let detectedSentiment = 'neutral';
if (sentimentOutput && sentimentOutput.scores && sentimentOutput.labels) {
const sortedSentimentResults = sentimentOutput.scores.map((score, index) => ({
label: sentimentOutput.labels[index],
score: score
})).sort((a, b) => b.score - a.score);
if (sortedSentimentResults.length > 0 && sortedSentimentResults[0].score > 0.7) {
detectedSentiment = sortedSentimentResults[0].label;
} else if (sortedSentimentResults.length > 0) {
const topLabel = sortedSentimentResults[0].label;
if (['negative', 'depressing', 'worrying'].includes(topLabel)) {
detectedSentiment = topLabel;
} else {
}
}
}
sendResponse({ type: "ANALYSIS_RESULT", result: { sentiment: detectedSentiment } });
break;
case 'ANALYZE_HEADLINE_CATEGORY':
const headline = message.payload.headline;
const selectedIssues = message.payload.selectedIssues || [];
const candidateLabels = ['gun-control', 'gun-rights', 'privacy', 'immigration', 'climate-change', 'healthcare', 'racial-justice', 'lgbtq-rights', 'economic-inequality', 'reproductive-rights', 'education-reform', 'criminal-justice', 'voting-rights', 'campaign-finance', 'foreign-policy', 'national-security', 'free-speech', 'net-neutrality', 'labor-rights', 'affordable-housing', 'environmental-protection', 'space-exploration', 'drug-policy-reform', 'veterans-affairs', 'senior-citizen-rights'];
const analysisOutput = await classifier(headline, candidateLabels);
let categories = [];
if (analysisOutput && analysisOutput.scores && analysisOutput.labels) {
const sortedResults = analysisOutput.scores.map((score, index) => ({
label: analysisOutput.labels[index],
score: score
})).sort((a, b) => b.score - a.score);
categories = sortedResults
.filter(item => item.score > 0.5 && selectedIssues.includes(item.label))
.map(item => item.label);
if (categories.length === 0 && sortedResults.length > 0) {
const topLabel = sortedResults[0].label;
if (selectedIssues.includes(topLabel)) {
categories.push(topLabel);
} else {
}
}
}
sendResponse({ type: "ANALYSIS_RESULT", result: { categories: categories } });
break;
default:
sendResponse({ type: "UNKNOWN_MESSAGE" });
break;
}
} catch (error) {
sendResponse({ type: "LLM_ERROR", error: "Processing error: " + error.message });
}
})();
return true;
});