
    is                        d Z ddlmZ ddlZddl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 erddlmZ dd	lmZ dd
ZddZddZ G d dee      Zy)aj  
Bedrock-specific RAG Ingestion implementation.

Bedrock Knowledge Bases handle embedding internally when files are ingested,
so this implementation uploads files to S3 and triggers ingestion jobs.

Supports two modes:
1. Use existing KB: Provide vector_store_id (KB ID)
2. Auto-create KB: Don't provide vector_store_id - creates all AWS resources automatically
    )annotationsN)TYPE_CHECKINGAnyDictListOptionalTuple)verbose_logger)
BaseAWSLLM)BaseRAGIngestion)Router)RAGIngestOptionsc                     | t        |       S dS )z#Cast config value to Optional[str].N)str)values    x/Users/manta/Documents/Projects/TheRoad-I1/.venv/lib/python3.12/site-packages/litellm/rag/ingestion/bedrock_ingestion.py_get_str_or_noner      s    *3u:44    c                     | |S t        |       S )z&Cast config value to int with default.)int)r   defaults     r   _get_intr   !   s    }u:r   c                f    d| v r,| j                  d      }t        |      dk\  r|d   }d| d| S | S )a  
    Normalize a caller ARN to the format required by OpenSearch data access policies.

    OpenSearch Serverless data access policies require:
    - IAM users: arn:aws:iam::account-id:user/user-name
    - IAM roles: arn:aws:iam::account-id:role/role-name

    But get_caller_identity() returns for assumed roles:
    - arn:aws:sts::account-id:assumed-role/role-name/session-name

    This function converts assumed-role ARNs to the proper IAM role ARN format.
    z:assumed-role//      arn:aws:iam::z:role/)splitlen)
caller_arn
account_idparts	role_names       r   _normalize_principal_arnr$   (   sK     :%   %u:?aI":,fYK@@r   c                      e Zd ZdZ	 d	 	 	 ddZd Zd Zd ZddZ	 	 	 	 	 	 	 	 ddZ	dd	Z
	 	 	 	 	 	 	 	 dd
Z	 	 	 	 	 	 	 	 ddZddZddZ	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 	 	 ddZy)BedrockRAGIngestiona  
    Bedrock Knowledge Base RAG ingestion.

    Supports two modes:
    1. **Use existing KB**: Provide vector_store_id
    2. **Auto-create KB**: Don't provide vector_store_id - creates S3 bucket,
       OpenSearch Serverless collection, IAM role, KB, and data source automatically

    Optional config:
    - vector_store_id: Existing KB ID (if not provided, auto-creates)
    - s3_bucket: S3 bucket (auto-created if not provided)
    - embedding_model: Bedrock embedding model (default: amazon.titan-embed-text-v2:0)
    - wait_for_ingestion: Wait for completion (default: True)
    - ingestion_timeout: Max seconds to wait (default: 300)

    AWS Auth (uses BaseAWSLLM):
    - aws_access_key_id, aws_secret_access_key, aws_session_token
    - aws_region_name (default: us-west-2)
    - aws_role_name, aws_session_name, aws_profile_name
    - aws_web_identity_token, aws_sts_endpoint, aws_external_id
    Nc                   t        j                  | ||       t        j                  |        | j                  j	                  d      xs | j                  j	                  d      | _        | j                  j	                  d      | _        | j                  j	                  d      | _        | j                  j	                  d      r$t        | j                  j	                  d            nd | _	        | j                  j	                  d      xs d| _
        | j                  j	                  d	d
      | _        t        | j                  j	                  d      d      | _        | j                  j	                  d      }| j                  |rt        |      nd       | _        d | _        d | _        | j                  xs d| _        d
| _        i | _        y )N)ingest_optionsroutervector_store_idknowledge_base_iddata_source_id	s3_bucket	s3_prefixembedding_modelzamazon.titan-embed-text-v2:0wait_for_ingestionFingestion_timeouti,  aws_region_name)r2   zdata/)r   __init__r   vector_store_configgetr+   _data_source_id
_s3_bucketr   
_s3_prefixr/   r0   r   r1   )get_aws_region_name_for_non_llm_api_callsr2   r,   r-   r.   _config_initialized_created_resources)selfr(   r)   _aws_regions       r   r3   zBedrockRAGIngestion.__init__V   s   
 	!!$~fUD! "&!9!9!=!="
 "?%%))*=> 	
  $77;;<LM2266{C ''++K8 ((,,[9: 	 $$(():; .- 	
 #'":":">"> %#
 '/$$(()<=s'

 ..223DE#MM0;C,  N  

 .2(,"oo8#(  35r   c                   K   | j                   ry| j                  r| j                          d| _         y| j                          d{    d| _         y7 w)zHLazily initialize KB config - either detect from existing or create new.NT)r:   r+   _auto_detect_config%_create_knowledge_base_infrastructure)r<   s    r   _ensure_config_initializedz.BedrockRAGIngestion._ensure_config_initialized   sR     ##!!$$&
 $(  <<>>>#'  ?s   AAAAc                   t        j                  d| j                          | j                  d      }|j	                  | j                        }|j                  dg       }|st        d| j                   d      | j                  r| j                  | _        n/|d   d   | _        t        j                  d	| j                          |j                  | j                  | j                  
      }|j                  di       j                  di       j                  di       }|j                  dd      }|rv| j                  xs |j                  d      d   | _        t        j                  d| j                          |j                  dg       }|r| j                  s|d   | _        yyy| j                  st        d| j                   d      | j                  | _        y)zFAuto-detect data source ID and S3 bucket from existing Knowledge Base.z0Auto-detecting data source and S3 bucket for KB=bedrock-agentknowledgeBaseIddataSourceSummariesz)No data sources found for Knowledge Base zL. Please create a data source first or provide data_source_id and s3_bucket.r   dataSourceIdzAuto-detected data source: rE   rG   
dataSourcedataSourceConfigurations3Configuration	bucketArn :zAuto-detected S3 bucket: inclusionPrefixesz0Could not auto-detect S3 bucket for data source z%. Please provide s3_bucket in config.N)r
   debugr+   _get_boto3_clientlist_data_sourcesr5   
ValueErrorr6   r,   infoget_data_sourcer7   r   r-   r8   r.   )r<   bedrock_agentds_responsedata_sources
ds_details	s3_config
bucket_arnprefixess           r   r?   z'BedrockRAGIngestion._auto_detect_config   s   >t?U?U>VW	
 ..? $55 22 6 
 #'<bA;D<R<R;S T] ]  "&"6"6D".q/."AD"=d>Q>Q=R ST #22 22,, 3 

 NN<,S*B/S"B' 	 ]];3
!__I
0@0@0Eb0IDN";DNN;K LM !}}%8"=H!)! !0x ?? FtGZGZF[ \: :  "__DNr   c                  K   t        j                  d       t        j                         j                  dd }| j
                  xs d| }| j                  d      }|j                         }|d   }|d   }| j                  xs | j                  |      | _
        | j                  |||       d{   \  }}| j                  |       d{    | j                  |||       d{   }	| j                  ||	|       d{   | _        | j!                  |      | _        t        j                  d| j                   d	| j"                   d
| j                          y7 7 7 {7 bw)z9Create all AWS resources needed for a new Knowledge Base.z5Creating new Bedrock Knowledge Base infrastructure...N   litellm-kb-stsAccountArnz!Created KB infrastructure: kb_id=z, ds_id=z	, bucket=)r
   rU   uuiduuid4hexingest_namerR   get_caller_identityr7   _create_s3_bucketr-   _create_opensearch_collection_create_opensearch_index_create_bedrock_role_create_knowledge_baser+   _create_data_sourcer,   )
r<   	unique_idkb_namera   caller_identityr!   r    collection_namecollection_arnrole_arns
             r   r@   z9BedrockRAGIngestion._create_knowledge_base_infrastructure   sz    ST JJL$$Ra(	""?I;&? $$U+113$Y/
$U+
 MD,B,B9,M 150R0Rz:1
 +
'
 ++O<<< 22z>
 

 (,'B'BX~(
 "

 #66w?/0F0F/G H(()4>>2BD	
)+

 	=

"
sI   B/E(1E 2E(E"E((E$)E(E&AE("E($E(&E(c                   | j                  d      }d| }t        j                  d|        d|i}| j                  dk7  rd| j                  i|d<    |j                  d
i | || j
                  d<   t        j                  d	|        |S )z$Create S3 bucket for KB data source.s3r`   zCreating S3 bucket: Bucketz	us-east-1LocationConstraintCreateBucketConfigurationr-   zCreated S3 bucket:  )rR   r
   rQ   r2   create_bucketr;   rU   )r<   ro   rv   bucket_namecreate_paramss        r   ri   z%BedrockRAGIngestion._create_s3_bucket   s    ##D)#I;/3K=AB)1;(?;.$d&:&::M56 	)=)/:,1+?@r   c                J  K   | j                  d      }d| }t        j                  d|        |j                  | ddt	        j
                  dd| gdgd	d
             |j                  | ddt	        j
                  dd| gddd| gdgd	dg             t        ||      }t        j                  d| d|        d| d|g}t        t        |            }|j                  | ddt	        j
                  dd| dgdgddd| gdgdg|dg             |j                  |d      }|d   d   }	|| j                  d <   t        j                  d!       t        d"      D ]D  }
|j                  |	g#      }|d$   d%   d&   }|d'k(  r n*t        j                  d(       d){    F t!        d*      |d$   d%   d+   }t        j"                  d,|        t        j                  d-       t        j                  d"       d){    ||fS 7 j7 
w).z;Create OpenSearch Serverless collection for vector storage.opensearchserverlessr`   z+Creating OpenSearch Serverless collection: z-enc
encryption
collectionzcollection/)ResourceTypeResourceT)RulesAWSOwnedKey)nametypepolicyz-netnetwork	dashboard)r   AllowFromPubliczCaller ARN: z, Normalized: r   z:rootz-accessdataindexzindex//*zaoss:*)r   r   
Permission)r   	PrincipalVECTORSEARCH)r   r   createCollectionDetailidopensearch_collectionz1Waiting for OpenSearch collection to be active...<   )idscollectionDetailsr   statusACTIVE   Nz3OpenSearch collection did not become active in timearnzCreated OpenSearch collection: z4Waiting for data access policy to propagate (60s)...)rR   r
   rQ   create_security_policyjsondumpsr$   listsetcreate_access_policycreate_collectionr;   rangebatch_get_collectionasynciosleepTimeoutErrorrU   )r<   ro   r!   r    ossrr   normalized_caller_arn
principalsresponsecollection_id_status_responser   rs   s                 r   rj   z1BedrockRAGIngestion._create_opensearch_collection  s     $$%;<'	{39/9JK	

 	""#$D):: -9+66G)H(I $(
 	# 	
" 	""#$D)::
 1=/:?:K-L,M
 1</:?:K-L,M	" ,0 	# 	
2 !9Z P:,n5J4KL	
 &j\79NO
#j/*
  #$G,::
 18/5o5Fb-I,J/7j 1=/:?:K-L,M/7j" &0 	! 	
2 ((  ) 
 !!9:4@;J 78 	PQrA!66M?6KO$%89!<XFF!--"""  TUU()<=a@G=o=NOP 	STmmB.. # 	 s%   F2H#4H5A!H#H!	H#!H#c                J  K   ddl m}m} ddlm} | j                  t        | j                  j                  d            t        | j                  j                  d            t        | j                  j                  d            | j                        }| j                  d      }|j                  |g	      }|d
   d   d   }|j                  dd      }	 ||j                  |j                  | j                  d|j                        }
 ||	ddg|
dd|      }d}ddddiddddddddd d!d"d#d id$id%}d&}d'}d(}t!        |      D ]9  }	 |j"                  j%                  ||)       t'        j(                  d*|         y( t7        d2| d3|       # t*        $ r}}|}t-        |      }d+|j/                         v sd,|j/                         v rAt'        j0                  d-|d.z    d/| d0| d1       t3        j4                  |       d({  7   n Y d(}~d(}~ww xY ww)4z>Create vector index in OpenSearch collection with retry logic.r   )
OpenSearchRequestsHttpConnection)AWS4Authaws_access_key_idaws_secret_access_keyaws_session_token)r   r   r   r2   r   )namesr   collectionEndpointzhttps://rM   aoss)session_tokeni  )hostportT)hosts	http_authuse_sslverify_certsconnection_classbedrock-kb-indexr   i   )knnzknn.algo_param.ef_search
properties
knn_vectori   faisshnswl2)enginer   
space_type)r   	dimensionmethodtextF)r   r   r   )%bedrock-knowledge-base-default-vectorAMAZON_BEDROCK_METADATAAMAZON_BEDROCK_TEXT_CHUNK)settingsmappingsr_      N)r   bodyzCreated OpenSearch index: authorization_exceptionsecurity_exceptionz"OpenSearch index creation attempt r   r   z& failed due to authorization. Waiting zs for policy propagation...z(Failed to create OpenSearch index after zC attempts. Data access policy may not have propagated. Last error: )opensearchpyr   r   requests_aws4authr   get_credentialsr   r4   r5   r2   rR   r   replace
access_key
secret_keytokenr   indicescreater
   rU   	Exceptionr   lowerwarningr   r   RuntimeError)r<   rr   r   r   r   credentialsr   collectionsendpointr   authclient
index_name
index_bodymax_retriesretry_delay
last_errorattempte	error_strs                       r   rk   z,BedrockRAGIngestion._create_opensearch_index  s    C. **.((,,-@A #3((,,-DE# /((,,-@A !00 + 
 $$%;<..o5F.G23A67KL
B/""""  %++
  #./3
 (
 $C"PQ ,%)&-$**.#> 9?/O28&1A

( 
[)G%%JZ%H##&@$MN	 *, 6{m DGGQlT
 	
#  
F	-1BB+y/@@"**<Wq[M;- X##.-/JL "--444  5s=   EH#5FH#	H #A+HHHH#H  H#c                  K   | j                  d      }d| }t        j                  d|        ddddidd	|id
d| j                   d| diddgd}|j	                  |t        j                  |            }|d   d   }|| j                  d<   dddgd| j                   d| j                   gdddg|gddddgd| j                   d| j                   dgdgd}	|j                  || dt        j                  |	             t        j                  d       d {    t        j                  d!|        |S 7 w)"zCreate IAM role for Bedrock KB.iamzlitellm-bedrock-kb-zCreating IAM role: z
2012-10-17AllowServicezbedrock.amazonaws.comzsts:AssumeRolezaws:SourceAccountzaws:SourceArnarn:aws:bedrock:rN   z:knowledge-base/*)StringEqualsArnLike)Effectr   Action	Condition)Version	Statement)RoleNameAssumeRolePolicyDocumentRolerc   iam_rolezbedrock:InvokeModel::foundation-model/)r   r   r   zaoss:APIAccessAllzs3:GetObjectzs3:ListBucketarn:aws:s3:::r   z-policy)r   
PolicyNamePolicyDocument
   NzCreated IAM role: )rR   r
   rQ   r2   create_roler   r   r;   r/   r-   put_role_policyr   r   rU   )
r<   ro   r!   rs   r   r#   trust_policyr   rt   permissions_policys
             r   rl   z(BedrockRAGIngestion._create_bedrock_role  s     $$U+))5	29+>? $ &"+-D!E.)<j(I+/?@T@T?UUVWaVbbs-t$"	

" ??%)ZZ%= # 
 F#E*.7
+ $ &45*4+?+?*@@STXThThSij! &23!/ 0 &-?''78''7r:!
4 	#G,::&89 	 	
 mmB0
;< 	 s   D$E&E'Ec                  K   | j                  d      }t        j                  d|        |j                  ||ddd| j                   d| j
                   idd|d	d
ddddd      }|d   d   }|| j                  d<   t        j                  d       t        d      D ]@  }|j                  |      }|d   d   }	|	dk(  r n*t        j                  d       d{    B t        d      t        j                  d|        |S 7 +w)zCreate Bedrock Knowledge Base.rC   zCreating Knowledge Base: VECTORembeddingModelArnr   r   )r    vectorKnowledgeBaseConfigurationOPENSEARCH_SERVERLESSr   r   r   )metadataField	textFieldvectorFieldr   )collectionArnfieldMappingvectorIndexName)r   !opensearchServerlessConfiguration)r   roleArnknowledgeBaseConfigurationstorageConfigurationknowledgeBaserE   knowledge_basez*Waiting for Knowledge Base to be active...   rD   r   r   r   Nz,Knowledge Base did not become active in timezCreated Knowledge Base: )rR   r
   rQ   create_knowledge_baser2   r/   r;   r   get_knowledge_baser   r   r   rU   )
r<   rp   rt   rs   rW   r   kb_idr   	kb_statusr   s
             r   rm   z*BedrockRAGIngestion._create_knowledge_base$  sM     ..?8	BC 66 '+;D<P<P;QQdeieyeydz){5( 0%3)B%@'N%
 (:6" 7 
, )*;<49 01 	IJrA%888OI/9F!--"""  MNN6ug>? #s   CDD
,Dc                H   | j                  d      }t        j                  d| j                          |j	                  | j                  | ddd| j
                   | j                  gdd      }|d	   d
   }|| j                  d<   t        j                  d|        |S )z*Create Data Source for the Knowledge Base.rC   zCreating Data Source for KB: z
-s3-sourceS3r  )rL   rP   )r   rK   )rE   r   rJ   rI   rG   data_sourcezCreated Data Source: )	rR   r
   rQ   r+   create_data_sourcer-   r.   r;   rU   )r<   rp   rW   r   ds_ids        r   rn   z'BedrockRAGIngestion._create_data_sourceS  s    ..?<T=S=S<TUV 33 229J'#00@!A*...)9$% 4 

 &~616.3E7;<r   c                   	 ddl }| j                  t        | j                  j                  d            t        | j                  j                  d            t        | j                  j                  d            | j                  t        | j                  j                  d            t        | j                  j                  d            t        | j                  j                  d	            t        | j                  j                  d
            t        | j                  j                  d            t        | j                  j                  d            
      }|j                  |j                  |j                  |j                  | j                        }|j                  |      S # t        $ r t        d      w xY w)zCGet a boto3 client for the specified service using BaseAWSLLM auth.r   NzHboto3 is required for Bedrock ingestion. Install with: pip install boto3r   r   r   aws_session_nameaws_profile_nameaws_role_nameaws_web_identity_tokenaws_sts_endpointaws_external_id)
r   r   r   r2   r%  r&  r'  r(  r)  r*  )r   r   r   region_name)boto3ImportErrorr   r   r4   r5   r2   Sessionr   r   r   r   )r<   service_namer,  r   sessions        r   rR   z%BedrockRAGIngestion._get_boto3_clientj  s   	 **.((,,-@A #3((,,-DE# /((,,-@A !00-((,,-?@ .((,,-?@ +((,,_= $4((,,-EF$ .((,,-?@ -((,,->?5 + 
@ --)44"-"8"8)//,,	   
 ~~l++[  	Z 	s   F+ +G c                   K   yw)z
        Bedrock handles embedding internally - skip this step.

        Returns:
            None (Bedrock embeds when files are ingested)
        Nrz   )r<   chunkss     r   embedzBedrockRAGIngestion.embed  s      s   c                  K   | j                          d{    |r|s,t        j                  d       t        | j                        dfS | j                  d      }| j                  j                  d       d| }t        j                  d| j                   d|        |j                  | j                  |||xs d       t        j                  d| j                   d|        | j                  d	      }t        j                  d
| j                   d| j                          |j                  | j                  | j                        }	|	d   d   }
t        j                  d|
        | j                  rTddl}|j                         }|j                         |z
  | j                   k  r|j#                  | j                  | j                  |
      }|d   d   }t        j                  d|
 d|        |dk(  r?|d   j%                  di       }t        j                  d|j%                  dd       d       n|dk(  r.|d   j%                  dg       }t        j&                  d|        n]|dv rt)        j*                  d       d{    nt        j                  d|        n"|j                         |z
  | j                   k  r| j                  rt-        | j                        |fS d|fS 7 7 jw) aK  
        Store content in Bedrock Knowledge Base.

        Bedrock workflow:
        1. Auto-detect data source and S3 bucket (if not provided)
        2. Upload file to S3 bucket
        3. Start ingestion job
        4. (Optional) Wait for ingestion to complete

        Args:
            file_content: Raw file bytes
            filename: Name of the file
            content_type: MIME type
            chunks: Ignored - Bedrock handles chunking
            embeddings: Ignored - Bedrock handles embedding

        Returns:
            Tuple of (knowledge_base_id, file_key)
        Nz:No file content or filename provided for Bedrock ingestionrv   r   zUploading file to s3://zapplication/octet-stream)rw   KeyBodyContentTypezUploaded file to s3://rC   zStarting ingestion job for KB=z, DS=rH   ingestionJobingestionJobIdzStarted ingestion job: r   )rE   rG   r9  r   zIngestion job z	 status: COMPLETE
statisticszIngestion complete: numberOfNewDocumentsIndexedz docs indexedFAILEDfailureReasonszIngestion failed: )STARTINGIN_PROGRESSr   zUnknown ingestion status: )rA   r
   r   r   r+   rR   r.   rstriprQ   r-   
put_objectrU   r,   start_ingestion_jobr0   timer1   get_ingestion_jobr5   errorr   r   r   )r<   file_contentfilenamecontent_typer2  
embeddings	s3_clients3_keyrW   ingestion_responsejob_idtime_module
start_time
job_statusr   statsfailure_reasonss                    r   storezBedrockRAGIngestion.store  s    8 --///8""L $D$:$:;TAA **40	NN))#./q
;6t~~6FaxPQ>>$B(B	 	 	
 	4T^^4DAfXNO ..?,T-C-C,DE$J]J]I^_	
 +>> 22,, ? 
 $N34DE5fX>? ""&$))+J""$z1D4J4JJ*<<$($:$:!%!4!4#) = 

 $N3H=$$~fXYvh%OPZ'&~6::<LE"''.uyy9VXY/Z.[[hi x'&0&@&D&D("'O #((+=o=N)OP::!--***"**-Gx+PQ3 ""$z1D4J4JJ6 /3.D.Ds4))*PVVV$PVVVE 	0z +s(   K=K8I9K=K;>K=(K=;K=)N)r(   z'RAGIngestOptions'r)   zOptional['Router'])ro   r   returnr   )ro   r   r!   r   r    r   rU  zTuple[str, str])rr   r   )ro   r   r!   r   rs   r   rU  r   )rp   r   rt   r   rs   r   rU  r   )rp   r   rU  r   )r/  r   )r2  	List[str]rU  Optional[List[List[float]]])rG  zOptional[bytes]rH  Optional[str]rI  rX  r2  rV  rJ  rW  rU  z#Tuple[Optional[str], Optional[str]])__name__
__module____qualname____doc__r3   rA   r?   r@   ri   rj   rk   rl   rm   rn   rR   r3  rT  rz   r   r   r&   r&   ?   s,   2 &*.5*.5 #.5`(7-r)
V&r/r/*-r/;>r/	r/h[
zFF*-F?BF	FP--&)-;>-	-^.1,f

 
%
^W%^W  ^W $	^W
 ^W 0^W 
-^Wr   r&   )r   r   rU  rX  )r   r   r   r   rU  r   )r    r   r!   r   rU  r   )r\  
__future__r   r   r   rd   typingr   r   r   r   r   r	   litellm._loggingr
   !litellm.llms.bedrock.base_aws_llmr   $litellm.rag.ingestion.base_ingestionr   litellmr   litellm.types.ragr   r   r   r$   r&   rz   r   r   <module>rd     sR   	 #    B B + 8 A25
.HW*J HWr   