Repository navigation
feat(embed): resolve encoder model and width from config - #12
Merged
Merged
Conversation
`EMBED_DIM` was pinned to 1024 and `EMBED_MODEL` to `BAAI/bge-m3`, so any other encoder was rejected outright: all three ingest paths compared the response width against the constant, and the Gemini path forced `outputDimensionality: 1024`. A locally served 768-d encoder such as `google/embeddinggemma-2` could not be used at all. Both values now come from `[embed] model` / `[embed] dim` in `.leio-code/config.toml`, with `LEIO_CODE_EMBED_MODEL` / `LEIO_CODE_EMBED_DIM` overriding and the old pair as defaults, so existing stores are unaffected. Also fixes false provenance: embedded rows stamped `embed_model` from the constant rather than the configured id, so a row embedded by any other encoder still claimed to be bge-m3. Rows now carry the pair that actually produced them. The Gemini substitution is resolved once in `resolved_model` before the stamp is taken, rather than inside the request builder, so the id sent and the id recorded cannot drift apart. `embed_query_url()` stays env-only — an inspected tree must not choose the host that receives query text or `LEIO_CODE_EMBED_API_KEY`. Width mismatches remain errors, now against the configured width; the search path already refuses to score vectors whose width differs from the query's. 900 tests pass, clippy clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
EMBED_DIMwas pinned to1024andEMBED_MODELtoBAAI/bge-m3. All three ingest paths compared the response width against the constant (src/embed.rsOpenAI / TEI / Gemini parsers) and the Gemini path forcedoutputDimensionality: 1024, so no other encoder could be used at all.Concretely:
google/embeddinggemma-2is 768-d (text_config.embedding_dim = 768; Matryoshka cuts are 512/256/128, never 1024), so it was rejected outright.What changed
[embed] dimand[embed] modelare now load-bearing.config::embed_dim()mirrors the existingembed_model():LEIO_CODE_EMBED_DIM→[embed] dim→DEFAULT_EMBED_DIM(1024). Zero and unparseable values fall back rather than producing empty vectors.embed_texts_remoteand the three parsers takedim, and Gemini sends it asoutputDimensionality. Mismatches are still hard errors, now naming both widths.embed_modelfrom theEMBED_MODELconstant, so a row embedded by any other encoder still claimedBAAI/bge-m3. Rows now carry the pair that produced them.resolved_model(), called once before the stamp. Previously a Gemini URL with no[embed] modelwould sendmodels/gemini-embedding-2and stampBAAI/bge-m3— the same bug class in a different place.Compatibility
Defaults are unchanged, so a repo with no
[embed]table behaves exactly as before. Changingmodelordimmakes existing stored vectors incomparable; rebuild withexport arrow-nodes.Notes for review
embed_query_url()is untouched. It stays env-only so an inspected tree cannot choose the host receiving query text orLEIO_CODE_EMBED_API_KEY.embed_texts()(query path) resolves dim from the inspected repo, mirroring the pre-existingembed_model(repo_root)call on the same line. The isolation property is about the URL and key, not the width — flagging it so it is a decision rather than an oversight.src/local_nodes.rs:405, which only scores stored vectors whose length equals the query's; others fall through to on-demand embedding or lexical ranking. A header check would be redundant with that guard.docs/CLI-GUIDE.mdsays plainly not to point one store at two encoders.Verification
cargo test— 900 passed, 0 failedcargo clippy --all-targets— cleancargo fmtappliedNew tests cover a 768-d encoder accepted end-to-end through all three parsers, a 1024-d response rejected against a 768-d store, config resolution and its zero/default fallbacks, and that the stamped model equals the model actually sent.
🤖 Generated with Claude Code