o
    Ԣi*                     @   sn   d dl Z d dlZd dlmZmZ d dlZd dlmZ d dlm	Z	 e
eZG dd dZdadefdd	ZdS )
    N)ListOptional)Session)get_embedding_factoryc                   @   s  e Zd Zdd Zdededee fddZ					d%d	e	d
ee	 dee	 dee	 dee dee dee
e  fddZd	e	d
e	de	dee
e  fddZd	e	d
e	dee
e  fddZ					d%de
e	 d
ee	 dee	 dee	 dee dee de
ee
e   fddZ	d&de
e	 d
e	dede
ee
e   fddZd'dee	 fddZ			d(de
e	 d
ee	 dee	 dee	 de
ee
e   f
ddZd)d	e	d!ed"ede
e	 fd#d$ZdS )*EmbeddingServicec                 C   s
   d| _ d S )Nztext-embedding-v3)default_model)self r	   Q/lsinfo/ai/hellotax_ai/base_platform/app/services/llm/multi_provider_embedding.py__init__   s   
zEmbeddingService.__init__dbmodel_idreturnc              
   C   s  ddl m}m} ddlm} z| }d| }||}|r@td|  ||	|j
|d k }	|	r=|	 |d< |W S ||	|j
|k }
|
s[td| d	 W d
S ||	|j
|
jk }	|	sxtd|
j d	 W d
S |
j|
j|	jp|	j|	j
d}|j||dd td|  |
j|
j|	 |	jp|	jd}|W S  ty } ztd|  W Y d
}~d
S d
}~ww )z
        DEPRECATED: Legacy method for backward compatibility.
        New code should use embedding_backend_factory directly.
        r   )ModelModelProvider)get_query_cache_servicezcache:model_config:z$Model config cache hit for model_id=provider_idapi_keyz	Model ID z does not existNzProvider ID )
model_name
model_codebase_urlr   i  )ttlz3Cached model config (without API key) for model_id=)r   r   r   r   z#Failed to get model configuration: )app.models.providerr   r   app.services.cache.query_cacher   getloggerdebugqueryfilteridfirstget_api_keyerrorr   namecoder   default_base_urlset	Exception)r   r   r   r   r   r   cache_service	cache_keycached_configprovidermodelcache_configconfiger	   r	   r
   get_model_config   s\   






z!EmbeddingService.get_model_configNtextr,   r   r   c              
   C   sP  |r|  std d S |r#|r#td|  t j|||ddS |p'| j}zY|s3td W d S d| v p>d| v }|rW|rWd|v rWtd	|  | 	|||W S |rat
j||d
}nt
j|d}|jj||d}	|	jd j}
tdt|
  |
W S  ty } ztd|  dd l}t|  W Y d }~d S d }~ww )Nz(Text is empty, cannot generate embeddingz7Using provider registry embedding routing for model_id=T)r1   r   r   	normalizezAPI key not providedvlvisionzdashscope.aliyuncs.comz1Using native DashScope API for multimodal model: )r   r   )r   r,   inputr   z4Successfully generated embedding vector, dimension: z%Failed to generate embedding vector: )stripr   warninginfor   generate_embeddingr   r"   lower_generate_embedding_dashscopeopenaiOpenAI
embeddingscreatedata	embeddinglenr'   	traceback
format_exc)r   r1   r,   r   r   r   r   is_multimodalclientresponserB   r/   rD   r	   r	   r
   r:   I   sJ   



z#EmbeddingService.generate_embeddingc              
   C   s  zd|  v sd|  v rd}|dd|igid}n
d}|d|gid}d	| d
d}td| d| d|  tj|||dd}|jdkr| }td|  d|v rd|d v r|d d }	|	rt|	dkr|	d d }
tdt|
  |
W S td W d S td|  W d S td|j d|j	  W d S  t
y } ztd|  dd l}t|  W Y d }~d S d }~ww )Nr3   r4   zchttps://dashscope.aliyuncs.com/api/v1/services/embeddings/multimodal-embedding/multimodal-embeddingcontentsr1   r5   zWhttps://dashscope.aliyuncs.com/api/v1/services/embeddings/text-embedding/text-embeddingtextszBearer zapplication/json)AuthorizationzContent-TypezDashScope API request: url=z, model=z, data=   )headersjsontimeout   zDashScope API response: outputr?   r   rB   z@Successfully generated embedding vector (DashScope), dimension: z,DashScope API returned empty embeddings listz*DashScope API response format unexpected: zDashScope API call failed: z - zDashScope API call exception: )r;   r   r9   requestspoststatus_coderN   rC   r"   r1   r'   rD   rE   )r   r1   r,   r   urlrA   rM   rH   resultembeddings_listrB   r/   rD   r	   r	   r
   r<      sT   

z.EmbeddingService._generate_embedding_dashscopec              
   C   s   z(ddl m} td|  ||}|j|dd}|r&tdt|  |W S  tyN } ztd|  dd l}t|	  W Y d }~d S d }~ww )Nr   get_local_bge_servicezUsing local BGE model: T)r2   z@Successfully generated embedding vector (local BGE), dimension: z Local BGE model call exception: )
"app.services.llm.local_bge_servicerY   r   r9   encoderC   r'   r"   rD   rE   )r   r1   r,   rY   bge_servicerB   r/   rD   r	   r	   r
   _generate_embedding_local_bge   s   z.EmbeddingService._generate_embedding_local_bgerJ   c           
      C   sb   |sg S |r|rt d|  t j|||dddS g }|D ]}| ||||}	||	 q|S )Nz=Using provider registry batch embedding routing for model_id=    T)rJ   r   r   
batch_sizer2   )r   r9   r   generate_embeddings_batchr:   append)
r   rJ   r,   r   r   r   r   r?   r1   rB   r	   r	   r
   r`      s    
z*EmbeddingService.generate_embeddings_batchr^   r_   c           	   
   C   s   z-ddl m} tdt| d|  ||}|j||dd}tdt| d |W S  tyY } z td	|  dd l}t|	  d gt| W  Y d }~S d }~ww )
Nr   rX   zBatch encoding z texts with local BGE model: T)r_   r2   zSuccessfully batch encoded z textsz$Local BGE batch encoding exception: )
rZ   rY   r   r9   rC   encode_batchr'   r"   rD   rE   )	r   rJ   r,   r_   rY   r\   r?   r/   rD   r	   r	   r
   $_generate_embeddings_batch_local_bge   s   z5EmbeddingService._generate_embeddings_batch_local_bger   c              
   C   sR   zddl m} || W d S  ty( } ztd|  W Y d }~d S d }~ww )Nr   )unload_local_bge_servicez(Failed to unload local embedding model: )rZ   rd   r'   r   r8   )r   r   rd   r/   r	   r	   r
   unload_local_embedding_model  s   z-EmbeddingService.unload_local_embedding_modelc                 C   s,   g }|D ]}|  ||||}|| q|S N)r:   ra   )r   rJ   r,   r   r   r?   r1   rB   r	   r	   r
   generate_embeddings_batch_old  s
   z.EmbeddingService.generate_embeddings_batch_old  rP   
chunk_sizeoverlapc                 C   s\   t ||kr	|gS g }d}|t |k r,|| }||| }|| || }|t |k s|S )Nr   )rC   ra   )r   r1   ri   rj   chunksstartendchunkr	   r	   r
   
chunk_text-  s   
zEmbeddingService.chunk_text)NNNNN)r^   rf   )NNN)rh   rP   )__name__
__module____qualname__r   r   intr   dictr0   strr   floatr:   r<   r]   r`   rc   re   rg   ro   r	   r	   r	   r
   r      s    ;

>

C


"

$r   r   c                   C   s   t d u rt a t S rf   )_embedding_servicer   r	   r	   r	   r
   get_embedding_serviceD  s   rx   )r=   rR   typingr   r   loggingsqlalchemy.ormr   3app.services.llm.backends.embedding_backend_factoryr   	getLoggerrp   r   r   rw   rx   r	   r	   r	   r
   <module>   s   
  6