
    Ngo>                    D   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j%        e&          Z' G d de          Z( G d d          Z)dS )    )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d2d&            Zed3d'            Zed4d(            Z	 	 d5d6d/Z	 	 d5d7d1ZdS )8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_kwargsvaluesr   returnc           	        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         p| j        |d         d<   |d         p| 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)clsr7   s     ]/var/www/html/ai-engine/env/lib/python3.11/site-packages/langchain_community/llms/sparkllm.pyvalidate_environmentzSparkLLM.validate_environment   sE   !5X&""
 "
~
 #7i(##
 #

 &:.&&
 &
!"
 #7i(#2	#
 #
 &:)&	&
 &
!" 17}0E0X~}-*0/*FSY~w'*.)?+01?+ 23/
 
 
x     c                    dS )zReturn type of llm.zspark-llm-chat )selfs    rD   	_llm_typezSparkLLM._llm_type   s
      rF   c                Z    | 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   )rI   normal_paramss     rD   _default_paramszSparkLLM._default_params   sA     !% 5n#3Z+
 
 6-54#455rF   promptstopOptional[List[str]]run_manager"Optional[CallbackManagerForLLMRun]kwargsc                &   | j         r!d} | j        |||fi |D ]}||j        z  }|S d}| j                            d|dg| 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-   datarZ   )	r+   _streamtextr   arunr)   r6   	subscriber/   )rI   rO   rP   rR   rT   
completionchunkrZ   s           rD   _callzSparkLLM._call   s    $ > 	J%fdKJJ6JJ ) )ej(


001N		
 	
 	
 {,,T5I,JJ 	4 	4GW$$ 3JJrF   Iterator[GenerationChunk]c              +    K   | j                             d|dg| j        | j        d           | j                             | j                  D ]>}d|vr|d         }|r|                    |           t          |d                   V  ?d S )NrW   rX   Tr[   r\   rZ   )r^   )r   runr)   r6   r`   r/   on_llm_new_tokenr   )rI   rO   rP   rR   rT   rZ   deltas          rD   r]   zSparkLLM._stream   s       	001		
 	
 	
 {,,T5I,JJ 	9 	9GW$$FOE 4,,U333!uY'78888888	9 	9rF   )r7   r   r8   r   )r8   r(   )r8   r5   )NN)
rO   r(   rP   rQ   rR   rS   rT   r   r8   r(   )
rO   r(   rP   rQ   rR   rS   rT   r   r8   rd   )__name__
__module____qualname____doc__r   __annotations__r   r   r    r"   r$   r&   r)   r+   r/   r1   r3   dictr6   r   rE   propertyrJ   rN   rc   r]   rH   rF   rD   r   r      s        V Vp F"'%H"E"E"ELEEEE#(5Y#G#G#GMGGGG*&+eD&M&M&MMMMM-#(5Y#G#G#GMGGGG&+eD&H&H&HHHHH"M""""I/ 59===O====0K+ENNNN.#(5#>#>#>L>>>>Q( ( ( X(T       X  
6 
6 
6 X
6 %):>	# # # # #P %):>	9 9 9 9 9 9 9rF   r   c                      e Zd ZdZ	 	 	 d-d.dZed/d            Z	 	 d0d1dZ	 	 d0d2dZd3dZ	d4d!Z
d5d"Zd6d$Z	 d7d8d'Zd9d:d,ZdS );rB   z
    Use websocket-client to call the SparkLLM interface provided by Xfyun,
    which is the iFlyTek's open platform for AI capabilities
    Nr   r(   r   r!   r#   r   rA   r6   Optional[dict]c                    	 dd l }|| _        n# t          $ r t          d          w xY w|sdn|| _        || _        || _        |pd| _        t                      | _        ddd| _	        || _
        || _        d S )Nr   zhCould not import websocket client python package. Please install it with `pip install websocket-client`.r>   r@   rV   	assistantrZ   rY   )	websocketwebsocket_clientImportErrorr#   r   r6   rA   r   queueblocking_messager   r!   )rI   r   r   r!   r#   rA   r6   ru   s           rD   __init__z_SparkLLMClient.__init__  s    	$-D!! 	 	 	I  	 ;BN22w 	 ((9M"'''
,. D D$s    (r8   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)r#   r   r!   r   
parsed_urlr   r   signature_originsignature_shasignature_sha_base64authorization_originr   params_dictencoded_paramsurls                  rD   _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";//!!!#	
 	
 
rF   Fmessages
List[Dict]user_idr+   r*   Nonec                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)rv   enableTraceWebSocketApprB   r   r#   r   r!   r   r   r   r   r   r   r6   r+   run_forever)rI   r   r   r6   r+   wss         rD   rf   z_SparkLLMClient.runW  s     	))%000"//'' 
 ]]L 0 

 

 
/;/C$++ 
rF   threading.Threadc                l    t          j        | j        ||||f          }|                                 |S )N)targetargs)	threadingThreadrf   start)rI   r   r   r6   r+   	ws_threads         rD   r_   z_SparkLLMClient.arunp  sI     $8	
 
 
	 	rF   r   r   errorOptional[Any]c                f    | j                             d|i           |                                 d S )Nr   )rx   putclose)rI   r   r   s      rD   r   z_SparkLLMClient.on_error  s,    
'(((





rF   close_status_coder.   close_reasonc                |    t                               d||di           | j                            ddi           d S )Nlog)r   r   doneT)loggerdebugrx   r   )rI   r   r   r   s       rD   r   z_SparkLLMClient.on_close  sP    ):$0 	
 	
 	
 	
~&&&&&rF   c                    ddd| _         t          j        |                     |j        |j        |j                            }|                    |           d S )NrV   rs   rt   )r   r   r6   )ry   jsondumps
gen_paramsr   r   r6   send)rI   r   r\   s      rD   r   z_SparkLLMClient.on_open  s[    ,. D DzOObjr   
 

 	rF   messagec                    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statusr^   rZ   r\      usage)r   loadsrx   r   r   r+   ry   get)	rI   r   r   r\   r   r   r   rZ   
usage_datas	            rD   r   z_SparkLLMClient.on_message  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




 {rF   listrn   c                    | j         |ddd| j        iidd|iid}|r!|d         d                             |           t                              d|            |S )	N)r   uidchatdomainr   r^   )r   	parameterr   r   zSpark Request Parameters: )r   rA   updater   r   )rI   r   r   r6   r\   s        rD   r   z_SparkLLMClient.gen_params  s     "&W== 8T->"?@!FH#56
 
  	;f%,,\:::8$88999rF   r,   r-   Optional[int]Generator[Dict, None, None]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\   )rx   r   EmptyTimeoutErrorConnectionError)rI   r-   rZ   _s       rD   r`   z_SparkLLMClient.subscribe  s      	*...99;   "UGUUU   '!!%gg&6777'!!  W$$MMM!	s   ! AAA)NNN)r   r(   r   r(   r!   r(   r#   r   rA   r   r6   rq   )r#   r(   r   r(   r!   r(   r8   r(   )NF)
r   r   r   r(   r6   rq   r+   r*   r8   r   )
r   r   r   r(   r6   rq   r+   r*   r8   r   )r   r   r   r   r8   r   )r   r   r   r.   r   r(   r8   r   )r   r   r8   r   )r   r   r   r(   r8   r   )N)r   r   r   r(   r6   rq   r8   rn   )r,   )r-   r   r8   r   )ri   rj   rk   rl   rz   staticmethodr   rf   r_   r   r   r   r   r   r`   rH   rF   rD   rB   rB     s.         "&&*'+% % % % %< * * * \*` (,    : (,    &   	' 	' 	' 	'      8 LP          rF   rB   )*
__future__r   r   r   r   r   loggingrx   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   	getLoggerri   r   r   rB   rH   rF   rD   <module>r      s   " " " " " "                             A A A A A A A A A A A A A A A A 8 8 8 8 8 8 8 8 8 8 - - - - - - = = = = = = 3 3 3 3 3 3 2 2 2 2 2 2 ? ? ? ? ? ? ? ?      		8	$	$i9 i9 i9 i9 i9s i9 i9 i9XO O O O O O O O O OrF   