Skip to content

HybridQuery.yieldCombinedScoreAs() emits invalid FT.HYBRID (COMBINE arg-count off-by-2) → silent fallback to FT.AGGREGATE #30

Description

@guyroyse

Summary

Calling .yieldCombinedScoreAs(...) on a HybridQuery produces an FT.HYBRID command whose COMBINE RRF <n> argument count does not include the appended YIELD_SCORE_AS <name> tokens. Those two tokens therefore fall outside the COMBINE clause, Redis rejects the command with YIELD_SCORE_AS: Unknown argument, and the client silently falls back to AggregateHybridQuery (FT.AGGREGATE) — which combines with a hardcoded LINEAR weighting instead of the requested RRF, changing both the result set and the ranking, with only a WARN surfaced to the caller.

Environment

  • com.redis:redisvl 0.13.1
  • Redis 8.6.2 (built-in query engine; FT.HYBRID available)
  • Jedis 7.3.0
  • Java 17+ (reproduced on JDK 25)

Reproduction

HybridQuery query = HybridQuery.builder()
    .text("creature crossed the road at night")
    .textFieldName("observed")
    .vector(queryVector)               // float[1536]
    .vectorFieldName("embedding")
    .textScorer("BM25STD")
    .combinationMethod(HybridQuery.CombinationMethod.RRF)
    .rrfWindow(20)
    .rrfConstant(60)
    .numResults(5)
    .returnFields(List.of("id", "state", "county", "classification", "observed"))
    .yieldCombinedScoreAs("score")     // <-- triggers the bug
    .build();
index.query(query);

Log:

WARN com.redis.vl.index.SearchIndex - FT.HYBRID failed, falling back to
AggregateHybridQuery (FT.AGGREGATE): YIELD_SCORE_AS: Unknown argument

Captured command (redis-cli MONITOR)

The command redisvl-java actually sends (vector blobs elided as <vec>):

FT.HYBRID bigfoot SEARCH <vec> SCORER BM25STD VSIM @embedding $vector KNN 2 K 5
  COMBINE RRF 4 WINDOW 20 CONSTANT 60.0 YIELD_SCORE_AS score
  LOAD 5 @id @state @county @classification @observed LIMIT 0 5 PARAMS 2 vector <vec>

COMBINE RRF 4 is followed by WINDOW 20 CONSTANT 60.0 (4 tokens) and then YIELD_SCORE_AS score. The count 4 omits the two YIELD_SCORE_AS score tokens, so they are parsed outside the COMBINE clause → YIELD_SCORE_AS: Unknown argument.

For comparison, the equivalent redisvl (Python 0.20.1) command, which Redis accepts:

FT.HYBRID bigfoot SEARCH <vec> SCORER BM25STD VSIM @embedding $vector
  COMBINE RRF 6 WINDOW 20 CONSTANT 60 YIELD_SCORE_AS score
  LOAD 5 ... LIMIT 0 5 PARAMS 2 vector <vec>

Here COMBINE RRF 6 correctly counts all six following tokens (WINDOW 20 CONSTANT 60 YIELD_SCORE_AS score).

Root cause

The COMBINE RRF <n> argument count is derived from the window/constant args but is not incremented when YIELD_SCORE_AS <name> is appended.

Impact

  • The combined score cannot be retrieved on the native FT.HYBRID path (without the yield, scores come back as 1.0).
  • The silent fallback to FT.AGGREGATE uses a hardcoded LINEAR blend (0.3*text_score + 0.7*vector_similarity), not the requested RRF, so the result set and ranking differ from what was configured — and the caller only sees a WARN.

Suggested fix

Include the YIELD_SCORE_AS <name> tokens (2) in the COMBINE RRF <n> (and COMBINE LINEAR <n>) argument count when yieldCombinedScoreAs is set — i.e. emit COMBINE RRF 6 … rather than COMBINE RRF 4 … in the example above.

Separately, consider surfacing the FT.HYBRIDFT.AGGREGATE fallback more prominently (it silently changes the combination algorithm).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions