fix(rag): bound per-query top_k and score_threshold like the session config (#1102)
What
The session config bounds top_k and score_threshold, but the per-query path (rag.query and rag.search) copied them straight through. A score_threshold outside 0...1 or NaN, or a negative top_k, was used as-is or silently fell back to the default, so retrieval mis-ranked with no error.
Both entry points now reject those values with RAC_ERROR_INVALID_ARGUMENT, through one validate_retrieval_bounds helper beside the BM25/RRF check.
One deliberate deviation from the issue: top_k == 0 stays valid, meaning "use the session default". The web SDK already sends topK: 0 for an unset value and documents it that way, so rejecting zero would break callers. Only negative top_k is an error.
Not done: the issue's third item (range annotations on the four proto fields). That is a schema change that also touches idl/VERSION and SCHEMA_LOCK, which are already being sequenced across the stack, so it is left for that step.
Verification
test_advanced_modality_proto_abi: all new checks pass (negativetop_k,score_threshold1.5, NaNscore_threshold, andtop_k0 accepted). The only failures are the two existing Windows VLM model-path checks, which fail the same way without this change.test_rag_fusion: 14 checks, 0 failures.
Stacking
Stacked on #1066 (fix/web-rag-knobs-cross-wasm-provider-1057), which sits on #1048 → #1017. The diff includes those commits until they merge.
Closes #1102
Summary by cubic
Per-query RAG retrieval (rag.query and rag.search) now bounds top_k and score_threshold like the session config, so a negative top_k or a score_threshold outside 0...1 (or NaN) is rejected with RAC_ERROR_INVALID_ARGUMENT instead of silently mis-ranking results. The PR also threads BM25, RRF, and vector-store knobs through the whole stack.
top_k == 0stays the "use the session default" sentinel that every SDK already sends.- BM25 (
bm25_k1,bm25_b), RRF (rrf_k), andvector_storeare validated at the ABI boundary and wired into session config, per-query overrides, the retrieve backend, and all SDK bindings (Kotlin, Python, Swift, Web). - The retrieve operator parses floats with the classic locale and rejects malformed params; the converter formats floats the same way so they round-trip.
- The Web cross-WASM RAG provider rejects the native-only knobs with an error instead of silently ignoring them.
VECTOR_STORE_USEARCHis whitelisted on-device; PGVECTOR returnsNOT_SUPPORTEDand unknown enum values returnINVALID_ARGUMENT.- The
VectorStoreenum moved fromsolutions.prototorag.protoandIDL_VERSIONbumped to 1.7.0; proto range annotations on the new fields are left for a separate schema change.
Summary by CodeRabbit
- New Features
- RAG retrieval options now support per-query BM25 tuning, reciprocal-rank-fusion tuning, and USEARCH vector-store selection across Kotlin, Python, Swift, and Web SDKs.
- Retrieval settings can be customized at the session level, with per-query overrides where supported. Omitted options continue to use session defaults.
- Ranking results are more consistent when candidates have equal scores.
- Bug Fixes
- Invalid retrieval settings are rejected with errors instead of being silently accepted or misinterpreted.
- Cross-WASM queries report an error when given native-only retrieval options.