11import json
22import os
3- from typing import Any , Callable , Optional , Type , List
4-
3+ from typing import Any , Callable , List , Optional , Type
54
65try :
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
1110except 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