JavaScript Mapping Library
Earlier this week I mentioned I’m looking at my previous server-based generative AI demos and seeing which could possibly make sense using on-device AI with Chrome’s AI support. I remembered a demo from last year where I tested spam detection using Google Gemini. That demo had worked out rather well and so I thought I’d try it out in Chrome.
Spam detection is important, and a server-based solution could have many users, especially in sites that make use of a lot of user generated content. But what would be the point doing this in the browser? Consider the fact that many of the Chrome AI APIs help with writing, I think such a solution could be useful in helping flag content that may be considered spam by others. So for example, your web-based CMS system may let you craft email content, and being able to see in real-time if the content would be diverted to someone’s spam folder could be incredibly useful.
To build my spam checking tool, I relied on the following features:
Here’s how I did this. The first two aspects are handled by the code that creates the session object:
session = await window.LanguageModel.create({ initialPrompts: [ { role: 'system', content: 'You analyze a string and detect if it would be flagged as spam. You return a true/false result for that as well as a list of reasons.' }, ], monitor(m) { m.addEventListener("downloadprogress", e => { console.log(`Downloaded $ {e.loaded * 100}%`); /* why this? the download event _always_ runs at least once, so this prevents the msg showing up when its already done. I've seen it report 0 and 1 in this case, so we skip both */ if(e.loaded === 0 || e.loaded === 1) return; $ result.innerHTML = `Downloading, currently at $ {Math.floor(e.loaded * 100)}%`; }); } });
You’ll notice that I’m using the system prompt to both explain what I want and help shape the output. But to really specify how the output should be returned, you must make use of JSON schema. I created this schema for my demo:
const spamCheckResultSchema = { type:"object", properties: { spam:{ type:"boolean" }, reasons: { type:"array", items: { type:"string" } } } };
Basically, a top level spam true/false value and an array of reasons backing up why something was flagged a certain way.
The last aspect is the easiest – taking the user input and passing it to the model:
let result = await session.prompt(input, { responseConstraint: spamCheckResultSchema });
And that’s it. The rest of my demo is just DOM manipulation, and I’ll include it below, but keep in mind that as of today, this feature (the Prompt API specifically) is behind a flag in Chrome. It’s released for extensions, but not the main browser yet. With that in mind, here’s a few samples:
Given:
CAPITAL CREDIT ASSOCIATES The Capital Recovery Division Attorney of Record: Stanley Woods Email: attorney.stanley.woods@gmail.com Case Reference: CF-9814725D3 Subject: Past Due Loan Amount – $ 1,825.60 This correspondence concerns the above case reference linked to your account with Capital Credit Associates. Despite prior efforts to connect with you by phone and mail, we have not received any acknowledgment or response. Accordingly, your file has been escalated to our Legal Resolution Department, which has now categorized your account as non-compliant and ready for formal litigation review. The National Financial Compliance Office has reported the following statutory violations connected to your account activity: Breach of Federal Lending Guidelines Misuse of Negotiable Instruments Unauthorized Funds Withdrawal Obtaining Credit Under False Pretenses
I get:
Was it spam? Yes Reasons Given: Aggressive tone and threat of litigation Demand for payment with vague details Generic subject line ( Past Due Loan Amount without specifying the lender directly) Reference to escalation to Legal Resolution Department Mention of statutory violations without specifics (creating fear) Lack of specific details about the alleged debt Generic email address (gmail.com) Pressure tactics to elicit a quick response
That seems right on the money. Now if I try something more innocent:
Hi, I attended your presentation about cat developer relations, and I was wondering if a) I could get a copy of your slide deck and b) would you be open to giving the talk to our local cat user group?
The result is:
Was it spam? No Reasons Given: Request for information (slide deck) Request to present at a user group (potentially legitimate outreach) Non-aggressive language No attempt to solicit personal information Clear and straightforward query
All in all, this seems to work rather well I think. If you want to give it a shot yourself, or just see the code, you can check out the embed below.
See the Pen Spam Detection Test by Raymond Camden (@cfjedimaster) on CodePen.
Photo by Hannes Johnson on Unsplash
Raymond Camden
You must be logged in to post a comment.
This site uses Akismet to reduce spam. Learn how your comment data is processed.