ó
    ‡Ž¡j’  ã                   ó  • S r SSKrSSKJr  SSKJr  SSKJrJr  \" 5       (       a  SSK	J
r
Jr  SSKJrJr  SS	KJr  S
SKJr  S
SKJrJrJrJr  \(       a  SSKJrJr  \R4                  " \5      r " S S\SS9r1 Skr " S S5      rg)z4
Handler for the /v1/audio/transcriptions endpoint.
é    N)ÚTYPE_CHECKINGé   )Úlogging)Úis_serve_availableÚrequires)ÚHTTPExceptionÚRequest)ÚJSONResponseÚStreamingResponse)ÚTranscriptionCreateParamsBaseé   )ÚModelManager)ÚDirectStreamerÚGenerateManagerÚGenerationStateÚ_StreamError)ÚPreTrainedModelÚProcessorMixinc                   ó    • \ rS rSr% \\S'   Srg)Ú%TransformersTranscriptionCreateParamsé)   Ústream© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__ÚboolÚ__annotations__Ú__static_attributes__r   ó    Ú´C:\Users\johnn\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\transformers/cli/serving/transcription.pyr   r   )   s   ‡ Ø†Lr!   r   F)Útotal>   ÚpromptÚincludeÚlanguageÚtemperatureÚresponse_formatÚchunking_strategyÚtimestamp_granularitiesc            
       óÌ   • \ rS rSrSrS\S\4S jrS\\	   SS4S	 jr
S
\S\\-  4S jr\\" SS9S\SSSSS\4S j5       5       rS\SSSSS\S\4
S jrS\SSSSS\S\4
S jrSrg)ÚTranscriptionHandleré8   a¢  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                 ó   • Xl         X l        g)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__ÚTranscriptionHandler.__init__C   s   € ð +ÔØ 0Õr!   Ú	form_keysÚreturnNc                 ó¶   • U[        [        S[        5       5      -
  nU(       a  [        SSU 3S9eU[        -  nU(       a  [
        R                  SU 35        gg)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)r1   r4   Ú
unexpectedÚunuseds       r"   Ú_validate_requestÚ&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              ƒ   ó¸  #   • SSK Jn  U" 5       (       d  [        S5      eUR                  5        ISh  v•N nU R	                  [        UR                  5       5      5        US   n[        U[        5      (       a
  [        SSS9eUR                  5       I Sh  v•N nUS	   n[        U[        5      (       d
  [        SS
S9e[        UR                  SS5      5      R                  5       S:H  nSSS5      ISh  v•N   U R                  R                  W5      nU R                  R                  U5      u  pšU R                   R#                  U5      n[        U[$        5      (       d
  [        SSS9eUnU R'                  WX©5      nW(       a  U R)                  XÉX­5      $ U R+                  XÉX­5      I Sh  v•N $  GN‚ GN! NÃ! , ISh  v•N  (       d  f       NØ= f N&7f)a6  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_multipart_availablezaMissing python-multipart dependency for file uploads. Install with `pip install python-multipart`NÚfiler8   z Expected file upload, got stringr9   ÚmodelzExpected model name as stringr   ÚfalseÚtruei�  z;Audio transcription requires sequential generation (not CB))Útransformers.utils.import_utilsrG   ÚImportErrorÚformrC   r=   ÚkeysÚ
isinstanceÚstrr   ÚreadÚgetÚlowerr.   Úprocess_model_nameÚload_model_and_processorr/   Úget_managerr   Ú_prepare_audio_inputsÚ
_streamingÚ_non_streaming)r1   rE   rG   rN   Ú
file_fieldÚ
file_bytesrI   r   Úmodel_id_and_revisionÚaudio_modelÚaudio_processorÚbase_managerÚgen_managerÚaudio_inputss                 r"   Úhandle_requestÚ#TranscriptionHandler.handle_requestU   s�  é € õ 	Ká%×'Ñ'ÜØsóð ð —<‘<—>”> TØ×"Ñ"¤3 t§y¡y£{Ó#3Ô4Ø˜f™ˆJÜ˜*¤c×*Ñ*Ü#°Ð<^Ñ_Ð_Ø)Ÿ™Ó0×0ˆJØ˜‘MˆEÜ˜e¤S×)Ñ)Ü#°Ð<[Ñ\Ð\Ü˜Ÿ™ (¨GÓ4Ó5×;Ñ;Ó=ÀÑGˆF÷ "—>ð !%× 2Ñ 2× EÑ EÀeÓ LÐØ'+×'9Ñ'9×'RÑ'RÐShÓ'iÑ$ˆØ×,Ñ,×8Ñ8Ð9NÓOˆÜ˜,¬×8Ñ8Ü¨CÐ8uÑvÐvØ"ˆØ×1Ñ1°*¸oÓ[ˆæØ—?‘? ;¸_Ó[Ð[Ø×(Ñ(¨À?Óa×aÐaò+ "ò
 1÷ "—>—>�>úñ* bùse   ‚2G´F6µG¸A F>ÂF9ÂAF>Ã-GÃ8F<Ã9B8GÆ1GÆ2GÆ9F>Æ<GÆ>GÇGÇGÇG)Úlibrosa)Úbackendsr\   r_   r   r^   r   c                 ó
  • SSK nUR                  R                  nUR                  [        R
                  " U 5      USS9u  pVU" XTSS9R                  UR                  5      nUS   R                  UR                  5      US'   U$ )z-Load audio bytes and convert to model inputs.r   NT)ÚsrÚmonoÚpt)Úsampling_rateÚreturn_tensorsÚinput_features)	re   Úfeature_extractorrk   ÚloadÚioÚBytesIOÚtoÚdeviceÚdtype)r\   r_   r^   re   rk   Úaudio_arrayÚ_rb   s           r"   rX   Ú*TranscriptionHandler._prepare_audio_inputs}   sƒ   € ó 	à'×9Ñ9×GÑGˆØ Ÿ™¤b§j¢j°Ó&<ÀÐUY˜ÐZ‰ˆÙ& {Ð`dÑe×hÑhØ×Ñó
ˆð *6Ð6FÑ)G×)JÑ)JÈ;×K\ÑK\Ó)]ˆÐ%Ñ&ØÐr!   ra   rb   c              ƒ   óÂ   #   • SSK Jn  UR                  " UR                  40 UD6I S h  v•N nUR	                  USS9S   n[        U" US9R                  SS95      $  N37f)Nr   )ÚTranscriptionT)Úskip_special_tokens)Útext)Úexclude_none)Úopenai.types.audiory   Úasync_submitÚgenerateÚbatch_decoder
   Ú
model_dump)r1   ra   r^   r_   rb   ry   Úgenerated_idsr{   s           r"   rZ   Ú#TranscriptionHandler._non_streaming�   sg   é € õ 	5à)×6Ò6°{×7KÑ7KÑ\È|Ñ\×\ˆØ×+Ñ+¨MÈtÐ+ÐTÐUVÑWˆÜ™M¨tÑ4×?Ñ?ÈTÐ?ÐRÓSÐSñ ]ùs   ‚'A©Aª4Ac                 ó,  ^^
^^• SS K n[        US5      (       a  UR                  OUnUR                  5       mUR	                  5       m[        UR                  TT5      n0 UESU0Em
UU
UU4S jnUR                  U5        U4S jn	[        U	" 5       SS9$ )Nr   Ú	tokenizerÚstreamerc            	      ó¶   >•  TR                   " S0 TD6  g ! [         a8  n TR                  TR                  [	        [        U 5      5      5         S n A g S n A ff = f)Nr   )r   Ú	ExceptionÚcall_soon_threadsafeÚ
put_nowaitr   rQ   )Úer^   Ú
gen_kwargsÚloopÚqueues    €€€€r"   Ú_runÚ-TranscriptionHandler._streaming.<locals>._run®   sN   ø€ ðRØ×$Ò$Ñ2 zÓ2øÜó RØ×)Ñ)¨%×*:Ñ*:¼LÌÈQËÓ<P×QÑQûðRús   ƒ –
A .AÁAc                 ó²   >#   •  TR                  5       I S h  v•N n U c  g [        U [        5      (       a  SU R                   S37v •  g SU  S37v •  MP   N<7f)Nzdata: {"error": "z"}

zdata: z

)rS   rP   r   Úmsg)r{   rŽ   s    €r"   Ússe_genÚ0TranscriptionHandler._streaming.<locals>.sse_gen¶   sY   øé € ØØ"ŸY™Y›[×(�Ø‘<ØÜ˜d¤L×1Ñ1Ø.¨t¯x©x¨j¸Ð@Ó@ØØ˜t˜f DÐ)Ó)ñ Ù(ùs   ƒA˜A™=Aztext/event-stream)Ú
media_type)	ÚasyncioÚhasattrr…   Úget_running_loopÚQueuer   Ú
_tokenizerÚsubmitr   )r1   ra   r^   r_   rb   r–   r…   r†   r�   r“   rŒ   r�   rŽ   s     `       @@@r"   rY   ÚTranscriptionHandler._streaming�   s“   û€ ó 	ä18¸È+×1VÑ1V�O×-Ò-Ð\kˆ	Ø×'Ñ'Ó)ˆØ&Ÿ}™}›ˆÜ! )×"6Ñ"6¸¸eÓDˆØ;˜Ð; j°(Ñ;ˆ
÷	Rð 	Rð 	×Ñ˜4Ô õ	*ô !¡£Ð7JÑKÐKr!   )r/   r.   )r   r   r   r   Ú__doc__r   r   r2   r=   rQ   rC   r	   r
   r   rc   Ústaticmethodr   ÚbytesÚdictrX   r   rZ   rY   r    r   r!   r"   r,   r,   8   s  † ñð1 lð 1Àoô 1ðY¨3¨s©8ð Y¸ô Yð&b¨Gð &b¸ÐGXÑ8Xô &bðP Ù�|Ñ$ðØðØ,<ðØK\ðà	óó %ó ððTà$ðTð 'ðTð *ð	Tð
 ðTð 
ôTð #Là$ð#Lð 'ð#Lð *ð	#Lð
 ð#Lð 
÷#Lr!   r,   ) r�   rp   Útypingr   Úutilsr   Úutils.import_utilsr   r   Úfastapir   r	   Úfastapi.responsesr
   r   Ú.openai.types.audio.transcription_create_paramsr   r.   r   r   r   r   r   Útransformersr   r   Ú
get_loggerr   r?   r   r>   r,   r   r!   r"   Ú<module>r©      su   ðñó 
Ý  å ß >ñ ×Ñß.ßAÝ\å 'ß QÓ Qö ß<ð 
×	Ò	˜HÓ	%€ôÐ,IÐQVò òÐ ÷HLò HLr!   