Ë
    Gêñi2  ã                   ó   — d Z ddlZddlmZ ddlmZ ddlmZ  e«       rddlm	Z	m
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mZ erddlmZmZ  ej2                  e«      Z G d„ ded¬«      Zh d£Z G d„ d«      Zy)z4
Handler for the /v1/audio/transcriptions endpoint.
é    N)ÚTYPE_CHECKINGé   )Úlogging)Úis_serve_available)ÚHTTPExceptionÚRequest)ÚJSONResponseÚStreamingResponse)ÚTranscriptionCreateParamsBaseé   )ÚModelManager)ÚDirectStreamerÚGenerateManagerÚGenerationStateÚ_StreamError)ÚPreTrainedModelÚProcessorMixinc                   ó   — e Zd ZU eed<   y)Ú%TransformersTranscriptionCreateParamsÚstreamN)Ú__name__Ú
__module__Ú__qualname__ÚboolÚ__annotations__© ó    úh/var/www/pod-logistic/pod-ai/venv/lib/python3.12/site-packages/transformers/cli/serving/transcription.pyr   r   )   s   … Ø„Lr   r   F)Útotal>   ÚpromptÚincludeÚlanguageÚtemperatureÚresponse_formatÚchunking_strategyÚtimestamp_granularitiesc            
       ó¦   — e Zd ZdZdedefd„Zdee   ddfd„Z	d	e
deez  fd
„Zededddddefd„«       Zdedddddedef
d„Zdedddddedef
d„Zy)ÚTranscriptionHandleraº  Handler for ``POST /v1/audio/transcriptions``.

    Accepts a multipart/form-data request with an audio file and model name,
    runs speech-to-text, and returns an OpenAI-compatible Transcription response.

    Standalone (does not extend :class:`BaseHandler`) because audio requests use
    multipart form data, not JSON bodies, and don't need generation config or
    validation. Shares the :class:`GenerationState` for thread safety.
    Úmodel_managerÚgeneration_statec                 ó    — || _         || _        y)zÏ
        Args:
            model_manager (`ModelManager`): Handles model loading, caching, and lifecycle.
            generation_state (`GenerationState`): Shared generation state for thread safety.
        N)r)   r*   )Úselfr)   r*   s      r   Ú__init__zTranscriptionHandler.__init__C   s   € ð +ˆÔØ 0ˆÕr   Ú	form_keysÚreturnNc                 ó¨   — |t        t        dt        «       «      z
  }|rt        dd|› �¬«      ‚|t        z  }|rt
        j                  d|› �«       yy)z&Validate transcription request fields.Ú__mutable_keys__é¦  z"Unexpected fields in the request: ©Ústatus_codeÚdetailz,Ignoring unsupported fields in the request: N)Úgetattrr   Úsetr   ÚUNUSED_TRANSCRIPTION_FIELDSÚloggerÚwarning_once)r,   r.   Ú
unexpectedÚunuseds       r   Ú_validate_requestz&TranscriptionHandler._validate_requestL   s^   € à¤Ô)NÐPbÔdgÓdiÓ!jÑjˆ
ÙÜ¨CÐ:\Ð]gÐ\hÐ8iÔjÐjØÔ8Ñ8ˆÙÜ×ÑÐ"NÈvÈhÐ WÕXð r   Úrequestc              ƒ   óÂ  K  — ddl m}m}  |«       st        d«      ‚ |«       st        d«      ‚|j	                  «       4 ƒd{  –—† }| j                  t        |j                  «       «      «       |d   }t        |t        «      rt        dd¬	«      ‚|j                  «       ƒ d{  –—† }|d
   }t        |t        «      st        dd¬	«      ‚t        |j                  dd«      «      j                  «       dk(  }ddd«      ƒd{  –—†  | j                  j                  «      }	| j                  j!                  |	«      \  }
}| j"                  j%                  |	«      }t        |t&        «      st        dd¬	«      ‚|}| j)                  ||
«      }r| j+                  ||
||«      S | j-                  ||
||«      ƒ d{  –—† S 7 �Œ}7 �Œ7 ŒÂ# 1 ƒd{  –—†7  sw Y   ŒÒxY w7 Œ!­w)af  Parse multipart form, run transcription, return result.

        Args:
            request (`Request`): FastAPI request containing multipart form data with
                ``file`` (audio bytes), ``model`` (model ID), and optional ``stream`` flag.

        Returns:
            `JSONResponse | StreamingResponse`: Transcription result or SSE stream.
        r   )Úis_librosa_availableÚis_multipart_availablezVMissing librosa dependency for audio transcription. Install with `pip install librosa`zaMissing python-multipart dependency for file uploads. Install with `pip install python-multipart`NÚfiler2   z Expected file upload, got stringr3   ÚmodelzExpected model name as stringr   ÚfalseÚtruei�  z;Audio transcription requires sequential generation (not CB))Útransformers.utils.import_utilsr@   rA   ÚImportErrorÚformr=   r7   ÚkeysÚ
isinstanceÚstrr   ÚreadÚgetÚlowerr)   Úprocess_model_nameÚload_model_and_processorr*   Úget_managerr   Ú_prepare_audio_inputsÚ
_streamingÚ_non_streaming)r,   r>   r@   rA   rH   Ú
file_fieldÚ
file_bytesrC   r   Úmodel_id_and_revisionÚaudio_modelÚaudio_processorÚbase_managerÚgen_managerÚaudio_inputss                  r   Úhandle_requestz#TranscriptionHandler.handle_requestU   sÃ  è ø€ ÷ 	aá#Ô%ÜÐvÓwÐwÙ%Ô'ÜØsóð ð —<‘<“>÷ 		Hð 		H TØ×"Ñ"¤3 t§y¡y£{Ó#3Ô4Ø˜f™ˆJÜ˜*¤cÔ*Ü#°Ð<^Ô_Ð_Ø)Ÿ™Ó0×0ˆJØ˜‘MˆEÜ˜e¤SÔ)Ü#°Ð<[Ô\Ð\Ü˜Ÿ™ (¨GÓ4Ó5×;Ñ;Ó=ÀÑGˆF÷		H÷ 		Hð !%× 2Ñ 2× EÑ EÀeÓ LÐØ'+×'9Ñ'9×'RÑ'RÐShÓ'iÑ$ˆ�_Ø×,Ñ,×8Ñ8Ð9NÓOˆÜ˜,¬Ô8Ü¨CÐ8uÔvÐvØ"ˆØ×1Ñ1°*¸oÈ{Ó[ˆáØ—?‘? ;°¸_ÈlÓ[Ð[Ø×(Ñ(¨°kÀ?ÐT`Óa×aÐað+		Hùð
 1ùð		Hø÷ 		H÷ 		Hñ 		Húð* búsi   ‚AGÁG ÁGÁAGÂ%GÂ&AGÃ8GÄGÄB7GÆ;GÆ<GÇGÇGÇGÇGÇGÇGrV   rY   r   rX   r   c                 ó  — ddl }|j                  j                  }|j                  t	        j
                  | «      |d¬«      \  }} |||d¬«      j                  |j                  «      }|d   j                  |j                  «      |d<   |S )z-Load audio bytes and convert to model inputs.r   NT)ÚsrÚmonoÚpt)Úsampling_rateÚreturn_tensorsÚinput_features)	ÚlibrosaÚfeature_extractorrb   ÚloadÚioÚBytesIOÚtoÚdeviceÚdtype)rV   rY   rX   re   rb   Úaudio_arrayÚ_r\   s           r   rR   z*TranscriptionHandler._prepare_audio_inputs   s‡   € ó
 	à'×9Ñ9×GÑGˆØ Ÿ™¤b§j¡j°Ó&<ÀÐUY˜ÓZ‰ˆ�QÙ& {À-Ð`dÔe×hÑhØ×Ñó
ˆð *6Ð6FÑ)G×)JÑ)JÈ;×K\ÑK\Ó)]ˆÐ%Ñ&ØÐr   r[   r\   c              ƒ   óÔ   K  — ddl m}  |j                  |j                  fi |¤Žƒ d {  –—† }|j	                  |d¬«      d   }t         ||¬«      j                  d¬«      «      S 7 Œ<­w)Nr   )ÚTranscriptionT©Úskip_special_tokens)Útext)Úexclude_none)Úopenai.types.audiorp   Úasync_submitÚgenerateÚbatch_decoder	   Ú
model_dump)r,   r[   rX   rY   r\   rp   Úgenerated_idsrs   s           r   rT   z#TranscriptionHandler._non_streamingŽ   sj   è ø€ õ 	5à6˜k×6Ñ6°{×7KÑ7KÑ\È|Ñ\×\ˆØ×+Ñ+¨MÈtÐ+ÓTÐUVÑWˆÜ™M¨tÔ4×?Ñ?ÈTÐ?ÓRÓSÐSð ]ús   ‚'A(©A&ª=A(c                 ó(  ‡‡
‡‡— dd l }t        |d«      r|j                  n|}|j                  «       Š|j	                  «       Št        |j                  ‰‰d¬«      }i |¥d|i¥Š
ˆˆ
ˆˆfd„}|j                  |«       ˆfd„}	t         |	«       d¬	«      S )
Nr   Ú	tokenizerTrq   Ústreamerc            	      ó´   •— 	  ‰j                   di ‰¤Ž y # t        $ r8} ‰j                  ‰j                  t	        t        | «      «      «       Y d } ~ y d } ~ ww xY w)Nr   )rw   Ú	ExceptionÚcall_soon_threadsafeÚ
put_nowaitr   rK   )ÚerX   Ú
gen_kwargsÚloopÚqueues    €€€€r   Ú_runz-TranscriptionHandler._streaming.<locals>._run¯   sP   ø€ ðRØ$�×$Ñ$Ñ2 zÓ2øÜò RØ×)Ñ)¨%×*:Ñ*:¼LÌÈQËÓ<P×QÑQûðRús   ƒ –	AŸ.AÁAc                 ó¤   •K  — 	 ‰j                  «       ƒ d {  –—† } | €y t        | t        «      rd| j                  › d�­–— y d| › d�­–— ŒI7 Œ5­w)Nzdata: {"error": "z"}

zdata: z

)rM   rJ   r   Úmsg)rs   r…   s    €r   Ússe_genz0TranscriptionHandler._streaming.<locals>.sse_gen·   sW   øè ø€ ØØ"ŸY™Y›[×(�Ø�<ØÜ˜d¤LÔ1Ø.¨t¯x©x¨j¸Ð@Ó@ØØ˜t˜f DÐ)Ó)ð Ø(ús   ƒA˜A™6Aztext/event-stream)Ú
media_type)	ÚasyncioÚhasattrr|   Úget_running_loopÚQueuer   Ú
_tokenizerÚsubmitr
   )r,   r[   rX   rY   r\   r‹   r|   r}   r†   r‰   rƒ   r„   r…   s     `       @@@r   rS   zTranscriptionHandler._streamingž   s�   û€ ó 	ä18¸È+Ô1V�O×-Ò-Ð\kˆ	Ø×'Ñ'Ó)ˆØ&Ÿ}™}›ˆÜ! )×"6Ñ"6¸¸eÐY]Ô^ˆØ;˜Ð; j°(Ñ;ˆ
÷	Rð 	×Ñ˜4Ô ô	*ô !¡£Ð7JÔKÐKr   )r   r   r   Ú__doc__r   r   r-   r7   rK   r=   r   r	   r
   r]   ÚstaticmethodÚbytesÚdictrR   r   rT   rS   r   r   r   r(   r(   8   sû   „ ñð1 lð 1Àoó 1ðY¨3¨s©8ð Y¸ó Yð(b¨Gð (b¸ÐGXÑ8Xó (bðT ðØðØ,<ðØK\ðà	òó ððTà$ðTð 'ðTð *ð	Tð
 ðTð 
óTð #Là$ð#Lð 'ð#Lð *ð	#Lð
 ð#Lð 
ô#Lr   r(   )r‘   rh   Útypingr   Úutilsr   Úutils.import_utilsr   Úfastapir   r   Úfastapi.responsesr	   r
   Ú.openai.types.audio.transcription_create_paramsr   r)   r   r   r   r   r   Útransformersr   r   Ú
get_loggerr   r9   r   r8   r(   r   r   r   ú<module>r�      st   ðñó 
Ý  å Ý 4ñ Ôß.ßAÝ\å 'ß QÓ Qñ ß<ð 
ˆ×	Ñ	˜HÓ	%€ôÐ,IÐQVõ òÐ ÷ILò ILr   