
    rOi8M                         d dl Z d dlmZ d dlmZ d dlmZ d dlmZm	Z	m
Z
mZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZmZ d dlmZ d dlmZ d dlmZ d dlm Z m!Z! d dl"m#Z#  G d de!      Z$ G d d      Z%y)    N)defaultdict)deepcopy)get_all_start_methods)IterableAnyTypeget_args)	BaseModel)models)INFERENCE_OBJECT_TYPES)InspectorEmbed)Embedder)NumericVectorNumericVectorStruct)ModelSchemaParser)	FieldPath)FastEmbedMisc)ParallelWorkerPoolWorker)
iter_batchc                   j    e Zd ZdedefdZedededd fd       Zdee	eef      dee	eef      fdZ
y)	ModelEmbedderWorker
batch_sizekwargsc                 2    t        di || _        || _        y )N )ModelEmbeddermodel_embedderr   )selfr   r   s      i/volume1/homes/robertsu/coba/app/.venv/lib/python3.12/site-packages/qdrant_client/embed/model_embedder.py__init__zModelEmbedderWorker.__init__   s    +5f5$    returnc                      | dd|d|S )N   )threadsr   r   r   )clsr   r   s      r    startzModelEmbedderWorker.start   s    >1>v>>r"   itemsc              #      K   |D ]9  \  }}|t        | j                  j                  || j                              f ; y w)Ninference_batch_size)listr   embed_models_batchr   )r   r)   idxbatchs       r    processzModelEmbedderWorker.process   sK     JC''::DOO ;    s   A AN)__name__
__module____qualname__intr   r!   classmethodr(   r   tupler1   r   r"   r    r   r      sl    %3 %# % ?s ?c ?6K ? ?	XeCHo6 	8E#s(O;T 	r"   r   c                   x   e Zd ZdZ	 	 ddedz  dedefdZ	 	 ddee	e   z  ded	e
d
e	e   fdZ	 	 dde	eeef   ez     d	e
de
dz  d
e	eeef   ez     fdZ	 	 ddeeeef   ez     dede
d
e	e   fdZ	 	 	 	 ddeeef   ez  dee   dz  dedede
dz  d
eeef   eeef   z  ez  ez  ej(                  z  fdZdej,                  d
dfdZ	 d dej,                  dede
d
eej(                  z  fdZddede
d
dfdZded
eej(                  z  fdZdej,                  d
ej,                  fdZed
ee   fd       Z y)!r   @   Nparseris_local_moder   c                     i | _         i | _        t        |      | _        | | _        t        j                         | _        t        dd| j                  i|| _	        y )N)r:   use_core_bm25r   )
_batch_accumulator_embed_storager   _embed_inspector_is_builtin_embedder_availabler   is_installed_fastembed_availabler   embedder)r   r:   r;   r   s       r    r!   zModelEmbedder.__init__-   sZ     LNVX .f =2?.?+$1$>$>$@! ]t/R/R]V\]r"   
raw_modelsis_queryr   r#   c              #      K   | j                   st        j                          t        |t              r|g}t        ||      D ]  }| j                  |||      E d{      y7 w)a2  Embed raw data fields in models and return models with vectors

            If any of model fields required inference, a deepcopy of a model with computed embeddings is returned,
            otherwise returns original models.
        Args:
            raw_models: Iterable[BaseModel] - models which can contain fields with raw data
            is_query: bool - flag to determine which embed method to use. Defaults to False.
            batch_size: int - batch size for inference
        Returns:
            list[BaseModel]: models with embedded fields
        r+   N)rA   r   import_fastembed
isinstancer
   r   r.   )r   rE   rF   r   raw_models_batchs        r    embed_modelszModelEmbedder.embed_models:   sj     " 22**,j),$J *:z B.. ( /    !Cs   AA&A$A&parallelc              #     K   | j                   st        j                          d}t        |t              rt        |      |k  rd}||dk(  s|r-t        ||      D ]  }| j                  ||      E d{     yd}t        ||      }|dk(  rt        j                         }dt               v rdnd	}|J t        || j                         || j                  
      }	|	j                  ||      D ]  }|E d{     y7 7 	w)a1  Embed raw data fields in models and return models with vectors

        Requires every input sequences element to contain raw data fields to inference.
        Does not accept ready vectors.

        Args:
            raw_models: Iterable[BaseModel] - models which contain fields with raw data to inference
            batch_size: int - batch size for inference
            parallel: int - number of parallel processes to use. Defaults to None.

        Returns:
            Iterable[Union[dict[str, BaseModel], BaseModel]]: models with embedded fields
        FTNr%   r+   )sizer   
forkserverspawn)num_workersworkerstart_methodmax_internal_batch_size)r   )rA   r   rH   rI   r-   lenr   r.   os	cpu_countr   r   _get_worker_classMAX_INTERNAL_BATCH_SIZEordered_map)
r   rE   r   rL   is_smallr0   multiprocessing_batch_sizeraw_models_batchesrS   pools
             r    embed_models_strictz!ModelEmbedder.embed_models_strictU   s    & 22**,j$':+x1}#J
;225z2ZZZ < *+&!+J=W!X1}<<>+7;P;R+R<X_L'''%$--/)(,(D(D	D ))"/I *  !  # [( !s%   A1D3D4BD9D:DDr,   c              #       K    j                   st        j                          |D ]  } j                  |d         j                  s|E d{    y fd|D        E d{    y7 7 w)af  Embed a batch of models with raw data fields and return models with vectors

            If any of model fields required inference, a deepcopy of a model with computed embeddings is returned,
            otherwise returns original models.
        Args:
            raw_models: list[Union[dict[str, BaseModel], BaseModel]] - models which can contain fields with raw data
            is_query: bool - flag to determine which embed method to use. Defaults to False.
            inference_batch_size: int - batch size for inference
        Returns:
            Iterable[BaseModel]: models with embedded fields
        T)rF   accumulatingNc              3   H   K   | ]  }j                  |d         yw)FrF   ra   r,   N)_process_model).0	raw_modelr,   rF   r   s     r    	<genexpr>z3ModelEmbedder.embed_models_batch.<locals>.<genexpr>   s9       ",I ##%!&)=	 $  ",s   ")rA   r   rH   rd   r>   )r   rE   rF   r,   rf   s   ` `` r    r.   z ModelEmbedder.embed_models_batch   su     " 22**,#I	H4P $ &&!!! ",   "s$   AA2A.A2(A0)A20A2modelpathsra   c           
         t        |t        t                    r1|r| j                  |       n|J d       | j	                  |||      S ||st        |      n|}t        |t              rJ|j                         D ]5  \  }}|r| j                  ||d       | j                  |||d|      ||<   7 |S ||n| j                  j                  |      }|D ]  }t        |t              s|gn|}	|	D ]  }
t        |
|j                  d      }||j                  r!| j                  ||j                  |||       Jt        |t              }|r|n|g}|s_|J d       |D cg c]  }| j	                  |||       }}|rt        |
|j                  |       t        |
|j                  |d          |D ]  }| j                  |          |S c c}w )	ab  Embed model's fields requiring inference

        Args:
            model: Qdrant http model containing fields to embed
            paths: Path to fields to embed. E.g. [FieldPath(current="recommend", tail=[FieldPath(current="negative", tail=None)])]
            is_query: Flag to determine which embed method to use. Defaults to False.
            accumulating: Flag to determine if we are accumulating models for batch embedding. Defaults to False.
            inference_batch_size: Optional[int] - batch size for inference

        Returns:
            A deepcopy of the method with embedded fields
        Nz3inference_batch_size should be passed for inferencerF   r,   T)ra   Frc   r   )rI   r	   r   _accumulate_drain_accumulatorr   dictr)   rd   r@   inspectr-   getattrcurrenttailsetattr)r   rh   ri   rF   ra   r,   keyvaluepath
list_modelitemcurrent_modelwas_listdata
embeddingss                  r    rd   zModelEmbedder._process_model   s$   6 eX&<=>  ' )4IHI4..%)= /   =+7HUOUEeT"#kkm
U''u4'H!%!4!4!)%*-A "5 "E#J	 , L*0E0E0M0Me0TD(25$(?%UJ" 'dllD A (99''%		!)%1-A (   *->H5=MM?M'0<QPQ< )6	& )6 !33 $xNb 4  )6	 # & $#D$,,
C#D$,,
1F$1D ,,T2 %2? # F &s   !Gr{   c                     t        |t              r'|j                         D ]  }| j                  |        yt        |t              r3|D ].  }t        |t        t                    s y| j                  |       0 t        |t        t                    sy| j                  |      }|j                  | j                  vrg | j                  |j                  <   | j                  |j                     j                  |       y)aH  Add data to batch accumulator

        Args:
            data: models.VectorStruct - any vector struct data, if inference object types instances in `data` - add them
                to the accumulator, otherwise - do nothing. `InferenceObject` instances are converted to proper types.

        Returns:
            None
        N)rI   rn   valuesrl   r-   r	   r   _resolve_inference_objectrh   r>   append)r   r{   ru   s      r    rl   zModelEmbedder._accumulate  s     dD!  ' 'dD!!%2H)IJ  ' 
 $)? @A--d3::T44424D##DJJ/

+2248r"   c                 ,   t        |t              r1|j                         D ]  \  }}| j                  |||      ||<    |S t        |t              rIt        |      D ]9  \  }}t        |t        t                    s|c S | j                  |||      ||<   ; |S t        |t        t                    s|S | j                  r&| j                  j                  |j                  d      s| j                  ||       | j                  |j                        S )at  Drain accumulator and replaces inference objects with computed embeddings
            It is assumed objects are traversed in the same order as they were added to the accumulator

        Args:
            data: models.VectorStruct - any vector struct data, if inference object types instances in `data` - replace
                them with computed embeddings. If embeddings haven't yet been computed - compute them and then replace
                inference objects.
            inference_batch_size: int - batch size for inference

        Returns:
            NumericVectorStruct: data with replaced inference objects
        rk   N)rI   rn   r)   rm   r-   	enumerater	   r   r?   getrh   _embed_accumulator_next_embed)r   r{   rF   r,   rt   ru   is          r    rm   z ModelEmbedder._drain_accumulator+  s    dD!"jjl
U 33HCW 4 S	 + KdD!%dO5!%2H)IJK11HCW 2 Q	 , K(12
 K""$*=*=*A*A$**d*S##XL`#a

++r"   c           
          dt         t           dt        dt        dt         t           t         t
        j                     z  f fd} j                  D ]  }t         j                  j                  |       j                  j                  |       j                  j                  |       j                  j                  |       j                  j                  |      f      rt        | d        j                  j!                         D ]  \  }} ||||       j"                  |<     j                  j%                          y)	a  Embed all accumulated objects for all models

        Args:
            is_query: bool - flag to determine which embed method to use. Defaults to False.
            inference_batch_size: int - batch size for inference
        Returns:
            None
        objects
model_namer   r#   c                    g }g }g }t        t              }t        |       D ]  \  }}t        |t        j
                        }	t        t        ||            D ]_  \  }
\  }}||j                  k(  s|	|k(  s||
   j                  |       ||
   j                  |	r|j                  n|j                           |g|t        |      <   |j                  |j                         |j                  |	       |j                  |	r|j                  n|j                  g        g }t        t        ||            D ]X  \  }\  }}	|j                  j                  j                  ||	r||   nd|	s||   nd|xs i |      D cg c]  }| c}       Z t        |      }g gt        |       z  }|j!                         D ]  }|D ]  }t#        |      ||<     |S c c}w )a,  
            Assemble batches by options and data type based groups, embeds and return embeddings in the original order.
            If models.Document model is bm25 and Qdrant version is 1.15.3 or higher, return the document without changes
            to be processed by Qdrant itself.
            N)r   textsimagesrF   optionsr   )r   r-   r   rI   r   Documentzipr   r   textimagerU   extendrD   embediterr~   next)r   r   r   unique_optionsunique_options_is_textbatchesgroup_indicesr   objis_textjr   options_is_textr|   	embeddingiter_embeddingsordered_embeddingsindicesindexrF   r   s                      r    r   z/ModelEmbedder._embed_accumulator.<locals>.embed_  s    46N13"!#G2=d2CM#G,3$S&//:5>(>?61A1 #++-'_2L%a(//2
))g#((399M6 ;<M#n"56"))#++6*11':NNCHHSYY#GH -  J)23~G]3^)_%%GW!! *.)<)<'107'!*T5<71:$%-$+Mr'1 *= *
*I "*
 *` #:.O=?D3w<<O(//1$E04_0E&u- % 2 &%%
s    	G
z is not found among supported models.Check if `cloud_inference` is set to True or `fastembed` is installed (for local inference)?)r   r   r   N)r-   r   strr5   r   r   r   r>   anyrD   is_supported_text_modelis_supported_sparse_model(is_supported_late_interaction_text_modelis_supported_image_model.is_supported_late_interaction_multimodal_model
ValueErrorr)   r?   clear)r   rF   r,   r   rh   r{   s   ``    r    r   z ModelEmbedder._embed_accumulatorU  s,   2	&012	&?B2	&PS2	&- 4#882	&h ,,EMM99%@MM;;EBMMJJ5QMM::5AMMPPQVW !g s t  -  2288:KE4).;O*D& ; 	%%'r"   r   c                 >    | j                   |   j                  d      S )zGet next computed embedding from embedded batch

        Args:
            model_name: str - retrieve embedding from the storage by this model name

        Returns:
            NumericVector | models.Document : computed embedding
        r   )r?   pop)r   r   s     r    r   zModelEmbedder._next_embed  s      "":.22155r"   c                 8   t        |t        j                        s|S |j                  }|j                  }|j
                  }t        | j                  j                  |      | j                  j                  |      | j                  j                  |      f      rt        j                  |||      S | j                  j                  |      rt        j                  |||      S | j                  j                  |      rt        | d      t        | d      )a  Resolve inference object into a model

        Args:
            data: models.VectorStruct - data to resolve, if it's an inference object, convert it to a proper type,
                otherwise - keep unchanged

        Returns:
            models.VectorStruct: resolved data
        )rh   r   r   )rh   r   r   z- does not support `InferenceObject` interfacez is not among supported models)rI   r   InferenceObjectrh   objectr   r   rD   r   r   r   r   r   Imager   r   )r   r{   r   ru   r   s        r    r   z'ModelEmbedder._resolve_inference_object  s     $ 6 67KZZ
,,55jA77
CFFzR
 ??%QQ==11*=<<jwOO==GG
S
|+XYZZJ<'EFGGr"   c                     t         S )N)r   )r'   s    r    rX   zModelEmbedder._get_worker_class  s    ""r"   )NF)F   )r   N)NFFN)r   )!r2   r3   r4   rY   r   boolr   r!   r
   r   r5   rK   rn   r   r_   r-   r.   r   r   r   r   rd   VectorStructrl   r   rm   r   r   r   r6   r   r   rX   r   r"   r    r   r   *   s     ,0#^!D(^ ^ 	^  	 33  	
 
)	< #	2!T#y.1I=>2! 2! *	2!
 
$sI~&2	32!n $%	"c9n-	9:" " "	"
 
)	"N )-"+/^CN#i/^ I%^ 	^
 ^ "Dj^ 	S)^
sM!
"	#
	 	 //		^@ 3 3  > VW(,''(,37(,OR(,	v	.(,TQ(4 Q(s Q([_ Q(f	6c 	6mfoo.M 	6Hf.A.A HfFYFY H@ #$':"; # #r"   r   )&rV   collectionsr   copyr   multiprocessingr   typingr   r   r   r	   pydanticr
   qdrant_client.httpr   qdrant_client.embed.commonr   #qdrant_client.embed.embed_inspectorr   qdrant_client.embed.embedderr   qdrant_client.embed.modelsr   r   !qdrant_client.embed.schema_parserr   qdrant_client.embed.utilsr   qdrant_client.fastembed_commonr    qdrant_client.parallel_processorr   r   qdrant_client.uploader.uploaderr   r   r   r   r"   r    <module>r      sP    	 #  1 0 0  % = > 1 I ? / 8 G 6& *k# k#r"   