Skip to content

fix(memory): normalize gRPC query vector to fix near-zero cosine scores#3422

Merged
bug-ops merged 1 commit intomainfrom
3421-grpc-cosine-norm
Apr 25, 2026
Merged

fix(memory): normalize gRPC query vector to fix near-zero cosine scores#3422
bug-ops merged 1 commit intomainfrom
3421-grpc-cosine-norm

Conversation

@bug-ops
Copy link
Copy Markdown
Owner

@bug-ops bug-ops commented Apr 25, 2026

Summary

Test plan

  • 4 new unit tests for l2_normalize (unit vector, arbitrary [3,4]→[0.6,0.8], zero vector, idempotency)
  • All 8543 workspace unit tests pass
  • Live session test: start Zeph with cargo run --features full -- --config .local/config/testing.toml, verify skill candidates score 0.20–0.45 instead of ~0.022

Closes #3391
Closes #3421

…ro cosine scores

Qdrant stores Cosine-distance vectors as unit vectors internally. The REST
API normalizes the query vector server-side; the gRPC path does not. Sending
an un-normalized vector via gRPC produces near-zero dot-product scores
(~0.022) even when the collection dimension matches, making skill injection
non-functional (issue #3391).

Fix: L2-normalize the query vector in QdrantOps::search before passing it to
SearchPointsBuilder. Zero-magnitude vectors are left unchanged to avoid
division by zero.

Add unit tests for l2_normalize covering: unit vector, arbitrary vector,
zero vector (no-op), and already-unit idempotency.
@github-actions github-actions Bot added memory zeph-memory crate (SQLite) rust Rust code changes bug Something isn't working size/S Small PR (11-50 lines) labels Apr 25, 2026
@bug-ops bug-ops merged commit ca5e062 into main Apr 25, 2026
32 checks passed
@bug-ops bug-ops deleted the 3421-grpc-cosine-norm branch April 25, 2026 23:09
bug-ops added a commit that referenced this pull request Apr 26, 2026
…antOps

The deprecated gRPC search_points path produced near-zero cosine scores
(~0.011) for skill injection, causing all candidates to fall below the
0.20 threshold and zero skills to be injected per turn.

Replace SearchPointsBuilder + client.search_points() with
QueryPointsBuilder + client.query() as recommended by qdrant-client
1.17.0. The Query API returns correct scores (~0.53) for the same
unit-normalized vectors.

Also remove the l2_normalize workaround added in #3422 — it had no
effect since Ollama embeddings are already unit-normalized (norm ≈ 1.0).

Closes #3425
bug-ops added a commit that referenced this pull request Apr 26, 2026
…antOps (#3428)

The deprecated gRPC search_points path produced near-zero cosine scores
(~0.011) for skill injection, causing all candidates to fall below the
0.20 threshold and zero skills to be injected per turn.

Replace SearchPointsBuilder + client.search_points() with
QueryPointsBuilder + client.query() as recommended by qdrant-client
1.17.0. The Query API returns correct scores (~0.53) for the same
unit-normalized vectors.

Also remove the l2_normalize workaround added in #3422 — it had no
effect since Ollama embeddings are already unit-normalized (norm ≈ 1.0).

Closes #3425
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working memory zeph-memory crate (SQLite) rust Rust code changes size/S Small PR (11-50 lines)

Projects

None yet

1 participant