Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Laya Fun AdBlocker 🧹

A Chrome extension (Manifest V3) that spots ads on any website in real time and pops their DOM elements out of the page. The semantic call, "is this element an ad?", is made by a local Laya typed-decision model (MLX, Apple Silicon). Everything else is plain code.

This is a fun side project, not a real ad blocker. It will miss ads, it will occasionally eat something that is not an ad, and it does nothing about tracking, malware, or video ads. If you want a real ad blocker, use uBlock Origin. If you want to see a tiny local decision model judge DOM elements, read on.

Local only: no key, no cloud. The model runs on your Mac via server/server.py (MLX, 7–14 ms per short decision, 0 output tokens). Nothing leaves your browser except to http://127.0.0.1:8765. Start the server, then browse.

How it works

  1. Find candidates (code) – src/content.js looks for ad-shaped elements: iframe / ins, id and class tokens like ad, sponsored, banner, data-ad-* attributes, links to ad networks, and short labels such as "Sponsored", "Advertisement", "Anzeige", "Werbung". Tight wrappers are collapsed into one candidate. Anything too big (half the viewport, contains main or h1) is skipped. Teaser cards are climbed from the label up to the whole card (article / li), stopping at page-level containers, at 35 % of the viewport, at 1500 characters of text, or when the parent holds a second label (then it is a feed, not a card).
  2. Describe compactly (code) – each candidate becomes a small JSON object: tag, classes, label, text excerpt, link hosts, iframe host, shape ("wide horizontal banner"), whether it has a standard IAB size, and any recognized ad network. Numbers are turned into words up front because the model is weak on numbers.
  3. Judge (local Laya) – the service worker (src/background.js → src/laya.js) sends one request per batch with one noul question per candidate (Is candidates[i] a paid advertisement …?) to the local server (POST http://127.0.0.1:8765/judge), which runs laya_mlx (multilingual checkpoint by default, so German labels work). The answer is one probability per element.
  4. Act (code) – everything with P(ad) ≥ threshold (default 0.70) gets a pulsing red outline, shrinks and fades away, and is removed with element.remove(). A MutationObserver plus a scroll handler catch lazy-loaded ads; batches are debounced by 600 ms and capped at 30 candidates per request.

Requirements

  • macOS on Apple Silicon, Python 3.11+, Chrome/Chromium
  • First run downloads the checkpoint; later inference is fully local
pip install -r requirements.txt

Install

  1. Start the local judge:
    npm run server
    # or: LAYA_HEURISTIC=1 python3 server/server.py  (no model, for UI testing)
  2. Open chrome://extensions, enable Developer mode.
  3. Load unpacked → pick this folder.
  4. Click the icon, hit Test (should say OK – model: local).
  5. Browse. The badge shows how many ads were removed on the current tab; a small toast appears in the corner after each batch.

Popup options

Option Effect
On / off Pause the content script
Local judge server URL of the local server (default http://127.0.0.1:8765/judge)
Threshold Probability above which an element is removed (0.30–0.95)
Mode Remove or Highlight only (debug: red outline plus the probability)
Pop animation On: pulse outline for ~0.9 s, then shrink and fade out. Off: remove instantly
Toast Corner toast after each batch
Rescan page Forget the "already judged" set and scan again

The animation is skipped automatically when the tab is hidden, and a 2.5 s fail-safe timer removes the element even if the animation timeline is frozen.

What leaves your browser

Per batch, one request to 127.0.0.1 containing: the page hostname and title, and for each candidate the fields listed under step 2 (up to 220 characters of visible text, link hostnames, image alt texts, attribute names). Nothing else. No cloud, no storage on any server.

Testing without installing

# terminal 1: local judge (heuristic = no model download, for UI flow)
LAYA_HEURISTIC=1 python3 server/server.py

# terminal 2: static server
npm run serve
# then open http://localhost:8787/test/harness.html

test/harness.html loads test/fixture.html (a German news page with an article, navigation, comments, a newsletter box, a teaser grid and eight different ads) with a faked chrome API and runs the real content script. Without the server it falls back to a heuristic. The fixture text is German on purpose: it exercises the German labels.

# only check the local judge with hand-written candidates (needs server running)
npm run live-check

With the heuristic server: 11/11 hand-written candidates correct, 8/8 ads removed in the harness, 0 false removals. With the real multilingual checkpoint expect similar, at roughly 7–14 ms per short decision plus batching.

Limits

  • Ads inside cross-origin iframes are removed as a whole iframe; the script never sees their content.
  • The model reads literally. Ads that hide without a label, ad-network link, or ad-like class never reach the candidate list.
  • Every batch is a local inference call. Tune the threshold and the candidate heuristics on the sites you actually visit.
  • Sites that detect missing ad slots may behave oddly. That is part of the fun.

Attribution

Local inference via the laya-mlx MLX port (Apache-2.0, see NOTICE). Checkpoints and weights are by their respective owners; prompt construction and output schema follow upstream Laya conventions.

Contributing

Issues and PRs are welcome. Good first targets: more label words for other languages, better card detection on specific sites, and a smarter candidate heuristic that keeps the token count low. Keep the split intact: rules and thresholds in code, only the semantic judgment goes to the model.

License

MIT, see LICENSE.

About

Fun Chrome extension: local Laya decision model judges DOM elements, pops ads off the page. No cloud, no key.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages