Skip to content
This repository was archived by the owner on Nov 10, 2025. It is now read-only.

Commit df8cdcf

Browse files
Implement improvements on the QdrantVectorSearchTool
- Allow search filters to be set at the constructor level - Fix issue that prevented multiple records from being returned
1 parent e7a182a commit df8cdcf

1 file changed

Lines changed: 38 additions & 16 deletions

File tree

crewai_tools/tools/qdrant_vector_search_tool/qdrant_search_tool.py

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import json
22
import os
3-
from typing import Any, Callable, Optional, Type, List
4-
3+
from typing import Any, Callable, List, Optional, Type
54

65
try:
76
from qdrant_client import QdrantClient
8-
from qdrant_client.http.models import Filter, FieldCondition, MatchValue
7+
from qdrant_client.http.models import FieldCondition, Filter, MatchValue
98

109
QDRANT_AVAILABLE = True
1110
except ImportError:
@@ -57,8 +56,8 @@ class QdrantVectorSearchTool(BaseTool):
5756
description: str = "A tool to search the Qdrant database for relevant information on internal documents."
5857
args_schema: Type[BaseModel] = QdrantToolSchema
5958
query: Optional[str] = None
60-
filter_by: Optional[str] = None
61-
filter_value: Optional[str] = None
59+
filter_conditions: Optional[list[tuple[str, Any]]] = []
60+
search_filter: Optional[Filter] = None
6261
collection_name: Optional[str] = None
6362
limit: Optional[int] = Field(default=3)
6463
score_threshold: float = Field(default=0.35)
@@ -101,6 +100,18 @@ def __init__(self, **kwargs):
101100
"The 'qdrant-client' package is required to use the QdrantVectorSearchTool. "
102101
"Please install it with: uv add qdrant-client"
103102
)
103+
if kwargs.get("filter_conditions"):
104+
must_conditions = []
105+
for filter_condition in kwargs.get("filter_conditions"):
106+
must_conditions.append(
107+
FieldCondition(
108+
key=filter_condition[0],
109+
match=MatchValue(value=filter_condition[1]),
110+
)
111+
)
112+
self.search_filter = Filter(must=must_conditions)
113+
else:
114+
self.search_filter = None
104115

105116
def _run(
106117
self,
@@ -126,14 +137,26 @@ def _run(
126137
if not self.qdrant_url:
127138
raise ValueError("QDRANT_URL is not set")
128139

129-
# Create filter if filter parameters are provided
130-
search_filter = None
140+
# If filter_by and filter_value are provided, add them to the search filter
141+
# without modifying the original search filter
142+
search_filter = self.search_filter.copy() if self.search_filter else None
131143
if filter_by and filter_value:
132-
search_filter = Filter(
133-
must=[
144+
if (
145+
search_filter
146+
and hasattr(search_filter, "must")
147+
and isinstance(search_filter.must, list)
148+
):
149+
search_filter.must.append(
134150
FieldCondition(key=filter_by, match=MatchValue(value=filter_value))
135-
]
136-
)
151+
)
152+
else:
153+
search_filter = Filter(
154+
must=[
155+
FieldCondition(
156+
key=filter_by, match=MatchValue(value=filter_value)
157+
)
158+
]
159+
)
137160

138161
# Search in Qdrant using the built-in query method
139162
query_vector = (
@@ -151,12 +174,11 @@ def _run(
151174

152175
# Format results similar to storage implementation
153176
results = []
154-
# Extract the list of ScoredPoint objects from the tuple
155-
for point in search_results:
177+
for point in search_results.points:
156178
result = {
157-
"metadata": point[1][0].payload.get("metadata", {}),
158-
"context": point[1][0].payload.get("text", ""),
159-
"distance": point[1][0].score,
179+
"distance": point.score,
180+
"metadata": point.payload.get("metadata", {}),
181+
"context": point.payload.get("text", ""),
160182
}
161183
results.append(result)
162184

0 commit comments

Comments
 (0)