
    qi,                        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mZm	Z	 ddl
mZ ddlmZ ddlmZmZmZ ddl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"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0 ddl1m2Z2 ddl3m4Z4m5Z5 ddl6m7Z7 ddl8m9Z9m:Z: ddl;m<Z< ddl=m>Z> ddl?m@Z@mAZAmBZBmCZC ddlDmEZE 	 ddlFmGZGmHZH ddlImJZJ ddlKmLZLmMZMmNZNmOZOmPZP ddlQmRZR ddlSmTZT ddlUmVZV  G d deZ      Z[ G d d e      Z\ G d! d"e      Z]e G d# d$             Z^ G d% d&e      Z_ G d' d(e      Z`e G d) d*eA             Za G d+ d,e>      Zby# eW$ r7ZX ej                  deX         ej                  d        eZdeX       dZX[Xww xY w)-zAWS Nova Sonic LLM service implementation for Pipecat AI framework.

This module provides a speech-to-speech LLM service using AWS Nova Sonic, which supports
bidirectional audio streaming, text generation, and function calling capabilities.
    N)	dataclassfield)Enum)files)AnyListOptional)logger)	BaseModelField)ToolsSchema)AWSNovaSonicLLMAdapterRole)AggregationTypeBotStoppedSpeakingFrameCancelFrameEndFrameFrameFunctionCallFromLLMInputAudioRawFrameInterruptionFrameLLMContextFrameLLMFullResponseEndFrameLLMFullResponseStartFrameLLMTextFrame
StartFrameTranscriptionFrameTTSAudioRawFrameTTSStartedFrameTTSStoppedFrameTTSTextFrameUserStartedSpeakingFrameUserStoppedSpeakingFrame)
LLMContext)LLMAssistantAggregatorParamsLLMUserAggregatorParams)LLMContextAggregatorPair)OpenAILLMContextOpenAILLMContextFrame)FrameDirection)
LLMService)	NOT_GIVENLLMSettings	_NotGiven_warn_deprecated_param)time_now_iso8601)BedrockRuntimeClient0InvokeModelWithBidirectionalStreamOperationInput)Config)BidirectionalInputPayloadPart'InvokeModelWithBidirectionalStreamInput,InvokeModelWithBidirectionalStreamInputChunk1InvokeModelWithBidirectionalStreamOperationOutput(InvokeModelWithBidirectionalStreamOutput)SigV4AuthScheme)StaticCredentialsResolver)DuplexEventStreamzException: zSIn order to use AWS services, you need to `pip install pipecat-ai[aws-nova-sonic]`.zMissing module: c                       e Zd ZdZy)&AWSNovaSonicUnhandledFunctionExceptionzHException raised when the LLM attempts to call an unregistered function.N)__name__
__module____qualname____doc__     U/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/services/aws/nova_sonic/llm.pyr=   r=   Z   s    RrC   r=   c                       e Zd ZdZdZdZdZy)ContentTypezContent types supported by AWS Nova Sonic.

    Parameters:
        AUDIO: Audio content type.
        TEXT: Text content type.
        TOOL: Tool content type.
    AUDIOTEXTTOOLN)r>   r?   r@   rA   rG   rH   rI   rB   rC   rD   rF   rF   `   s     EDDrC   rF   c                       e Zd ZdZdZdZy)	TextStagezText generation stages in AWS Nova Sonic responses.

    Parameters:
        FINAL: Final text that has been fully generated.
        SPECULATIVE: Speculative text that is still being generated.
    FINALSPECULATIVEN)r>   r?   r@   rA   rL   rM   rB   rC   rD   rK   rK   n   s     EKrC   rK   c                   @    e Zd ZU dZeed<   eed<   eed<   eed<   d Z	y)CurrentContenta]  Represents content currently being received from AWS Nova Sonic.

    Parameters:
        type: The type of content (audio, text, or tool).
        role: The role generating the content (user, assistant, etc.).
        text_stage: The stage of text generation (final or speculative).
        text_content: The actual text content if applicable.
    typerole
text_stagetext_contentc                     d| j                   j                   d| j                  j                   d| j                  r| j                  j                   dS d dS )z-String representation of the current content.zCurrentContent(
  type=z	,
  role=z,
  text_stage=Nonez
))rP   namerQ   rR   selfs    rD   __str__zCurrentContent.__str__   sm    iinn% &iinn% &48OODOO00P Q	
 JPP Q	
rC   N)
r>   r?   r@   rA   rF   __annotations__r   rK   strrY   rB   rC   rD   rO   rO   z   s%     
J
rC   rO   c                   x   e Zd ZU dZ ed      Zee   ed<    ed      Z	ee   ed<    ed      Z
ee   ed<    ed	      Zee   ed
<    ed      Zee   ed<    ed      Zee   ed<    ed      Zee   ed<    ed      Zee   ed<    ed      Zee   ed<    ed      Zee   ed<   edd       Zy)Paramsa  Configuration parameters for AWS Nova Sonic.

    .. deprecated:: 0.0.105
        Use ``settings=AWSNovaSonicLLMSettings(...)`` for inference settings
        and ``audio_config=AudioConfig(...)`` for audio configuration.

    Parameters:
        input_sample_rate: Audio input sample rate in Hz.
        input_sample_size: Audio input sample size in bits.
        input_channel_count: Number of input audio channels.
        output_sample_rate: Audio output sample rate in Hz.
        output_sample_size: Audio output sample size in bits.
        output_channel_count: Number of output audio channels.
        max_tokens: Maximum number of tokens to generate.
        top_p: Nucleus sampling parameter.
        temperature: Sampling temperature for text generation.
        endpointing_sensitivity: Controls how quickly Nova Sonic decides the
            user has stopped speaking. Can be "LOW", "MEDIUM", or "HIGH", with
            "HIGH" being the most sensitive (i.e., causing the model to respond
            most quickly).
            If not set, uses the model's default behavior.
            Only supported with Nova 2 Sonic (the default model).
    >  defaultinput_sample_rate   input_sample_size   input_channel_count]  output_sample_rateoutput_sample_sizeoutput_channel_count   
max_tokens?top_pffffff?temperatureNendpointing_sensitivityc                     t        | j                  | j                  | j                  | j                  | j
                  | j                        S )zFReturn an ``AudioConfig`` populated from this instance's audio fields.)ra   rc   re   rg   rh   ri   )AudioConfigra   rc   re   rg   rh   ri   rW   s    rD   audio_configzParams.audio_config   sG     "44"44 $ 8 8#66#66!%!:!:
 	
rC   )returnrr   )r>   r?   r@   rA   r   ra   r	   intrZ   rc   re   rg   rh   ri   rk   rm   floatro   rp   r[   propertyrs   rB   rC   rD   r]   r]      s    2 (-U';x};',R'8x}8).q)9#9 ).e(<<(-b(99*/*:(3-: !&d 3J3"3/E8E?/#(#5K%5 .34-@Xc]@	
 	
rC   r]   c                       e Zd ZU dZ ed      Zee   ed<    ed      Z	ee   ed<    ed      Z
ee   ed<    ed	      Zee   ed
<    ed      Zee   ed<    ed      Zee   ed<   y)rr   a  Audio configuration for AWS Nova Sonic.

    Parameters:
        input_sample_rate: Audio input sample rate in Hz.
        input_sample_size: Audio input sample size in bits.
        input_channel_count: Number of input audio channels.
        output_sample_rate: Audio output sample rate in Hz.
        output_sample_size: Audio output sample size in bits.
        output_channel_count: Number of output audio channels.
    r^   r_   ra   rb   rc   rd   re   rf   rg   rh   ri   N)r>   r?   r@   rA   r   ra   r	   ru   rZ   rc   re   rg   rh   ri   rB   rC   rD   rr   rr      s    	 (-U';x};',R'8x}8).q)9#9 ).e(<<(-b(99*/*:(3-:rC   rr   c                   `    e Zd ZU dZ ed       Zeez  ed<    ed       Z	edz  ez  ed<   y)AWSNovaSonicLLMSettingsa  Settings for AWSNovaSonicLLMService.

    Parameters:
        voice: Voice identifier for speech synthesis.
        endpointing_sensitivity: Controls how quickly Nova Sonic decides the
            user has stopped speaking. Can be "LOW", "MEDIUM", or "HIGH".
    c                      t         S Nr,   rB   rC   rD   <lambda>z AWSNovaSonicLLMSettings.<lambda>   s    9 rC   )default_factoryvoicec                      t         S r|   r}   rB   rC   rD   r~   z AWSNovaSonicLLMSettings.<lambda>   s    T] rC   Nrp   )
r>   r?   r@   rA   r   r   r[   r.   rZ   rp   rB   rC   rD   rz   rz      s7     #3DEE3?E6;L]6^S4Z)3^rC   rz   c                   x    e Zd ZU dZeZeed<   eZdddddddddd	de	d	e	d
e
e	   de	de	de	de
e   de
e   de
e   de
e	   de
e   def fdZdedee	ef   f fdZdef fdZdef fdZdef fdZd Zdedef fdZdefd Zdefd!Z d"efd#Z!d$ Z"d% Z#d&efd'Z$d( Z%d) Z&de'fd*Z(defd+Z)defd,Z*defd-Z+d. Z,de-e   fd/Z.d0 Z/dPd1e	d2e0d3efd4Z1d5e2fd6Z3d7 Z4d8 Z5d9e	fd:Z6d; Z7d< Z8d= Z9d> Z:d? Z;d@ Z<dA Z=dB Z>dC Z?dD Z@dE ZAd1e	fdFZBdG ZCdH ZD eE        eF       dIdeGdJeEdKeFdeHfdLZIdMZJdN ZKdO ZL xZMS )QAWSNovaSonicLLMServicezAWS Nova Sonic speech-to-speech LLM service.

    Provides bidirectional audio streaming, real-time transcription, text generation,
    and function calling capabilities using AWS Nova Sonic model.
    	_settingsNamazon.nova-2-sonic-v1:0matthewT)	session_tokenmodelvoice_idparamsrs   settingssystem_instructiontoolssend_transcription_framessecret_access_keyaccess_key_idr   regionr   r   r   rs   r   r   r   r   c                n   t        ddddddddddddd      }|dk7  rt        d	t         d	       ||_        |dk7  rt        d
t         d       ||_        |
t        dt         d       |
|_        |ddl}|j                         5  |j                  d       |j                  dt        d       ddd       |	sD|j                  |_
        |j                  |_        |j                  |_        |j                  |_        |	|j                  |	       t        | @  dd|i| || _        || _        || _        || _        d| _        |xs ||j,                  n	t/               | _        || _        | j4                  j                  rN| j7                         s>t9        j:                  d| j4                  j                   d       d| j4                  _        |sFddl}|j                         5  |j                  d       |j                  dt        d       ddd       d| _        d| _        d| _         d| _!        d| _"        d| _#        d| _$        d| _%        d| _&        d| _'        d| _(        d| _)        d| _*        d| _+        d| _,        d| _-        d| _.        t_               | _0        d| _1        te        d      jg                  d      }ti        jj                  |jk                  d      d      5 }|jm                  |jo                               | _8        ddd       y# 1 sw Y   exY w# 1 sw Y   xY w# 1 sw Y   yxY w)a	  Initializes the AWS Nova Sonic LLM service.

        Args:
            secret_access_key: AWS secret access key for authentication.
            access_key_id: AWS access key ID for authentication.
            session_token: AWS session token for authentication.
            region: AWS region where the service is hosted.
                Supported regions:
                - Nova 2 Sonic (the default model): "us-east-1", "us-west-2", "ap-northeast-1"
                - Nova Sonic (the older model): "us-east-1", "ap-northeast-1"
            model: Model identifier. Defaults to "amazon.nova-2-sonic-v1:0".

                .. deprecated:: 0.0.105
                    Use ``settings=AWSNovaSonicLLMSettings(model=...)`` instead.

            voice_id: Voice ID for speech synthesis.
                Note that some voices are designed for use with a specific language.
                Options:
                - Nova 2 Sonic (the default model): see https://docs.aws.amazon.com/nova/latest/nova2-userguide/sonic-language-support.html
                - Nova Sonic (the older model): see https://docs.aws.amazon.com/nova/latest/userguide/available-voices.html.

                .. deprecated:: 0.0.105
                    Use ``settings=AWSNovaSonicLLMSettings(voice=...)`` instead.

            params: Model parameters for audio configuration and inference.

                .. deprecated:: 0.0.105
                    Use ``settings=AWSNovaSonicLLMSettings(...)`` for inference
                    settings and ``audio_config=AudioConfig(...)`` for audio
                    configuration.

            audio_config: Audio configuration (sample rates, sample sizes,
                channel counts). If not provided, defaults are used.
            settings: AWS Nova Sonic LLM settings. If provided together with
                deprecated top-level parameters, the ``settings`` values take
                precedence.
            system_instruction: System-level instruction for the model.

                .. deprecated:: 0.0.105
                    Use ``settings=AWSNovaSonicLLMSettings(system_instruction=...)`` instead.
            tools: Available tools/functions for the model to use.
            send_transcription_frames: Whether to emit transcription frames.

                .. deprecated:: 0.0.91
                    This parameter is deprecated and will be removed in a future version.
                    Transcription frames are always sent.

            **kwargs: Additional arguments passed to the parent LLMService.
        r   Nr   rn   rj   rl   F)r   r   r   ro   rk   rm   top_kfrequency_penaltypresence_penaltyseedfilter_incomplete_user_turnsuser_turn_completion_configrp   r   r   r   r   r   alwaysa  The `params` parameter is deprecated. Use `settings=AWSNovaSonicLLMSettings(...)` for inference settings (temperature, max_tokens, top_p, endpointing_sensitivity) and `audio_config=AudioConfig(...)` for audio configuration (sample rates, sample sizes, channel counts).   )
stacklevelr   z4endpointing_sensitivity is not supported for model 'zn' and will be ignored. This parameter is only supported starting with Nova 2 Sonic (amazon.nova-2-sonic-v1:0).zx`send_transcription_frames` is deprecated and will be removed in a future version. Transcription frames are always sent. zpipecat.services.aws.nova_sonicz	ready.wavrbrB   )9rz   r/   r   r   r   warningscatch_warningssimplefilterwarnDeprecationWarningro   rk   rm   rp   apply_updatesuper__init___secret_access_key_access_key_id_session_token_region_clientrs   rr   _audio_config_toolsr   %_is_endpointing_sensitivity_supportedr
   warning_context_stream_receive_task_prompt_name_input_audio_content_name_content_being_received_assistant_is_responding_may_need_repush_assistant_text_ready_to_send_context_handling_bot_stopped_speaking_triggering_assistant_response"_waiting_for_trigger_transcription_disconnecting_connected_time_wants_connection_user_text_buffer_assistant_text_bufferset_completed_tool_calls_audio_input_startedr   joinpathwaveopen
readframes
getnframes!_assistant_response_trigger_audio)rX   r   r   r   r   r   r   r   rs   r   r   r   r   kwargsdefault_settingsr   	file_pathwav_file	__class__s                     rD   r   zAWSNovaSonicLLMService.__init__   sm   F 3,#"!).(,$(
" .."7,CWM%*"y ":/FP%-")"$&=?S 3E/ ((* 
%%h/D
 '   
 /5/A/A ,.4.?.? +)/ &;A;Y;Y 8 ))(3 	
%	
	
 #4++7; * 
#)#5F;= 	  NN22>>@NNFt~~G[G[F\ ]j j 6:DNN2(((* %%h/<& 	   /3  	 6:+/8<&AE$(-%/4,&+#.3+.3+27/#04!&!#&(#%(U"$)!;<EEkR	YYy~~d+T2 	`h5=5H5HI\I\I^5_D2	` 	`q
 
h H	` 	`s$   *L%*L#%L+LL(+L4deltart   c                 l   K   t         |   |       d{   }|s|S | j                  |       |S 7 w)zgApply a settings delta.

        Settings are stored but not applied to the active connection.
        N)r   _update_settings _warn_unhandled_updated_settings)rX   r   changedr   s      rD   r   z'AWSNovaSonicLLMService._update_settings  s=     
 077N 	--g6 8s   424framec                    K   t         |   |       d{    d| _        | j                          d{    y7 $7 w)zStart the service and initiate connection to AWS Nova Sonic.

        Args:
            frame: The start frame triggering service initialization.
        NT)r   startr   _start_connectingrX   r   r   s     rD   r   zAWSNovaSonicLLMService.start  s>      gmE"""!%$$&&& 	#&   ?;?=??c                    K   t         |   |       d{    d| _        | j                          d{    y7 $7 w)z}Stop the service and close connections.

        Args:
            frame: The end frame triggering service shutdown.
        NF)r   stopr   _disconnectr   s     rD   r   zAWSNovaSonicLLMService.stop  s>      gl5!!!!&    	" r   c                    K   t         |   |       d{    d| _        | j                          d{    y7 $7 w)zCancel the service and close connections.

        Args:
            frame: The cancel frame triggering service cancellation.
        NF)r   cancelr   r   r   s     rD   r   zAWSNovaSonicLLMService.cancel  s>      gnU###!&    	$ r   c                 $  K   t        j                  d       | j                  d       d{    | j                  }| j	                          d{    | j                          d{    | j                  |       d{    y7 Z7 87 "7 w)zReset the conversation state while preserving context.

        Handles bot stopped speaking event, disconnects from the service,
        and reconnects with the preserved context.
        zResetting conversationF&delay_to_catch_trailing_assistant_textN)r
   debug_handle_bot_stopped_speakingr   r   r   _handle_contextrX   contexts     rD   reset_conversationz)AWSNovaSonicLLMService.reset_conversation  s      	-.//W\/]]] --   $$&&&""7+++ 	^
 	!&+sE   +BB#BB
B)B*BBB
BBB	directionc                 \  K   t         |   ||       d{    t        |t        t        f      rUt        |t              r|j
                  nt        j                  |j
                        }| j                  |       d{    n}t        |t              r| j                  |       d{    nSt        |t              r| j                  d       d{    n(t        |t              r| j                          d{    | j                  ||       d{    y7 7 7 x7 O7 (7 w)zProcess incoming frames and handle service-specific logic.

        Args:
            frame: The frame to process.
            direction: The direction the frame is traveling.
        NTr   )r   process_frame
isinstancer   r)   r   r$   from_openai_contextr   r   _handle_input_audio_framer   r   r   _handle_interruption_frame
push_frame)rX   r   r   r   r   s       rD   r   z$AWSNovaSonicLLMService.process_frame  s      g#E9555eo/DEF e_5 33EMMB 
 &&w///12007776733[_3```0111333ooeY///! 	6 07`3/sj   D,DA)D,D")D,+D$,*D,D&(D,?D( D,D*D,"D,$D,&D,(D,*D,r   c                    K   | j                   ry | j                  s || _        | j                          d {    y | j                  d       d {    y 7  7 w)NTsend_new_results)r   r   '_finish_connecting_if_context_available!_process_completed_function_callsr   s     rD   r   z&AWSNovaSonicLLMService._handle_context(  sZ     }} $DM>>@@@ 88$8OOO	 A Ps!   4AAAAAAc                 p   K   | j                   ry | j                  |j                         d {    y 7 wr|   )r   _send_user_audio_eventaudio)rX   r   s     rD   r   z0AWSNovaSonicLLMService._handle_input_audio_frame6  s,      ..))%++666s   ,646r   c                     K    j                   ry d _          fd}r j                   |              y  |        d {    y 7 w)NTc                     K   j                   r> rt        j                  d       d {    d_         j                          d {    d_        y 7 +7 w)Ng      ?F)r   asynciosleep _report_assistant_response_endedr   )r   rX   s   rD   finalize_assistant_responsezXAWSNovaSonicLLMService._handle_bot_stopped_speaking.<locals>.finalize_assistant_responseD  sT     ,," : "-----05-;;===27D/	 .=s!   'AAA	A
AA)r   create_task)rX   r   r   s   `` rD   r   z3AWSNovaSonicLLMService._handle_bot_stopped_speaking>  sC     ...2+	8: 28:;-///s   >A
AA
c                 4   K   | j                   rd| _        y y w)NT)r   r   rW   s    rD   r   z1AWSNovaSonicLLMService._handle_interruption_framef  s     ((37D0 )s   c                   K   	 t        j                  d       | j                  ry t        t	        j
                               | _        t        t	        j
                               | _        | j                         | _        | j                  j                  t        | j                  j                               d {   | _        | j                          d {    d| _        | j!                          d {    y 7 A7 &7 	# t"        $ rB}| j%                  d| |       d {  7   | j'                          d {  7   Y d }~y d }~ww xY ww)NzConnecting...)model_idTzInitialization error: 	error_msg	exception)r
   infor   r[   uuiduuid4r   r   _create_client&invoke_model_with_bidirectional_streamr2   r   r   r   _send_session_start_eventr   r   	Exception
push_errorr   rX   es     rD   r   z(AWSNovaSonicLLMService._start_connectingn  s    	%KK(|| !$DJJL 1D-0->D*  ..0DL "&!T!T@$..J^J^_" DL
 00222 +/D'>>@@@
 3 A 	%//.DQC,HTU/VVV""$$$	%s   E!D EBD ;C=<D C?D 7D8D <E=D ?D D 	EE	%D(&E	>E?E	E	EEr   c                 l  K   | j                   j                         D ]  }|j                  d      s|j                  d      dvs)|j                  d      }|s=|| j                  vsL|r)| j	                  ||j                  d             d {    | j                  j                  |        y 7 "w)NrQ   content)IN_PROGRESS	CANCELLEDtool_call_id)r   get_messagesgetr   _send_tool_resultadd)rX   r   messager  s       rD   r   z8AWSNovaSonicLLMService._process_completed_function_calls  s     }}113 	AG{{6"w{{9'=Ea'a&{{>:L8R8R$R'"44\7;;yCYZZZ..22<@	A [s(   /B4B4B4B4)&B4B2#B4c                    K   | j                   r| j                  sy t        j                  d       | j	                  d       d {    | j                         }|j                  | j                         }|d   r|d   n|j                  | j                        }t        j                  d|        | j                  |       d {    |d   r|d   n| j                  j                  }t        j                  d|        |r)| j                  |t        j                         d {    |d	   }d }t!        |      D ]g  \  }}|t#        |      d
z
  k(  }	|	r |j$                  t        j&                  k(  r|}9| j                  |j(                  |j$                         d {    i | j+                          d {    |r0| j                  |j(                  |j$                  d       d {    | j-                  | j/                               | _        t3        j2                         | _        t        j                  d       | j6                  r| j9                          d {    y y 7 '7 7 I7 7 7 7 w)Nz,Finishing connecting (setting up session)...Fr   r   zUsing tools: r   zUsing system instruction: )textrQ   messagesrd   T)r  rQ   interactivezFinished connecting)r   r   r
   r  r   get_llm_adapterget_llm_invocation_paramsfrom_standard_toolsr   r   _send_prompt_start_eventr   r   _send_text_eventr   SYSTEM	enumeratelenrQ   USERr  _send_audio_input_start_eventr   _receive_task_handlerr   timer   r    _send_assistant_response_trigger)
rX   adapterllm_connection_paramsr   r   r  last_user_messageir  is_last_messages
             rD   r   z>AWSNovaSonicLLMService._finish_connecting_if_context_available  si     $"="=BC 44e4LLL +/*>*>*@ ' A A$-- P %W- "'*,,T[[9 	
 	}UG,-++E222 %%9: ""6722 	
 	12D1EFG''-?dkk'RRR )4 #H- 	RJAw3x=1#44O7<<499#<$+!++GLL+QQQ	R 00222  ''&++2C2H2HVZ (   
 "--d.H.H.JK  $yy{)* ..77999 /y 	M 	3 S R 	3 :s   AI>I-B I>I0A"I>*I3+A9I>$I6%I>>I8?1I>0I:1A5I>&I<'I>0I>3I>6I>8I>:I><I>c                 F  K   	 t        j                  d       d| _        | j                  r| j	                          d {    d | _        d | _        | j                  r)| j                  j                          d {    d | _        t        j                  d       d {    | j                  r,| j                  | j                  d       d {    d | _
        d | _        d | _        d | _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d | _        d| _        d| _        t1               | _        d| _        t        j                  d       y 7 $7 7 7 # t6        $ r)}| j9                  d	| |
       d {  7   Y d }~y d }~ww xY ww)NzDisconnecting...Trd   g      ?)timeoutFr   zFinished disconnectingzError disconnecting: r  )r
   r  r   r   _send_session_end_eventsr   r   closer   r   r   cancel_taskr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r
  r  r  s     rD   r   z"AWSNovaSonicLLMService._disconnect  s    5	VKK*+ #'D ||33555# !DM ||ll((***# --""" !!&&t'9'93&GGG%)" !%D-1D*+/D(,1D)38D0*/D'27D/27D/6;D3"'D#'D %'D"*,D'),D&(-D%KK01W 6 + # H0  	V//.CA3,GST/UUU	Vs   F!;E, E# ;E, ;E&<#E, E( 0E, E*BE, "F!#E, &E, (E, *E, ,	F5FFFF!FF!c                     t        d| j                   d| j                  | j                  | j                  | j                  t               dt        d      i      }t        |      S )Nzhttps://bedrock-runtime.z.amazonaws.comzaws.auth#sigv4bedrock)service)endpoint_urir   aws_access_key_idaws_secret_access_keyaws_session_token!aws_credentials_identity_resolverauth_schemes)config)r3   r   r   r   r   r:   r9   r1   )rX   r<  s     rD   r  z%AWSNovaSonicLLMService._create_client  s^    3DLL>P<<"11"&"9"9"11.G.I*OI,NO
 $622rC   c                 4    | j                   j                  dk(  S )Nzamazon.nova-sonic-v1:0)r   r   rW   s    rD    _is_first_generation_sonic_modelz7AWSNovaSonicLLMService._is_first_generation_sonic_model$  s    ~~##'???rC   c                 $    | j                          S r|   r>  rW   s    rD   r   z<AWSNovaSonicLLMService._is_endpointing_sensitivity_supported(  s     88:::rC   c                 "    | j                         S r|   r@  rW   s    rD   %_is_assistant_response_trigger_neededz<AWSNovaSonicLLMService._is_assistant_response_trigger_needed-  s    4466rC   c           	      <  K   | j                   j                  rd| j                   j                   dnd}d| j                   j                   d| j                   j                   d| j                   j                   d| d	}| j                  |       d {    y 7 w)	Nz[,
              "turnDetectionConfiguration": {
                "endpointingSensitivity": "z"
              }r   z
        {
          "event": {
            "sessionStart": {
              "inferenceConfiguration": {
                "maxTokens": z,
                "topP": z!,
                "temperature": z
              }-
            }
          }
        }
        )r   rp   rk   rm   ro   _send_client_event)rX   turn_detection_configsession_starts      rD   r	  z0AWSNovaSonicLLMService._send_session_start_event5  s      ~~55	,,0NN,R,R+S T
  	
 #nn778 9--. /  $ : :; <&' (	 %%m444s   BBBBc                 t  K   | j                   sy |rdt        j                  |       dnd}d| j                    d| j                  j                   d| j                  j
                   d| j                  j                   d| j                  j                   d	| d
}| j                  |       d {    y 7 w)Nz,
        "toolUseOutputConfiguration": {
          "mediaType": "application/json"
        },
        "toolConfiguration": {
          "tools": z
        }
        r   zZ
        {
          "event": {
            "promptStart": {
              "promptName": "z",
              "textOutputConfiguration": {
                "mediaType": "text/plain"
              },
              "audioOutputConfiguration": {
                "mediaType": "audio/lpcm",
                "sampleRateHertz": z$,
                "sampleSizeBits": z",
                "channelCount": z,
                "voiceId": "z^",
                "encoding": "base64",
                "audioType": "SPEECH"
              }rD  )
r   jsondumpsr   rg   rh   ri   r   r   rE  )rX   r   tools_configprompt_starts       rD   r  z/AWSNovaSonicLLMService._send_prompt_start_eventN  s        
 JJu%& '	  	 #//0 1$ %)$6$6$I$I#J K##'#5#5#H#H"I J!!%!3!3!H!H I J!^^112 3  	!* %%l333s   B.B80B61B8c                 .  K   | j                   sy d| j                    d| j                   d| j                  j                   d| j                  j                   d| j                  j
                   d}| j                  |       d {    d| _        y 7 w)Ng
        {
            "event": {
                "contentStart": {
                    "promptName": "'",
                    "contentName": "a  ",
                    "type": "AUDIO",
                    "interactive": true,
                    "role": "USER",
                    "audioInputConfiguration": {
                        "mediaType": "audio/lpcm",
                        "sampleRateHertz": z,,
                        "sampleSizeBits": z*,
                        "channelCount": z,
                        "audioType": "SPEECH",
                        "encoding": "base64"
                    }
                }
            }
        }
        T)r   r   r   ra   rc   re   rE  r   )rX   audio_content_starts     rD   r%  z4AWSNovaSonicLLMService._send_audio_input_start_eventv  s       #$ %)$5$5#6 7%%)%C%C$D E, -1,>,>,P,P+Q R++/+=+=+O+O*P Q))-););)O)O(P Q	* %%&9:::$(! 	;s   BBBBr  rQ   r  c           	        K   | j                   r| j                  r|syt        t        j                               }d| j                   d| dt        j                  |       d|j                   d	}| j                  |       d{    t        j                  |      }d| j                   d| d| d	}| j                  |       d{    d
| j                   d| d}| j                  |       d{    y7 u7 37 	w)a  Send a text event to the LLM.

        Args:
            text: The text content to send.
            role: The role associated with the text (e.g., USER, ASSISTANT, SYSTEM).
            interactive: Whether the content is interactive. Defaults to False.
                False: conversation history or system instruction, sent prior to interactive audio
                True: text input sent during (or at the start of) interactive audio
        NrN  rO  zJ",
                    "type": "TEXT",
                    "interactive": z,
                    "role": "z",
                    "textInputConfiguration": {
                        "mediaType": "text/plain"
                    }
                }
            }
        }
        zd
        {
            "event": {
                "textInput": {
                    "promptName": "z"",
                    "content": z3
                }
            }
        }
        e
        {
            "event": {
                "contentEnd": {
                    "promptName": "4"
                }
            }
        }
        )	r   r   r[   r  r  rI  rJ  valuerE  )	rX   r  rQ   r  content_nametext_content_startescaped_text
text_inputtext_content_ends	            rD   r   z'AWSNovaSonicLLMService._send_text_event  s8     ||4#4#4D4::<("$ %)$5$5#6 7%%1N 3$$(JJ{$;#< ="jj\ *	  %%&8999zz$'$ %)$5$5#6 7%%1N 3  ,~ .	

 %%j111 $ %)$5$5#6 7%%1N 3		 %%&67775 	: 	2 	8s7   BDC;AD	C=
+D5C?6D=D?Dr   c                    K   | j                   r| j                  sy t        j                  |      }d| j                   d| j
                   d|j                  d       d}| j                  |       d {    y 7 w)Nze
        {
            "event": {
                "audioInput": {
                    "promptName": "rO  z#",
                    "content": "utf-8rS  )r   r   base64	b64encoder   r   decoderE  )rX   r   blobaudio_events       rD   r   z-AWSNovaSonicLLMService._send_user_audio_event  s     ||4#<#<&$ %)$5$5#6 7%%)%C%C$D E!!%W!5 6 7	
 %%k222s   A2A<4A:5A<c                    K   | j                   r| j                  sy d| j                   d}| j                  |       d {    d}| j                  |       d {    y 7  7 w)Nzd
        {
            "event": {
                "promptEnd": {
                    "promptName": "rS  zc
        {
            "event": {
                "sessionEnd": {}
            }
        }
        )r   r   rE  )rX   
prompt_endsession_ends      rD   r0  z/AWSNovaSonicLLMService._send_session_end_events  su     ||4#4#4$ %)$5$5#6 7		
 %%j111 %%k222 	2 	3s#   >A% A!A%A#A%#A%c           
        K   | j                   r| j                  sy t        t        j                               }d| j                   d| d| d}| j                  |       d {    t        j                  dd| j                  |t        |t              rt        j                  |      n|dii      }| j                  |       d {    d| j                   d| d	}| j                  |       d {    y 7 7 37 	w)
NrN  rO  z",
                    "interactive": false,
                    "type": "TOOL",
                    "role": "TOOL",
                    "toolResultInputConfiguration": {
                        "toolUseId": "z",
                        "type": "TEXT",
                        "textInputConfiguration": {
                            "mediaType": "text/plain"
                        }
                    }
                }
            }
        }
        event
toolResult)
promptNamecontentNamer  rR  rS  )
r   r   r[   r  r  rE  rI  rJ  r   dict)rX   r  resultrU  result_content_startresult_contentresult_content_ends          rD   r  z(AWSNovaSonicLLMService._send_tool_result  s$    ||4#4#44::<($$ %)$5$5#6 7%%1N 3'
 (4n 	5	 ( %%&:;;; &*&7&7'39CFD9Q4::f#5W]#

 %%n555"$ %)$5$5#6 7%%1N 3		 %%&89993 	< 	6 	:s7   A!D #C:$A$D C<	+D 4C>5D <D >D 
event_jsonc                    K   | j                   sy t        t        |j                  d                  }| j                   j                  j                  |       d {    y 7 w)Nr[  )bytes_)rT  )r   r6   r4   encodeinput_streamsend)rX   rn  re  s      rD   rE  z)AWSNovaSonicLLMService._send_client_event,  sM     ||</z7H7H7QR
 ll'',,U333s   AA%A#A%c                 n  K   	 | j                   r| j                  s| j                   j                          d {   }|d   j                          d {   }|j                  r+|j                  j
                  r|j                  j
                  j                  d      }t        j                  |      }d|v r|d   }d|v r| j                  |       d {    nd|v r| j                  |       d {    nd|v r| j                  |       d {    nwd|v r| j                  |       d {    nYd|v r| j                  |       d {    n;d	|v r| j                  |       d {    nd
|v r| j                  |       d {    | j                   r| j                  sy y y y 7 v7 ^7 7 7 7 7 l7 P7 4# t         $ rd}| j                  rY d }~y | j#                  d| |       d {  7   | j$                  r| j'                          d {  7   Y d }~y Y d }~y d }~ww xY ww)Nrd   r[  re  completionStartcontentStart
textOutputaudioOutputtoolUse
contentEndcompletionEndzError processing responses: r  )r   r   await_outputreceiverT  rp  r^  rI  loads_handle_completion_start_event_handle_content_start_event_handle_text_output_event_handle_audio_output_event_handle_tool_use_event_handle_content_end_event_handle_completion_end_eventr
  r  r   r   )rX   outputrj  response_data	json_datarn  r  s          rD   r&  z,AWSNovaSonicLLMService._receive_task_handlerD  s    '	0,,t':':#||88::%ay0022<<FLL$7$7$*LL$7$7$>$>w$GM $

= 9I)+%.w%7
,
:"&"E"Ej"QQQ+z9"&"B"B:"NNN)Z7"&"@"@"LLL*j8"&"A"A*"MMM&*4"&"="=j"III)Z7"&"@"@"LLL,
:"&"C"CJ"OOO= ,,t':':,':,:2 R O M N J M P 	0"" //.J1#,NZ[/\\\%%--/// &	0s   H57G F1G F4BG F7G 8F99G F;G 4F=5G F?G 0G1G GG -H51G 4G 7G 9G ;G =G ?G G G 	H2H-H5H-8G;9$H-H H-#
H5-H22H5c                    K   y wr|   rB   rX   rn  s     rD   r  z5AWSNovaSonicLLMService._handle_completion_start_eventn  	        c                   K   |d   }|d   }|d   }d }d|v r)t        j                  |d         }|j                  d      }t        t	        |      t        |      |rt        |      nd d       }|| _        |j                  t
        j                  k(  rc|j                  t        j                  k(  rE| j                  s8d| _        | j                          d {    | j                          d {    y y y y 7  7 
w)Nrv  rP   rQ   additionalModelFieldsgenerationStage)rP   rQ   rR   rS   T)rI  r~  r  rO   rF   r   rK   r   rQ   	ASSISTANTrP   rG   r    _report_user_transcription_ended"_report_assistant_response_started)rX   rn  content_startrP   rQ   generation_stageadditional_model_fieldsr  s           rD   r  z2AWSNovaSonicLLMService._handle_content_start_eventq  s     ">2V$V$"m3&*jj?V1W&X#6::;LM !T"d6Fy!12D	
 (/$<<4>>)||{0004448D1??AAAAACCC	 5 1 * BCs$   CC;C7C;.C9/	C;9C;c                 \   K   | j                   sy | j                   }|d   d   }||_        y w)Nrw  r  )r   rS   )rX   rn  r  rS   s       rD   r  z0AWSNovaSonicLLMService._handle_text_output_event  s6     ++..!,/	:  ,s   *,c                   K   | j                   sy |d   d   }t        j                  |      }t        || j                  j
                  | j                  j                        }| j                  |       d {    y 7 w)Nrx  r  )r   sample_ratenum_channels)r   r\  	b64decoder   r   rg   ri   r   )rX   rn  audio_contentr   r   s        rD   r  z1AWSNovaSonicLLMService._handle_audio_output_event  st     ++ #=1)<   / **==++@@

 ooe$$$s   A5A?7A=8A?c                   K   | j                   r| j                  sy | j                          d {    |d   }|d   }|d   }t        j                  |d         }| j                  |      rm|| j                  j                         v sd | j                  j                         v r4t        | j                  |||      g}| j                  |       d {    y y t        d| d      7 7 w)Nry  toolName	toolUseIdr  )r   r  function_name	argumentsz(The LLM tried to call a function named 'z;', but there isn't a callback registered for that function.)r   r   r  rI  r~  has_function
_functionskeysr   run_function_callsr=   )rX   rn  tool_user  r  r  function_calls_llms          rD   r  z-AWSNovaSonicLLMService._handle_tool_use_event  s    ++4== 33555 i( ,,JJx	23	 ]+ 4 4 66$$//BVBVBX:X' $%1&3"+	&" --.@AAA ;Y 9:=/  JE  F - 	6( Bs"   -C,C(B"C,C*C,*C,c                   K   | j                   sy | j                   }|d   }|d   }d | _         |j                  t        j                  k(  rs|j                  t
        j                  k(  rU|j                  t        j                  k(  r7|dk7  r1| j                  r$| j                  |j                         d {    y y y y y |j                  t        j                  k(  r`|j                  t
        j                  k(  rB|j                  t        j                  k(  r$| j                  |j                         d {    y y y y 7 7 
w)Nrz  
stopReasonINTERRUPTED)r   rQ   r   r  rP   rF   rH   rR   rK   rL   r   %_report_assistant_response_text_addedrS   r$  %_report_user_transcription_text_added)rX   rn  r  content_endstop_reasons        rD   r  z0AWSNovaSonicLLMService._handle_content_end_event  s    ++.. .!,/ (,$<<4>>)||{///%%8[M=Y44"HHI]I]^^^ 5 >Z8 0 \\TYY&||{///%%8DDWEYEYZZZ 9 0 ' _
 [s%   B1D?3D;4A>D?2D=3	D?=D?c                    K   y wr|   rB   r  s     rD   r  z3AWSNovaSonicLLMService._handle_completion_end_event  r  r  c                    K   t        j                  d       | j                  t                      d {    | j                  t	                      d {    y 7 &7 w)NzAssistant response started)r
   r   r   r   r   rW   s    rD   r  z9AWSNovaSonicLLMService._report_assistant_response_started  sM     12 oo79::: ooo/000 	; 	1s!   2AA AAAAc                    K   | j                   sy t        j                  d|        | j                  |       d {    | xj                  |z  c_        y 7 w)NzAssistant response text added: )r   r
   r   $_push_assistant_response_text_framesr   rX   r  s     rD   r  z<AWSNovaSonicLLMService._report_assistant_response_text_added  sR     }}6tf=> 77=== 	##t+# 	>s   :AAAc                 N  K   | j                   sy t        j                  d       | j                  r| j                   j	                         }|r|d   nd }|r2|j                  d      dk7  s|j                  d      | j                  k7  rD| j                  t                      d {    | j                  | j                         d {    d| _        | j                  t                      d {    | j                  t                      d {    d| _        y 7 x7 W7 17 w)NzAssistant response endedrQ   	assistantr  Fr   )r   r
   r   r   r  r  r   r   r   r  r   r    )rX   r  last_messages      rD   r   z7AWSNovaSonicLLMService._report_assistant_response_ended  s    }}/0
 // }}113H+38B<L ##F+{:##I.$2M2MM
 oo&?&ABBB??@[@[\\\38D0 oo57888 ooo/000 ')# C\ 	9 	1sH   B"D%$D%"D%D'D%/D!0 D%D#D%D%!D%#D%c                    K   t        |      }d|_        | j                  |       d {    t        |t        j
                        }d|_        | j                  |       d {    y 7 @7 w)NF)aggregated_byT)r   append_to_contextr   r!   r   SENTENCEincludes_inter_frame_spaces)rX   r  llm_text_frametts_text_frames       rD   r  z;AWSNovaSonicLLMService._push_assistant_response_text_frames&  se      &d++0(oon--- &d/:R:RS592oon--- 	.
 	.s!   'A.A*:A.$A,%A.,A.c                    K   | j                   sy t        j                  d|        | xj                  | j                  rd| z  c_        y |z  c_        y w)NzUser transcription text added:  )r   r
   r   r   r  s     rD   r  z<AWSNovaSonicLLMService._report_user_transcription_text_addedB  sM     }}6tf=> 	0F0FAdV*PDPs   AAc                 "  K   | j                   sy t        j                  d       | j                  xr+ | j                  j                         j                         dk(  }|r2t        j                  d       | j                  t               d {    t        | j                  dt                     }| j                  |t        j                         d {    |r| j                  t               d {    d| _        d| _        y 7 {7 47 w)NzUser transcription endedreadyzaWrapping assistant response trigger transcription with upstream UserStarted/StoppedSpeakingFramesr   )r  user_id	timestamp)r   F)r   r
   r   r   r   striplowerbroadcast_framer"   r   r0   r   r*   UPSTREAMr#   )rX   3should_wrap_in_user_started_stopped_speaking_framesr   s      rD   r  z7AWSNovaSonicLLMService._report_user_transcription_endedR  s     }}/1* 33 B&&,,.446'A 	< ?LLs &&'?@@@ #''?O?Q
 ooe~/F/FoGGG ?&&'?@@@ "$ 38/! A 	H As7   BDD	ADDD5D6DDDuser_paramsassistant_paramsr  r  c                H    t        j                  |      }t        |||      S )aR  Create context aggregator pair for managing conversation context.

        NOTE: this method exists only for backward compatibility. New code
        should instead do::

            context = LLMContext(...)
            context_aggregator = LLMContextAggregatorPair(context)

        Args:
            context: The OpenAI LLM context.
            user_params: Parameters for the user context aggregator.
            assistant_params: Parameters for the assistant context aggregator.

        Returns:
            A pair of user and assistant context aggregators.

        .. deprecated:: 0.0.99
            `create_context_aggregator()` is deprecated and will be removed in a future version.
            Use the universal `LLMContext` and `LLMContextAggregatorPair` instead.
            See `OpenAILLMContext` docstring for migration guide.
        r  )r$   r   r'   )rX   r   r  r  s       rD   create_context_aggregatorz0AWSNovaSonicLLMService.create_context_aggregator  s)    : 009'?O
 	
rC   zStart speaking when you hear the user say 'ready', but don't consider that 'ready' to be a meaningful part of the conversation other than as a trigger for you to start speaking.c                    K   | j                         s.t        j                  d| j                  j                   d       y| j
                  ryd| _        | j                  r| j                          d{    yy7 w)zTrigger an assistant response by sending audio cue.

        Sends a pre-recorded "ready" audio trigger to prompt the assistant
        to start speaking. This is useful for controlling conversation flow.
        z1Assistant response trigger not needed for model 'z'; skipping. An LLMRunFrame() should be sufficient to prompt the assistant to respond, assuming the context ends in a user message.NT)rB  r
   r   r   r   r   r   r(  rW   s    rD   trigger_assistant_responsez1AWSNovaSonicLLMService.trigger_assistant_response  s{      99;NNCDNNDXDXCY Z? ?
 ...2+ 77999  9s   A2A=4A;5A=c                   K   | j                   sy 	 t        j                  d       d| _        d}t	        || j
                  j                  z  | j
                  j                  z  | j
                  j                  dz  z        }t        j                         }d}| j                   $|| j                   z
  |k  r||| j                   z
  z
  nd }|rrt        j                  d| d       d|z  }t	        ||z        }t        |      D ]8  }| j                  |       d {    t        j                  |       d {    : t        d	t        | j                        |      D 	cg c]  }	| j                  |	|	|z     }
}	|
D ]8  }| j                  |       d {    t        j                  |       d {    : 	 d
| _        y 7 7 c c}	w 7 57 # d
| _        w xY ww)Nz%Sending assistant response trigger...Tg{Gz?   g      ?z(Leading assistant response trigger with zs of blank audio    r   F)r   r
   r   r   ru   r   ra   re   rc   r'  ranger   r   r   r#  r   r   )rX   chunk_duration
chunk_sizecurrent_timemax_blank_audio_durationblank_audio_durationblank_audio_chunk
num_chunks_r,  audio_chunkschunks               rD   r(  z7AWSNovaSonicLLMService._send_assistant_response_trigger  s    ##1	8LL@A6:D3!N$$667$$889 %%77!;=J  99;L'*$ ''3!D$8$88<TT )L4;O;O,OP 	 ! $>?S>TTde %,j$8! !5!FG
z* 8A556GHHH!--7778 q#d&L&L"MzZ 66q1z>JL  & 411%888mmN3334 38D/% I7
 93 38D/sq   GD	G GG 7G8(G  G9G G
G 1G2G 9GG G G G 	GG)F)Nr>   r?   r@   rA   rz   SettingsrZ   r   adapter_classr[   r	   r]   rr   r   boolr   ri  r   r   r   r   r   r   r   r   r   r   r*   r   r$   r   r   r   r   r   r   r   r   r   r1   r  r>  r   rB  r	  r   r  r%  r   r   bytesr   r0  r  rE  r&  r  r  r  r  r  r  r  r  r  r   r  r  r  r&   r%   r(   r'   r  ,AWAIT_TRIGGER_ASSISTANT_RESPONSE_INSTRUCTIONr  r(  __classcell__)r   s   @rD   r   r      s    'H&& +M (,/!#'.26:,0'+*.}` }` 	}`
  }}` }` }` }`  }` {+}` 23}` %SM}` $}` $(}`F,C SRUX .' '! !!+ !,(0 0> 02PZ P75G 7&0Y] &0P8%<	A 	AG:R6Vp
3 4 
3@$ @;t ;
7t 752&4DI &4P)8983 98d 98 98v3% 3$303:j43 40(0TD6	,% >[01,"!)F.s .8Q 28x 0G/H9U9W 
! 
 -	 

 7 
 
" 
R	c 1
:.68rC   r   )crA   r   r\  rI  r'  r  r   dataclassesr   r   enumr   importlib.resourcesr   typingr   r   r	   logurur
   pydanticr   r   %pipecat.adapters.schemas.tools_schemar   0pipecat.adapters.services.aws_nova_sonic_adapterr   r   pipecat.frames.framesr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   *pipecat.processors.aggregators.llm_contextr$   +pipecat.processors.aggregators.llm_responser%   r&   5pipecat.processors.aggregators.llm_response_universalr'   1pipecat.processors.aggregators.openai_llm_contextr(   r)   "pipecat.processors.frame_processorr*   pipecat.services.llm_servicer+   pipecat.services.settingsr,   r-   r.   r/   pipecat.utils.timer0   aws_sdk_bedrock_runtime.clientr1   r2   aws_sdk_bedrock_runtime.configr3   aws_sdk_bedrock_runtime.modelsr4   r5   r6   r7   r8   smithy_aws_core.auth.sigv4r9   smithy_aws_core.identity.staticr:   smithy_core.aio.eventstreamr;   ModuleNotFoundErrorr  errorr
  r=   rF   rK   rO   r]   rr   rz   r   rB   rC   rD   <module>r     sr         (  % & &  % = Y     , B [ > 3 _ _ /, 6  ;I=	Y 	$ 	  	  
 
 
45
Y 5
p;) ;. 
_k 
_ 
_R8Z R8A  ,FLL;qc"#FLL] &qc*
++,s   <.E F2FF