Fuze
ONGOINGA bookmark manager that recommends saved pages for the project you are building, with its retrieval quality and latency measured.
Personal project, ongoing · Jul 2025 – present · 681 commits
THE PROBLEM
Saved bookmarks and posts pile up across tabs and apps and can't be searched by meaning, and a project needs the few saved pages that help with it, not a list of everything loosely related.
HOW IT WORKS
- You create a project and tasks; the engine builds an intent from your own words and ranks saved pages by their best matching passage. Pages are split into overlapping chunks, embedded with bge-small (384 dimensions) and stored in PostgreSQL with pgvector, searched with HNSW indexes and diversified with MMR.
- RQ workers on Redis fetch and embed pages in the background; Gemini adds a content profile per page and refines the intent, in jobs that no request waits for. A small cross-encoder flags weak matches, which the page folds behind a toggle.
- A React frontend on Vercel, a Flask API in a Docker container on a free Hugging Face Space (gunicorn with gevent, workers under supervisord), Supabase Postgres, Upstash Redis and a Manifest V3 browser extension.
THE PIPELINE
- Save a pageFrom the browser extension, which can send the text the browser already rendered, or from a URL.
- Acquire the textOrdered tiers: extension capture, official site APIs, the backend's own fetch, a remote reader, then the Wayback Machine, with SSRF and robots.txt checks first.
- RQ workers on RedisSplit the text into overlapping passages of about 200 words and embed them with bge-small (384 dimensions); Gemini adds a content profile.
- PostgreSQL with pgvectorPassages and profiles stored with HNSW indexes; every vector records its embedding model.
- Retrieve and rankNearest passages for your project and task, diversified with MMR; a cross-encoder flags weak matches.
ENGINEERING EVIDENCE
- On BEIR SciFact (300 queries, run through the production search code) passage retrieval scores nDCG@10 0.718. On a long-document variant it scores 0.504 against 0.016 for one embedding per document. ADR-007-intent-engine.md ↗
- Live semantic-search latency on the deployed Space, 30 samples per endpoint: p50 3,026 ms down to about 1,700 ms (1,661 at the best run, -45%) and SQL statements per search from about 10 to 1, with each run recorded and the unexplained remainder written down. README.md ↗
- A cross-encoder rerank was measured and left off for search: it moved nDCG@10 by -0.008 and +0.004 for about 700 ms a query. It is used only to flag weak matches. ADR-007-intent-engine.md ↗
- The free Redis plan's 500,000 monthly commands ran out. Removing the scheduler and per-bookmark polling brought an idle 10-minute sample to 2 commands. OPERATIONS.md ↗
- The passage table has an HNSW index (m=16, ef_construction=64) created in an Alembic migration. 0011_content_chunks.py ↗
- Backend CI, Frontend CI, a Docker build check and the Space sync all pass on the latest commit (5e47109).
DECISIONS & INVESTIGATIONS
Semantic search p50 went from 3,026 to 1,661 ms (-45%) and p95 from 3,915 to 2,071 ms (-47%) at the best run; the latest run is 1,686 ms p50.
- Passage retrieval scored 0.504 nDCG@10 where one vector per document scored 0.016, on long documentsADOPTED
On the original abstracts, passages barely change the score for bge-small (0.718 against 0.713) and MiniLM (0.652 against 0.648) and help e5-small more (0.687 against 0.636).
Defects the 198-test suite did not catch: (1) alembic.ini was never copied into the image, so the migration step in start.sh (added 2026-07-27) had probably failed on every boot behind its '|| echo Warning' fallback;...
At 75 concurrent users about 38% of authenticated requests returned 401 'Token has been revoked' for tokens that were never revoked (approximate figure from gaps.md and the commit message; no raw Locust output is...
- Rejected a modular ML rewrite, then rebuilt a similar pipeline behind flags three days laterSUPERSEDED
The new code is only partly live.
With the floor at -5, 89% of the irrelevant and 45% of the loosely related results were marked weak, and the strong list was 81% clearly useful against 60% unfiltered; 23% of the useful results were also marked weak,...
- A processing job now fetches the bookmark's stored URL, after four bookmarks got a neighbour's textADOPTED
Two tests pin the behaviour: the stored URL wins over the job's, and a job for another user's bookmark does nothing.
A 10-minute idle sample of the production Redis read 2 commands, and a pass over 150 stuck bookmarks costs under 10 commands, which a test asserts.
There is now one engine to evaluate, measured on BEIR SciFact instead of by a regression gate that compared two paths sharing one engine.
The gate passes with a delta of exactly 0.0000 because both sides run the same class. golden_baseline_v1.json was generated by generate_golden_baseline.py, which runs SmartEngine; ADR-006 calls it the baseline of the...
Start-up no longer loads the model weights, and the port can bind quickly.
WHAT ISN'T DONE
- Throughput under load is not measured on the live Space: its benchmark is 30 samples per endpoint from one machine in India. Recommendation quality is measured offline, not on real users' feedback.
- About 900 ms of each semantic search is unexplained. Postgres runs the statement in about 2 ms, yet a trivial query from the Space to the database (Supabase, Singapore) costs 213-228 ms. Moving the database closer is written up and deferred; the Space's own region is not documented.
- SciFact is scientific abstracts, not bookmarks, so no benchmark on real saved pages exists. The weak-match floor was calibrated on one 238-bookmark library over 15 requests, 23% of useful results were also flagged, and the repository does not record who assigned the relevance labels.
- The browser extension has not been exercised end to end in real Chrome against the deployed backend.
- The earlier two-stage recommendation pipeline, its shadow mode and the golden-set regression gate were deleted on 12 Oct 2026, and the decision records about them carry a note saying so.
- Built with an AI coding assistant: 11 of the 681 commits carry a Claude co-author trailer, all from before 12 Oct 2026, so that count understates it.
NEXT STEPS
Each one comes from a gap listed above. It says what fixing the gap would take; it is not a promise.
- Move the database closer to the Space, then re-run the live benchmark to see how much of the unexplained 900 ms was distance.
- Record who assigned the weak-match relevance labels, and re-check them with independent raters before quoting the figures as a benchmark.
- Add a retrieval benchmark on real saved pages, since SciFact only stands in for them.
STACK
- Python
- Flask
- PostgreSQL
- pgvector
- Redis
- RQ
- SentenceTransformers
- Gemini
- React
- Vite
- Alembic
- GitHub Actions