feat: complete catalog-driven preprocessing
Publish documentation / publish (push) Successful in 2m12s
Publish documentation / publish (push) Successful in 2m12s
This commit is contained in:
@@ -188,6 +188,194 @@ def _store(
|
||||
)
|
||||
|
||||
|
||||
def test_explicit_collections_route_reference_and_memory_independently():
|
||||
calls = []
|
||||
|
||||
def request(method, url, *, json=None, timeout=None):
|
||||
calls.append((method, url, json))
|
||||
if method == "GET" and url.endswith("/collections/demo"):
|
||||
return FakeResponse(404, {"status": "error"})
|
||||
if method == "GET":
|
||||
return FakeResponse(200, {
|
||||
"result": {
|
||||
"config": {"params": {"vectors": {"size": 1024, "distance": "Cosine"}}},
|
||||
"payload_schema": {
|
||||
field: {"data_type": "keyword"}
|
||||
for field in (
|
||||
"content_hash", "document_id", "kind", "record_key", "record_kind",
|
||||
"vector_generation", "workspace_id", "workspace_revision",
|
||||
)
|
||||
},
|
||||
}
|
||||
})
|
||||
if method == "POST" and url.endswith("/points/query"):
|
||||
return FakeResponse(200, {"result": {"points": []}})
|
||||
if method == "PUT" and "/points" in url:
|
||||
return FakeResponse(200, {"result": {"status": "acknowledged"}})
|
||||
raise AssertionError((method, url, json))
|
||||
|
||||
store = QdrantVectorStore(
|
||||
base_url="http://qdrant:6333",
|
||||
collections={"reference": "demo-reference", "memory": "demo-memory"},
|
||||
workspace_id="demo",
|
||||
workspace_revision="a" * 40,
|
||||
expected_dimension=1024,
|
||||
request=request,
|
||||
)
|
||||
store.search(["schema_records"], [0.2] * 1024, limit=1)
|
||||
store.search(["memory"], [0.2] * 1024, limit=1)
|
||||
store.upsert("memory", [_write_record("memory:1", "memory")])
|
||||
|
||||
urls = [url for _method, url, _payload in calls]
|
||||
assert any("/collections/demo-reference/points/query" in url for url in urls)
|
||||
assert any("/collections/demo-memory/points/query" in url for url in urls)
|
||||
assert any("/collections/demo-memory/points" in url for url in urls)
|
||||
assert not any("/collections/demo-reference/points?" in url for url in urls)
|
||||
|
||||
|
||||
def test_clear_drops_reference_without_deleting_memory_collection():
|
||||
calls = []
|
||||
|
||||
def request(method, url, *, json=None, timeout=None):
|
||||
calls.append((method, url))
|
||||
if method == "GET" and url.endswith("/collections/demo"):
|
||||
return FakeResponse(404, {"status": "error"})
|
||||
if method == "GET" and url.endswith("/collections/demo-reference"):
|
||||
return FakeResponse(200, {"result": {}})
|
||||
if method == "DELETE" and url.endswith("/collections/demo-reference"):
|
||||
return FakeResponse(200, {"status": "ok"})
|
||||
raise AssertionError((method, url, json))
|
||||
|
||||
store = QdrantVectorStore(
|
||||
base_url="http://qdrant:6333",
|
||||
collections={"reference": "demo-reference", "memory": "demo-memory"},
|
||||
workspace_id="demo",
|
||||
expected_dimension=1024,
|
||||
request=request,
|
||||
)
|
||||
|
||||
assert store.clear_reference() is True
|
||||
assert ("DELETE", "http://qdrant:6333/collections/demo-reference") in calls
|
||||
assert not any(method == "DELETE" and url.endswith("/collections/demo-memory") for method, url in calls)
|
||||
|
||||
|
||||
def test_clear_can_create_memory_collection_before_payload_indexes_become_visible():
|
||||
calls = []
|
||||
memory_created = False
|
||||
|
||||
def request(method, url, *, json=None, timeout=None):
|
||||
nonlocal memory_created
|
||||
calls.append((method, url, json))
|
||||
if method == "GET" and url.endswith("/collections/demo"):
|
||||
return FakeResponse(200, {"result": {}})
|
||||
if method == "GET" and url.endswith("/collections/demo-memory"):
|
||||
if not memory_created:
|
||||
return FakeResponse(404, {"status": "error"})
|
||||
return FakeResponse(200, {
|
||||
"result": {
|
||||
"config": {"params": {"vectors": {"size": 1024, "distance": "Cosine"}}},
|
||||
# Qdrant exposes newly-created payload indexes asynchronously.
|
||||
"payload_schema": {},
|
||||
}
|
||||
})
|
||||
if method == "PUT" and url.endswith("/collections/demo-memory"):
|
||||
memory_created = True
|
||||
return FakeResponse(200, {"status": "ok"})
|
||||
if method == "PUT" and url.endswith("/collections/demo-memory/index"):
|
||||
return FakeResponse(200, {"status": "ok"})
|
||||
if method == "POST" and url.endswith("/collections/demo/points/scroll"):
|
||||
return FakeResponse(200, {
|
||||
"result": {"points": [], "next_page_offset": None}
|
||||
})
|
||||
if method == "DELETE" and url.endswith("/collections/demo"):
|
||||
return FakeResponse(200, {"status": "ok"})
|
||||
if method == "GET" and url.endswith("/collections/demo-reference"):
|
||||
return FakeResponse(404, {"status": "error"})
|
||||
raise AssertionError((method, url, json))
|
||||
|
||||
store = QdrantVectorStore(
|
||||
base_url="http://qdrant:6333",
|
||||
collections={"reference": "demo-reference", "memory": "demo-memory"},
|
||||
workspace_id="demo",
|
||||
expected_dimension=1024,
|
||||
collection_lifecycle="require_existing",
|
||||
request=request,
|
||||
)
|
||||
|
||||
assert store.clear_reference() is True
|
||||
assert memory_created is True
|
||||
assert any(method == "DELETE" and url.endswith("/collections/demo") for method, url, _ in calls)
|
||||
|
||||
|
||||
def test_clear_migrates_legacy_memory_before_retiring_shared_collection():
|
||||
calls = []
|
||||
legacy_point = {
|
||||
"id": "legacy-memory-id",
|
||||
"vector": [0.25] * 1024,
|
||||
"payload": {
|
||||
"workspace_id": "demo",
|
||||
"kind": "memory",
|
||||
"record_kind": "memory",
|
||||
"record_key": "memory:legacy",
|
||||
"content_hash": "sha256:" + "a" * 64,
|
||||
},
|
||||
}
|
||||
ready_memory = {
|
||||
"result": {
|
||||
"config": {"params": {"vectors": {"size": 1024, "distance": "Cosine"}}},
|
||||
"payload_schema": {
|
||||
field: {"data_type": "keyword"}
|
||||
for field in (
|
||||
"content_hash", "document_id", "kind", "record_key", "record_kind",
|
||||
"vector_generation", "workspace_id", "workspace_revision",
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
def request(method, url, *, json=None, timeout=None):
|
||||
calls.append((method, url, json))
|
||||
if method == "GET" and url.endswith("/collections/demo"):
|
||||
return FakeResponse(200, {"result": {}})
|
||||
if method == "GET" and url.endswith("/collections/demo-memory"):
|
||||
return FakeResponse(200, ready_memory)
|
||||
if method == "POST" and url.endswith("/collections/demo/points/scroll"):
|
||||
assert json["with_vector"] is True
|
||||
return FakeResponse(200, {
|
||||
"result": {"points": [legacy_point], "next_page_offset": None}
|
||||
})
|
||||
if method == "PUT" and "/collections/demo-memory/points?wait=true" in url:
|
||||
return FakeResponse(200, {"status": "ok"})
|
||||
if method == "DELETE" and url.endswith("/collections/demo"):
|
||||
return FakeResponse(200, {"status": "ok"})
|
||||
if method == "GET" and url.endswith("/collections/demo-reference"):
|
||||
return FakeResponse(200, {"result": {}})
|
||||
if method == "DELETE" and url.endswith("/collections/demo-reference"):
|
||||
return FakeResponse(200, {"status": "ok"})
|
||||
raise AssertionError((method, url, json))
|
||||
|
||||
store = QdrantVectorStore(
|
||||
base_url="http://qdrant:6333",
|
||||
collections={"reference": "demo-reference", "memory": "demo-memory"},
|
||||
workspace_id="demo",
|
||||
expected_dimension=1024,
|
||||
request=request,
|
||||
)
|
||||
|
||||
assert store.clear_reference() is True
|
||||
migrated = next(
|
||||
payload for method, url, payload in calls
|
||||
if method == "PUT" and "/collections/demo-memory/points?wait=true" in url
|
||||
)
|
||||
assert migrated == {"points": [legacy_point]}
|
||||
deleted = [url for method, url, _payload in calls if method == "DELETE"]
|
||||
assert deleted == [
|
||||
"http://qdrant:6333/collections/demo",
|
||||
"http://qdrant:6333/collections/demo-reference",
|
||||
]
|
||||
assert not any(url.endswith("/collections/demo-memory") for url in deleted)
|
||||
|
||||
|
||||
def _ready_collection_with_bm25(fake: FakeQdrantHttp) -> None:
|
||||
fake.collection = {"vectors": {"size": 1024, "distance": "Cosine"}}
|
||||
fake.payload_indexes = {
|
||||
|
||||
Reference in New Issue
Block a user