Skip to content

bug(vector_stores/redis): search score hardcoded for cosine, breaks L2 ranking #7249

Open

Description

@ktz03

Description

Same class of bug as #6546 / #6547 / #7229, but in the Redis vector store.

RedisDB.search hardcodes:

score=max(0.0, 1.0 - float(result["vector_distance"]))

That mapping is only correct for cosine. create_col(..., distance=...) already accepts a metric and writes it into the RedisVL schema (distance_metric), but search scoring never reads that metric — L2 (and similar unbounded distances) collapse almost every hit with d > 1 to 0.0, breaking ranking and score thresholds.

Also, RedisDB.__init__ / RedisDBConfig have no distance field, so the default index is always created as cosine in DEFAULT_FIELDS, and there is nowhere for operators to declare the metric used for scoring.

Steps to Reproduce

  1. Create a Redis collection with a non-cosine metric:
    store.create_col(name="demo", vector_size=768, distance="l2")
  2. Insert vectors and search.
  3. Observe returned scores: neighbors with L2 distance > 1 become 0.0 under 1 - distance.

Expected Behavior

  • Config / constructor can declare a distance metric (default cosine).
  • create_col(..., distance=...) persists the metric for scoring, not only for FT.CREATE.
  • Search converts distance → similarity in a metric-aware way (same approach as fix(vector_stores/s3_vectors): make search score metric-aware #6547):
    • cosine / ip: max(0, 1 - d)
    • l2: 1 / (1 + d) so scores stay in (0, 1] and preserve ordering

Additional Context

Activity

  1. added a commit that references this issue on Sep 8, 2026
    930a019
  2. ktz03 commented on Sep 8, 2026

    @ktz03
    Author

    PR ready for this issue (Redis sibling of #6546/#7229). It will auto-reopen once labeled accepted.

    @kartik-mem0 when convenient, could you add accepted? Preferred sequence: Valkey #7229 → this Redis fix → Weaviate #7250 / Vertex #7232.

  3. added a commit that references this issue on Sep 8, 2026
    8159432
  4. ktz03 commented on Sep 8, 2026

    @ktz03
    Author

    PR ready for this issue (Redis sibling of #6546/#7229). It will auto-reopen once labeled accepted.

    @kartik-mem0 when convenient, could you add accepted? Preferred sequence: Valkey #7229 → this Redis fix → Weaviate #7250 / Vertex #7232.

  5. blazingretinol commented on Sep 25, 2026

    @blazingretinol
    Contributor

    Traced this on main and could not confirm it as a live bug. RedisDBConfig has no distance field, extra keys are rejected, and RedisDB.init always builds the index with distance_metric cosine in DEFAULT_FIELDS. Memory never calls create_col with a distance argument, so mem0's Redis store is cosine only today: the L2 score collapse you describe can't happen through any setting we expose. create_col(distance=...) is real code but only reachable by calling it directly on the store object, bypassing config entirely. PRs #7251 and #7253 are identical and would add the missing config plus the metric-aware scoring together, that combination is what this actually needs.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    sdk-pythonPython SDK specificvector-storeVector store backends (Qdrant, PGVector, Redis, etc.)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions