fix: make qdrant vector hit parsing total

This commit is contained in:
2026-08-11 08:40:53 +02:00
parent 2f3325c03f
commit f7b442be61
2 changed files with 83 additions and 3 deletions
+70
View File
@@ -892,3 +892,73 @@ def test_scroll_accepts_null_or_missing_terminal_offset(next_page_offset):
expected_dimension=1024, request=request,
)
assert store.existing_hashes("memory", ["memory"]) == {}
_QUERY_PAYLOAD = {
"record_key": "memory:1",
"record_kind": "memory",
"kind": "memory",
"ref": "ref:memory:1",
"title": "title:memory:1",
"content": "content:memory:1",
}
def _query_response_store(points):
fake = FakeQdrantHttp()
fake.collection = {"vectors": {"size": 1024, "distance": "Cosine"}}
fake.payload_indexes = set(_REQUIRED_INDEXES)
original = fake.request
def request(method, url, **kwargs):
if method == "POST" and url.endswith("/points/query"):
return FakeResponse(200, {"result": {"points": points}})
return original(method, url, **kwargs)
store = _store(fake)
store._request = request
return store
@pytest.mark.parametrize("leaf", [
"record_key", "record_kind", "kind", "ref", "title", "content",
])
def test_query_rejects_non_string_required_vector_hit_payload_leaves(leaf):
payload = {**_QUERY_PAYLOAD, leaf: 1}
store = _query_response_store([{"id": "p1", "score": 0.9, "payload": payload}])
with pytest.raises(VectorResponseError):
store.search(["memory"], [0.2] * 1024, limit=1, kinds=["memory"])
@pytest.mark.parametrize("leaf", [
"record_key", "record_kind", "kind", "ref", "title", "content",
])
def test_query_rejects_missing_required_vector_hit_payload_leaves(leaf):
payload = {key: value for key, value in _QUERY_PAYLOAD.items() if key != leaf}
store = _query_response_store([{"id": "p1", "score": 0.9, "payload": payload}])
with pytest.raises(VectorResponseError):
store.search(["memory"], [0.2] * 1024, limit=1, kinds=["memory"])
def test_query_rejects_heterogeneous_record_keys_before_sorting_hits():
store = _query_response_store([
{"id": "p1", "score": 0.9, "payload": _QUERY_PAYLOAD},
{
"id": "p2",
"score": 0.8,
"payload": {**_QUERY_PAYLOAD, "record_key": 2},
},
])
with pytest.raises(VectorResponseError):
store.search(["memory"], [0.2] * 1024, limit=2, kinds=["memory"])
@pytest.mark.parametrize("score", [True, False, 10**1000, float("nan"), float("inf"), float("-inf")])
def test_query_rejects_scores_that_cannot_be_finite_float(score):
store = _query_response_store([{"id": "p1", "score": score, "payload": _QUERY_PAYLOAD}])
with pytest.raises(VectorResponseError):
store.search(["memory"], [0.2] * 1024, limit=1, kinds=["memory"])
+13 -3
View File
@@ -1,5 +1,6 @@
"""Qdrant-backed vector store for one workspace-owned semantic collection."""
import math
import re
from collections.abc import Callable
from uuid import NAMESPACE_URL, uuid5
@@ -477,16 +478,25 @@ class QdrantVectorStore:
raise VectorResponseError("Qdrant returned malformed query response")
payload = point.get("payload")
score = point.get("score")
required_payload_leaves = (
"record_key", "record_kind", "kind", "ref", "title", "content"
)
if (
not isinstance(payload, dict)
or type(score) not in (int, float)
or any(
key in payload and not isinstance(payload[key], str)
for key in ("record_key", "record_kind", "kind", "ref", "title", "content")
key not in payload or not isinstance(payload[key], str)
for key in required_payload_leaves
)
):
raise VectorResponseError("Qdrant returned malformed query response")
return hit_from_metadata(float(score), payload)
try:
similarity = float(score)
except (OverflowError, ValueError) as exc:
raise VectorResponseError("Qdrant returned malformed query response") from exc
if not math.isfinite(similarity):
raise VectorResponseError("Qdrant returned malformed query response")
return hit_from_metadata(similarity, payload)
def _call(self, method: str, path: str, payload: dict | None, allow_missing: bool = False) -> dict | None:
try: