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

S3 Vectors is AWS's native vector storage service that provides:
- Purpose-built vector buckets for storing and querying vectors
- Vector indexes with configurable dimensions and distance metrics
- Metadata filtering for semantic search

This implementation:
1. Auto-creates vector buckets and indexes if not provided
2. Uses LiteLLM's embedding API (supports any provider)
3. Uses httpx + AWS SigV4 signing (no boto3 dependency for S3 Vectors APIs)
4. Stores vectors with metadata using PutVectors API
    )annotationsN)TYPE_CHECKINGAnyDictListOptionalTuple)verbose_logger)S3_VECTORS_DEFAULT_DIMENSION"S3_VECTORS_DEFAULT_DISTANCE_METRIC/S3_VECTORS_DEFAULT_NON_FILTERABLE_METADATA_KEYS)
safe_dumps)
BaseAWSLLM)get_async_httpx_clienthttpxSpecialProvider)BaseRAGIngestion)Router)RAGIngestOptionsc                      e Zd ZdZ	 d	 	 	 ddZddZddZd Z	 	 d	 	 	 	 	 	 	 	 	 ddZd Z	d	 Z
dd
Z	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 d	 	 	 	 	 	 	 ddZy)S3VectorsRAGIngestiona  
    S3 Vectors RAG ingestion using httpx + AWS SigV4 signing.

    Workflow:
    1. Auto-create vector bucket if needed (CreateVectorBucket API)
    2. Auto-create vector index if needed (CreateVectorIndex API)
    3. Generate embeddings using LiteLLM (supports any provider)
    4. Store vectors with PutVectors API

    Configuration:
    - vector_bucket_name: S3 vector bucket name (required)
    - index_name: Vector index name (auto-creates if not provided)
    - dimension: Vector dimension (default: S3_VECTORS_DEFAULT_DIMENSION)
    - distance_metric: "cosine" or "euclidean" (default: S3_VECTORS_DEFAULT_DISTANCE_METRIC)
    - non_filterable_metadata_keys: List of metadata keys to exclude from filtering
    Nc                   t        j                  | ||       t        j                  |        | j                  d   | _        | j                  j                  d      | _        | j                  j                  dt              | _        | j                  j                  dt              | _
        | j                         | _        | j                  j                  d      }| j                  |rt        |      nd       | _        | j!                  | j                  j                  d      	      }t#        t$        j&                  |d|ind 
      | _        d| _        y )N)ingest_optionsroutervector_bucket_name
index_namedistance_metricnon_filterable_metadata_keysaws_region_name)r   
ssl_verify)r   )llm_providerparamsF)r   __init__r   vector_store_configr   getr   r   r   r   r   _get_dimension_from_config	dimension)get_aws_region_name_for_non_llm_api_callsstrr   _get_ssl_verifyr   r   RAGasync_httpx_client_config_initialized)selfr   r   _aws_regionr   s        {/Users/manta/Documents/Projects/TheRoad-I1/.venv/lib/python3.12/site-packages/litellm/rag/ingestion/s3_vectors_ingestion.pyr"   zS3VectorsRAGIngestion.__init__<   s>   
 	!!$~fUD! #'":":;O"P2266|D#77;;A 
 -1,D,D,H,H*;-
) 88: ..223DE#MM0;C,  N  

 ))//33LA * 

 #9-111;1GL*-T#
 $)     c                  K   | j                   rd| j                   vrt        S 	 | j                   d   }t        j                  d|        d}| j                  r'| j                  j                  ||g       d{   }n t        j
                  ||g       d{   }|j                  rPt        |j                        dkD  r8t        |j                  d   d         }t        j                  d| d	|        |S t        S 7 7 h# t        $ r/}t        j                  d
| dt         d       Y d}~t        S d}~ww xY ww)z
        Auto-detect dimension by making a test embedding request.

        Makes a single embedding request with a test string to determine
        the output dimension of the embedding model.
        modelz=Auto-detecting dimension by making test embedding request to testr2   inputNr   	embeddingzAuto-detected dimension z for embedding model z6Could not auto-detect dimension from embedding model: z. Using default dimension of .)embedding_configr   r
   debugr   
aembeddinglitellmdatalen	Exceptionwarning)r-   
model_name
test_inputresponser&   es         r/   %_get_dimension_from_embedding_requestz;S3VectorsRAGIngestion._get_dimension_from_embedding_requestd   sU     $$t7L7L(L//	..w7J  OPZ|\
  J{{!%!7!7$ZL "8 "  ")!3!3$ZL" 
 }}X]]!3a!7a 0 =>	$$.yk9Nzl[ !  ,++  	""H L..J-K1N 
 ,+	sT   !EAD :D; D DAD ;ED D 	D> D9/
E9D>>Ec                P    d| j                   v rt        | j                   d         S y)z
        Get vector dimension from config if explicitly provided.

        Returns None if dimension should be auto-detected.
        r&   N)r#   int)r-   s    r/   r%   z0S3VectorsRAGIngestion._get_dimension_from_config   s+     $222t//<==r0   c                `  K   | j                   ry| j                  | j                          d{   | _        | j                          d{    | j                  s+t        j                         j                  dd }d| | _        | j                          d{    d| _         y7 x7 ]7 w)z,Lazily initialize S3 Vectors infrastructure.N   zlitellm-index-T)	r,   r&   rD   _ensure_vector_bucket_existsr   uuiduuid4hex_ensure_vector_index_exists)r-   	unique_ids     r/   _ensure_config_initializedz0S3VectorsRAGIngestion._ensure_config_initialized   s     ## >>!#'#M#M#OODN //111 

((!,I .yk:DO..000#'  P 	2 	1s4   -B.B(B.B*AB.B,B.*B.,B.c                  K   	 ddl }ddlm} ddlm} | j                  | j                  j                  d      | j                  j                  d      | j                  j                  d      | j                  | j                  j                  d	      | j                  j                  d
      | j                  j                  d      | j                  j                  d      | j                  j                  d      | j                  j                  d      
      }|i }|r=d|d<   t        j                  |j                  d            j                         }	|	|d<   n&t        j                  d      j                         |d<   |j                  ||||      }
|
j                         } ||j                   |j"                  |j$                  |j&                        } ||d| j                        j)                  |       t+        |j&                  j-                               }|j/                         }|dk(  r(| j0                  j3                  |||       d{   }|S |dk(  r(| j0                  j5                  |||       d{   }|S |dk(  r'| j0                  j                  ||       d{   }|S t7        d|       # t
        $ r t        d      w xY w7 7 Z7 0w)z
        Helper to sign and execute AWS API requests using httpx + SigV4.

        Pattern from litellm/integrations/s3_v2.py
        r   N)	SigV4Auth)
AWSRequestz=Missing botocore to call S3 Vectors. Run 'pip install boto3'.aws_access_key_idaws_secret_access_keyaws_session_tokenaws_session_nameaws_profile_nameaws_role_nameaws_web_identity_tokenaws_sts_endpointaws_external_id)
rS   rT   rU   r   rV   rW   rX   rY   rZ   r[   zapplication/jsonzContent-Typezutf-8zx-amz-content-sha256r0   )r<   headers)methodurlr<   r\   	s3vectorsPUTPOSTGET)r\   zUnsupported HTTP method: )requestsbotocore.authrQ   botocore.awsrequestrR   ImportErrorget_credentialsr#   r$   r   hashlibsha256encode	hexdigestRequestpreparer]   r^   bodyr\   add_authdictitemsupperr+   putpost
ValueError)r-   r]   r^   r<   r\   rc   rQ   rR   credentialscontent_hashreqpreppedaws_requestsigned_headersmethod_upperrB   s                   r/   _sign_and_execute_requestz/S3VectorsRAGIngestion._sign_and_execute_request   s    	/6 **"66::;NO"&":":">">?V"W"66::;NO 00!5599:LM!5599:LM2266G#'#;#;#?#?($ "5599:LM 44889JK + 
  ?G&8GN#">>$++g*>?IIKL.:G*+ /6nnS.A.K.K.MG*+ vswG++- !>>OO	
 	+{D,@,@AJJ;W k11779: ||~5 !4488$ 9  H  V#!4499$ :  H  U"!4488n8UUH  8ABB  	O 	j VsL   K$K IK$K,K$K +K$1K"2K$KK$ K$"K$c                  K   t        j                  d| j                          t        | j                        dk  rt	        d| j                   d      | j                  j                  dd      j                  dd      j                         st	        d| j                   d      d	| j                   d
}t        d| j                  i      }	 | j                  d||       d{   }|j                  dk(  r$t        j                  d| j                   d       y	 	 t        j                  d| j                          d	| j                   d}t        d| j                  i      }| j                  d||       d{   }|j                  dv r#t        j                  d| j                          y|j                  dk(  r$t        j                  d| j                   d       yt        j                  d|j                   d|j                          |j                          y7 C# t        $ r$}t        j                  d| d       Y d}~5d}~ww xY w7 # t        $ r}t        j                   d|         d}~ww xY ww)z[Create vector bucket if it doesn't exist using GetVectorBucket and CreateVectorBucket APIs.z"Ensuring S3 vector bucket exists:    zInvalid vector_bucket_name 'zy': AWS S3 bucket names must be at least 3 characters long. Please provide a valid bucket name (e.g., 'my-vector-bucket').- r7   z': AWS S3 bucket names can only contain lowercase letters, numbers, hyphens, and periods. Please provide a valid bucket name (e.g., 'my-vector-bucket').https://s3vectors.z.api.aws/GetVectorBucketvectorBucketNamera   r<   N   zVector bucket  existsz%Bucket check failed (may not exist): , attempting to createzCreating vector bucket: z.api.aws/CreateVectorBucketr      zCreated vector bucket:    already existszCreateVectorBucket failed:  - zError creating vector bucket: )r
   r9   r   r=   ru   replaceisalnumr   r   r}   status_coder>   infoerrortextraise_for_status	exception)r-   get_urlget_bodyrB   rC   
create_urlcreate_bodys          r/   rI   z2S3VectorsRAGIngestion._ensure_vector_bucket_exists  s    01H1H0IJ	

 t&&'!+.t/F/F.G HQ R 
 &&..sB7??RHPPR.t/F/F.G HQ R  't';';&<<TU143J3JKL
	!;;h <  H ##s*$$~d6M6M5Ng%VW +	  #;D<S<S;T!UV$T%9%9$::UV  %&8$:Q:Q%RSK!;;
 <  H ##z1##&=d>U>U=V$WX%%,$$$T%<%<$=_M $$1(2F2F1Gs8==/Z ))+E  	  7s:PQ 	   	$$'EaS%IJ	s   CJ
H. (H+)6H. J
"A I  I4I  7J
82I  *J
+?I  *J
+H. .	I7IJ
IJ
I   	J)JJJ
c                  K   t        j                  d| j                   d| j                          d| j                   d}t        | j                  | j                  d      }	 | j                  d||       d{   }|j                  d	k(  r$t        j                  d
| j                   d       y	 	 t        j                  d| j                   d| j                   d| j                          | j                  | j                  d| j                  | j                  d}| j                  rd| j                  i|d<   d| j                   d}| j                  d|t        |             d{   }|j                  dv r#t        j                  d| j                          y|j                  dk(  r$t        j                  d
| j                   d       yt        j                  d|j                   d|j                          |j                          y7 # t        $ r$}t        j                  d| d       Y d}~d}~ww xY w7 # t        $ r}t        j                   d|         d}~ww xY ww)zLCreate vector index if it doesn't exist using GetIndex and CreateIndex APIs.zEnsuring vector index exists: /r   z.api.aws/GetIndex)r   	indexNamera   r   Nr   zVector index r   z$Index check failed (may not exist): r   zCreating vector index: z with dimension=z	, metric=float32)r   r   dataTyper&   distanceMetricnonFilterableMetadataKeysmetadataConfigurationz.api.aws/CreateIndexr   zCreated vector index: r   r   zCreateIndex failed: r   zError creating vector index: )r
   r9   r   r   r   r   r}   r   r>   r&   r   r   r   r   r   r   r   )r-   r   r   rB   rC   index_configr   s          r/   rM   z1S3VectorsRAGIngestion._ensure_vector_index_existsA  s{    ,T-D-D,EQtFWX	

 't';';&<<MN!%!8!8tW

	!;;h <  H ##s*$$}T__4EW%MN +#	  )$//)::J4>>JZZcdhdxdxcyz %)$;$;!__%!^^"&"6"6L 00/1R1R945 .d.B.B-CCWXJ!;;
L)A <  H ##z1##&<T__<M$NO%%,$$}T__4E_%UV$$*8+?+?*@HMM?S ))+Y  	  6qc9OP 	4  	$$'DQC%HI	s   A"I7%H <H=6H 3I76B9I /I04I $I7%2I I7?I I7H 	I$I=I7II7I 	I4I//I44I7c                r  K   t        j                  dt        |       d| j                   d| j                          d| j
                   d}| j                  | j                  |d}	 | j                  d|t        |             d	{   }|j                  d
v r/t        j                  dt        |       d| j                          y	t        j                  d|j                   d|j                          |j                          y	7 # t        $ r}t        j                  d|         d	}~ww xY ww)z
        Call PutVectors API to store vectors in S3 Vectors.

        Args:
            vectors: List of vector objects with keys: "key", "data", "metadata"
        zStoring z vectors in r   r   z.api.aws/PutVectors)r   r   vectorsra   r   Nr   zSuccessfully stored z vectors in index zPutVectors failed with status : zError storing vectors: )r
   r9   r=   r   r   r   r}   r   r   r   r   r   r   r>   r   )r-   r   r^   request_bodyrB   rC   s         r/   _put_vectorsz"S3VectorsRAGIngestion._put_vectors  s;     	s7|nL1H1H0I4??J[\	
 #4#7#7"88KL !% 7 7
	!;;*\": <  H ##z1##*3w<.8J4??J[\ $$4X5I5I4J"X]]O\ ))+  	$$'>qc%BC	sI   A&D7) D 	D
A D 
D7?D 
D7D 	D4D//D44D7c                  K   |sy| j                   st        j                  d       ddi| _         | j                   j                  dd      }t        j                  dt        |       d|        t        |      }| j                  r&| j                  j                  ||       d{   }nt        j                  ||       d{   }|j                  D cg c]  }|d   	 c}S 7 A7 #c c}w w)	z
        Generate embeddings using LiteLLM's embedding API.

        Supports any embedding provider (OpenAI, Bedrock, Cohere, etc.)
        NzBNo embedding config provided, using default text-embedding-3-smallr2   text-embedding-3-smallzGenerating embeddings for z chunks using r4   r6   )r8   r
   r?   r$   r9   r=   listr   r:   r;   r<   )r-   chunksembedding_modelinput_chunksrB   items         r/   embedzS3VectorsRAGIngestion.embed  s       $$""T &-.F$GD!//33G=UV(V^OCTU	

 #'v,;;![[33%\ 4  H %//%\ H /7mm<md[!m<< =s6   B%C2'C)(C2C+C2C-&C2+C2-C2c                  K   | j                          d{    |r|s"d}t        j                  |       t        |      g }t	        t        ||            D ]B  \  }\  }	}
|	t        |      d}|r||d<   |r| d| nd| d|
i|d}|j                  |       D | j                  |       d{    | j                   d	| j                   }||fS 7 7 %w)
av  
        Store vectors in S3 Vectors using PutVectors API.

        Steps:
        1. Ensure vector bucket exists (auto-create if needed)
        2. Ensure vector index exists (auto-create if needed)
        3. Prepare vector data with metadata
        4. Call PutVectors API with httpx + SigV4 signing

        Args:
            file_content: Raw file bytes (not used for S3 Vectors)
            filename: Name of the file
            content_type: MIME type (not used for S3 Vectors)
            chunks: Text chunks
            embeddings: Vector embeddings

        Returns:
            Tuple of (index_name, filename)
        Na  No text content could be extracted from the file for embedding. Possible causes:
  1. PDF files require OCR - add 'ocr' config with a vision model (e.g., 'anthropic/claude-3-5-sonnet-20241022')
  2. Binary files cannot be processed - convert to text first
  3. File is empty or contains no extractable text
For PDFs, either enable OCR or use a PDF extraction library to convert to text before ingestion.)source_textchunk_indexfilename_chunk_r   )keyr<   metadata:)rO   r
   r   ru   	enumeratezipr(   appendr   r   r   )r-   file_contentr   content_typer   
embeddings	error_msgr   ichunkr6   r   
vector_objvector_store_ids                 r/   storezS3VectorsRAGIngestion.store  s    8 --///s    +Y'' %.s6:/F%G!A!y  %"1v(H
 '/$ -5(1QC(F1#,"I.$J NN:&! &H& ((( "445Qt6GH((O 	0F 	)s"   CCBC1C2$CCc           	       K   t        j                  d| d|        | j                  s	ddi| _        | j                  j                  dd      }t	        j
                  ||g       d{   }|j                  d   d   }d	| j                   d
}| j                  |d|i|ddd}	 | j                  d|t        |             d{   }|j                  dk(  r|j                         }	t        j                  dt        |	j                  dg              d       |	j                  d      rR|	d   D ]J  }
|
j                  di       }|j                  dd      }|j                         |j                         v sH|	c S  |	S t        j                  d|j                   d|j                           y7 H7 # t"        $ r"}t        j$                  d|        Y d}~yd}~ww xY ww)a  
        Query S3 Vectors using QueryVectors API.

        Args:
            vector_store_id: Index name
            query: Query text
            top_k: Number of results to return

        Returns:
            Query results with vectors and metadata
        zQuerying index z with query: r2   r   r4   Nr   r6   r   z.api.aws/QueryVectorsr   T)r   r   queryVectortopKreturnDistancereturnMetadatara   r   r   zQuery returned r   z resultsr   r   r   z QueryVectors failed with status r   zError querying vectors: )r
   r9   r8   r$   r;   r:   r<   r   r   r}   r   r   jsonr=   lowerr   r   r>   r   )r-   r   querytop_kr   rB   query_embeddingr^   r   resultsresultr   r   rC   s                 r/   query_vector_storez(S3VectorsRAGIngestion.query_vector_store  s     	.?}UGTU $$%,.F$GD!//33G=UV ++/%QQ"--*;7 #4#7#7"88MN !% 7 7(%7""
	!;;*\": <  H ##s*"--/$$%c'++i*D&E%FhO
 ;;y)"))"4#)::j"#=&.ll="&E ;;=K,=,=,??#*N	 #5 $$6x7K7K6LBx}}o^ Q R 2  	$$'?s%CD	sm   A(G%*F2+;G%' F7 F5B2F7 ;F7 >G%?F7 G%/F7 1G%5F7 7	G" GG%G""G%)N)r   z'RAGIngestOptions'r   zOptional['Router'])returnrF   )r   zOptional[int])NN)
r]   r(   r^   r(   r<   Optional[str]r\   zOptional[Dict[str, str]]r   r   )r   zList[Dict[str, Any]])r   	List[str]r   Optional[List[List[float]]])r   zOptional[bytes]r   r   r   r   r   r   r   r   r   z#Tuple[Optional[str], Optional[str]])   )r   r(   r   r(   r   rF   r   zOptional[Dict[str, Any]])__name__
__module____qualname____doc__r"   rD   r%   rO   r}   rI   rM   r   r   r   r    r0   r/   r   r   *   s   ( &*&)*&) #&)P(,T(4 #,0QQ Q 	Q
 *Q 
Qf>@<|$L%=%= 
%%=NC)%C)  C) $	C)
 C) 0C) 
-C)L >?A"A+.A7:A	!Ar0   r   ) r   
__future__r   rh   rJ   typingr   r   r   r   r   r	   r;   litellm._loggingr
   litellm.constantsr   r   r   *litellm.litellm_core_utils.safe_json_dumpsr   !litellm.llms.bedrock.base_aws_llmr   &litellm.llms.custom_httpx.http_handlerr   r   $litellm.rag.ingestion.base_ingestionr   r   litellm.types.ragr   r   r   r0   r/   <module>r      sY    #   B B  + 
 B 8 B2h,j hr0   