fix: 适配qdrant-client 1.17.0 API变更,search方法改为query_points [AC-AISVC-50]

- qdrant-client 1.10+ 版本移除了 search() 方法,改用 query_points()
- 使用 collection_exists() 替代 get_collections() 检查集合存在
- 更新返回结果处理:results.points 替代 results
- 更新 pyproject.toml 版本约束为 >=1.9.0,<2.0.0
- 修正 README.md 中的 docker 命令示例
This commit is contained in:
MerCry 2026-02-26 19:05:58 +08:00
parent d660c19ab9
commit 15016d3448
3 changed files with 20 additions and 15 deletions

View File

@ -114,10 +114,10 @@ docker exec -it ai-ollama ollama pull toshk0/nomic-embed-text-v2-moe:Q6_K
```bash ```bash
# 检查服务状态 # 检查服务状态
docker compose ps docker ps
# 查看后端日志,找到自动生成的 API Key # 查看后端日志,找到自动生成的 API Key
docker compose logs -f ai-service | grep "Default API Key" docker logs -f ai-service | grep "Default API Key"
``` ```
> **重要**: 后端首次启动时会自动生成一个默认 API Key请从日志中复制该 Key用于前端配置。 > **重要**: 后端首次启动时会自动生成一个默认 API Key请从日志中复制该 Key用于前端配置。

View File

@ -8,7 +8,7 @@ import logging
from typing import Any from typing import Any
from qdrant_client import AsyncQdrantClient from qdrant_client import AsyncQdrantClient
from qdrant_client.models import Distance, PointStruct, VectorParams, MultiVectorConfig from qdrant_client.models import Distance, PointStruct, VectorParams, QueryRequest
from app.core.config import get_settings from app.core.config import get_settings
@ -61,8 +61,7 @@ class QdrantClient:
collection_name = self.get_collection_name(tenant_id) collection_name = self.get_collection_name(tenant_id)
try: try:
collections = await client.get_collections() exists = await client.collection_exists(collection_name)
exists = any(c.name == collection_name for c in collections.collections)
if not exists: if not exists:
if use_multi_vector: if use_multi_vector:
@ -213,36 +212,42 @@ class QdrantClient:
try: try:
logger.info(f"[AC-AISVC-10] Searching in collection: {collection_name}") logger.info(f"[AC-AISVC-10] Searching in collection: {collection_name}")
exists = await client.collection_exists(collection_name)
if not exists:
logger.warning(f"[AC-AISVC-10] Collection {collection_name} does not exist")
continue
try: try:
results = await client.search( results = await client.query_points(
collection_name=collection_name, collection_name=collection_name,
query_vector=(vector_name, query_vector), query=query_vector,
using=vector_name,
limit=limit, limit=limit,
with_vectors=with_vectors, with_vectors=with_vectors,
score_threshold=score_threshold,
) )
except Exception as e: except Exception as e:
if "vector name" in str(e).lower() or "Not existing vector" in str(e): if "vector name" in str(e).lower() or "Not existing vector" in str(e) or "using" in str(e).lower():
logger.info( logger.info(
f"[AC-AISVC-10] Collection {collection_name} doesn't have vector named '{vector_name}', " f"[AC-AISVC-10] Collection {collection_name} doesn't have vector named '{vector_name}', "
f"trying without vector name (single-vector mode)" f"trying without vector name (single-vector mode)"
) )
results = await client.search( results = await client.query_points(
collection_name=collection_name, collection_name=collection_name,
query_vector=query_vector, query=query_vector,
limit=limit, limit=limit,
with_vectors=with_vectors, with_vectors=with_vectors,
score_threshold=score_threshold,
) )
else: else:
raise raise
logger.info( logger.info(
f"[AC-AISVC-10] Collection {collection_name} returned {len(results)} raw results" f"[AC-AISVC-10] Collection {collection_name} returned {len(results.points)} raw results"
) )
hits = [] hits = []
for result in results: for result in results.points:
if score_threshold is not None and result.score < score_threshold:
continue
hit = { hit = {
"id": str(result.id), "id": str(result.id),
"score": result.score, "score": result.score,

View File

@ -14,7 +14,7 @@ dependencies = [
"tenacity>=8.2.0", "tenacity>=8.2.0",
"sqlmodel>=0.0.14", "sqlmodel>=0.0.14",
"asyncpg>=0.29.0", "asyncpg>=0.29.0",
"qdrant-client>=1.7.0", "qdrant-client>=1.9.0,<2.0.0",
"tiktoken>=0.5.0", "tiktoken>=0.5.0",
"openpyxl>=3.1.0", "openpyxl>=3.1.0",
"python-docx>=1.1.0", "python-docx>=1.1.0",