Back to Articles

Anti-ChatGPT: Building a Semantic Content Filter with LLMs

[ View on GitHub ]

Anti-ChatGPT: Building a Semantic Content Filter with LLMs

Hook

What if the best defense against AI-generated content flooding the web is... more AI? Anti-ChatGPT uses GPT to evaluate and remove content from web pages based on semantic meaning rather than keyword matching.

Context

Traditional content blockers rely on pattern matching, CSS selectors, and curated filter lists. They're fast and private, but fundamentally limited by their literal approach. If you want to block political content, you maintain a list of political keywords. If you want to hide promotional material, you write regex patterns for common marketing phrases. This works until content creators change their vocabulary.

Anti-ChatGPT takes a different approach: instead of matching patterns, it understands meaning. You define what you don't want to see in natural language—"political content," "clickbait headlines," "promotional material"—and the extension evaluates every piece of content on the page against those criteria using GPT. It's semantic filtering: blocking based on what content means, not what words it contains. The repository bills itself as "antivirus for your mind," positioning AI models as the immune system that protects you from manipulative or unwanted information.

Technical Insight

The architecture follows a classic Chrome extension pattern with a modern AI twist. A manifest v3 configuration defines a content script that runs on every page, intercepting the DOM before it renders. The content script walks through text nodes and images, extracts their content, and sends it to a background service worker that manages API calls to OpenAI and Replicate.

Here's the core filtering logic from the content script:

function shouldBlockElement(text, blacklist) {
  return fetch('https://api.openai.com/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${apiKey}`
    },
    body: JSON.stringify({
      model: 'gpt-3.5-turbo',
      messages: [
        {
          role: 'system',
          content: 'You are a content filter. Reply with only YES or NO.'
        },
        {
          role: 'user',
          content: `Does this content match any of these criteria: ${blacklist.join(', ')}?\n\nContent: ${text}`
        }
      ]
    })
  })
  .then(res => res.json())
  .then(data => data.choices[0].message.content.includes('YES'));
}

The elegance is in the simplicity: rather than building a complex classification system, the extension outsources the decision entirely to GPT. The model receives user-defined blacklist criteria ("political content," "ads," "negative news") and evaluates each piece of content as a binary classification task. If GPT responds with "YES," the DOM element gets removed.

For images, the extension uses a two-step process. First, it sends images to CLIP-interrogator via Replicate's API to generate text descriptions. Then it evaluates those descriptions using the same GPT-based filtering:

async function analyzeImage(imageUrl, blacklist) {
  // Step 1: Generate caption with CLIP
  const caption = await fetch('https://api.replicate.com/v1/predictions', {
    method: 'POST',
    headers: {
      'Authorization': `Token ${replicateKey}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      version: 'clip-interrogator-version-id',
      input: { image: imageUrl }
    })
  }).then(/* ... extract caption from response ... */);

  // Step 2: Evaluate caption against blacklist
  return shouldBlockElement(caption, blacklist);
}

This multimodal approach handles both text-heavy sites and image-centric platforms like Instagram or Pinterest. The configuration lives in Chrome's sync storage, allowing users to define custom blacklists that sync across their devices.

The most interesting architectural decision is the complete dependence on external APIs. There's no local model, no caching layer, no attempt to batch requests. Every piece of content triggers an API call. This creates a fascinating tension: the extension is simultaneously powerful (because it leverages state-of-the-art models) and impractical (because every page load becomes a waterfall of API requests).

The manifest v3 service worker handles API key management and request routing, but there's no sophisticated rate limiting or error handling. If the API is slow, your page loads slowly. If you hit rate limits, content just doesn't get filtered. The implementation prioritizes demonstration over production readiness—you can see how semantic filtering works, but you wouldn't want to browse with this daily.

What makes this architecturally noteworthy isn't the sophistication of the implementation, but the concept it proves: LLMs are genuinely good at this kind of semantic evaluation. Traditional approaches require maintaining explicit lists of patterns. This approach requires only natural language descriptions of what you want to avoid. That's a fundamental shift in how content filtering can work.

Gotcha

The most glaring issue is cost and latency. If you visit a page with 200 text elements and 50 images, the extension makes 250 API calls before you see content. At OpenAI's pricing (roughly $0.002 per request for GPT-3.5-turbo) and Replicate's image analysis costs, heavy browsing could easily cost $10-20 per day. The latency is equally problematic—you're waiting for sequential API calls to complete before content renders, turning snappy page loads into multi-second delays.

Then there's the privacy paradox. The stated goal is protecting your mind from manipulative content, but the implementation sends your entire browsing history to OpenAI and Replicate. Every headline you read, every image you view, every piece of content on every page gets transmitted to third-party AI services. If you're concerned about big tech surveillance or data collection, this extension makes the problem worse, not better. You're trading one form of information exposure for another.

The filtering is also binary and blunt. Content either matches your blacklist or it doesn't—there's no nuance, no confidence scores, no user control over individual decisions. And because GPT's outputs can be inconsistent, the same content might be filtered on one page load and visible on the next. For a tool positioned as protective infrastructure for your browsing experience, the unreliability undermines trust.

Verdict

Use if: you want to experiment with semantic content filtering, you're researching AI-powered browser extensions, you have API credits to burn, and you're comfortable with the privacy implications of sending your browsing data to OpenAI. This is a fascinating proof-of-concept that demonstrates how LLMs can enable entirely new categories of user-facing tools. Skip if: you need actual privacy protection (the irony is too thick), you want performant browsing without multi-second delays on every page, you need cost-effective filtering, or you want production-ready content blocking. Traditional extensions like uBlock Origin or Privacy Badger are dramatically more practical for real-world use. Anti-ChatGPT is intellectually interesting but practically limited—treat it as an experiment, not a solution.