@@ -186,45 +186,59 @@ def initialize(self):
186186 # Log index creation failure but continue
187187 logger .warning (f"Failed to create index: { str (e )} " )
188188
189+ # Create max_sim function for multi-vector similarity search
190+ # This function is specific to multi-vector operations and belongs here
189191 try :
190- # First, try to drop the existing function if it exists
191192 with self .get_connection () as conn :
192- conn .execute (
193+ exists_check = conn .execute (
193194 """
194- DROP FUNCTION IF EXISTS max_sim(bit[], bit[])
195+ SELECT EXISTS (
196+ SELECT 1 FROM pg_proc
197+ WHERE proname = 'max_sim'
198+ AND pg_get_function_arguments(oid) = 'document bit[], query bit[]'
199+ )
195200 """
196- )
197- logger .info ("Dropped existing max_sim function" )
198-
199- # Create max_sim function
200- conn .execute (
201+ ).fetchone ()[0 ]
202+
203+ if not exists_check :
204+ logger .info ("Creating max_sim function for multi-vector similarity search" )
205+ conn .execute (
206+ """
207+ CREATE OR REPLACE FUNCTION public.max_sim(document bit[], query bit[])
208+ RETURNS double precision
209+ LANGUAGE SQL
210+ IMMUTABLE
211+ PARALLEL SAFE
212+ AS $$
213+ WITH queries AS (
214+ SELECT row_number() OVER () AS query_number, *
215+ FROM (SELECT unnest(query) AS query) AS foo
216+ ),
217+ documents AS (
218+ SELECT unnest(document) AS document
219+ ),
220+ similarities AS (
221+ SELECT
222+ query_number,
223+ 1.0 - (bit_count(document # query)::float /
224+ greatest(bit_length(query), 1)::float) AS similarity
225+ FROM queries CROSS JOIN documents
226+ ),
227+ max_similarities AS (
228+ SELECT MAX(similarity) AS max_similarity FROM similarities GROUP BY query_number
229+ )
230+ SELECT COALESCE(SUM(max_similarity), 0.0) FROM max_similarities
231+ $$
201232 """
202- CREATE OR REPLACE FUNCTION max_sim(document bit[], query bit[]) RETURNS double precision AS $$
203- WITH queries AS (
204- SELECT row_number() OVER () AS query_number, *
205- FROM (SELECT unnest(query) AS query) AS foo
206- ),
207- documents AS (
208- SELECT unnest(document) AS document
209- ),
210- similarities AS (
211- SELECT
212- query_number,
213- 1.0 - (bit_count(document # query)::float /
214- greatest(bit_length(query), 1)::float) AS similarity
215- FROM queries CROSS JOIN documents
216- ),
217- max_similarities AS (
218- SELECT MAX(similarity) AS max_similarity FROM similarities GROUP BY query_number
219- )
220- SELECT SUM(max_similarity) FROM max_similarities
221- $$ LANGUAGE SQL
222- """
223- )
224- logger .info ("Created max_sim function successfully" )
233+ )
234+ conn .commit ()
235+ logger .info ("Created max_sim function successfully" )
236+ else :
237+ logger .debug ("max_sim function already exists" )
238+
225239 except Exception as e :
226- logger .error (f"Error creating max_sim function: { str (e )} " )
227- # Continue even if function creation fails - it might already exist and be usable
240+ logger .error (f"Error creating or checking max_sim function: { str (e )} " )
241+ # Continue - we'll get a runtime error if the function is actually missing
228242
229243 logger .info ("MultiVectorStore initialized successfully" )
230244 return True
@@ -279,7 +293,6 @@ async def query_similar(
279293 doc_ids : Optional [List [str ]] = None ,
280294 ) -> List [DocumentChunk ]:
281295 """Find similar chunks using the max_sim function for multi-vectors."""
282- # try:
283296 # Convert query embeddings to binary format
284297 binary_query_embeddings = self ._binary_quantize (query_embedding )
285298
0 commit comments