
    NgY                        d dl Z d dl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 d dlmZ d dl	m
Z
 d dlmZmZmZmZmZmZmZmZmZ d dlmZmZmZ d dlmZ d dlmZ d d	lmZmZ d d
l m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+ d dl,m-Z-m.Z. d dl/m0Z0m1Z1m2Z2 d dl3m4Z4m5Z5 d dl6m7Z7 d dl8m9Z9m:Z:m;Z;  ej<        e=          Z>dZ?dZ@de#deAfdZBdeeCef         de#fdZDdeeCef         dee$         de$fdZE G d de          ZF G d d          ZGdS )    N)datetime)Queue)mktime)	AnyDict	GeneratorIteratorListMappingOptionalTypecast)	urlencodeurlparse
urlunparse)format_date_time)CallbackManagerForLLMRun)BaseChatModelgenerate_from_stream)	AIMessageAIMessageChunkBaseMessageBaseMessageChunkChatMessageChatMessageChunkFunctionMessageChunkHumanMessageHumanMessageChunkSystemMessageToolMessageChunk)make_invalid_tool_callparse_tool_call)ChatGenerationChatGenerationChunk
ChatResult)get_from_dict_or_envget_pydantic_field_names)
get_fields)
ConfigDictFieldmodel_validatorz$wss://spark-api.xf-yun.com/v3.5/chatzgeneralv3.5messagereturnc                    t          | t                    rd| j        d}nt          | t                    rd| j        d}nt          | t                    r_d| j        d}d| j        v r!| j        d         |d<   |d         dk    rd |d<   d| j        v r!| j        d         |d<   |d         dk    rd |d<   n2t          | t                    rd| j        d}nt          d	|            |S )
Nuser)rolecontent	assistantfunction_callr1    
tool_callssystemzGot unknown type )
isinstancer   r1   r   r   additional_kwargsr   
ValueError)r,   message_dicts     d/var/www/html/ai-engine/env/lib/python3.11/site-packages/langchain_community/chat_models/sparkllm.pyconvert_message_to_dictr<   9   s   ';'' 8 &7?CC	G\	*	* 8 &7?CC	GY	'	' 8 +HHg777,3,Eo,VL)I&",,*.Y'7444)0)B<)PL&I&",,*.Y'	G]	+	+ 8 (W_EE6W66777    _dictc           
      `   | d         }| d         }|dk    rt          |          S |dk    rg }i }|                     d          x}rt          |          |d<   g }|                     d          x}r}||d<   | d         D ]n}	 |                    t	          |d	                     (# t
          $ r:}	|                    t          |t          |	                               Y d }	~	gd }	~	ww xY wni }|pd
}
t          |
|||          S |dk    rt          |          S t          ||          S )Nr0   r1   r/   r1   r2   r3   r5   T)	return_idr4   )r1   r8   r5   invalid_tool_callsr6   r1   r0   )r   getdictappendr"   	Exceptionr!   strr   r   r   )r>   msg_rolemsg_contentrB   r8   r3   r5   raw_tool_callsraw_tool_caller1   s              r;   convert_dict_to_messagerN   S   s   V}H	"K6K0000	[	 	 "$!IIo666= 	E15m1D1Do.
"YY|444> 
	#.<l+!&|!4  %%omt&T&T&TUUUU    &--.}c!ffEE        !##/!1	
 
 
 	
 
X		[1111;X>>>>s   $B((
C,20C''C,default_classc                    t          t          |                     d                    }t          t          |                     d          pd          }i }|                     d          r+t          | d                   }d|v r|d         d|d<   ||d<   |                     d          r| d         |d<   |dk    s|t          k    rt	          |          S |d	k    s|t
          k    rt          ||
          S |dk    s|t          k    rt          || d                   S |dk    s|t          k    rt          || d                   S |s|t          k    rt          ||          S  ||          S )Nr0   r1   r4   r3   namer5   r/   r@   r2   )r1   r8   function)r1   rQ   tooltool_call_id)r1   rT   rC   )	r   rH   rD   rE   r   r   r   r    r   )r>   rO   rI   rJ   r8   r3   s         r;   _convert_delta_to_message_chunkrU   v   s    C6**++HsEIIi006B77K yy!! ;U?344]""}V'<'D$&M&!-:/*yy >*/*=,'6].??? 5555	[	 	 M^$C$CkEVWWWW	Z		=4H#H#H#KeFmLLLL	V		}0@@@%BWXXXX	 2]&666(CCCC}[1111r=   c                      e Zd ZU dZedefd            Zedee	e	f         fd            Z
dZeed<    edd          Zee	         ed	<   	  edd
          Zee	         ed<   	  edd          Zee	         ed<   	  edd          Zee	         ed<   	  edd          Zee	         ed<   	 dZe	ed<   dZeed<   	  edd          Zeed<   	  ed          Zeed<   	 dZeed<   	  ee          Zee	ef         ed <   	  ed!"          Z e d#$          ed%edefd&                        Z! e d#$          ed%ee	ef         defd'                        Z"	 	 d0d(e#e$         d)ee#e	                  d*ee%         d+ede&e'         f
d,Z(	 	 	 d1d(e#e$         d)ee#e	                  d*ee%         d-ee         d+ede)fd.Z*ede	fd/            Z+dS )2ChatSparkLLMu-  IFlyTek Spark chat model integration.

    Setup:
        To use, you should have the environment variable``IFLYTEK_SPARK_API_KEY``,
        ``IFLYTEK_SPARK_API_SECRET`` and ``IFLYTEK_SPARK_APP_ID``.

    Key init args — completion params:
        model: Optional[str]
            Name of IFLYTEK SPARK model to use.
        temperature: Optional[float]
            Sampling temperature.
        top_k: Optional[float]
            What search sampling control to use.
        streaming: Optional[bool]
             Whether to stream the results or not.

    Key init args — client params:
        api_key: Optional[str]
            IFLYTEK SPARK API KEY. If not passed in will be read from env var IFLYTEK_SPARK_API_KEY.
        api_secret: Optional[str]
            IFLYTEK SPARK API SECRET. If not passed in will be read from env var IFLYTEK_SPARK_API_SECRET.
        api_url: Optional[str]
            Base URL for API requests.
        timeout: Optional[int]
            Timeout for requests.

    See full list of supported init args and their descriptions in the params section.

    Instantiate:
        .. code-block:: python

            from langchain_community.chat_models import ChatSparkLLM

            chat = ChatSparkLLM(
                api_key="your-api-key",
                api_secret="your-api-secret",
                model='Spark4.0 Ultra',
                # temperature=...,
                # other params...
            )

    Invoke:
        .. code-block:: python

            messages = [
                ("system", "你是一名专业的翻译家，可以将用户的中文翻译为英文。"),
                ("human", "我喜欢编程。"),
            ]
            chat.invoke(messages)

        .. code-block:: python

            AIMessage(
                content='I like programming.',
                response_metadata={
                    'token_usage': {
                        'question_tokens': 3,
                        'prompt_tokens': 16,
                        'completion_tokens': 4,
                        'total_tokens': 20
                    }
                },
                id='run-af8b3531-7bf7-47f0-bfe8-9262cb2a9d47-0'
            )

    Stream:
        .. code-block:: python

            for chunk in chat.stream(messages):
                print(chunk)

        .. code-block:: python

            content='I' id='run-fdbb57c2-2d32-4516-b894-6c5a67605d83'
            content=' like programming' id='run-fdbb57c2-2d32-4516-b894-6c5a67605d83'
            content='.' id='run-fdbb57c2-2d32-4516-b894-6c5a67605d83'

        .. code-block:: python

            stream = chat.stream(messages)
            full = next(stream)
            for chunk in stream:
                full += chunk
            full

        .. code-block:: python

            AIMessageChunk(
                content='I like programming.',
                id='run-aca2fa82-c2e4-4835-b7e2-865ddd3c46cb'
            )

    Response metadata
        .. code-block:: python

            ai_msg = chat.invoke(messages)
            ai_msg.response_metadata

        .. code-block:: python

            {
                'token_usage': {
                    'question_tokens': 3,
                    'prompt_tokens': 16,
                    'completion_tokens': 4,
                    'total_tokens': 20
                }
            }

    r-   c                     dS )z9Return whether this model can be serialized by Langchain.F )clss    r;   is_lc_serializablezChatSparkLLM.is_lc_serializable  s	     ur=   c                     ddddddS )NIFLYTEK_SPARK_APP_IDIFLYTEK_SPARK_API_KEYIFLYTEK_SPARK_API_SECRETIFLYTEK_SPARK_API_URLIFLYTEK_SPARK_LLM_DOMAIN)spark_app_idspark_api_keyspark_api_secretspark_api_urlspark_llm_domainrY   selfs    r;   
lc_secretszChatSparkLLM.lc_secrets  s"     34 :4 :
 
 	
r=   Nclientapp_id)defaultaliasrb   api_keyrc   
api_secretrd   api_urlre   modelrf   lc_userspark_user_idF	streaming   timeout)rm   request_timeoutg      ?rl   temperature   top_k)default_factorymodel_kwargsT)populate_by_namebefore)modevaluesc           	      8   t          |ddgd          |d<   t          |ddgd          |d<   t          |ddgd	          |d<   t          |d
dt                    |d
<   t          |ddt                    |d<   d t          |                                           D             }|                    d          |d         d<   |                    d          |d         d<   t          |d         |d         |d         |d
         |d         |d                   |d<   |S )Nrb   rk   r]   rc   rn   r^   rd   ro   r_   re   r`   rf   ra   c                 2    i | ]\  }}|j         ||j         S Nrx   ).0rQ   fields      r;   
<dictcomp>z5ChatSparkLLM.validate_environment.<locals>.<dictcomp>O  s2     
 
 
e}( %-(((r=   ry   r}   r{   )rk   rn   ro   rp   spark_domainr}   rj   )r&   SPARK_API_URLSPARK_LLM_DOMAINr(   itemsrD   _SparkLLMClient)rZ   r   default_valuess      r;   validate_environmentz!ChatSparkLLM.validate_environment/  sr    "6X&""
 "
~
 #7i(##
 #

 &:.&&
 &
!"
 #7#	#
 #
 &:&	&
 &
!"
 
)#4466
 
 

 1?0B0B=0Q0Q~}-*8*<*<W*E*E~w'*.)?+01?+ 23/
 
 
x r=   c           
         t          |           }|                    di           }t          |          D ]Y}||v rt          d| d          ||vr<t                              d| d| d| d           |                    |          ||<   Z|                    |                                          }|rt          d| d	          ||d<   |S )
z>Build extra kwargs from additional params that were passed in.r}   zFound z supplied twice.z	WARNING! z/ is not default parameter.
                    zJ was transferred to model_kwargs.
                    Please confirm that z is what you intended.zParameters za should be specified explicitly. Instead they were passed in as part of `model_kwargs` parameter.)	r'   rD   listr9   loggerwarningpopintersectionkeys)rZ   r   all_required_field_namesextra
field_nameinvalid_model_kwargss         r;   build_extrazChatSparkLLM.build_extrae  s4    $<C#@#@ 

>2..v,, 		; 		;JU"" !F*!F!F!FGGG!999N* N NN N)3N N N  
 %+JJz$:$:j!7DDUZZ\\RR 	T2 T T T  
 "'~r=   messagesstoprun_managerkwargsc              +   z  K   t           }| j                            d |D             | j        | j        d           | j                            | j                  D ]^}d|vr|d         }t          ||          }t          |          }	|r)|	                    t          |j                  |	           |	V  _d S )Nc                 ,    g | ]}t          |          S rY   r<   r   ms     r;   
<listcomp>z(ChatSparkLLM._stream.<locals>.<listcomp>  !    :::A$Q'':::r=   T)rt   rv   datar,   )chunk)r   rj   arunrs   r}   	subscriberw   rU   r$   on_llm_new_tokenrH   r1   )
rh   r   r   r   r   default_chunk_classr1   deltar   cg_chunks
             r;   _streamzChatSparkLLM._stream  s       -:::::	 	 	
 	
 	
 {,,T5I,JJ 	 	GW$$FOE3E;NOOE*5999H Q,,S-?-?x,PPPNNNN	 	r=   streamc                    |s| j         r  | j        d
|||d|}t          |          S | j                            d |D             | j        | j        d           i }i }| j                            | j                  D ]}	d|	v r|	d         |d<   d|	vr|	d         }t          |          }
t          |
          g}t          ||	          S )N)r   r   r   c                 ,    g | ]}t          |          S rY   r   r   s     r;   r   z*ChatSparkLLM._generate.<locals>.<listcomp>  r   r=   Fr   usagetoken_usager   r   )generations
llm_outputrY   )rt   r   r   rj   r   rs   r}   r   rw   rN   r#   r%   )rh   r   r   r   r   r   stream_iter
completionr   r1   r,   r   s               r;   	_generatezChatSparkLLM._generate  s"     	5T^ 	5&$, !+ IO K (444:::::		
 	
 	
 

{,,T5I,JJ 	) 	)G'!!,3G,<
=)W$$ JJ)*55%g6667kjIIIIr=   c                     dS )Nzspark-llm-chatrY   rg   s    r;   	_llm_typezChatSparkLLM._llm_type  s    r=   )NNNNN),__name__
__module____qualname____doc__classmethodboolr[   propertyr   rH   ri   rj   r   __annotations__r*   rb   r   rc   rd   re   rf   rs   rt   rw   intry   floatr{   rE   r}   r)   model_configr+   r   r   r
   r   r   r	   r$   r   r%   r   r   rY   r=   r;   rW   rW      s        m m^ 4    [ 
DcN 
 
 
 X
 FC"'%H"E"E"EL(3-EEE#(5Y#G#G#GM8C=GGG&+eD&M&M&MhsmMMM#(5Y#G#G#GM8C=GGG&+eD&H&H&HhsmHHH"M3"""It/ 59555OS5550s+++K++++E3NNN.#(5#>#>#>L$sCx.>>>Q:  L _(###.$ .3 . . . [ $#.h _(###c3h C    [ $#: %):>	 {# tCy! 67	
  
%	&   8 %):>!%J J{#J tCy!J 67	J
 J J 
J J J J@  3       X     r=   rW   c                      e Zd ZdZ	 	 	 ddedededee         dee         dee         fd	Zedededed
efd            Z		 	 d de
e         dedee         ded
df
dZ	 	 d de
e         dedee         ded
ej        f
dZdedee         d
dfdZdededed
dfdZded
dfdZdeded
dfdZ	 d!dededee         d
efdZd"dee         d
eeddf         fdZdS )#r   z
    Use websocket-client to call the SparkLLM interface provided by Xfyun,
    which is the iFlyTek's open platform for AI capabilities
    Nrk   rn   ro   rp   r   r}   c                    	 dd l }|| _        n# t          $ r t          d          w xY w|st          n|| _        || _        || _        |pt          | _        t                      | _
        ddd| _        || _        || _        d S )Nr   zhCould not import websocket client python package. Please install it with `pip install websocket-client`.r4   r2   rC   )	websocketwebsocket_clientImportErrorr   rp   rk   r}   r   r   r   queueblocking_messagern   ro   )rh   rk   rn   ro   rp   r   r}   r   s           r;   __init__z_SparkLLMClient.__init__  s    	$-D!! 	 	 	I  	 -4@}}((<,<"'''
,. D D$s    (r-   c                    t          t          t          j                                                                        }t          |           }|j        }|j        }d| d| d| d}t          j	        |
                    d          |
                    d          t          j                                                  }t          j        |                              d          }	d| d	|	 d
}
t          j        |

                    d                                        d          }|||d}t#          |          }t%          |j        |j        |j        |j        ||j        f          }|S )zK
        Generate a request url with an api key and an api secret.
        zhost: z
date: z
GET z	 HTTP/1.1zutf-8)	digestmod)encodingz	api_key="zQ", algorithm="hmac-sha256",         headers="host date request-line", signature="")authorizationdatehost)r   r   r   now	timetupler   netlocpathhmacnewencodehashlibsha256digestbase64	b64encodedecoder   r   schemeparamsfragment)rp   rn   ro   r   
parsed_urlr   r   signature_originsignature_shasignature_sha_base64authorization_originr   params_dictencoded_paramsurls                  r;   _create_urlz_SparkLLMClient._create_url  s     x|~~'?'?'A'A B BCC g&&
 MDMM$MMdMMM g&&##G,,n
 
 
 &((	 	  &/>>EEwEWW N7  N  N6J N  N  N()=)D)DW)M)MNNUU V 
 

 )6tTRR";//!!!#	
 	
 
r=   Fr   user_idrt   c                 d   | j                             d           | j                             t                              | j        | j        | j                  | j        | j	        | j
        | j                  }||_        ||_        || j        n||_        ||_        |                                 d S )NF)
on_messageon_erroron_closeon_open)r   enableTraceWebSocketAppr   r   rp   rn   ro   r   r   r   r   r   r   r}   rt   run_forever)rh   r   r   r}   rt   wss         r;   runz_SparkLLMClient.run  s     	))%000"//'' 
 ]]L 0 

 

 
/;/C$++ 
r=   c                 l    t          j        | j        ||||f          }|                                 |S )N)targetargs)	threadingThreadr   start)rh   r   r   r}   rt   	ws_threads         r;   r   z_SparkLLMClient.arun'  sI     $8	
 
 
	 	r=   r   errorc                 f    | j                             d|i           |                                 d S )Nr  )r   putclose)rh   r   r  s      r;   r   z_SparkLLMClient.on_error:  s,    
'(((





r=   close_status_codeclose_reasonc                 |    t                               d||di           | j                            ddi           d S )Nlog)r  r  doneT)r   debugr   r  )rh   r   r  r  s       r;   r   z_SparkLLMClient.on_close>  sP    ):$0 	
 	
 	
 	
~&&&&&r=   c                     ddd| _         t          j        |                     |j        |j        |j                            }|                    |           d S )Nr4   r2   rC   )r   r   r}   )r   jsondumps
gen_paramsr   r   r}   send)rh   r   r   s      r;   r   z_SparkLLMClient.on_openI  s[    ,. D DzOObjr   
 

 	r=   r,   c                     t          j        |          }|d         d         }|dk    rD| j                            dd| d|d         d          i           |                                 d S |d         d	         }|d
         }|d         d         d         }|j        r)| j                            d|d         d         i           n| j        dxx         |z  cc<   |dk    r|j        s!| j                            d| j        i           |r>|                    di                               di                               di           ni }| j                            d|i           |                                 d S d S )Nheadercoder   r  zCode: z	, Error: r,   payloadchoicesstatustextr1   r      r   )r  loadsr   r  r  rt   r   rD   )	rh   r   r,   r   r  r  r  r1   
usage_datas	            r;   r   z_SparkLLMClient.on_messageR  s   z'""H~f%199JNNM4MM$x.2KMMN   HHJJJJJ9oi0GX&Ffoa(3G| <
(:;<<<<%i000G;000{{| DJNNFD,A#BCCC DHHY++//<<@@LLL 
 
4555




 {r=   c                     | j         |ddd| j        iidd|iid}|r!|d         d                             |           t                              d|            |S )	N)rk   uidchatdomainr,   r  )r  	parameterr  r   zSpark Request Parameters: )rk   r   updater   r  )rh   r   r   r}   r   s        r;   r  z_SparkLLMClient.gen_paramsm  s     "&W== 8T->"?@!FH#56
 
  	;f%,,\:::8$88999r=   ru   rv   c              #      K   	 	 | j                             |          }n*# t           j        $ r}t          d| d          d }~ww xY wd|v rt	          |d                   d|v r|V  jd|v rd S d|vrd S |V  z)	NTr   z-SparkLLMClient wait LLM api response timeout z secondsr  r   r  r   )r   rD   EmptyTimeoutErrorConnectionError)rh   rv   r1   _s       r;   r   z_SparkLLMClient.subscribe{  s      	*...99;   "UGUUU   '!!%gg&6777'!!  W$$MMM!	s   ! AAAr   )NFr   )ru   )r   r   r   r   rH   r   rE   r   staticmethodr   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r   rY   r=   r;   r   r     s         "&&*'+% %% % 	%
 #% sm% tn% % % %8 *S *3 *C *C * * * \*` (, t*  tn	
  
   : (, t*  tn	
  
	   &3 x}     	'3 	'3 	'c 	'd 	' 	' 	' 	'# $    S 3 4    8 LP '*:B4.	    # 	$dBR8S      r=   r   )Hr   r   r   r  loggingr   r   r   r   timer   typingr   r   r   r	   r
   r   r   r   r   urllib.parser   r   r   wsgiref.handlersr   langchain_core.callbacksr   *langchain_core.language_models.chat_modelsr   r   langchain_core.messagesr   r   r   r   r   r   r   r   r   r   r    *langchain_core.output_parsers.openai_toolsr!   r"   langchain_core.outputsr#   r$   r%   langchain_core.utilsr&   r'   langchain_core.utils.pydanticr(   pydanticr)   r*   r+   	getLoggerr   r   r   r   rE   r<   rH   rN   rU   rW   r   rY   r=   r;   <module>r6     s                               V V V V V V V V V V V V V V V V V V V V V V 8 8 8 8 8 8 8 8 8 8 - - - - - -                                                     
        5 4 4 4 4 4 7 7 7 7 7 7 7 7 7 7		8	$	$6  [ T    4 ?738#4  ?  ?  ?  ?  ?F2382-12B-C22 2 2 26k  k  k  k  k = k  k  k \	M M M M M M M M M Mr=   