Skip to content

fix(core): key the embedding cache by the embedder's identity, not its name (#1536) - #1544

Merged
ajianaz merged 1 commit into
developfrom
fix/embedding-cache-identity
Oct 22, 2026
Merged

ajianaz merged 1 commit into
developfrom
fix/embedding-cache-identity

Conversation

@ajianaz

@ajianaz ajianaz commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator

What

The persistent embedding cache (embed_cache.db) was keyed by inner.name(), a constant per backend (openai, ollama, embeddinggemma-q4). Embedder gains a provided method identity() (default name:dims); openai and ollama return backend, model, dimensions and a short hash of the endpoint (the API key is not part of it); the cache is keyed by it. A cached vector whose length is not the embedder's dimensions is ignored and an empty vector is not stored. In ensure_embedder the cache now wraps the primary and the fallback wraps the cached primary, so vectors the cloud produced never enter the cache. Rows written under the old key are deleted once, when the cache is first opened (PRAGMA user_version 0 to 1); invalidate_model removes every identity of a model.

Why

Switching [embedding] model, dims or the endpoint served the vector of the previous configuration for any text already cached, silently, and a cloud vector produced through a fallback was cached under the primary's name (#1536, owner decision: purge the old rows). With a fallback configured, a repeated text whose primary embedding keeps failing now calls the cloud each time; that is the price of not caching a wrong-model vector. Refs #1536, part of #1543.

Testing

  • clippy -D warnings, fmt, cargo test --workspace pass; cargo run -p docgen changes nothing
  • 9 new cache tests: identity default, another model / size / endpoint never gets another's vector, wrong-length stored vector ignored, empty vector not stored, old rows purged once and new rows survive, cloud fallback result never cached, remote identities include model/dims/endpoint but not the key, invalidating one model leaves the others. Two existing tests were fixed: the temp-file helper shared a file between parallel tests, and test_invalidate_model ran raw SQL with the old key instead of calling invalidate_model
  • reproduced with the real binaries against a mock embeddings endpoint (same text, config model-a then model-b, one store): develop never sends model-b (endpoint saw 1 request, model-a); this branch sends it (2 requests) and a repeat of model-b is a cache hit; a cache written by develop (openai) is purged and replaced by openai:model-a:768:<hash> with user_version=1; the ONNX path gives identical recall results and caches under embeddinggemma-q4:768
  • reviewed locally with the Cora MCP agent reviewer before pushing: no blocking finding; the moved guard.take().unwrap() calls became explicit errors, and the fallback trade-off above is recorded

@github-actions

Copy link
Copy Markdown

🔍 Cora AI Code Review

✅ No issues found. Code looks good!


Review powered by cora-code · BYOK · MIT

@ajianaz
ajianaz merged commit 83e2d19 into develop Oct 22, 2026
15 checks passed
@ajianaz
ajianaz deleted the fix/embedding-cache-identity branch October 22, 2026 06:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant