
    NgT              	       ,   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Zddl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mZmZmZ ddlmZ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% erddl&Z'ddl(m)c m*c m+Z,  ej-        e.          Z/d	Z0d
Z1dZ2d'dZ3 G d d          Z4 e4            Z5 e4            Z6 G d de7e	          Z8 G d de!          Z9 G d de!          Z: G d d          Z;dee7         de<deee7         eej=                 f         fdZ>ddde7fdZ?ded         dee7ddf         fd Z@eeAe4f         ZBe7ZC G d! d"          ZDeDZEe7ZF G d# d$e9e:eeEeFf                   ZGee7eef         ZHeAZI G d% d&e9e:eeHeIf                   ZJeGZKeJZLeDZMdS )(z*A common module for NVIDIA Riva Runnables.    N)Enum)TYPE_CHECKINGAnyAsyncGeneratorAsyncIteratorDict	GeneratorIteratorListOptionalTupleUnioncast)
AnyMessageBaseMessage)PromptValue)RunnableConfigRunnableSerializable)
AnyHttpUrl	BaseModelFieldparse_obj_asroot_validator	validator      ?i  )
.!?   ¡   ¿returnriva.clientc                  `    	 ddl } n"# t          $ r}t          d          |d}~ww xY w| j        S )z5Import the riva client and raise an error on failure.r   NziCould not import the NVIDIA Riva client library. Please install it with `pip install nvidia-riva-client`.)riva.clientImportErrorclient)rivaerrs     e/var/www/html/ai-engine/env/lib/python3.11/site-packages/langchain_community/utilities/nvidia_riva.py_import_riva_clientr+   1   s\       G
 
 	
 ;s    
&!&c                       e Zd ZdZdS )	SentinelTzAn empty Sentinel type.N)__name__
__module____qualname____doc__     r*   r-   r-   >   s        !!!!r3   r-   c                   b    e Zd ZdZdZdZdZdZdZdZ	e
ded	d fd
            Zedd            ZdS )RivaAudioEncodinga  An enum of the possible choices for Riva audio encoding.

    The list of types exposed by the Riva GRPC Protobuf files can be found
    with the following commands:
    ```python
    import riva.client
    print(riva.client.AudioEncoding.keys())  # noqa: T201
    ```
    ALAWENCODING_UNSPECIFIEDFLAC
LINEAR_PCMMULAWOGGOPUSformat_coder"   c                     	 | j         | j        | j        d|         S # t          $ r}t	          d|           |d}~ww xY w)zReturn the audio encoding specified by the format code in the wave file.

        ref: https://mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
        )         z>The following wave file format code is not supported by Riva: N)r9   r6   r:   KeyErrorNotImplementedError)clsr<   r)   s      r*   from_wave_format_codez'RivaAudioEncoding.from_wave_format_codeX   sj    	~#(syAA+NN 	 	 	%8*58 8  	s    
?:?riva.client.AudioEncodingc                 H    t                      }t          |j        |           S )z-Returns the Riva API object for the encoding.)r+   getattrAudioEncodingselfriva_clients     r*   riva_pb2zRivaAudioEncoding.riva_pb2f   s"     *++{0$777r3   N)r"   rE   )r.   r/   r0   r1   r6   r7   r8   r9   r:   r;   classmethodintrD   propertyrL   r2   r3   r*   r5   r5   F   s          D1DJEG 8K    [ 8 8 8 X8 8 8r3   r5   c                       e Zd ZU dZ e ed          dddg          Zeeef         e	d<    edd	          Z
ee         e	d
<   edd            Z eddd          ededefd                        ZdS )RivaAuthMixinzBConfiguration for the authentication to a Riva service connection.zhttp://localhost:50051z1The full URL where the Riva service can be found.z"https://user@pass:riva.example.com)descriptionexamplesurlNz@A full path to the file where Riva's public ssl key can be read.rR   ssl_certr"   riva.client.Authc                     t                      }t          t          | j                  }|j        dk    }t          | j                                      d          d         }|                    | j        ||          S )z!Return a riva client auth object.https/   )rV   use_ssluri)	r+   r   r   rT   schemestrsplitAuthrV   )rJ   rK   rT   r\   url_no_schemes        r*   authzRivaAuthMixin.authz   sr     *++:tx((*'DH++C003]G   
 
 	
r3   T)preallow_reusevalc                     t          |t                    r(t          t          t	          t          |                    S t          t          |          S )z:Do some initial conversations for the URL before checking.)
isinstancer_   r   r   r   )rC   rf   s     r*   _validate_urlzRivaAuthMixin._validate_url   sA     c3 	C
LS$A$ABBBJ$$$r3   )r"   rW   )r.   r/   r0   r1   r   r   rT   r   r_   __annotations__rV   r   rO   rc   r   rM   r   ri   r2   r3   r*   rQ   rQ   m   s        LL"'%
+,,G*,PQ# # #Cz3	   
 $eV  Hhsm   
 
 
 
 X
 Yu$D111% %
 % % % [ 21% % %r3   rQ   c                       e Zd ZU dZ eej        d          Zeed<    edd          Z	e
ed<    edd	          Zeed
<   dS )RivaCommonConfigMixinz%A collection of common Riva settings.z!The encoding on the audio stream.)defaultrR   encodingi@  z*The sample rate frequency of audio stream.sample_rate_hertzzen-USzaThe [BCP-47 language code](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) for the target language.language_codeN)r.   r/   r0   r1   r   r5   r9   rn   rj   ro   rN   rp   r_   r2   r3   r*   rl   rl      s         //"'%!,7# # #H    #U"N  s    #  M3     r3   rl   c                   p    e Zd ZU dZej        ed<   ej        ed<   ddZddZ	ddZ
defd	Zdd
ZddZdS )_Eventz3A combined event that is threadsafe and async safe._event_aeventr"   Nc                 f    t          j                    | _        t          j                    | _        dS )zInitialize the event.N)	threadingEventrs   asynciort   rJ   s    r*   __init__z_Event.__init__   s"    o''}r3   c                 j    | j                                          | j                                         dS zSet the event.N)rs   setrt   ry   s    r*   r}   z
_Event.set   s.    r3   c                 j    | j                                          | j                                         dS r|   )rs   clearrt   ry   s    r*   r   z_Event.clear   s0    r3   c                 4    | j                                         S )zIndicate if the event is set.)rs   is_setry   s    r*   r   z_Event.is_set   s    {!!###r3   c                 8    | j                                          dS )zWait for the event to be set.N)rs   waitry   s    r*   r   z_Event.wait   s    r3   c                 H   K   | j                                          d{V  dS )z#Async wait for the event to be set.N)rt   r   ry   s    r*   
async_waitz_Event.async_wait   s2      l!!!!!!!!!!!r3   r"   N)r.   r/   r0   r1   rv   rw   rj   rx   rz   r}   r   boolr   r   r   r2   r3   r*   rr   rr      s         ==O]' ' ' '
   
   
$ $ $ $ $   " " " " " "r3   rr   output_directorysample_ratec                 (   | rt          j        ddd|           5 }|j        }ddd           n# 1 swxY w Y   t          j        |d          }|                    d           |                    d           |                    |           ||fS d	S )
zECreate a new wave file and return the wave write object and filename.bxz.wavF)modesuffixdeletedirNwbr>   r[   )NN)tempfileNamedTemporaryFilenamewaveopensetnchannelssetsampwidthsetframerate)r   r   fwav_file_namewav_files        r*   _mk_wave_filer      s      	)(fU8H
 
 
 	#FM	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 9]D11a   a   k***x((<s   /33rf   TTSInputTypec                     t          | t                    r|                                 S t          | t                    rt	          | j                  S t	          |           S )zAttempt to coerce the input value to a string.

    This is particularly useful for converting LangChain message to strings.
    )rh   r   	to_stringr   r_   content)rf   s    r*   _coerce_stringr      sQ    
 #{## }}#{##  3;s88Or3   inputsc              #   \  K   d}| D ]}t          |          }t          D ]/}||v r)|                    |d          \  }}||z   |z   V  d}||v )0||z  }t          |          t          k    r7t          dt          |          t                    D ]}|||dz            V  d}|r|V  dS dS )z9Filter the input chunks are return strings ready for TTS. r>   r      N)r   _SENTENCE_TERMINATORSr`   len_MAX_TEXT_LENGTHrange)r   bufferchunk
terminatorlast_sentenceidxs         r*   _process_chunksr      s     F  u%% 0 	 	J%%',{{:q'A'A$u},z9999 %%
 	% v;;)))QF-=>> , ,S37]+++++F   r3   c                      e Zd ZU dZej        ed<   ej        ed<   ej        ed<   e	ed<   e	ed<   e	ed<   e
ej                 ed<   dd
eddfdZdeeddf         fdZdee         fdZedefd            Zedefd            Zedefd            Zedefd            Zddede
e         ddfdZddede
e         ddfdZdde
e         ddfdZdde
e         ddfdZded         ddfdZdS )AudioStreamz%A message containing streaming audio.	_put_lock_queueoutputhangupuser_talking
user_quiet_workerr   maxsizer"   Nc                    t          j                    | _        t          j        |          | _        t          j                    | _        t                      | _        t                      | _	        t                      | _
        d| _        dS )zInitialize the queue.)r   N)rv   Lockr   queueQueuer   r   rr   r   r   r   r   )rJ   r   s     r*   rz   zAudioStream.__init__  s_    "))k'222kmmhh (("HHr3   c              #      K   	 	 | j                             dt                    }n# t          j        $ r Y 4w xY w|t
          k    rdS |V  | j                                          b)zReturn an error.TN)r   get_QUEUE_GET_TIMEOUTr   EmptyHANGUP	task_donerJ   next_vals     r*   __iter__zAudioStream.__iter__  s      	$;??41CDD;    6!! NNNK!!###	$s    & 88c                
  K   	 	 t          j                                        d| j        j        dt
                     d{V }n# t          j        $ r Y Rw xY w|t          k    rdS |W V  | j        	                                 )z4Iterate through all items in the queue until HANGUP.TN)
rx   get_event_looprun_in_executorr   r   r   r   r   r   r   r   s     r*   	__aiter__zAudioStream.__aiter__&  s      	$!(!7!9!9!I!I$+/41C" "       ;    6!! NNNNK!!###	$s   >A AAc                 4    | j                                         S )z(Indicate if the audio stream has hungup.)r   r   ry   s    r*   hungupzAudioStream.hungup9  s     {!!###r3   c                 4    | j                                         S )z-Indicate in the input stream buffer is empty.)r   emptyry   s    r*   r   zAudioStream.empty>  s     {  """r3   c                     | j         o| j        }| j        duo2| j                                         o| j                                        }|o|S )z;Indicate if the audio stream has hungup and been processed.N)r   r   r   is_aliver   )rJ   
input_doneoutput_dones      r*   completezAudioStream.completeC  s]     [/TZ
L$ $L))+++$!!## 	
 )k)r3   c                 F    | j         r| j                                         S dS )z&Indicate if the ASR stream is running.F)r   r   ry   s    r*   runningzAudioStream.runningN  s'     < 	+<((***ur3   itemtimeoutc                     | j         5  | j        rt          d          |t          u r| j                                         | j                            ||           ddd           dS # 1 swxY w Y   dS )zPut a new item into the queue.z?The audio stream has already been hungup. Cannot put more data.r   N)r   r   RuntimeErrorr   r   r}   r   put)rJ   r   r   s      r*   r   zAudioStream.putU  s    ^ 	3 	3{ "U   v~~!!!KOOD'O222	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3s   AA**A.1A.c                    K   t          j                    }t          j        |                    d| j        |          |           d{V  dS )z$Async put a new item into the queue.N)rx   r   wait_forr   r   )rJ   r   r   loops       r*   aputzAudioStream.aput`  sS      %''t33D$(DII7SSSSSSSSSSSr3   c                 <    |                      t          |           dS )zSend the hangup signal.N)r   r   rJ   r   s     r*   closezAudioStream.closee  s    !!!!!r3   c                 L   K   |                      t          |           d{V  dS )zAsync send the hangup signal.N)r   r   r   s     r*   aclosezAudioStream.aclosei  s2      ii(((((((((((r3   	responseszrasr.StreamingRecognizeResponsec                      j         rt          d          t          j        dd          d
 fd}t          j        |           _        d	 j        _         j                                                                          dS )zIDrain the responses from the provided iterator and put them into a queue.z,An ASR instance has already been registered.r[   r   r   r"   Nc                                                       D ]} | j        s
| j        D ]}|j        s
|j        rrj                                         j                                         t          t          |j        d         j
                  }j                            |           j                                        s2j                                         j                                         όdS )zConsume the ASR Generator.r   N)r   resultsalternativesis_finalr   r   r   r}   r   r_   
transcriptr   r   r   )responseresultr   has_startedr   rJ   s      r*   workerz$AudioStream.register.<locals>.workert  s   % 0 0' &. 0 0F!. !  0)//111++---%)#v/B1/E/P%Q%Q

3333!.5577 0)--///--///0	0 0r3   )targetTr   )	r   r   rv   BarrierThreadr   daemonstartr   )rJ   r   r   r   s   `` @r*   registerzAudioStream.registerm  s    < 	OMNNN'1555	0 	0 	0 	0 	0 	0 	0 	0* !'v666"r3   )r   N) r.   r/   r0   r1   rv   r   rj   r   r   rr   r   r   rN   rz   r	   bytesr   r   StreamInputTyper   rO   r   r   r   r   r   r   r   r   r   r
   r   r2   r3   r*   r   r      sq        //~KKNNNi&''''  D    $)E4$56 $ $ $ $"$!? $ $ $ $& $ $ $ $ X$ #t # # # X# *$ * * * X*     X	3 	3 	3(3- 	34 	3 	3 	3 	3T T T# TRV T T T T
" "Xc] "d " " " ") )HSM )T ) ) ) )(+L"M RV      r3   r   c            	       H   e Zd ZU dZdZeed<   dZeed<    edd          Z	e
ed	<    ed
d          Zeed<    ed
d          Zeed<    ed
          edeeef         deeef         fd                        Zedd            ZddZ	 ddedee         dedefdZdS )RivaASRzNA runnable that performs Automatic Speech Recognition (ASR) using NVIDIA Riva.nvidia_riva_asrr   zA Runnable for converting audio bytes to a string.This is useful for feeding an audio stream into a chain andpreprocessing that audio to create an LLM prompt.rR   r>   z7The number of audio channels in the input audio stream.rU   audio_channel_countTz\Controls whether or not Riva should attempt to filter profanity out of the transcribed text.profanity_filterz]Controls whether Riva should attempt to correct senetence puncuation in the transcribed text.enable_automatic_punctuationrd   valuesr"   c                 "    t                      }|S z4Validate the Python environment and input arguments.r+   rC   r   _s      r*   _validate_environmentzRivaASR._validate_environment        !!r3   &riva.client.StreamingRecognitionConfigc                     t                      }|                    d|                    | j        | j        | j        d| j        | j        | j                            S )z)Create and return the riva config object.Tr>   )rn   ro   r   max_alternativesr   r   rp   )interim_resultsconfig)	r+   StreamingRecognitionConfigRecognitionConfigrn   ro   r   r   r   rp   rI   s     r*   r  zRivaASR.config  sm     *++55 00"&"8$($<!"!%!6-1-N"0 1   6 
 
 	
r3   riva.client.ASRServicec                     t                      }	 |                    | j                  S # t          $ r}t	          d          |d}~ww xY w);Connect to the riva service and return the a client object.z5Error raised while connecting to the Riva ASR server.N)r+   
ASRServicerc   	Exception
ValueErrorrJ   rK   r)   s      r*   _get_servicezRivaASR._get_service  s_    )++	))$)444 	 	 	G 	   * 
A	AA	Ninputr  kwargsc                    |j         sE|                                 }|                    || j                  }|                    |           g }|j        s|j        j        5  |j        j                            d          }ddd           n# 1 swxY w Y   |r|j        	                                sf	 ||j        
                                gz  }n# t          j        $ r Y Iw xY w|j                                         |j        	                                ft                              dt!          |                     d                    |                                          S |j        dS )z3Transcribe the audio bytes into a string with Riva.)audio_chunksstreaming_configg?NzRiva ASR returning: %s r   )r   r  streaming_response_generatorr  r   r   r   	not_emptyr   r   
get_nowaitr   r   r   _LOGGERdebugreprjoinstrip)rJ   r  r  r  servicer   full_responsereadys           r*   invokezRivaASR.invoke  s    } 	&''))G<<"!% =  I NN9%%% $&. 	7' 9 9.33C889 9 9 9 9 9 9 9 9 9 9 9 9 9 9  7,,,.. -!%%,*A*A*C*C)DD ; ! ! ! !L**,,,  ,,,.. - 6]8K8KLLLxx..44666 . 	7 rs$   # BBB6C C&%C&)r"   r  )r"   r  r   )r.   r/   r0   r1   r   r_   rj   rR   r   r   rN   r   r   r   r   rM   r   r   r  rO   r  r  ASRInputTyper   r   ASROutputTyper)  r2   r3   r*   r   r     s        
 YX!D#!!!	<      %u	P         #U5  d    */<* * * $    ^4S> d38n    [ 
 
 
 
 X
     ,0     (  	 
 
           r3   r   c                      e Zd ZU dZdZeed<   dZeed<    edd          Z	eed	<    ed
d          Z
ee         ed<    ed          edeeef         deeef         fd                        Z ed          ededefd                        ZddZ	 ddedee         dedefdZ	 ddee         dee         dee         dee         fdZ	 ddee         dee         dee         deed
f         fdZd
S )RivaTTSz?A runnable that performs Text-to-Speech (TTS) with NVIDIA Riva.nvidia_riva_ttsr   z_A tool for converting text to speech.This is useful for converting LLM output into audio bytes.rR   zEnglish-US.Female-1zThe voice model in Riva to use for speech. Pre-trained models are documented in [the Riva documentation](https://docs.nvidia.com/deeplearning/riva/user-guide/docs/tts/tts-overview.html).rU   
voice_nameNzThe directory where all audio files should be saved. A null value indicates that wave files should not be saved. This is useful for debugging purposes.r   Tr   r   r"   c                 "    t                      }|S r  r  r  s      r*   r  zRivaTTS._validate_environment   r  r3   vc                     |rLt          j        |          }|                    dd           t          |                                          S |S )NT)parentsexist_ok)pathlibPathmkdirr_   absolute)rC   r1  dirpaths      r*   _output_directory_validatorz#RivaTTS._output_directory_validator'  sN      	+l1ooGMM$M666w''))***r3   "riva.client.SpeechSynthesisServicec                     t                      }	 |                    | j                  S # t          $ r}t	          d          |d}~ww xY w)r  z5Error raised while connecting to the Riva TTS server.N)r+   SpeechSynthesisServicerc   r  r  r  s      r*   r  zRivaTTS._get_service0  s_    )++	55di@@@ 	 	 	G 	r  r  r  r  c                 n    d                     |                     t          |g                              S )zDPerform TTS by taking a string and outputting the entire audio file.r3   )r$  	transformiter)rJ   r  r  r  s       r*   r)  zRivaTTS.invoke:  s*     xxtUG}}55666r3   c              +     K   |                                  }t          | j        | j                  \  }}t	          |          D ]}t
                              d|           |                    || j        | j	        | j
        j        | j                  }|D ]7}	t          t          |	j                  }
|r|                    |
           |
V  8|r1|                                 t
                              d|           dS dS )zHPerform TTS by taking a stream of characters and streaming output bytes.zRiva TTS chunk: %s)textr/  rp   rn   sample_rate_hzzRiva TTS wrote file: %sN)r  r   r   ro   r   r!  r"  synthesize_onliner/  rp   rn   rL   r   r   audiowriteframesrawr   )rJ   r  r  r  r&  r   r   r   r   resprE  s              r*   r?  zRivaTTS.transformC  s0      ##%% #0!4#9#
 #
x
 %U++ 	 	EMM.666  11?"0/#5 2  I "  UDJ// 3++E222	  	DNNMM3]CCCCC	D 	Dr3   c                V   	
K   t          j                    t          j                    t          j                    d	fd}dt          t
                   ffd
d	
 fd	d		fd}                     |                      }                     |                      }	 	 t          j                                        d           d{V }n# t           j	        j
        $ r Y Fw xY w                                 |t          u rn|W V  m| d{V  | d{V  dS )
zGIntercept async transforms and route them to the synchronous transform.r"   Nc                     K   2 3 d{V }                      |            6                      t                     dS )z#Produce input into the input queue.N)
put_nowait_TRANSFORM_END)rf   r  input_queues    r*   	_producerz%RivaTTS.atransform.<locals>._produceru  se      " , , , , , , ,c&&s++++ #"">22222s   #c               3      K   	 	                      d          } n# t          j        $ r Y *w xY w| t          k    rdS | V  ?)zIterate over the input_queue.Tr   r   N)r   r   r   rK  )rf   rL  s    r*   _input_iteratorz+RivaTTS.atransform.<locals>._input_iterator{  sf      %//#/66CC{   H.((E			s    //c                                                                  D ]}                     |                                t                     dS )z!Consume the input with transform.N)r?  rJ  rK  )rf   rO  	out_queuerJ   s    r*   	_consumerz%RivaTTS.atransform.<locals>._consumer  sW    ~~oo&7&788 * *$$S))))  00000r3   c                  D   K                        d            d{V  dS )z"Coroutine that wraps the consumer.N)r   )rR  r   s   r*   _consumer_coroz*RivaTTS.atransform.<locals>._consumer_coro  s5      &&tY77777777777r3   Tr   r   )rx   get_running_loopr   r   r
   r   create_taskr   r   
exceptionsTimeoutErrorr   rK  )rJ   r  r  r  rM  rT  producerconsumerrf   rR  rO  rL  r   rQ  s   ``       @@@@@r*   
atransformzRivaTTS.atransformj  s      '))#(;==#*=??		3 	3 	3 	3 	3 	3 	3		,!7 		 		 		 		 		 			1 	1 	1 	1 	1 	1 	1 	1	8 	8 	8 	8 	8 	8 	8 ##IIKK00##NN$4$455		#,Y]]__cBBBBBBBB%2   !!!n$$IIII		 s   --C C21C2)r"   r;  r   )r.   r/   r0   r1   r   r_   rj   rR   r   r/  r   r   r   rM   r   r   r  r   r:  r  r   r   TTSOutputTyper)  r
   r?  r   r   r[  r2   r3   r*   r-  r-     sg        
 JI!D#!!!	E     ea  J    ',e5' ' 'hsm    ^4S> d38n    [ 
 Y!""C C    [ #"    ,07 77 (7 	7
 
7 7 7 7 ,0%D %D%%D (%D 3-	%D
 
-	 %D %D %D %DT ,05 5\*5 (5 3-	5
 
t+	,5 5 5 5 5 5r3   r-  )r"   r#   )Nr1   rx   loggingr5  r   r   rv   r   enumr   typingr   r   r   r   r   r	   r
   r   r   r   r   r   langchain_core.messagesr   r   langchain_core.prompt_valuesr   langchain_core.runnablesr   r   pydanticr   r   r   r   r   r   r%   r(   riva.client.proto.riva_asr_pb2r'   protoriva_asr_pb2rasr	getLoggerr.   r!  r   r   r   r+   r-   r   rK  r_   r5   rQ   rl   rr   float
Wave_writer   r   r   r   r   StreamOutputTyper   r*  r+  r   r   r\  r-  NVIDIARivaASRNVIDIARivaTTSNVIDIARivaStreamr2   r3   r*   <module>ro     s   0 0                                            < ; ; ; ; ; ; ; 4 4 4 4 4 4 I I I I I I I I                 2111111111111
'
H
%
%  9 
 
 
 
" " " " " " " " 
$8 $8 $8 $8 $8T $8 $8 $8N% % % % %I % % %B    I   (" " " " " " " "Dsm27
8C=(4?334   "	 	3 	 	 	 	H^4 3d?9S    6 y() L L L L L L L L` c c c c c}45c c cP S*k12_ _ _ _ _}45_ _ _F    r3   