Skip to main content

Gemini embedder for mcp-fts5-starter — drop-in hybrid BM25 + dense retrieval via Google's Gemini Embeddings API.

Project description

mcp-fts5-starter-gemini

Gemini embedder for mcp-fts5-starter — drop-in hybrid BM25 + dense retrieval via Google's Gemini Embeddings API.

License Python

What this is

The parent project ships with an Embedder Protocol and stops short of any actual provider — by design. This repo is the canonical example of that Protocol implemented against a real backend, so you can graduate from BM25-only to hybrid retrieval (BM25 + dense vectors fused with RRF) by changing one line:

from mcp_fts5_starter.search import SearchDB
from mcp_fts5_starter_gemini import GeminiEmbedder

db = SearchDB("data/index.db", embedder=GeminiEmbedder())  # GOOGLE_API_KEY in env

Use this as a working reference. To wire OpenAI, Ollama, sentence-transformers, or anything else, copy the ~150 lines in src/mcp_fts5_starter_gemini/embedder.py and swap the API call.

Quick demo (no API key needed)

The repo ships with five sample notes and a JSON cache of their pre-computed embeddings. The demo runs the same four paraphrased queries against two indexes — BM25 only and BM25 + Gemini — to show what hybrid retrieval actually buys you:

git clone https://github.com/zx22413/mcp-fts5-starter-gemini
cd mcp-fts5-starter-gemini
uv sync
uv run python scripts/demo.py

Real output:

Query: 'speeding up code with memoization'
  BM25 only       :
    (no hits)
  BM25 + Gemini   :
    [ +0.016]  Caching strategies                (notes/caching.md)

Query: 'managing many simultaneous database connections'
  BM25 only       :
    (no hits)
  BM25 + Gemini   :
    [ +0.016]  Database connection pooling       (notes/connection-pooling.md)

Query: 'throttling clients that send too many requests'
  BM25 only       :
    (no hits)
  BM25 + Gemini   :
    [ +0.016]  API rate limits                   (notes/rate-limits.md)
    ...

Query: 'deferring slow work outside the request'
  BM25 only       :
    (no hits)
  BM25 + Gemini   :
    [ +0.016]  Background job queues             (notes/job-queues.md)
    ...

The queries are intentionally written without any of the keywords the documents actually use. BM25 has zero recall on all four. Gemini bridges the semantic gap and the right document surfaces every time.

Real usage

import os
from mcp_fts5_starter.search import SearchDB
from mcp_fts5_starter.ingest import sync
from mcp_fts5_starter_gemini import GeminiEmbedder

embedder = GeminiEmbedder(api_key=os.environ["GOOGLE_API_KEY"])
db = SearchDB("data/index.db", embedder=embedder)
sync(db, "data/my-notes")             # embeds each doc once during ingest
results = db.search("how do I cache?") # query-time embedding + RRF fusion

The Embedder Protocol is just embed(texts: list[str]) -> list[list[float]]GeminiEmbedder adds:

  • API-key resolution (GOOGLE_API_KEYGEMINI_API_KEY → constructor arg)
  • Batching to Gemini's 100-input cap
  • Exponential-backoff retries on 429 Too Many Requests
  • A defensive raise when Gemini's response is missing the expected shape

Configuration

Env var Purpose
GOOGLE_API_KEY Primary Gemini API key
GEMINI_API_KEY Fallback — checked if the above is unset
Constructor arg Default Notes
model "gemini-embedding-001" Pin to a specific model so dimensions are stable
output_dim 1536 Supported: 128 / 256 / 512 / 768 / 1536 / 3072
task_type None (symmetric SEMANTIC_SIMILARITY) Set "RETRIEVAL_DOCUMENT" / "RETRIEVAL_QUERY" for asymmetric retrieval
batch_size 100 Gemini's per-call cap

Task type and the symmetry trade-off

The parent's Embedder Protocol takes a flat list[str] — there's no in-band signal for "is this a document or a query." GeminiEmbedder defaults to SEMANTIC_SIMILARITY, which is symmetric — cosine similarity stays meaningful in both directions.

Gemini's docs claim a small recall improvement from using RETRIEVAL_DOCUMENT for ingest and RETRIEVAL_QUERY for search. To get that, instantiate two embedders and wire them at different points in your stack. For most personal-corpus workloads, the symmetric default is good enough.

Refreshing the embedding cache

The committed data/sample/embeddings.json was generated by:

GEMINI_API_KEY=... uv run python scripts/precompute-embeddings.py

Re-run that script if you change the sample corpus, the demo queries, or the embedding model/dimension. The keys in the JSON are SHA-256 hashes of normalized text — ChangeLog records every refresh.

Status

🚧 Alpha — pre-PyPI. Install from source: pip install git+https://github.com/zx22413/mcp-fts5-starter-gemini. v0.1.0 ships to PyPI once the Trusted Publisher is configured.

Companion repos

Repo Role
mcp-fts5-starter The MCP server template + FTS5 index this plugs into
forget-rag Memory-decay layer for FTS5 — different problem, same backend

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_fts5_starter_gemini-0.1.0.tar.gz (148.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_fts5_starter_gemini-0.1.0-py3-none-any.whl (9.4 kB view details)

Uploaded Python 3

File details

Details for the file mcp_fts5_starter_gemini-0.1.0.tar.gz.

File metadata

  • Download URL: mcp_fts5_starter_gemini-0.1.0.tar.gz
  • Upload date:
  • Size: 148.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mcp_fts5_starter_gemini-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1ec7f1d23b7461522c182f19c45137c64f31e40fe0d66e5e228ce3e0167e50f7
MD5 2c6fa8ba143055235cc489d3b150bb3f
BLAKE2b-256 3f29dbdb21e62c8f474bc03d8ec04ae78d02f4a615903c0f08f575210ddc2686

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcp_fts5_starter_gemini-0.1.0.tar.gz:

Publisher: publish.yml on zx22413/mcp-fts5-starter-gemini

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mcp_fts5_starter_gemini-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mcp_fts5_starter_gemini-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f5b263ecefe520a114fb6edb920b67644e51adf3d2518d8a87c9950d5e78cf8d
MD5 22d08bdefd650084c8e42f2abbe67320
BLAKE2b-256 0aed557b99cce6b665e0dea0642ad0092749c82b83d8ed317e14b9adb1bd5ed1

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcp_fts5_starter_gemini-0.1.0-py3-none-any.whl:

Publisher: publish.yml on zx22413/mcp-fts5-starter-gemini

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page