Ë
    uPêj—2  ã            
       ó6  — U d dl Z d dlmZ d dlmZmZmZ d dlZd dlm	Z	m
Z
mZmZ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 d dlmZmZ d d	l­ d d
lmZmZ d dlm Z   e	«       Z!ee"d<   de#de$dz  de$dz  de%e$e$f   fd„Z&dee$ef   dedee$ef   fd„Z'de(dededz  fd„Z)dede%e$ef   fd„Z*dedee$ef   fd„Z+dede%e$ef   fd„Z,e!j[                  d e
e«      gedg¬«      e!j[                  d e
e«      gedg¬«       e
e«      fdededefd „«       «       Z.y)!é    N)ÚMapping)ÚAnyÚFinalÚcast)Ú	APIRouterÚDependsÚHTTPExceptionÚRequestÚResponseÚ
UploadFile)ÚORJSONResponse)Úverbose_proxy_logger)ÚOCR_REQUEST_FORMAT_HEADERÚOCR_REQUEST_FORMAT_PARAMÚOCRResponseÚparse_ocr_request_format)Ú%convert_file_document_to_url_documentÚget_mime_type)Ú*)ÚUserAPIKeyAuthÚuser_api_key_auth)ÚProxyBaseLLMRequestProcessingÚrouterÚfile_contentÚfilenameÚcontent_typeÚreturnc                 óœ   — |r"|j                  d«      d   j                  «       nd}|r|dk(  r|rt        |«      }t        d| |xs ddœ«      S )zè
    Convert uploaded file bytes into a Mistral-format document dict with base64 data URI.

    Delegates to convert_file_document_to_url_document after resolving MIME type
    from the upload's content_type header or filename.
    ú;r   Nzapplication/octet-streamÚfile)Útyper    Ú	mime_type)ÚsplitÚstripr   r   )r   r   r   r"   s       új/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/ocr_endpoints/endpoints.pyÚ_build_document_from_uploadr&      s`   € ñ 7C�×"Ñ" 3Ó'¨Ñ*×0Ñ0Ô2È€IÙ˜	Ð%?Ò?ÙÜ% hÓ/ˆIä0àØ Ø"Ò@Ð&@ñ	
óð ó    ÚdataÚrequestc                 óL  — | j                  t        «      }|j                  j                  t        «      }|�|n|}|€| S 	 t	        t        |t        «      r|j                  «       j                  «       n|«      }i | ¥t        |i¥S # t        $ r}t        dd|› i¬«      ‚d}~ww xY w)z›
    Resolve the requested response format from the body or the `x-req-format` header.

    An explicit `req_format` in the body wins over the header.
    Ni�  Úerror)Ústatus_codeÚdetail)Úgetr   Úheadersr   r   Ú
isinstanceÚstrr$   ÚlowerÚ
ValueErrorr	   )r(   r)   Ú
body_valueÚheader_valueÚ	raw_valueÚrequest_formatÚes          r%   Ú_with_request_formatr9   3   sª   € ð Ÿ™Ô!9Ó:€JØ!Ÿ/™/×-Ñ-Ô.GÓH€LØ%/Ð%;‘zÀ€IØÐØˆðGÜ 8Ü)3°I¼sÔ)CˆI�O‰OÓ×#Ñ#Ô%Èó!
ˆð
 >ˆdÐ=Ô,¨nÑ=Ð=øô ò GÜ¨°WÀÀÐ4EÔFÐFûðGús   Á 9B Â	B#ÂBÂB#ÚresponseÚfastapi_responsec           
      ó  — t        | t        «      sy| j                  «       }|€yt        t	        j
                  |«      d|j                  j                  «       D ��ci c]  \  }}|j                  «       dvr||“Œ c}}¬«      S c c}}w )zí
    Return the provider's native payload when the caller asked for
    `req_format=native` and the provider config captured it, carrying over the
    LiteLLM response headers (cost, call id, etc.) built for the normalized response.
    Nzapplication/json)zcontent-lengthúcontent-type)ÚcontentÚ
media_typer/   )	r0   r   Úget_provider_native_responser   ÚorjsonÚdumpsr/   Úitemsr2   )r:   r;   Únative_payloadÚkeyÚvalues        r%   Ú_native_responserG   G   s‡   € ô �h¤Ô,ØØ$×AÑAÓC€NØÐØÜÜ—‘˜^Ó,Ø%ð /×6Ñ6×<Ñ<Ó>÷
á��UØ�y‰y‹{Ð"DÑDð �‰Jó
ôð ùó
s   ÁBc              ƒ   ó2  K  — 	 | j                  «       ƒ d{  –—† }|j                  d«      }|�t	        |t
        «      st        |d«      st        d«      ‚t        t
        |«      }|j                  d«      ƒ d{  –—†  |j                  «       ƒ d{  –—† }|st        d«      ‚t        ||j                  |j                  ¬	«      }d
|i}|j                  «       D ]9  \  }}|dv rŒt	        |t        «      r	 t        j                   |«      ||<   Œ5|||<   Œ; t%        j&                  d|j                  d«      |d   |j                  «       |S 7 �Œ5# t        $ r}t        d|› d�«      ‚d}~ww xY w7 Œô7 ŒÞ# t        j"                  t        f$ r |||<   Y Œ¹w xY w­w)zú
    Extract OCR data from a multipart form request.

    Uses the cached form if already parsed by auth middleware,
    otherwise parses the form from the request.

    Returns:
        A dict with 'document', 'model', and any other OCR params.
    Nz%Failed to parse multipart form data: uŒ   . When using curl with --form/-F, do NOT set the Content-Type header manually â€” curl will set it automatically with the required boundary.r    ÚreadzNMultipart OCR request must include a 'file' field with the document to processr   zUploaded file is empty)r   r   r   Údocument)r    rJ   zNOCR multipart form request parsed - model: %s, document_type: %s, filename: %sÚmodelr!   )ÚformÚ	Exceptionr3   r.   r0   r   Úhasattrr   ÚseekrI   r&   r   r   rC   r1   ÚjsonÚloadsÚJSONDecodeErrorr   Údebug)	r)   rL   r8   Úuploaded_filer   rJ   r(   Ú
field_nameÚfield_values	            r%   Ú_parse_multipart_formrW   ]   s®  è ø€ ð
Ø#ŸL™L›N×*ˆð —H‘H˜VÓ$€Mð Ð¤Z°¼zÔ%JÔSZÐ[hÐjpÔSqÜÐiÓjÐjäœ ]Ó3€Mð ×
Ñ
˜QÓ
×ÐØ -× 2Ñ 2Ó 4×4€LÙÜÐ1Ó2Ð2ä1Ø!Ø×'Ñ'Ø"×/Ñ/ô€Hð $.¨xÐ"8€Dà#'§:¡:£<ò 
+Ñˆ
�KØÐ-Ñ-Øä�k¤3Ô'ð/Ü#'§:¡:¨kÓ#:��ZÒ ð  +ˆD�Òð
+ô ×ÑØXØ�‰�ÓØ�ÑØ×Ñô	ð €Kðe +úÜò 
ÜØ3°A°3ð 7Vð Vó
ð 	
ûð
úð"  øØ4ùô& ×(Ñ(¬*Ð5ò /Ø#.��ZÓ ð/üs{   ‚F„E —E˜E œAFÁ:E/Á;FÂE1ÂA"FÃ6E3Ä>FÅE Å	E,ÅE'Å'E,Å,FÅ1FÅ3FÆFÆFÆFc              ƒ   óH   K  — t        t        | «      ƒ d{  –—† | «      S 7 Œ	­w)zAParse an OCR request and apply the `x-req-format` header, if any.N)r9   Ú_parse_ocr_request_body)r)   s    r%   Ú_parse_ocr_requestrZ   �   s   è ø€ äÔ&=¸gÓ&F× FÈÓPÐPÐ Fús   ‚"– —
"c              ƒ   óH  K  — | j                   j                  dd«      }d|j                  «       v rt        | «      ƒ d{  –—† S 	 | j	                  «       ƒ d{  –—† }|s@t        | dd«      �(t        j                  d«       t        | «      ƒ d{  –—† S t        d«      ‚	 t        j                  |«      }t        |t        «      r|j                  d«      nd}t        |t        «      r|j                  d«      dk(  rt        d«      ‚t        |t        «      rEdD ]@  }|j                  |«      }t        |t        «      sŒ%|j!                  d«      sŒ7t        d«      ‚ |S 7 �Œ7 �Œ	# t
        $ r d}Y �Œw xY w7 Œæ# t        j                  $ r}t        d	|› d
�«      ‚d}~ww xY w­w)a  
    Parse an OCR request, supporting both JSON and multipart form data.

    JSON body (existing behavior):
        {
            "model": "mistral/mistral-ocr-latest",
            "document": {"type": "document_url", "document_url": "https://..."}
        }

    Multipart form data (new):
        - file: the uploaded file
        - model: model name (form field)
        - Any other OCR params as form fields (pages, include_image_base64, etc.)

    Returns:
        A dict suitable for passing to the OCR processing pipeline.
    r=   Ú zmultipart/form-dataNr'   Ú_formuf   OCR request body is empty but form data is available from middleware â€” processing as multipart form.zªEmpty request body. For file uploads, use multipart/form-data content type with a file field. When using curl with --form/-F, do NOT set the Content-Type header manually.zInvalid JSON in request body: zy. Ensure the request body is valid JSON with Content-Type: application/json, or use multipart/form-data for file uploads.rJ   r!   r    zÅdocument type 'file' is not supported through the JSON API. To upload a local file, use multipart/form-data with a 'file' field. For JSON requests, use 'document_url' or 'image_url' document types.)Údocument_urlÚ	image_urlz
reducto://zÇreducto:// file IDs are not accepted through the proxy OCR API; upload the file in the same request via multipart/form-data with a 'file' field, or pass an inline base64 data URI as the document URL.)r/   r.   r2   rW   ÚbodyÚRuntimeErrorÚgetattrr   rS   r3   rA   rQ   rR   r0   Údictr1   Ú
startswith)r)   r   r`   r(   r8   ÚdocÚ	url_fieldÚ	url_values           r%   rY   rY   ¢   s§  è ø€ ð$ "Ÿ/™/×-Ñ-¨n¸bÓA€Là × 2Ñ 2Ó 4Ñ4Ü*¨7Ó3×3Ð3ðØ—\‘\“^×#ˆñ
 ô �7˜G TÓ*Ð6Ü ×&Ñ&Øxôô /¨wÓ7×7Ð7äðó
ð 	
ð
Ü—l‘l 4Ó(ˆô *4°D¼$Ô)?�—‘˜*Ô%ÀT€CÜ�#”tÔ §¡¨£°FÒ!:ÜðSó
ð 	
ô �#”tÔØ6ò 	ˆIØŸ™ 	Ó*ˆIÜ˜)¤SÕ)¨i×.BÑ.BÀ<Õ.PÜ ðBóð ð	ð €KðE 4ùð $úÜò à‹ðúð 8ùô ×!Ñ!ò 
ÜØ,¨Q¨Cð 0;ð ;ó
ð 	
ûð
üsƒ   ‚=F"¿EÁ F"ÁE$ ÁE!ÁE$ Á2F"ÂE6ÂF"Â E8 Â5BF"Ä>F"ÅF"Å!E$ Å$E3Å/F"Å2E3Å3F"Å8FÆFÆFÆF"z/v1/ocrÚocr)ÚdependenciesÚresponse_classÚtagsz/ocrÚuser_api_key_dictc              ƒ   ó„  K  — ddl m}m}m}m}m}m}m}	m}
m	}m
}m} i }	 t        t        | «      ƒ d{  –—† «      }t        |¬«      }|j                  | ||d|||||d|
|||	||¬«      ƒ d{  –—† }t!        ||«      xs |S 7 ŒM7 Œ# t"        $ r/}t        |¬«      }|j%                  ||||¬«      ƒ d{  –—†7  ‚d}~ww xY w­w)að  
    OCR endpoint for extracting text from documents and images.

    Supports two input modes:

    **1. JSON body** (Mistral OCR API compatible):
    ```bash
    curl -X POST "http://localhost:4000/v1/ocr"         -H "Authorization: Bearer sk-1234"         -H "Content-Type: application/json"         -d '{
            "model": "mistral-ocr",
            "document": {
                "type": "document_url",
                "document_url": "https://arxiv.org/pdf/2201.04234"
            }
        }'
    ```

    **2. Multipart form file upload**:
    ```bash
    curl -X POST "http://localhost:4000/v1/ocr"         -H "Authorization: Bearer sk-1234"         -F "model=mistral-ocr"         -F "file=@document.pdf"
    ```

    Response format is normalized to the LiteLLM OCR schema by default. Providers
    that support it (Azure Document Intelligence) can return their own payload
    instead, with cost tracking unchanged, via `x-req-format: native` (or
    `"req_format": "native"` in the body).
    r   )Úgeneral_settingsÚ
llm_routerÚproxy_configÚproxy_logging_objÚselect_data_generatorÚuser_api_baseÚuser_max_tokensÚ
user_modelÚuser_request_timeoutÚuser_temperatureÚversionN)r(   Úaocr)r)   r;   rl   Ú
route_typerq   ro   rn   rp   rr   rK   ru   rw   rv   rt   rs   rx   )r8   rl   rq   rx   )Úlitellm.proxy.proxy_serverrn   ro   rp   rq   rr   rs   rt   ru   rv   rw   rx   rc   rZ   r   Úbase_process_llm_requestrG   rM   Ú_handle_llm_api_exception)r)   r;   rl   rn   ro   rp   rq   rr   rs   rt   ru   rv   rw   rx   r(   Ú	processorr:   r8   s                     r%   rh   rh   ü   sú   è ø€ ÷b÷ ÷ ñ ð €Dð"
äÔ,¨WÓ5×5Ó6ˆô 2°tÔ<ˆ	à )× BÑ BØØ-Ø/ØØ/Ø!Ø-Ø%Ø"7ØØ!Ø-Ø!5Ø+Ø'Øð! !Có !
÷ 
ˆô&   Ð*:Ó;ÒG¸xÐGð1 6øð

ùô( ò 
Ü1°tÔ<ˆ	Ø×7Ñ7ØØ/Ø/Øð	 8ó 
÷ 
ð 
ð 	
ûð
üsV   ‚C  B ³B´8B Á,BÁ-B Â C ÂB ÂB Â	B=Â$B8Â2B5Â3B8Â8B=Â=C )/rP   Úcollections.abcr   Útypingr   r   r   rA   Úfastapir   r   r	   r
   r   r   Úfastapi.responsesr   Úlitellm._loggingr   Ú(litellm.llms.base_llm.ocr.transformationr   r   r   r   Úlitellm.ocr.mainr   r   Úlitellm.proxy._typesÚ$litellm.proxy.auth.user_api_key_authr   r   Ú'litellm.proxy.common_request_processingr   r   Ú__annotations__Úbytesr1   rc   r&   r9   ÚobjectrG   rW   rZ   rY   Úpostrh   © r'   r%   ú<module>rŽ      s¸  ðô Ý #ß #Ñ #ã ß T× TÝ ,å 1÷ó ÷ RÜ "ß RÝ Qá“€ˆÓ ðØðà�D‰jðð ˜‘*ðð 
ˆ#ˆsˆ(�^ó	ð2>˜w s¨C xÑ0ð >¸7ð >ÀwÈsÐTWÈxÑGXó >ð(˜vð ¸ð ÀhÐQUÁoó ð,=¨ð =°T¸#¸s¸(±^ó =ð@Q gð Q°'¸#¸s¸(Ñ2Có Qð
W¨7ð W°t¸CÀ¸H±~ó Wðt ‡�ØÙÐ+Ó,Ð-Ø!Ø
ˆð	 ó ð ‡�Ø
ÙÐ+Ó,Ð-Ø!Ø
ˆð	 ó ñ )0Ð0AÓ(BñV
ØðV
àðV
ð &òV
óóñV
r'   