
    >hFF                        d 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m	Z	m
Z
mZ ddlmZ ddlmZ ddlmZmZmZ  G d de      Ze G d	 d
             Ze G d de             Z G d d      Z G d de      Z	 	 	 	 	 d1dedededededededefdZedk(  r edd      ZdefdZ	  e d        ejC                  d!d"ejD                  e#      Z# e d$ e$e#       d%        e d&       ejK                  d'd(ejL                  )      Z# e d*e#         e d+       ejO                  g d,d-ejL                  .      Z# e d/e#        yy# e($ rZ) e d0e)        Y dZ)[)ydZ)[)ww xY w)2uZ   
支持文件上传的多模态OpenAI客户端
支持图像、文档等多种文件类型
    N)DictAnyListOptionalUnionCallable)	dataclass)Enum)SimpleOpenAIClientModelConfig
OutputModec                   $    e Zd ZdZdZdZdZdZdZy)FileTypeu   文件类型枚举imagedocumentaudiovideocodeN)	__name__
__module____qualname____doc__IMAGEDOCUMENTAUDIOVIDEOCODE     BC:\Users\win\Desktop\pyccd\funcs\utils\multimodal_openai_client.pyr   r      s    EHEEDr   r   c                       e Zd ZU dZdZeed<   dZeed<   dZeed<   dZ	e
e   ed	<   dZe
e   ed
<   dZe
e   ed<   dZe
e   ed<   d Zy)
FileConfigu   文件配置类i  @max_image_sizei   max_document_sizei  @max_audio_sizeNsupported_image_typessupported_document_typessupported_audio_typessupported_code_typesc                     | j                   	g d| _         | j                  	g d| _        | j                  	g d| _        | j                  
g d| _        y y )N)z
image/jpegz	image/jpgz	image/pngz	image/gifz
image/webpz	image/bmpz
image/tiff)	z
text/plainzapplication/pdfzapplication/mswordzGapplication/vnd.openxmlformats-officedocument.wordprocessingml.documentzapplication/vnd.ms-excelzAapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetztext/markdownztext/csvzapplication/json)z
audio/mpegz	audio/wavz	audio/oggz	audio/m4az
audio/flac)	ztext/x-pythonztext/javascriptztext/x-java-sourceztext/x-cz
text/x-c++z	text/htmlztext/csszapplication/x-shz
text/x-sql)r&   r'   r(   r)   selfs    r    __post_init__zFileConfig.__post_init__'   se    %%-*D&
 ((0-D) %%-*D& $$,)D% -r   )r   r   r   r   r#   int__annotations__r$   r%   r&   r   strr'   r(   r)   r-   r   r   r    r"   r"      se    *NC*-s-+NC+'+49+*.d3i.'+49+&*$s)*r   r"   c                   4    e Zd ZU dZdZeed<   dZeed<   d Z	y)MultimodalConfigu   多模态配置类gpt-4-vision-previewvision_modelNfile_configc                 <    | j                   t               | _         y y N)r5   r"   r+   s    r    r-   zMultimodalConfig.__post_init__J   s    #)|D $r   )
r   r   r   r   r4   r0   r/   r5   r"   r-   r   r   r    r2   r2   D   s    .L#."K",r   r2   c                   f    e Zd ZdZdefdZdedefdZdedede	fdZ
dedefd	Zdded
edefdZy)FileHandleru   文件处理器r5   c                     || _         y r7   )config)r,   r5   s     r    __init__zFileHandler.__init__S   s	    !r   	file_pathreturnc                 $   t         j                  j                  |      st        d|       t	        j
                  |      \  }}|ft         j                  j                  |      d   j                         }|dv rt        j                  S |dv rt        j                  S t        d|       |j                  d      rt        j                  S |j                  d      rt        j                  S |j                  d      rt        j                  S || j                   j"                  v rt        j                  S |j                  d	      r8|| j                   j$                  v rt        j                  S t        j                  S t        j                  S )
u   
        检测文件类型
        
        Args:
            file_path: 文件路径
            
        Returns:
            FileType: 文件类型
           文件不存在:    )	z.pyz.jsz.htmlz.cssz.javaz.cppz.cz.shz.sql)z.txtz.mdz.csvz.jsonu   无法识别文件类型: zimage/zaudio/zvideo/ztext/)ospathexistsFileNotFoundError	mimetypes
guess_typesplitextlowerr   r   r   
ValueError
startswithr   r   r   r;   r'   r)   )r,   r=   	mime_type_exts        r    detect_file_typezFileHandler.detect_file_typeV   sE    ww~~i(#&7	{$CDD ++I6	1''""9-a0668C[[}}$88((( #=i[!IJJ)>>!!!(+>>!!!(+>>!$++>>>$$$!!'*$-1Q1Q$Q8==hW_WhWhh$$$r   	file_typec                    t         j                  j                  |      st        d|       t         j                  j	                  |      }t        j                  |      \  }}|t        j                  k(  r?|| j                  j                  kD  r&t        d| d| j                  j                   d      |t        j                  k(  r?|| j                  j                  kD  r&t        d| d| j                  j                   d      |t        j                  k(  r?|| j                  j                  kD  r&t        d| d| j                  j                   d      |t        j                  k(  r&|| j                  j                   vrt        d|       |t        j                  k(  r&|| j                  j"                  vrt        d|       |t        j                  k(  r&|| j                  j$                  vrt        d	|       y
)u   
        验证文件是否符合要求
        
        Args:
            file_path: 文件路径
            file_type: 文件类型
            
        Returns:
            bool: 是否符合要求
        r@   u   图像文件过大: u    bytes, 最大支持: z bytesu   文档文件过大: u   音频文件过大: u   不支持的图像类型: u   不支持的文档类型: u   不支持的音频类型: T)rB   rC   rD   rE   getsizerF   rG   r   r   r;   r#   rJ   r   r$   r   r%   r&   r'   r(   )r,   r=   rP   	file_sizerL   rM   s         r    validate_filezFileHandler.validate_file{   s    ww~~i(#&7	{$CDDGGOOI.	 ++I6	1 &9t{{7Q7Q+Q3I;>TUYU`U`UoUoTppvwxx(+++	DKK<Y<Y0Y3I;>TUYU`U`UrUrTssyz{{(..(Y9S9S-S3I;>TUYU`U`UoUoTppvwxx &9DKK<]<]+]9)EFF(+++	AeAe0e9)EFF(..(Ydkk>_>_-_9)EFFr   c                     t        j                  |      \  }}t        |d      5 }t        j                  |j                               j                  d      }d| d| cddd       S # 1 sw Y   yxY w)u   
        将文件编码为base64字符串
        
        Args:
            file_path: 文件路径
            
        Returns:
            str: base64编码的文件数据
        rbutf-8zdata:z;base64,N)rF   rG   openbase64	b64encodereaddecode)r,   r=   rL   rM   filebase64_datas         r    encode_file_to_base64z!FileHandler.encode_file_to_base64   sj     !++I6	1)T" 	<d **499;7>>wGK9+Xk];	< 	< 	<s   :A))A2encodingc                 B   	 t        |d|      5 }|j                         cddd       S # 1 sw Y   yxY w# t        $ r_ dD ]J  }	 t        |d|      5 }|j                         cddd       c cY S # 1 sw Y   nxY w=# t        $ r Y Hw xY w t        d| d      w xY w)u   
        读取文本文件内容
        
        Args:
            file_path: 文件路径
            encoding: 文件编码
            
        Returns:
            str: 文件内容
        r)r`   N)gbkgb2312zlatin-1u   无法读取文件 u   ，编码格式不支持)rX   r[   UnicodeDecodeErrorrJ   )r,   r=   r`   r]   encs        r    read_text_filezFileHandler.read_text_file   s    	Xix8 #Dyy{# # #! 	X3 is; +t#yy{+ + + +) 	 29+=UVWW	Xs_   6 *	6 36 6 BA>A1#	A>,B1A:6A>=B>	B
B	B

BN)rW   )r   r   r   r   r"   r<   r0   r   rO   boolrT   r_   rg   r   r   r    r9   r9   P   sq    "J "#%# #%( #%J!s !x !D !F<s <s <X Xs X Xr   r9   c                        e Zd ZdZdef fdZ	 ddedee   dedeee	f   fd	Z
d
d
ej                  d
d
dfdedee   dee   dedee   deeegd
f      dedefdZdej                  d
d
fdedededee   deeegd
f      defdZdej                  d
d
fdedededee   deeegd
f      defdZdej                  d
d
fdedededee   deeegd
f      defdZdej                  d
d
fdee   dededee   deeegd
f      defdZ xZS )MultimodalOpenAIClientu4   支持多模态（文本+文件）的OpenAI客户端r;   c                 f    t         |   |       || _        t        |j                        | _        y r7   )superr<   multimodal_configr9   r5   file_handler)r,   r;   	__class__s     r    r<   zMultimodalOpenAIClient.__init__   s+     !''(:(:;r   autotext
file_pathsdetailr>   c           
         d|dg}|D ]^  }	 | j                   j                  |      }| j                   j                  ||       |t        j                  k(  r3| j                   j                  |      }|j                  d||dd       n|t        j                  t        j                  fv rV| j                   j                  |      }t        j                  j                  |      }	|j                  dd|	 d| dd       ne|t        j                  k(  rR| j                   j                  |      }t        j                  j                  |      }	|j                  dd	|	 d
d       a d|dS # t        $ rT}
t        d| d|
        |j                  ddt        j                  j                  |       d|
 dd       Y d}
~
d}
~
ww xY w)u  
        创建包含文件的消息
        
        Args:
            text: 文本内容
            file_paths: 文件路径列表
            detail: 图像详细程度 ("low", "high", "auto")
            
        Returns:
            Dict: 格式化的消息字典
        rq   )typerq   	image_url)urlrs   )ru   rv   u   

--- 文件: z ---
u   
--- 文件结束 ---
u   

--- 音频文件: u\    (base64编码) ---
注意: 这是一个音频文件，需要支持音频处理的模型。
u   处理文件 u	    失败: u   

--- 文件处理错误: u    ---
错误: 
Nuserrolecontent)rn   rO   rT   r   r   r_   appendr   r   rg   rB   rC   basenamer   	Exceptionprint)r,   rq   rr   rs   r|   r=   rP   r^   file_contentfilenamees              r    create_message_with_filesz0MultimodalOpenAIClient.create_message_with_files   s   " #D12# (	I' -->>yI	!!//	9E."&"3"3"I"I)"TKNN +#.&,&$  8#4#4hmm"DD#'#4#4#C#CI#NL!ww//	:HNN &"28*F<.Ph i$ 
 (..0"&"3"3"I"I)"TK!ww//	:HNN &"8
  Ca  !b$ ;(	V 
 	
  i[	!=>":277;K;KI;V:WWefgehhjk   s   EE00	G9A	GGNsystem_messagemodetimeoutcallbackc                     g }|r|j                  d|d       |r| j                  |||      }	nd|d}	|j                  |	       | j                  ||||      S )u  
        与AI聊天并携带文件
        
        Args:
            text: 文本消息
            file_paths: 文件路径列表
            system_message: 系统消息
            mode: 输出模式
            timeout: 超时时间
            callback: 流式输出回调函数
            detail: 图像详细程度
            
        Returns:
            str: AI响应
        systemrz   ry   )r}   r   chat_complete)
r,   rq   rr   r   r   r   r   rs   messagesuser_messages
             r    chat_with_filesz&MultimodalOpenAIClient.chat_with_files  se    2  OOX.IJ 99$
FSL$*t<L%!!(D'8DDr   u   请描述这张图片
image_pathquestionc                 2    | j                  ||gd|||      S )u2  
        分析单张图片
        
        Args:
            image_path: 图片路径
            question: 要问的问题
            mode: 输出模式
            timeout: 超时时间
            callback: 流式输出回调函数
            
        Returns:
            str: 分析结果
        uZ   你是一个专业的图像分析助手，请仔细观察图片并提供详细的分析。rq   rr   r   r   r   r   r   )r,   r   r   r   r   r   s         r    analyze_imagez$MultimodalOpenAIClient.analyze_image9  s0    * ##"|w $ 
 	
r   u   请分析这个代码文件code_file_pathc                 2    | j                  ||gd|||      S )u<  
        分析代码文件
        
        Args:
            code_file_path: 代码文件路径
            question: 要问的问题
            mode: 输出模式
            timeout: 超时时间
            callback: 流式输出回调函数
            
        Returns:
            str: 分析结果
        uu   你是一个专业的代码分析师，请仔细阅读代码并提供详细的分析、优化建议和潜在问题。r   r   )r,   r   r   r   r   r   s         r    analyze_codez#MultimodalOpenAIClient.analyze_codeW  s4    * ##&' S $ 
 	
r   u$   请总结这个文档的主要内容doc_pathc                 2    | j                  ||gd|||      S )u*  
        分析文档
        
        Args:
            doc_path: 文档路径
            question: 要问的问题
            mode: 输出模式
            timeout: 超时时间
            callback: 流式输出回调函数
            
        Returns:
            str: 分析结果
        u`   你是一个专业的文档分析师，请仔细阅读文档并提供准确的总结和分析。r   r   )r,   r   r   r   r   r   s         r    analyze_documentz'MultimodalOpenAIClient.analyze_documentu  s0    * ## z} $ 
 	
r   u   请分析这些文件c                 0    | j                  ||d|||      S )u>  
        批量分析多个文件
        
        Args:
            file_paths: 文件路径列表
            question: 要问的问题
            mode: 输出模式
            timeout: 超时时间
            callback: 流式输出回调函数
            
        Returns:
            str: 分析结果
        ui   你是一个专业的文件分析师，请仔细分析所有提供的文件并给出综合性的见解。r   r   )r,   rr   r   r   r   r   s         r    batch_analyze_filesz*MultimodalOpenAIClient.batch_analyze_files  s1    * ##! G $ 
 	
r   )rp   )r   r   r   r   r2   r<   r0   r   r   r   r   r   COMPLETEr   floatr   r   r   r   r   r   __classcell__)ro   s   @r    rj   rj      s   ></ < 	@
@
 I@
 	@

 
c3h@
J !%(,%..#'48'E'E I'E !	'E
 'E %'E 8SE4K01'E 'E 
'EX 0%..#'48

 
 	

 %
 8SE4K01
 

B 6%..#'48

 
 	

 %
 8SE4K01
 

B ?%..#'48

 
 	

 %
 8SE4K01
 

B 0%..#'48
I
 
 	

 %
 8SE4K01
 

r   rj   api_urlapi_key
model_name
max_tokenstemperaturer   r5   r>   c           
      T    t        | ||||||xs
 t                     }t        |      S )ub  
    创建多模态OpenAI客户端
    
    Args:
        api_url: API地址
        api_key: API密钥
        model_name: 模型名称
        max_tokens: 最大token数
        temperature: 温度参数
        timeout: 超时时间
        file_config: 文件配置
        
    Returns:
        MultimodalOpenAIClient: 多模态客户端实例
    )r   r   r   r   r   r   r5   )r2   r"   rj   )r   r   r   r   r   r   r5   r;   s           r    create_multimodal_clientr     s7    0 /:<F "&))r   __main__z*https://api.openai.com/v1/chat/completionszyour-api-key-here)r   r   r|   c                      t        | dd       y )N T)endflush)r   )r|   s    r    stream_callbackr     s    g2T*r   u   === 图片分析示例 ===zpath/to/your/image.jpgu'   请详细描述这张图片中的内容)r   r   r   r   u$   
图片分析完成，响应长度: u    字符u   
=== 代码分析示例 ===zpath/to/your/code.pyu3   请分析这个代码的功能和可能的优化点)r   r   r   u   代码分析结果: u   
=== 多文件分析示例 ===)z	image.jpgzdocument.txtzcode.pyu'   请综合分析这些文件的关联性)rr   r   r   u   多文件分析结果: u   测试失败: )r3   i  gffffff?g      N@N)*r   rY   rF   rB   jsontypingr   r   r   r   r   r   dataclassesr	   enumr
   simple_openai_clientr   r   r   r   r"   r2   r9   rj   r0   r.   r   r   r   clientr   r   r   STREAMresponselenr   r   r   r   r   r   r   r    <module>r      s  
   	  = = !  L Lt  % % %P ,{ , ,sX sXli
/ i
` -"!*!*!* !* 	!*
 !* !* !* !*J z%<#F+ +$*+''/>""$	 ( 
 	5c(m_GLM 	,-&&1J$$ ' 

 	$XJ/0 	/0--?>$$ . 

 	'z23M P  $qc"##$s   (BE E!EE!