
    7|ho>                    :   d dl m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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 d dl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!m"Z" d dl#m$Z$  ejJ                  e&      Z' G d de      Z( G d d      Z)y)    )annotationsN)datetime)Queue)mktime)AnyDict	GeneratorIteratorListOptional)	urlencodeurlparse
urlunparse)format_date_time)CallbackManagerForLLMRun)LLM)GenerationChunk)get_from_dict_or_envpre_init)Fieldc                     e Zd ZU dZdZded<    edd      Zded<   	  edd	      Zded
<   	  edd      Z	ded<   	  edd      Z
ded<   	  edd      Zded<   	 dZded<   dZded<   	  edd      Zded<   	 dZded<   	 dZded<   	  ee       Zd!ed"<   	 ed(d#       Zed)d$       Zed*d%       Z	 	 d+	 	 	 	 	 	 	 	 	 d,d&Z	 	 d+	 	 	 	 	 	 	 	 	 d-d'Zy).SparkLLMuT  iFlyTek Spark completion model integration.

    Setup:
        To use, you should set environment variables ``IFLYTEK_SPARK_APP_ID``,
        ``IFLYTEK_SPARK_API_KEY`` and ``IFLYTEK_SPARK_API_SECRET``.

    .. code-block:: bash

            export IFLYTEK_SPARK_APP_ID="your-app-id"
            export IFLYTEK_SPARK_API_KEY="your-api-key"
            export IFLYTEK_SPARK_API_SECRET="your-api-secret"

    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:
        app_id: Optional[str]
            IFLYTEK SPARK API KEY. Automatically inferred from env var `IFLYTEK_SPARK_APP_ID` if not provided.
        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.llms import SparkLLM

            llm = SparkLLM(
                app_id="your-app-id",
                api_key="your-api_key",
                api_secret="your-api-secret",
                # model='Spark4.0 Ultra',
                # temperature=...,
                # other params...
            )

    Invoke:
        .. code-block:: python

            input_text = "用50个字左右阐述，生命的意义在于"
            llm.invoke(input_text)

        .. code-block:: python

            '生命的意义在于实现自我价值，追求内心的平静与快乐，同时为他人和社会带来正面影响。'

    Stream:
        .. code-block:: python

            for chunk in llm.stream(input_text):
                print(chunk)

        .. code-block:: python

            生命 | 的意义在于 | 不断探索和 | 实现个人潜能，通过 | 学习 | 、成长和对社会 | 的贡献，追求内心的满足和幸福。

    Async:
        .. code-block:: python

            await llm.ainvoke(input_text)

            # stream:
            # async for chunk in llm.astream(input_text):
            #    print(chunk)

            # batch:
            # await llm.abatch([input_text])

        .. code-block:: python

            '生命的意义在于实现自我价值，追求内心的平静与快乐，同时为他人和社会带来正面影响。'

    Nr   clientapp_id)defaultaliasOptional[str]spark_app_idapi_keyspark_api_key
api_secretspark_api_secretapi_urlspark_api_urlmodelspark_llm_domainlc_userstrspark_user_idFbool	streaming   timeoutintrequest_timeoutg      ?floattemperature   top_k)default_factoryDict[str, Any]model_kwargsc           	     n   t        |ddgd      |d<   t        |ddgd      |d<   t        |ddgd	      |d<   t        |d
dgdd      |d
<   t        |ddgdd      |d<   |d   xs | j                  |d   d<   |d   xs | j                  |d   d<   t        |d   |d   |d   |d
   |d   |d         |d<   |S )Nr   r   IFLYTEK_SPARK_APP_IDr    r   IFLYTEK_SPARK_API_KEYr"   r!   IFLYTEK_SPARK_API_SECRETr$   r#   IFLYTEK_SPARK_API_URL$wss://spark-api.xf-yun.com/v3.5/chatr&   r%   IFLYTEK_SPARK_LLM_DOMAINgeneralv3.5r1   r6   r3   )r   r   r!   r#   spark_domainr6   r   )r   r1   r3   _SparkLLMClient)clsvaluess     `/var/www/html/test/engine/venv/lib/python3.12/site-packages/langchain_community/llms/sparkllm.pyvalidate_environmentzSparkLLM.validate_environment   s&   !5X&""
~
 #7i(##

 &:.&&
!"
 #7i(#2	#
 &:)&	&
!" 17}0E0X~}-*0/*FSYY~w'*.)?+01?+ 23/
x     c                     y)zReturn type of llm.zspark-llm-chat )selfs    rC   	_llm_typezSparkLLM._llm_type   s      rE   c                    | j                   | j                  | j                  | j                  | j                  d}i || j
                  S )z4Get the default parameters for calling SparkLLM API.)r&   streamr/   r3   r1   )r&   r+   r/   r3   r1   r6   )rH   normal_paramss     rC   _default_paramszSparkLLM._default_params   sL     !% 5 5nn#33ZZ++
 6-54#4#455rE   c                l   | j                   r-d} | j                  |||fi |D ]  }||j                  z  } |S d}| j                  j	                  d|dg| j
                  | j                  | j                          | j                  j                  | j                        D ]  }d|vr|d   d   } |S )av  Call out to an sparkllm for each generation with a prompt.
        Args:
            prompt: The prompt to pass into the model.
            stop: Optional list of stop words to use when generating.
        Returns:
            The string generated by the llm.

        Example:
            .. code-block:: python
                response = client("Tell me a joke.")
         userrolecontentr-   datarS   )	r+   _streamtextr   arunr)   r6   	subscriber/   )rH   promptstoprun_managerkwargs
completionchunkrS   s           rC   _callzSparkLLM._call   s    $ >>J%fdKJ6J )ejj(
)
01NN		
 {{,,T5I5I,J 	4GW$ 3J	4
 rE   c              +  *  K   | j                   j                  d|dg| j                  | j                  d       | j                   j	                  | j
                        D ]0  }d|vr|d   }|r|j                  |       t        |d          2 y w)NrP   rQ   TrT   rU   rS   )rW   )r   runr)   r6   rY   r/   on_llm_new_tokenr   )rH   rZ   r[   r\   r]   rS   deltas          rC   rV   zSparkLLM._stream   s      	01		
 {{,,T5I5I,J 	9GW$FOE,,U3!uY'788	9s   BB)rB   r   returnr   )re   r(   )re   r5   )NN)
rZ   r(   r[   Optional[List[str]]r\   "Optional[CallbackManagerForLLMRun]r]   r   re   r(   )
rZ   r(   r[   rf   r\   rg   r]   r   re   zIterator[GenerationChunk])__name__
__module____qualname____doc__r   __annotations__r   r   r    r"   r$   r&   r)   r+   r/   r1   r3   dictr6   r   rD   propertyrI   rM   r`   rV   rG   rE   rC   r   r      s   Vp FC"'H"EL-E#(Y#GM=G*&+D&MmM-#(Y#GM=G&+D&HmH"M3"It/ 9=OS=0K+E3N.#(#>L.>Q( (T     
6 
6 %):>	## "# 8	#
 # 
#P %):>	99 "9 8	9
 9 
#9rE   r   c                      e Zd ZdZ	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZedd       Z	 	 d	 	 	 	 	 	 	 	 	 ddZ	 	 d	 	 	 	 	 	 	 	 	 ddZddZ	ddZ
dd	Zdd
Z	 d	 	 	 	 	 	 	 ddZdddZy)r@   z
    Use websocket-client to call the SparkLLM interface provided by Xfyun,
    which is the iFlyTek's open platform for AI capabilities
    Nc                    	 dd l }|| _        |sdn|| _        || _        || _        |xs d| _        t               | _        ddd| _	        || _
        || _        y # t        $ r t        d      w xY w)Nr   zhCould not import websocket client python package. Please install it with `pip install websocket-client`.r<   r>   rO   	assistantrS   rR   )	websocketwebsocket_clientImportErrorr#   r   r6   r?   r   queueblocking_messager   r!   )rH   r   r   r!   r#   r?   r6   rs   s           rC   __init__z_SparkLLMClient.__init__  s    	$-D! ;B2w 	 ((9M"''
,. D$  	I 	s   A A.c                   t        t        t        j                         j	                                     }t        |       }|j                  }|j                  }d| d| d| d}t        j                  |j                  d      |j                  d      t        j                        j                         }t        j                  |      j!                  d      }	d| d	|	 d
}
t        j                  |
j                  d            j!                  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)r#   r   r!   r~   
parsed_urlr   r   signature_originsignature_shasignature_sha_base64authorization_originr}   params_dictencoded_paramsurls                  rC   _create_urlz_SparkLLMClient._create_url*  sf     x||~'?'?'A BC g&
  #D6$vdV9M g&##G,nn
 &(	 	  &//>EEwEW!*7) 466J5K1 N(()=)D)DW)MNUU V 

 )6tTR";/!!!!!!##	
 
rE   c                   | j                   j                  d       | j                   j                  t        j	                  | j
                  | j                  | j                        | j                  | j                  | j                  | j                        }||_        ||_        || j                  n||_        ||_        |j!                          y )NF)
on_messageon_erroron_closeon_open)rt   enableTraceWebSocketAppr@   r   r#   r   r!   r   r   r   r   messagesuser_idr6   r+   run_forever)rH   r   r   r6   r+   wss         rC   rb   z_SparkLLMClient.runW  s     	))%0""//''
 ]]]]LL 0 

 
/;/C$++ 
rE   c                p    t        j                  | j                  ||||f      }|j                          |S )N)targetargs)	threadingThreadrb   start)rH   r   r   r6   r+   	ws_threads         rC   rX   z_SparkLLMClient.arunp  s>     $$88	
	 	rE   c                ^    | j                   j                  d|i       |j                          y )Nerror)rv   putclose)rH   r   r   s      rC   r   z_SparkLLMClient.on_error  s     

'(

rE   c                r    t         j                  d||di       | j                  j                  ddi       y )Nlog)close_status_codeclose_reasondoneT)loggerdebugrv   r   )rH   r   r   r   s       rC   r   z_SparkLLMClient.on_close  s7    ):$0	
 	

~&rE   c                    ddd| _         t        j                  | j                  |j                  |j
                  |j                              }|j                  |       y )NrO   rq   rr   )r   r   r6   )rw   jsondumps
gen_paramsr   r   r6   send)rH   r   rU   s      rC   r   z_SparkLLMClient.on_open  sN    ,. DzzOObjjr  

 	rE   c                   t        j                  |      }|d   d   }|dk7  r:| j                  j                  dd| d|d   d    i       |j	                          y |d   d	   }|d
   }|d   d   d   }|j
                  r$| j                  j                  d|d   d   i       n| j                  dxx   |z  cc<   |dk(  r|j
                  s'| j                  j                  d| j                  i       |r2|j                  di       j                  di       j                  di       ni }| j                  j                  d|i       |j	                          y y )Nheadercoder   r   zCode: z	, Error: messagepayloadchoicesstatusrW   rS   rU      usage)r   loadsrv   r   r   r+   rw   get)	rH   r   r   rU   r   r   r   rS   
usage_datas	            rC   r   z_SparkLLMClient.on_message  sJ   zz'"H~f%19JJNNF4&	$x.2K1LMN HHJ9oi0GX&Ffoa(3G||

(:;<%%i0G;0{||JJNNFD,A,A#BC  HHY+//<@@L 
 

45
 rE   c                    | j                   |ddd| j                  iidd|iid}|r|d   d   j                  |       t        j	                  d|        |S )	N)r   uidchatdomainr   rW   )r   	parameterr   r   zSpark Request Parameters: )r   r?   updater   r   )rH   r   r   r6   rU   s        rC   r   z_SparkLLMClient.gen_params  sm     "&W= 8T->->"?@!FH#56
 f%,,\:1$89rE   c              #     K   	 	 | j                   j                  |      }d|v rt	        |d         d|v r| 9d|v ry d|vry | G# t         j                  $ r}t        d| d      d }~ww xY ww)NrT   z-SparkLLMClient wait LLM api response timeout z secondsr   r   r   rU   )rv   r   EmptyTimeoutErrorConnectionError)rH   r-   rS   _s       rC   rY   z_SparkLLMClient.subscribe  s     **...9
 '!%gg&677'! W$M!  ;; "CG9HU s'   A5A *A5A2A--A22A5)NNN)r   r(   r   r(   r!   r(   r#   r   r?   r   r6   Optional[dict])r#   r(   r   r(   r!   r(   re   r(   )NF)
r   
List[Dict]r   r(   r6   r   r+   r*   re   None)
r   r   r   r(   r6   r   r+   r*   re   zthreading.Thread)r   r   r   zOptional[Any]re   r   )r   r   r   r.   r   r(   re   r   )r   r   re   r   )r   r   r   r(   re   r   )N)r   listr   r(   r6   r   re   rm   )r,   )r-   zOptional[int]re   zGenerator[Dict, None, None])rh   ri   rj   rk   rx   staticmethodr   rb   rX   r   r   r   r   r   rY   rG   rE   rC   r@   r@     s%    "&&*'+%% % 	%
 % $% %%< * *` (,  %	
  
: (,  %	
  
&	'8 LP'*:H	rE   r@   )*
__future__r   r   r   r   r   loggingrv   r   r   r   timer   typingr   r   r	   r
   r   r   urllib.parser   r   r   wsgiref.handlersr   langchain_core.callbacksr   #langchain_core.language_models.llmsr   langchain_core.outputsr   langchain_core.utilsr   r   pydanticr   	getLoggerrh   r   r   r@   rG   rE   rC   <module>r      sq    "           A A 8 8 - = 3 2 ? 			8	$i9s i9XO OrE   