Ë
    tPêjùj  ã                   óø  — U d Z 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mZ ddlZddlmZ ddlmZ dd	lmZ dd
l­ ddlmZ ddlmZmZ ddl m!Z! ddl"m#Z#m$Z$m%Z% ddl&m'Z'm(Z(m)Z)m*Z*m+Z+ ddl,m-Z- ddl.m/Z/ erddl0m1Z1  e
«       Z2ee3d<   d3d„Z4de5e6ee7f      dede7ddfd„Z8de9de:e;   fd„Z<de9deddfd„Z=	 	 d4dede6e;e>e;f   dz  d e;dz  dee;e;e7z  dz  f   fd!„Z?	 	 d4ded"ee;e@e;e;dz  f   f   d#d$dede6e;e>e;f   dz  d e;dz  ddfd%„ZAde6e;e>e;f   d&e)de6e;e>e;f   fd'„ZBd(ed&e)de6e@e;ef   e6e;e>e;f   dz  e;dz  e;dz  f   fd)„ZCe2j‰                  d* ee«      ged+g¬,«      e2j‰                  d- ee«      ged+g¬,«       ee«      fd(ed.edefd/„«       «       ZEe2j‰                  d0 ee«      ged+g¬,«      e2j‰                  d1 ee«      ged+g¬,«       ee«      fd(ed.edefd2„«       «       ZFy)5zÔ
RAG Endpoints for LiteLLM Proxy.

Provides:
- /rag/ingest: All-in-one document ingestion pipeline (Upload -> Chunk -> Embed -> Vector Store)
- /rag/query: RAG query pipeline (Search -> Rerank -> LLM Completion)
é    N)ÚMapping)ÚTYPE_CHECKINGÚAnyÚFinal)Ú	APIRouterÚDependsÚHTTPExceptionÚRequestÚResponseÚstatus)ÚORJSONResponseÚStreamingResponse)Úverbose_proxy_logger)ÚDEFAULT_MAX_RECURSE_DEPTH)ÚCustomStreamWrapper)Ú*)Úis_request_body_safe)ÚUserAPIKeyAuthÚuser_api_key_auth)ÚProxyBaseLLMRequestProcessing)Ú_read_request_bodyÚ_safe_get_request_headersÚget_form_data)ÚMAX_UPLOAD_SIZE_BYTESÚEicarTestMalwareScannerÚMalwareScannerÚRejectedUploadÚvalidate_upload)Ú&assert_user_can_access_vector_store_id)ÚManagedVectorStoresRepository)ÚPrismaClientÚrouterÚreturnc                  ó0   — t        dddt        › d�i¬«      ‚)Né�  ÚerrorzMax depth of z/ exceeded while scanning vector_store_id values©Ústatus_codeÚdetail)r	   r   © ó    új/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/rag_endpoints/endpoints.pyÚ'_raise_vector_store_scan_depth_exceededr-   0   s&   € Ü
ØØ˜=Ô)BÐ(CÐCrÐsÐtôð r+   Úpayload_stackÚvalueÚ
next_depthc                 ó  — t        |t        «      r'|t        kD  r
t        «        | j	                  ||f«       y t        |t
        «      r:|t        kD  rt        d„ |D «       «      r
t        «        y | j	                  ||f«       y y )Nc              3   óH   K  — | ]  }t        |t        t        f«      –— Œ y ­w)N)Ú
isinstanceÚdictÚlist)Ú.0Úitems     r,   ú	<genexpr>z0_append_payload_to_scan_stack.<locals>.<genexpr>B   s   è ø€ ÒD°d”:˜d¤T¬4 L×1ÑDùs   ‚ ")r3   r4   r   r-   Úappendr5   Úany©r.   r/   r0   s      r,   Ú_append_payload_to_scan_stackr<   7   sr   € ô
 �%œÔØÔ1Ò1Ü3Ô5Ø×Ñ˜e ZÐ0Õ1Ü	�Eœ4Ô	 ØÔ1Ò1ÜÑD¸eÔDÔDÜ7Ô9ØØ×Ñ˜e ZÐ0Õ1ð 
!r+   Úpayloadc                 óÜ  — t        «       }| dfg}|rÚ|j                  «       \  }}|t        kD  r
t        «        t	        |t
        «      ry|j                  «       D ]e  \  }}|dk(  r3t	        |t        «      r|st        dddi¬«      ‚|j                  |«       Œ>t	        |t
        t        f«      sŒUt        |||dz   ¬«       Œg n(t	        |t        «      r|D ]  }t        |||dz   ¬«       Œ |rŒÚ|S )	Nr   Úvector_store_idr%   r&   z*vector_store_id must be a non-empty stringr'   é   r;   )ÚsetÚpopr   r-   r3   r4   ÚitemsÚstrr	   Úaddr5   r<   )r=   Úvector_store_idsr.   Úcurrent_payloadÚdepthÚkeyr/   r7   s           r,   Ú&_collect_vector_store_ids_from_payloadrJ   H   s  € Ü(+«ÐØ$ a˜L˜>€Má
Ø!.×!2Ñ!2Ó!4Ñˆ˜ØÔ,Ò,Ü3Ô5ä�o¤tÔ,Ø-×3Ñ3Ó5ò ‘
��UØÐ+Ò+Ü% e¬SÔ1¹Ü+Ø(+Ø$+Ð-YÐ#Zôð ð %×(Ñ(¨Ô/ØÜ˜e¤d¬D \Õ2Ü1Ø&3Ø#Ø#(¨1¡9öñô ˜¬Ô.Ø'ò �Ü-Ø"/ØØ$ q™yöðò- ð: Ðr+   Úuser_api_key_dictc              ƒ   ól   K  — t        t        | «      «      D ]  }t        ||¬«      ƒ d {  –—†  Œ y 7 Œ­w)N)r?   rK   )ÚsortedrJ   r   )r=   rK   r?   s      r,   Ú"_authorize_nested_vector_store_idsrN   l   s?   è ø€ ô "Ô"HÈÓ"QÓRò 
ˆÜ4Ø+Ø/ô
÷ 	
ñ 	
ñ
ð	
ús   ‚(4ª2«4ÚresponseÚ	file_dataÚfile_urlc                 ó~  — ddl m }m} d}t        | d«      r| j                  d«      }nt        | d«      r| j                  }d}d}d}|r8|d   }t        |«      dkD  rt        |d   «      nd}t        |«      dkD  r|d   nd}||||j                  |j                  «      j                  «       dœ}	|�||	d	<   |�||	d
<   |	S )a†  
    Build a file metadata entry for storing in vector_store_metadata.

    Args:
        response: The response from litellm.aingest containing file_id
        file_data: Optional tuple of (filename, content, content_type)
        file_url: Optional URL if file was ingested from URL

    Returns:
        Dictionary with file metadata (file_id, filename, file_url, ingested_at, etc.)
    r   )ÚdatetimeÚtimezoneNÚgetÚfile_idr@   é   )rV   ÚfilenamerQ   Úingested_atÚ	file_sizeÚcontent_type)	rS   rT   ÚhasattrrU   rV   ÚlenÚnowÚutcÚ	isoformat)
rO   rP   rQ   rS   rT   rV   rX   rZ   r[   Ú
file_entrys
             r,   Ú_build_file_metadata_entryrb   w   sÜ   € ÷  ,ð €GÜˆx˜ÔØ—,‘,˜yÓ)‰Ü	�˜9Ô	%Ø×"Ñ"ˆð €HØ€IØ€LáØ˜Q‘<ˆÜ),¨Y«¸!Ò);”C˜	 !™Ô%Àˆ	Ü'*¨9£~¸Ò'9�y ’|¸tˆð ØØØ—|‘| H§L¡LÓ1×;Ñ;Ó=ñ	€Jð ÐØ"+ˆ
�;ÑØÐØ%1ˆ
�>Ñ"àÐr+   Úingest_optionsÚprisma_clientr!   c              ƒ   óÌ  K  — ddl m} t        | d«      r| j                  d«      }n9t        | d«      r| j                  }n t        j                  dt        | «      «       y|�t        |t        «      st        j                  d«       y|j                  di «      }|j                  d	«      }	|j                  d
i «      }
|
j                  d«      }|
j                  d«      }i }d	dh}|j                  «       D ]  \  }}||vsŒ|€Œ|||<   Œ t        | ||¬«      }	 t        |«      j                  j                  d|i¬«      ƒ d{  –—† }|€yt        j                  d|«       d|gi}|xs d|dd › �}|xs d} |||	xs d|||||r|nd|j                   |j"                  ¬«	      ƒ d{  –—†  t        j                  d|«       yt        j                  d|«       |j$                  xs i }t        |t        «      rddl}|j)                  |«      }|j                  dg «      }|j+                  |«       ||d<   ddlm} t        |«      j                  j1                  d|id ||«      i¬«      ƒ d{  –—†  t        j                  d|j                  d«      xs |j                  dd«      |«       y7 �Œl7 �Œ7 ŒE# t2        $ r!}t        j4                  d||«       Y d}~yd}~ww xY w­w) a†  
    Helper function to save a newly created vector store from RAG ingest to the database.

    This function:
    - Extracts vector store ID and config from the ingest response
    - Checks if the vector store already exists in the database
    - Creates a new database entry if it doesn't exist
    - Adds the vector store to the registry
    - Tracks team_id and user_id for access control

    Args:
        response: The response from litellm.aingest()
        ingest_options: The ingest options containing vector store config
        prisma_client: The Prisma database client
        user_api_key_dict: User API key authentication info
    r   )Úcreate_vector_store_in_dbrU   r?   z8Unable to extract vector_store_id from response type: %sNz?Vector store ID is None or not a string, skipping database saveÚvector_storeÚcustom_llm_providerÚlitellm_vector_store_paramsÚvector_store_nameÚvector_store_description)rO   rP   rQ   )Úwherez0Saving newly created vector store %s to databaseÚingested_fileszRAG Vector Store - é   zCreated via RAG ingest endpointÚopenai)	r?   rh   rd   rj   rk   Úvector_store_metadataÚlitellm_paramsÚteam_idÚuser_idz.Vector store %s saved to database successfullyz:Vector store %s already exists, appending file to metadata)Ú
safe_dumpsrp   )rl   Údataz)Added file %s to vector store %s metadatarX   rQ   ÚUnknownz.Failed to save vector store %s to database: %s)Ú9litellm.proxy.vector_store_endpoints.management_endpointsrf   r\   rU   r?   r   ÚwarningÚtyper3   rD   rC   rb   r    ÚtableÚfind_uniqueÚinforr   rs   rp   ÚjsonÚloadsr9   Úlitellm.proxy.utilsrt   ÚupdateÚ	ExceptionÚ	exception)rO   rc   rd   rK   rP   rQ   rf   r?   Úvector_store_configrh   ri   Úcustom_vector_store_nameÚcustom_vector_store_descriptionÚprovider_specific_paramsÚexcluded_keysrI   r/   ra   Úexisting_vector_storeÚinitial_metadatarj   rk   Úexisting_metadatar}   rm   rt   Údb_errors                              r,   Ú(_save_vector_store_to_db_from_rag_ingestrŒ   «   s:  è ø€ õ0ô
 ˆx˜ÔØ"Ÿ,™,Ð'8Ó9‰Ü	�Ð,Ô	-Ø"×2Ñ2‰ä×$Ñ$Ð%_ÔaeÐfnÓaoÔpØàÐ¤j°Ä#Ô&FÜ×$Ñ$Ð%fÔgØà!/×!3Ñ!3°NÀBÓ!GÐØ!4×!8Ñ!8Ð9NÓ!OÐð *8×);Ñ);Ð<YÐ[]Ó)^ÐØ&A×&EÑ&EÐFYÓ&ZÐØ-H×-LÑ-LÐMgÓ-hÐ#ð ')ÐØ1Ð3DÐE€MØ)×/Ñ/Ó1ò 2‰
ˆˆUØ�mÒ#¨Ñ(9Ø,1Ð$ SÒ)ð2ô
 3ØØØô€Jð;tä-JÈ=Ó-Y×-_Ñ-_×-kÑ-kØ$ oÐ6ð .ló .
÷ (
Ðð
 !Ð(Ü ×%Ñ%Ð&XÐZiÔjð (8¸*¸Ð&FÐð (@Ò'nÐEXÐYhÐikÐjkÐYlÐXmÐCnÐØ.MÒ.rÐQrÐ$á+Ø /Ø$7Ò$C¸8Ø+Ø"3Ø)AØ&6Ù<TÑ 8ÐZ^Ø)×1Ñ1Ø)×1Ñ1ô
÷ 
ð 
ô !×%Ñ%Ð&VÐXgÕhä ×%Ñ%Ð&bÐdsÔtð !6× KÑ KÒ QÈrÐÜÐ+¬SÔ1Ûà$(§J¡JÐ/@Ó$AÐ!à$5×$9Ñ$9Ð:JÈBÓ$OˆNØ×!Ñ! *Ô-Ø2@ÐÐ.Ñ/õ 7ä/°Ó>×DÑD×KÑKØ(¨/Ð:Ø-©zÐ:KÓ/LÐMð Ló ÷ ð ô
 !×%Ñ%Ø;Ø—‘˜zÓ*ÒS¨j¯n©n¸ZÈÓ.SØõðe(
ùð
ùð<ùô ò tä×&Ñ&Ð'WÐYhÐjr×sÑsûðtüs€   ‚C=K$Ä K$ÄK$Ä*J7 ÅJ/ÅA#J7 Æ'J2Æ(J7 ÇK$ÇB,J7 É/J5É0>J7 Ê.K$Ê/J7 Ê2J7 Ê5J7 Ê7	K!Ë KËK$ËK!Ë!K$Úscannerc                 óÖ   — t        | d   |¬«      }t        |t        «      r.t        d|j                  |j
                  j                  dœ¬«      ‚|j                  | d   |j                  fS )Nr@   )Úcontentr�   r%   )r&   Úreasonr'   )	r   r3   r   r	   Úmessager�   r/   Úsafe_filenamer[   )rP   r�   Ú
validations      r,   Ú_secure_uploaded_filer”   )  sg   € ô (°	¸!±ÀgÔN€JÜ�*œnÔ-ÜØØ'×/Ñ/¸:×;LÑ;L×;RÑ;RÑSô
ð 	
ð ×#Ñ# Y¨q¡\°:×3JÑ3JÐJÐJr+   Úrequestc              ƒ   óÄ  K  — t        | «      }|j                  dd«      }d}d}d}i }d|v rÉt        | «      ƒ d{  –—† }|j                  d«      }	|	�Et        |	d«      r9|	j	                  t
        dz   «      ƒ d{  –—† }
|	j                  |
|	j                  f}|j                  d«      }|�rt        j                  |«      }|j                  d	i «      }|j                  d
«      }|j                  d«      }n½t        | «      ƒ d{  –—† }|j                  d	i «      }|j                  d
«      }|j                  d«      }|j                  d«      }	|	rct        |	t        «      rS|	j                  d«      }|	j                  d«      }|	j                  dd«      }|r|r	 t        j                  |«      }
||
|f}|€|€|€t!        dddi¬«      ‚|�t#        ||«      nd}d|vrt!        dddi¬«      ‚h d£}|j                  di «      }t        |t        «      r|D ]  }||v sŒt!        ddd|› d�i¬«      ‚ ||||fS 7 �Œú7 �Œ¾7 �Œ7# t        $ r}t!        ddd|› �i¬«      ‚d}~ww xY w­w)aÞ  
    Parse RAG ingest request.

    Supports:
    - Form: file + request JSON in form field
    - JSON body for URL-based ingestion

    Uploaded file bytes are validated against the vector-store upload controls
    (size limit, format allowlist with content inspection, archive rejection,
    and the injected malware scanner) and given a server-generated filename
    before they are returned.

    Returns:
        Tuple of (ingest_options, file_data, file_url, file_id)
    zcontent-typeÚ Nzmultipart/form-dataÚfileÚreadr@   r•   rc   rQ   rV   rX   r�   r[   zapplication/octet-streamr%   r&   zInvalid base64 content: r'   z'Must provide file, file_url, or file_idrg   z8ingest_options must contain 'vector_store' configuration>   Úapi_keyÚapi_baseÚaws_role_nameÚazure_ad_tokenÚaws_external_idÚaws_profile_nameÚaws_session_nameÚaws_sts_endpointÚaws_access_key_idÚaws_session_tokenÚvertex_credentialsÚaws_secret_access_keyÚvertex_ai_credentialsÚaws_web_identity_tokenú'z[' cannot be set in ingest_options.vector_store. Credentials must be configured server-side.)r   rU   r   r\   r™   r   rX   r[   Úorjsonr~   r   r3   r4   Úbase64Ú	b64decoder�   r	   r”   )r•   r�   Úheadersr[   rP   rQ   rV   rc   Ú	form_dataÚfile_objÚfile_contentÚrequest_json_strÚrequest_dataru   rX   Úcontent_b64ÚeÚsecured_file_dataÚ'_BLOCKED_VECTOR_STORE_CREDENTIAL_PARAMSÚvector_store_optsÚfields                        r,   Úparse_rag_ingest_requestr¸   6  sÂ  è ø€ ô& /¨wÓ7€GØ—;‘;˜~¨rÓ2€Là/3€IØ€HØ€GØ%'€Nà Ñ,ä!.¨wÓ!7×7ˆ	ð —=‘= Ó(ˆØÐ¤G¨H°fÔ$=Ø!)§¡Ô/DÀqÑ/HÓ!I×IˆLØ!×*Ñ*¨L¸(×:OÑ:OÐPˆIð 7@·m±mÀIÓ6NÐÚÜ"(§,¡,Ð/?Ó"@ˆLØ)×-Ñ-Ð.>ÀÓCˆNØ#×'Ñ'¨
Ó3ˆHØ"×&Ñ& yÓ1‰Gô /¨wÓ7×7ˆØŸ™Ð"2°BÓ7ˆØ—8‘8˜JÓ'ˆØ—(‘(˜9Ó%ˆð —8‘8˜FÓ#ˆÙœ
 8¬TÔ2Ø&Ÿl™l¨:Ó6ˆHØ!)§¡¨iÓ!8ˆKØ#Ÿ<™<¨Ð8RÓSˆLá™KðÜ#)×#3Ñ#3°KÓ#@�LØ!)¨<¸Ð F�Ið Ð˜XÐ-°'°/ÜØØÐFÐGô
ð 	
ð 6?Ð5JÔ˜i¨Ô1ÐPTð ð ˜^Ñ+ÜØØÐWÐXô
ð 	
ò6Ð+ð  (6×'9Ñ'9¸.È"Ó'MÐÜÐ#¤TÔ*Ø<ò 	ˆEØÐ)Ò)Ü#Ø #à 1 U Gð ,Fð "Fðôð ð	ð Ð,¨h¸Ð?Ð?ðy 8ùð
 Jùð 8úô  !ò Ü'Ø$'Ø 'Ð+CÀAÀ3Ð)GÐHôð ûðüs`   ‚8I ºH4»>I Á9H7Á:B	I ÄH:ÄBI ÆH= Æ2A'I ÈI È7I È:I È=	IÉIÉIÉI z/v1/rag/ingestÚrag)ÚdependenciesÚresponse_classÚtagsz/rag/ingestÚfastapi_responsec           	   ƒ   ó   K  — ddl m}m}m}m}m}m} 	 t        | t        «       ¬«      ƒ d{  –—† \  }	}
}}|j                  t        j                  j                  k(  r>|	j                  di «      j                  d«      st        t        j                   ddi¬	«      ‚t#        |	|¬
«      ƒ d{  –—†  	 t%        |	j                  di «      ||d¬«       i } ||| ||||¬«      ƒ d{  –—† }t+        j,                  d|	«       t/        j0                  d|	|
|||dœ|¤Žƒ d{  –—† }t+        j,                  d|du|dut3        |«      «       |�|�t5        ||	|||
|¬«      ƒ d{  –—†  |S t+        j6                  d|du|du«       |S 7 �ŒV7 ŒÙ# t&        $ r}t        ddt)        |«      i¬	«      ‚d}~ww xY w7 ŒÌ7 Œ•7 ŒU# t        $ r ‚ t8        $ r3}t+        j:                  d|«       t        ddt)        |«      i¬	«      ‚d}~ww xY w­w)aþ  
    RAG Ingest endpoint - all-in-one document ingestion pipeline.

    Supports form upload (for files) or JSON body (for URLs).

    ## Form upload (for files):
    ```bash
    curl -X POST "http://localhost:4000/v1/rag/ingest" \
        -H "Authorization: Bearer sk-1234" \
        -F file="@document.pdf" \
        -F 'ingest_options={"vector_store": {"custom_llm_provider": "openai"}}'
    ```

    ## JSON body (for URLs):
    ```bash
    curl -X POST "http://localhost:4000/v1/rag/ingest" \
        -H "Authorization: Bearer sk-1234" \
        -H "Content-Type: application/json" \
        -d '{
            "file_url": "https://example.com/document.pdf",
            "ingest_options": {"vector_store": {"custom_llm_provider": "openai"}}
        }'
    ```

    ## Bedrock:
    ```bash
    curl -X POST "http://localhost:4000/v1/rag/ingest" \
        -H "Authorization: Bearer sk-1234" \
        -F file="@document.pdf" \
        -F 'ingest_options={"vector_store": {"custom_llm_provider": "bedrock"}}'
    ```
    r   )Úadd_litellm_data_to_requestÚgeneral_settingsÚ
llm_routerrd   Úproxy_configÚversion)r�   Nrg   r?   r&   z†internal_user_viewer role can only ingest files to an existing vector store. Provide 'vector_store_id' in ingest_options.vector_store.r'   ©r=   rK   r—   )Úrequest_bodyrÀ   rÁ   Úmodelr%   ©ru   r•   rÀ   rK   rÃ   rÂ   zRAG Ingest - options: %s)rc   rP   rQ   rV   r"   z_RAG Ingest - Checking database save conditions: prisma_client=%s, response=%s, response_type=%s)rO   rc   rd   rK   rP   rQ   z5Skipping database save: prisma_client=%s, response=%szRAG Ingest failed: %séô  r*   )Úlitellm.proxy.proxy_serverr¿   rÀ   rÁ   rd   rÂ   rÃ   r¸   r   Ú	user_roleÚLitellmUserRolesÚINTERNAL_USER_VIEW_ONLYr/   rU   r	   r   ÚHTTP_403_FORBIDDENrN   r   Ú
ValueErrorrD   r   ÚdebugÚlitellmÚaingestry   rŒ   rx   r�   r‚   )r•   r½   rK   r¿   rÀ   rÁ   rd   rÂ   rÃ   rc   rP   rQ   rV   r³   r±   rO   s                   r,   Ú
rag_ingestrÒ   ²  sl  è ø€ ÷b÷ ðW
ä=UØÔ4Ó6ô>
÷ 8
Ñ4ˆ˜	 8¨Wð
 ×&Ñ&Ô*:×*RÑ*R×*XÑ*XÒXÐao×asÑasØ˜Bób
ç
‰#ÐÓ
 ðb!ô  Ü"×5Ñ5àð Pðôð ô 1Ø"Ø/ô
÷ 	
ð 	
ð
	KÜ Ø+×/Ñ/°ÀÓCØ!1Ø%Øõ	ð (*ˆÙ8ØØØ-Ø/ØØ%ô
÷ 
ˆô 	×"Ñ"Ð#=¸~ÔNô !(§¡ð !
Ø)ØØØØñ!
ð ñ!
÷ 
ˆô 	×"Ñ"ØmØ Ð%Ø˜DÐ Ü�‹Nô		
ð Ð$¨Ð)=Ü:Ø!Ø-Ø+Ø"3Ø#Ø!ô÷ ð ð ˆô	 !×(Ñ(ØGÈÐ^bÐIbÐdlÐtxÐdxôð ˆðY8
ùð 	
ùô ò 	KÜ¨C¸Ä#ÀaÃ&Ð8IÔJÐJûð	Kúð

øð
øð$ùô ò ØÜò 
Ü×&Ñ&Ð'>ÀÔBÜØØœS ›VÐ$ô
ð 	
ûð
üs¬   ‚G>”F6 ¬F­A>F6 Â+FÂ,F6 Â1F ÃF6 Ã#F0Ã$8F6 ÄF2ÄAF6 ÅF4ÅF6 Å$G>Å%F6 ÆG>ÆF6 ÆF6 Æ	F-ÆF(Æ(F-Æ-F6 Æ2F6 Æ4F6 Æ6G;Ç.G6Ç6G;Ç;G>z/v1/rag/queryz
/rag/queryc              ƒ   óä  K  — ddl m}m}m}m}m}m} 	 t        | «      ƒ d{  –—† }	|	j                  d«      }
|	j                  d«      }|	j                  d«      }|	j                  d«      }|	j                  dd	«      }|
st        d
ddi¬«      ‚|st        d
ddi¬«      ‚|st        d
ddi¬«      ‚t        |t        «      st        d
ddi¬«      ‚d|vrt        d
ddi¬«      ‚t        ||¬«      ƒ d{  –—†  i } ||| ||||¬«      ƒ d{  –—† }t        j                  d|
|«       t        j                   d$|
|||||dœ|¤Žƒ d{  –—† }t#        |di «      xs i }t%        j&                  ||j                  dd«      xs d|j                  dd«      xs d|j                  dd«      xs d|j                  dd«      xs d||j                  dd«      |¬«      }t        |t(        «      rt+         ||||| ¬«      d |¬!«      S |j,                  j/                  |«       |S 7 �Œû7 �Œ.7 �Œ7 Œà# t        $ r ‚ t0        $ r3}t        j2                  d"|«       t        d#dt5        |«      i¬«      ‚d}~ww xY w­w)%aÄ  
    RAG Query endpoint - search vector store, optionally rerank, and generate LLM response.

    This endpoint:
    1. Extracts the query from the last user message
    2. Searches the vector store for relevant context
    3. Optionally reranks the results
    4. Generates an LLM response with the retrieved context

    ## Example Request:
    ```bash
    curl -X POST "http://localhost:4000/v1/rag/query" \
        -H "Authorization: Bearer sk-1234" \
        -H "Content-Type: application/json" \
        -d '{
            "model": "gpt-4o-mini",
            "messages": [{"role": "user", "content": "What is LiteLLM?"}],
            "retrieval_config": {
                "vector_store_id": "vs_abc123",
                "custom_llm_provider": "openai",
                "top_k": 5
            }
        }'
    ```

    ## With Reranking:
    ```bash
    curl -X POST "http://localhost:4000/v1/rag/query" \
        -H "Authorization: Bearer sk-1234" \
        -H "Content-Type: application/json" \
        -d '{
            "model": "gpt-4o-mini",
            "messages": [{"role": "user", "content": "What is LiteLLM?"}],
            "retrieval_config": {
                "vector_store_id": "vs_abc123",
                "custom_llm_provider": "openai",
                "top_k": 10
            },
            "rerank": {
                "enabled": true,
                "model": "cohere/rerank-english-v3.0",
                "top_n": 3
            }
        }'
    ```
    r   )r¿   rÀ   rÁ   rÂ   Úselect_data_generatorrÃ   NrÆ   ÚmessagesÚretrieval_configÚrerankÚstreamFr%   r&   zmodel is requiredr'   zmessages is requiredzretrieval_config is requiredz"retrieval_config must be an objectr?   z/retrieval_config must contain 'vector_store_id'rÄ   rÇ   z+RAG Query - model: %s, retrieval_config: %s)rÆ   rÕ   rÖ   r×   rØ   r"   Ú_hidden_paramsÚlitellm_call_idr—   Úmodel_idÚ	cache_keyr›   Úresponse_cost)rK   Úcall_idrÛ   rÜ   r›   rÃ   rÝ   r±   )rO   rK   r±   r•   ztext/event-stream)Ú
media_typer¬   zRAG Query failed: %srÈ   r*   )rÉ   r¿   rÀ   rÁ   rÂ   rÔ   rÃ   r   rU   r	   r3   r4   rN   r   rÏ   rÐ   ÚaqueryÚgetattrr   Úget_custom_headersr   r   r¬   r€   r�   r‚   rD   )r•   r½   rK   r¿   rÀ   rÁ   rÂ   rÔ   rÃ   ru   rÆ   rÕ   rÖ   r×   rØ   r±   rO   Úhidden_paramsÚcustom_headersr³   s                       r,   Ú	rag_queryrå   F  së  è ø€ ÷~÷ ðd
ä.¨wÓ7×7ˆð —x‘x Ó(ˆØŸ(™( :Ó.ˆØ"&§(¡(Ð+=Ó">ÐØŸ™ Ó*ˆØŸ™ ¨5Ó1ˆñ ÜØØÐ!4Ð5ôð ñ ÜØØÐ!7Ð8ôð ñ  ÜØØÐ!?Ð@ôð ô Ð*¬DÔ1ÜØØÐ!EÐFôð ð Ð$4Ñ4ÜØØÐ!RÐSôð ô 1Ø$Ø/ô
÷ 	
ð 	
ð +-ˆÙ8ØØØ-Ø/ØØ%ô
÷ 
ˆô 	×"Ñ"Ð#PÐRWÐYiÔjô !(§¡ð !
ØØØ-ØØØñ!
ð ñ!
÷ 
ˆô  ' xÐ1AÀ2ÓFÒLÈ"ˆÜ =× PÑ PØ/Ø!×%Ñ%Ð&7¸Ó>ÒDÀ"Ø"×&Ñ& z°4Ó8Ò>¸BØ#×'Ñ'¨°TÓ:Ò@¸bØ"×&Ñ& z°4Ó8Ò>¸BØØ'×+Ñ+¨O¸TÓBØ%ô	!
ˆô �hÔ 3Ô4Ü$Ù%Ø%Ø&7Ø!-Ø#ô	ð /Ø&ô	ð 	ð 	× Ñ ×'Ñ'¨Ô7Øˆðs 8ùðF	
ùð
ùð
ùôJ ò ØÜò 
Ü×&Ñ&Ð'=¸qÔAÜØØœS ›VÐ$ô
ð 	
ûð
üs|   ‚I0”H( ¢H£CH( Ã2H Ã3H( Ä
H#Ä:H( ÅH&ÅB9H( Ç?I0È H( ÈI0ÈH( È H( È#H( È&H( È(I-È:.I(É(I-É-I0)r#   N)NN)GÚ__doc__rª   Úcollections.abcr   Útypingr   r   r   r©   Úfastapir   r   r	   r
   r   r   Úfastapi.responsesr   r   rÐ   Úlitellm._loggingr   Úlitellm.constantsr   Ú,litellm.litellm_core_utils.streaming_handlerr   Úlitellm.proxy._typesÚlitellm.proxy.auth.auth_utilsr   Ú$litellm.proxy.auth.user_api_key_authr   r   Ú'litellm.proxy.common_request_processingr   Ú-litellm.proxy.common_utils.http_parsing_utilsr   r   r   Ú+litellm.proxy.rag_endpoints.upload_securityr   r   r   r   r   Ú*litellm.proxy.vector_store_endpoints.utilsr   Ú'litellm.repositories.table_repositoriesr    r   r!   r"   Ú__annotations__r-   r5   ÚtupleÚintr<   ÚobjectrA   rD   rJ   rN   Úbytesrb   r4   rŒ   r”   r¸   ÚpostrÒ   rå   r*   r+   r,   ú<module>rü      sw  ðòó Ý #ß ,Ñ ,ã ß P× Pß ?ã Ý 1Ý 7Ý LÜ "Ý >ß RÝ Q÷ñ ÷
õ õõ RáÝ0á“€ˆÓ óð2Ø˜˜c 3˜h™Ñ(ð2àð2ð ð2ð 
ó	2ð"!°Fð !¸sÀ3¹xó !ðH
Øð
à%ð
ð 
ó
ð 04Øñ1Øð1à�S˜% �_Ñ%¨Ñ,ð1ð �D‰jð1ð ˆS�#˜‘)˜dÑ"Ð"Ñ#ó	1ðr 04Øñ{tØð{tà˜C  c¨3°©: oÑ!6Ð6Ñ7ð{tð "ð{tð &ð	{tð
 �S˜% �_Ñ%¨Ñ,ð{tð �D‰jð{tð 
ó{tð|
KØ�S˜% �_Ñ%ð
Kàð
Kð ˆ3��sˆ?Ñó
Kðy@Øðy@àðy@ð ˆ4��S�‰>˜5  e¨S Ñ1°DÑ8¸#À¹*ÀcÈDÁjÐPÑQóy@ðx ‡�ØÙÐ+Ó,Ð-Ø!Ø
ˆð	 ó ð ‡�ØÙÐ+Ó,Ð-Ø!Ø
ˆð	 ó ñ )0Ð0AÓ(BñE
ØðE
àðE
ð &òE
óóðE
ðP ‡�ØÙÐ+Ó,Ð-Ø!Ø
ˆð	 ó ð ‡�ØÙÐ+Ó,Ð-Ø!Ø
ˆð	 ó ñ )0Ð0AÓ(Bñ`
Øð`
àð`
ð &ò`
óóñ`
r+   