
    #ĭj                         U d Z ddlZddlZddlZddlZddlZddlmZmZm	Z	 ddl
mZ ddlZddlZddlmZmZmZmZ ddlmZ ddlmZmZ 	 ddlmZ d	Z ej:                  ej<                          ej>                  e       Z! ejD                  dd      Z#ejH                  jK                         rdndZ& e' ejD                  dd            Z( e' ejD                  dd            Z) G d de      Z* G d de      Z+ G d de      Z, G d d      Z- eddd      Z.e.j_                  ed gd	d gd g!       da0ee-   e1d"<   e.je                  d#      d$        Z3e.ji                  d%e,&      d'        Z5e.jm                  d(e+&      d)e*fd*       Z7e.jm                  d+       ed,      d-e(fd.ed/e8d0e'fd1       Z9e.jm                  d2       ed,      d-e(fd.ed/e8d0e'fd3       Z:e.jm                  d4      d)e;fd5       Z<e d6k(  rWddl=Z=e!j}                  d7e)        e!j}                  d8e#        e!j}                  d9e&         e=j~                  d:d;e)d<=       yy# e$ r d
ZY w xY w)>u%   WeMM-Embedding 独立服务 - FastAPI    N)ListOptionalUnion)Path)FastAPIHTTPException
UploadFileFile)CORSMiddleware)	BaseModelField)SentenceTransformerTF)level
WEMM_MODELztencent/WeMM-Embedding-2BcudacpuMAX_DIMENSION2048PORT8765c                   l    e Zd ZU dZeeeeeef      f   ed<    e	dde
d      Zee   ed<   dZeed	<   y)
EmbeddingRequestu   嵌入请求inputsN@   u   输出维度 (64-4096))geledescription	dimensionT	normalize)__name__
__module____qualname____doc__r   strr   dict__annotations__r   r   r   r   intr   bool     ;/Users/leo/.hermes/workspace/livekit-agents/wemm_service.pyr   r   #   sG    #tE#t),--..$Tb]PhiIx}iItr*   r   c                   <    e Zd ZU dZeee      ed<   eed<   eed<   y)EmbeddingResponseu   嵌入响应
embeddingsmodel
dimensionsN)	r    r!   r"   r#   r   floatr&   r$   r'   r)   r*   r+   r-   r-   *   s    T%[!!JOr*   r-   c                   6    e Zd ZU eed<   eed<   eed<   eed<   y)HealthResponsestatusmodel_loadeddevicecuda_availableN)r    r!   r"   r$   r&   r(   r)   r*   r+   r3   r3   1   s    KKr*   r3   c            	           e Zd ZdZdedefdZd Zd Z	 	 ddeee	eee
f      f   d	ee   d
edej                  fdZdeee	eee
f      f   d	ee   d
edej                  fdZdefdZy)WeMMServiceu   WeMM-Embedding 服务封装model_idr6   c                 .    || _         || _        d | _        y N)r:   r6   r/   )selfr:   r6   s      r+   __init__zWeMMService.__init__<   s     
r*   c                 ~   K   t        j                         }|j                  d| j                         d{   S 7 w)u   异步加载模型N)asyncioget_event_looprun_in_executor
_load_sync)r=   loops     r+   loadzWeMMService.loadA   s1     %%'))$@@@@s   4=;=c                     t         rXt        | j                  | j                  d      | _        t
        j                  d| j                   d| j                   d       yy)NT)r6   trust_remote_codeu   ✅ 模型加载完成: z ()F)_WEMM_AVAILABLEr   r:   r6   r/   loggerinfor=   s    r+   rC   zWeMMService._load_syncF   sO    ,{{"&DJ
 KK24==/DKK=PQRSr*   Nr   r   r   returnc                     K    j                   t        d      t        j                         }|j	                  d fd       d{   S 7 w)u   编码输入N   模型未加载c                  *    j                         S r<   )_encode_sync)r   r   r   r=   s   r+   <lambda>z$WeMMService.encode.<locals>.<lambda>^   s    D%%fiCr*   )r/   RuntimeErrorr@   rA   rB   )r=   r   r   r   rD   s   ```` r+   encodezWeMMService.encodeQ   sP      ::011%%'))C
 
 	
 
s   AAAAc                 \    i }|r||d<   |sd|d<    | j                   j                  |fi |S )Ntruncate_dimFnormalize_embeddings)r/   rT   )r=   r   r   r   argss        r+   rQ   zWeMMService._encode_synca   s@     #,D +0D'( tzz  0400r*   c                     | j                   d uS r<   )r/   rL   s    r+   is_readyzWeMMService.is_readyo   s    zz%%r*   )NT)r    r!   r"   r#   r$   r>   rE   rC   r   r   r%   r   r'   r(   npndarrayrT   rQ   rZ   r)   r*   r+   r9   r9   9   s    % c 
A
	 $(	
c4c4i 0112
 C=
 	

 

 1c4c4i 01121 C=1 	1
 
1&$ &r*   r9   zWeMM-Embedding Serviceu+   腾讯 WeMM-Embedding 多模态嵌入服务z1.0.0)titler   version*)allow_originsallow_credentialsallow_methodsallow_headersservicestartupc                     K   t         j                  d       t        t        t              at
        j                          d {   } | st         j                  d       y y 7 w)Nu$   🚀 启动 WeMM-Embedding 服务...u(   ❌ 模型加载失败，请检查依赖)rJ   rK   r9   MODEL_IDDEVICErd   rE   error)loadeds    r+   startup_eventrk      sI      KK68(F+G<<>!F?@  "s   AA#A!A#z/health)response_modelc                     K   t        t        rt        j                         rdndt        rt        j                         ndt        t        j
                  j                               S w)Nokri   F)r4   r5   r6   r7   )r3   rd   rZ   rh   torchr   is_availabler)   r*   r+   healthrq      sH     7#3#3#5t7+2W%%'zz..0	 s   A&A(z/embedrequestc                   K   t         rt         j                         st        dd      	 t         j                  | j                  | j
                  | j                         d {   }t        |j                         t        t        |j                        dkD  r|j                  d         S d      S 7 P# t        $ r3}t        j                  d|        t        d	t        |            d }~ww xY ww)
N  rO   status_codedetail)r   r      )r.   r/   r0   u   编码失败:   )rd   rZ   r   rT   r   r   r   r-   tolistrg   lenshape	ExceptionrJ   ri   r$   )rr   r.   es      r+   embedr      s     '**,4EFF<">>NN'''' * 
 

 !!((*/2:3C3C/Dq/Hz''+
 	
 OP
 	

  <~aS)*CF;;<sG   (C69B7 $B5%AB7 -C6.B7 4C65B7 7	C3 .C..C33C6z/embed/image. filequeryr   c                   K   t         rt         j                         st        dd      	 | j                          d{   }t	        j
                  dd      5 }|j                  |       |j                  }ddd       	 dd	g}|r|j                  d
|d       t         j                  ||       d{   }|d   j                         |j                  d   | j                  dt        j                  |       S 7 # 1 sw Y   xY w7 U# t        j                         w xY w# t        $ r3}t         j#                  d|        t        dt%        |            d}~ww xY ww)u!   上传图像文件并获取嵌入rt   rO   ru   Nz.jpgFsuffixdeleteimage)typer   textr   r   r   r   ry   	embeddingr0   r   u   图像编码失败: rz   rd   rZ   r   readtempfileNamedTemporaryFilewritenameappendrT   r{   r}   filenameosunlinkr~   rJ   ri   r$   	r   r   r   contentstmptmp_pathr   r.   r   s	            r+   embed_imager      s4     '**,4EFF<$ ((uEIIhxxH F	 &:;Fvu=>&~~f	~JJJ (]113(..r2 IIh) % FE K IIh <+A3/0CF;;<z   (E(D) C?D) D8D) 6D 7D81D )D) >E(?D) D
D) D D&&D) )	E%2.E  E%%E(z/embed/videoc                   K   t         rt         j                         st        dd      	 | j                          d{   }t	        j
                  dd      5 }|j                  |       |j                  }ddd       	 dd	g}|r|j                  d
|d       t         j                  ||       d{   }|d   j                         |j                  d   | j                  dt        j                  |       S 7 # 1 sw Y   xY w7 U# t        j                         w xY w# t        $ r3}t         j#                  d|        t        dt%        |            d}~ww xY ww)u2   上传视频文件并获取嵌入（采样64帧）rt   rO   ru   Nz.mp4Fr   video)r   r   r   r   r   r   ry   r   u   视频编码失败: rz   r   r   s	            r+   embed_videor      s/     '**,4EFF<$((uEIIhxxH F	 &:;Fvu=>&~~f	~JJJ (]113(..r2 IIh' %EE K IIh <+A3/0CF;;<r   z/similarityc                 <  K   t         rt         j                         st        dd      	 | j                  dg       }| j                  dt              }|st        dd      t         j                  ||       d	{   }t        j                  j                  |d
d      }||z  }t        j                  ||j                        }|j                         |dS 7 ^# t        $ r3}t        j                  d|        t        dt        |            d	}~ww xY ww)u   计算相似度rt   rO   ru   textsr   i  u   需要提供 texts 列表r   Nry   T)axiskeepdims)similaritieslabelsu   相似度计算失败: rz   )rd   rZ   r   getr   rT   r[   linalgnormdotTr{   r~   rJ   ri   r$   )rr   r   r   r.   r   
normalized
sim_matrixr   s           r+   
similarityr      s      '**,4EFF<GR(KK];	C8STT">>%9>EE
 yy~~jrD~A$&
VVJ
5
 '--/
 	
 F  <.qc23CF;;<s<   (DAC <C=AC DC 	D&.DDD__main__u"   🎯 启动服务: http://0.0.0.0:u   📊 模型: u   💻 设备: zwemm_service:appz0.0.0.0rK   )hostport	log_level)@r#   r@   loggingr   r   base64typingr   r   r   pathlibr   ro   numpyr[   fastapir   r   r	   r
   fastapi.middleware.corsr   pydanticr   r   sentence_transformersr   rI   ImportErrorbasicConfigINFO	getLoggerr    rJ   getenvrg   r   rp   rh   r'   r   r   r   r-   r3   r9   appadd_middlewarerd   r&   on_eventrk   r   rq   postr   r$   r   r   r%   r   uvicornrK   runr)   r*   r+   <module>r      s   +   	   ( (    < < 2 %9O   ',, '			8	$ 299\#>?::**,%IBIIov67
9299VV$%y 	 Y 7& 7&v 
"=   %%%   "&+	 % iA A >2 3 (#45<) < 6<* .Cy"!<
!<!< !< !<H .Cy" <
 < <  <  <F -<d < <8 z
KK4TF;<
KK-z*+
KK-x()GKK	 C  Os   I II