Support modern Qdrant search API
This commit is contained in:
@@ -3,7 +3,7 @@ from typing import List, Dict, Any, Optional
|
||||
from pathlib import Path
|
||||
|
||||
from .config import settings
|
||||
from .vector_store import get_client, _collection_name as VECTOR_COLLECTION
|
||||
from .vector_store import get_client, query_points
|
||||
from .embeddings import embed_text, get_embedding_size
|
||||
from .db import get_chunks_for_library, list_libraries
|
||||
|
||||
@@ -55,12 +55,7 @@ def search_docs(
|
||||
search_filter = None
|
||||
|
||||
# Perform vector search
|
||||
results = client.search(
|
||||
collection_name=VECTOR_COLLECTION,
|
||||
query_vector=query_embedding,
|
||||
limit=limit,
|
||||
search_filter=search_filter
|
||||
)
|
||||
results = query_points(client, query_embedding, limit, search_filter)
|
||||
|
||||
# Format and return results
|
||||
formatted_results = []
|
||||
|
||||
@@ -64,6 +64,37 @@ def get_embedding_size() -> int:
|
||||
return 384
|
||||
|
||||
|
||||
def query_points(
|
||||
client: Any,
|
||||
query_vector: List[float],
|
||||
limit: int,
|
||||
search_filter: Optional[Any] = None,
|
||||
) -> List[Any]:
|
||||
"""Run a vector query across old and new qdrant-client APIs."""
|
||||
legacy_search = getattr(client, "search", None)
|
||||
if callable(legacy_search):
|
||||
return legacy_search(
|
||||
collection_name=_collection_name,
|
||||
query_vector=query_vector,
|
||||
limit=limit,
|
||||
search_filter=search_filter,
|
||||
)
|
||||
|
||||
modern_query = getattr(client, "query_points", None)
|
||||
if not callable(modern_query):
|
||||
raise RuntimeError(
|
||||
"Installed qdrant-client supports neither search() nor query_points()"
|
||||
)
|
||||
|
||||
response = modern_query(
|
||||
collection_name=_collection_name,
|
||||
query=query_vector,
|
||||
limit=limit,
|
||||
query_filter=search_filter,
|
||||
)
|
||||
return list(response.points)
|
||||
|
||||
|
||||
def create_collection(client: Any, collection_name: str, size: int, distance: Any) -> None:
|
||||
"""Create a Qdrant collection across qdrant-client keyword changes."""
|
||||
vector_params = VectorParams(size=size, distance=distance)
|
||||
@@ -255,12 +286,7 @@ async def search_vectors(
|
||||
)
|
||||
|
||||
# Perform vector search
|
||||
results = client.search(
|
||||
collection_name=_collection_name,
|
||||
query_vector=query_vector,
|
||||
limit=limit,
|
||||
search_filter=search_filter
|
||||
)
|
||||
results = query_points(client, query_vector, limit, search_filter)
|
||||
|
||||
# Format results
|
||||
formatted_results = []
|
||||
|
||||
@@ -178,6 +178,40 @@ class TestSearchDocs:
|
||||
assert "title" in result
|
||||
assert "chunk_index" in result
|
||||
|
||||
def test_uses_modern_qdrant_query_points_api(self):
|
||||
"""New qdrant-client versions expose query_points instead of search."""
|
||||
from unittest.mock import patch
|
||||
from backend.app.search import search_docs
|
||||
|
||||
point = type("ScoredPoint", (), {
|
||||
"score": 0.91,
|
||||
"payload": {
|
||||
"id": "modern-result",
|
||||
"library_id": "documentation",
|
||||
"path": "docs/index.md",
|
||||
"title": "Index",
|
||||
"chunk_index": 0,
|
||||
},
|
||||
})()
|
||||
|
||||
class Response:
|
||||
points = [point]
|
||||
|
||||
class ModernClient:
|
||||
def query_points(self, **kwargs):
|
||||
assert kwargs["query"] == [0.1, 0.2]
|
||||
assert kwargs["limit"] == 3
|
||||
return Response()
|
||||
|
||||
with (
|
||||
patch("backend.app.search.embed_text", return_value=[0.1, 0.2]),
|
||||
patch("backend.app.search.get_client", return_value=ModernClient()),
|
||||
):
|
||||
results = search_docs("world generation", limit=3)
|
||||
|
||||
assert len(results) == 1
|
||||
assert results[0]["id"] == "modern-result"
|
||||
|
||||
|
||||
class TestGetLibraryDocs:
|
||||
"""Tests for get_library_docs() - document retrieval."""
|
||||
|
||||
Reference in New Issue
Block a user