o
    Zh@                     @  s   d dl mZ d dlZd dlZd dlmZ d dlmZmZm	Z	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 d dlmZ d dlmZ erLd dlZG d	d
 d
eZdS )    )annotationsN)repeat)	TYPE_CHECKINGAnyDictIterableListOptionalTupleTypeUnionDocument)
Embeddings)VectorStore)maximal_marginal_relevancec                   @  s  e Zd ZdZ		dVdWddZedXddZ		dYdZddZe				 		d[d\d'd(Z	d]d,d-Z
	.	d^d_d3d4Z	.	d^d`d6d7Z	.	d^dad9d:Zdbd<d=Z			dcdddAdBZ		dYdedDdEZe	dfdgdGdHZedhdIdJZ	.	K	LdidjdPdQZ	.	K	LdidkdRdSZdfdldTdUZdS )mSupabaseVectorStorea  `Supabase Postgres` vector store.

    It assumes you have the `pgvector`
    extension installed and a `match_documents` (or similar) function. For more details:
    https://integrations.langchain.com/vectorstores?integration_name=SupabaseVectorStore

    You can implement your own `match_documents` function in order to limit the search
    space to a subset of documents based on your own authorization or business logic.

    Note that the Supabase Python client does not yet support async operations.

    If you'd like to use `max_marginal_relevance_search`, please review the instructions
    below on modifying the `match_documents` function to return matched embeddings.


    Examples:

    .. code-block:: python

        from langchain_community.embeddings.openai import OpenAIEmbeddings
        from langchain_core.documents import Document
        from langchain_community.vectorstores import SupabaseVectorStore
        from supabase.client import create_client

        docs = [
            Document(page_content="foo", metadata={"id": 1}),
        ]
        embeddings = OpenAIEmbeddings()
        supabase_client = create_client("my_supabase_url", "my_supabase_key")
        vector_store = SupabaseVectorStore.from_documents(
            docs,
            embeddings,
            client=supabase_client,
            table_name="documents",
            query_name="match_documents",
            chunk_size=500,
        )

    To load from an existing table:

    .. code-block:: python

        from langchain_community.embeddings.openai import OpenAIEmbeddings
        from langchain_community.vectorstores import SupabaseVectorStore
        from supabase.client import create_client


        embeddings = OpenAIEmbeddings()
        supabase_client = create_client("my_supabase_url", "my_supabase_key")
        vector_store = SupabaseVectorStore(
            client=supabase_client,
            embedding=embeddings,
            table_name="documents",
            query_name="match_documents",
        )

      Nclientsupabase.client.Client	embeddingr   
table_namestr
chunk_sizeint
query_nameUnion[str, None]returnNonec                 C  sR   zddl }W n ty   tdw || _|| _|pd| _|p d| _|p%d| _dS )z Initialize with supabase client.r   NzXCould not import supabase python package. Please install it with `pip install supabase`.	documentsmatch_documentsr   )supabaseImportError_client
_embeddingr   r   r   )selfr   r   r   r   r   r!    r&   `/var/www/html/lang_env/lib/python3.10/site-packages/langchain_community/vectorstores/supabase.py__init__X   s   	

zSupabaseVectorStore.__init__c                 C  s   | j S N)r$   )r%   r&   r&   r'   
embeddingsq   s   zSupabaseVectorStore.embeddingstextsIterable[str]	metadatasOptional[List[Dict[Any, Any]]]idsOptional[List[str]]kwargsr   	List[str]c                 K  s<   |pdd |D }|  ||}| jt|}| |||S )Nc                 S     g | ]}t t qS r&   r   uuiduuid4.0_r&   r&   r'   
<listcomp>|       z1SupabaseVectorStore.add_texts.<locals>.<listcomp>)_texts_to_documentsr$   embed_documentslistadd_vectors)r%   r+   r-   r/   r1   docsvectorsr&   r&   r'   	add_textsu   s   zSupabaseVectorStore.add_textsr   r    clsType['SupabaseVectorStore']Optional[List[dict]] Optional[supabase.client.Client]Optional[str]'SupabaseVectorStore'c	                 K  sj   |st d|st d||}
dd |D }| ||}| j|||
|||fi |	 | |||||dS )z9Return VectorStore initialized from texts and embeddings.zSupabase client is required.z)Supabase document table_name is required.c                 S  r3   r&   r4   r7   r&   r&   r'   r:      r;   z2SupabaseVectorStore.from_texts.<locals>.<listcomp>)r   r   r   r   r   )
ValueErrorr=   r<   _add_vectors)rC   r+   r   r-   r   r   r   r   r/   r1   r*   r@   r&   r&   r'   
from_texts   s&   
zSupabaseVectorStore.from_textsrA   List[List[float]]List[Document]c                 C  s   |  | j| j|||| jS r)   )rJ   r#   r   r   )r%   rA   r   r/   r&   r&   r'   r?      s   zSupabaseVectorStore.add_vectors   querykfilterOptional[Dict[str, Any]]c                 K  $   | j |}| j|f||d|S NrP   rQ   )r$   embed_querysimilarity_search_by_vectorr%   rO   rP   rQ   r1   Zvectorr&   r&   r'   similarity_search   s   z%SupabaseVectorStore.similarity_searchList[float]c                 K  s*   | j |f||d|}dd |D }|S )NrU   c                 S  s   g | ]\}}|qS r&   r&   )r8   docr9   r&   r&   r'   r:          zCSupabaseVectorStore.similarity_search_by_vector.<locals>.<listcomp>)1similarity_search_by_vector_with_relevance_scores)r%   r   rP   rQ   r1   resultr   r&   r&   r'   rW      s   z/SupabaseVectorStore.similarity_search_by_vectorList[Tuple[Document, float]]c                 K  rS   rT   )r$   rV   r]   rX   r&   r&   r'   'similarity_search_with_relevance_scores   s   z;SupabaseVectorStore.similarity_search_with_relevance_scoresDict[str, Any]c                 C  s   t |d}|r||d< |S )N)Zquery_embeddingrQ   )dict)r%   rO   rQ   retr&   r&   r'   
match_args   s   
zSupabaseVectorStore.match_argspostgrest_filterscore_thresholdOptional[float]c                   s  |r9|  D ]2\}}t|tr8d|v r8|d }ddd |D }	d| d|	 d}
|r6d| d	|
 d}q|
}q| ||}| j| j|}|rU|j	d
d| d|_|j	d||_|
 }dd |jD } d ur fdd|D }t|dkrtd   |S )Nz$in,c                 s  s     | ]}d t | d V  qdS )'N)r   )r8   vr&   r&   r'   	<genexpr>   s    zXSupabaseVectorStore.similarity_search_by_vector_with_relevance_scores.<locals>.<genexpr>zmetadata->>z IN ()(z) and (andlimitc                 S  s>   g | ]}| d rt| di | d dd| ddfqS )contentmetadata rq   page_content
similarity        )getr   r8   searchr&   r&   r'   r:     s    


zYSupabaseVectorStore.similarity_search_by_vector_with_relevance_scores.<locals>.<listcomp>c                   s    g | ]\}}| kr||fqS r&   r&   )r8   r[   ru   rf   r&   r'   r:     s
    r   zDNo relevant docs were retrieved using the relevance score threshold )items
isinstancerb   joinrd   r#   rpcr   paramssetexecutedatalenwarningswarn)r%   rO   rP   rQ   re   rf   keyvalueZ	in_valuesZ
values_strZ
new_filtermatch_documents_paramsquery_builderresmatch_resultr&   rz   r'   r]      s@   	
zESupabaseVectorStore.similarity_search_by_vector_with_relevance_scores(List[Tuple[Document, float, np.ndarray]]c           	      C  sd   |  ||}| j| j|}|r|jdd| d|_|jd||_| }dd |jD }|S )Nrn   rm   rl   ro   c              	   S  s\   g | ]*}| d rt| di | d dd| ddtj| dddtjdd	fqS )
rp   rq   rr   rs   ru   rv   r   z[]rh   )sep)rw   r   npZ
fromstringstripfloat32rx   r&   r&   r'   r:   .  s    


zXSupabaseVectorStore.similarity_search_by_vector_returning_embeddings.<locals>.<listcomp>)rd   r#   r~   r   r   r   r   r   )	r%   rO   rP   rQ   re   r   r   r   r   r&   r&   r'   0similarity_search_by_vector_returning_embeddings  s   zDSupabaseVectorStore.similarity_search_by_vector_returning_embeddings"Optional[Iterable[Dict[Any, Any]]]c                 C  s(   |du rt i }dd t| |D }|S )z:Return list of Documents from list of texts and metadatas.Nc                 S  s   g | ]
\}}t ||d qS )rt   rq   r   )r8   textrq   r&   r&   r'   r:   J  s    
z;SupabaseVectorStore._texts_to_documents.<locals>.<listcomp>)r   zip)r+   r-   r@   r&   r&   r'   r<   A  s   z'SupabaseVectorStore._texts_to_documentsc                   s    fddt |D }g }tdt||D ],}	||	|	|  }
| ||
 }t|jdkr6tddd |jD | q|S )zAdd vectors to Supabase table.c                   s2   g | ]\}}|  | j | | jd qS ))idrp   r   rq   r   )r8   idxr   r   r/   r1   r&   r'   r:   ]  s    z4SupabaseVectorStore._add_vectors.<locals>.<listcomp>r   zError inserting: No rows addedc                 S  s$   g | ]}| d rt| d qS r   )rw   r   r8   ir&   r&   r'   r:   q  s   $ )		enumerateranger   from_Zupsertr   r   	Exceptionextend)r   r   rA   r   r/   r   r1   rowsZid_listr   chunkr^   r&   r   r'   rJ   Q  s   
z SupabaseVectorStore._add_vectors         ?fetch_klambda_multfloatc           
        s\   |  ||}dd |D  dd |D }ttj|gtjd|||d} fdd|D }	|	S )a  Return docs selected using the maximal marginal relevance.

        Maximal marginal relevance optimizes for similarity to query AND diversity
        among selected documents.

        Args:
            embedding: Embedding to look up documents similar to.
            k: Number of Documents to return. Defaults to 4.
            fetch_k: Number of Documents to fetch to pass to MMR algorithm.
            lambda_mult: Number between 0 and 1 that determines the degree
                        of diversity among the results with 0 corresponding
                        to maximum diversity and 1 to minimum diversity.
                        Defaults to 0.5.
        Returns:
            List of Documents selected by maximal marginal relevance.
        c                 S     g | ]}|d  qS )r   r&   r8   Z	doc_tupler&   r&   r'   r:     r\   zOSupabaseVectorStore.max_marginal_relevance_search_by_vector.<locals>.<listcomp>c                 S  r   )   r&   r   r&   r&   r'   r:     r\   )Zdtype)rP   r   c                   s   g | ]} | qS r&   r&   r   Zmatched_documentsr&   r'   r:     r\   )r   r   r   arrayr   )
r%   r   rP   r   r   r1   r^   Zmatched_embeddingsZmmr_selectedZfiltered_documentsr&   r   r'   'max_marginal_relevance_search_by_vectorw  s   z;SupabaseVectorStore.max_marginal_relevance_search_by_vectorc                 K  s"   | j |}| j||||d}|S )a  Return docs selected using the maximal marginal relevance.

        Maximal marginal relevance optimizes for similarity to query AND diversity
        among selected documents.

        Args:
            query: Text to look up documents similar to.
            k: Number of Documents to return. Defaults to 4.
            fetch_k: Number of Documents to fetch to pass to MMR algorithm.
            lambda_mult: Number between 0 and 1 that determines the degree
                        of diversity among the results with 0 corresponding
                        to maximum diversity and 1 to minimum diversity.
                        Defaults to 0.5.
        Returns:
            List of Documents selected by maximal marginal relevance.

        `max_marginal_relevance_search` requires that `query_name` returns matched
        embeddings alongside the match documents. The following function
        demonstrates how to do this:

        ```sql
        CREATE FUNCTION match_documents_embeddings(query_embedding vector(1536),
                                                   match_count int)
            RETURNS TABLE(
                id uuid,
                content text,
                metadata jsonb,
                embedding vector(1536),
                similarity float)
            LANGUAGE plpgsql
            AS $$
            # variable_conflict use_column
        BEGIN
            RETURN query
            SELECT
                id,
                content,
                metadata,
                embedding,
                1 -(docstore.embedding <=> query_embedding) AS similarity
            FROM
                docstore
            ORDER BY
                docstore.embedding <=> query_embedding
            LIMIT match_count;
        END;
        $$;
        ```
        )r   )r$   rV   r   )r%   rO   rP   r   r   r1   r   r@   r&   r&   r'   max_marginal_relevance_search  s
   9z1SupabaseVectorStore.max_marginal_relevance_searchc                 K  sN   |du rt ddd |D }|D ]}| j| j d|d   qdS )zUDelete by vector IDs.

        Args:
            ids: List of ids to delete.
        NzNo ids provided to delete.c                 S  s   g | ]}d |iqS r   r&   )r8   r   r&   r&   r'   r:     s
    z.SupabaseVectorStore.delete.<locals>.<listcomp>r   )rI   r#   r   r   deleteeqr   )r%   r/   r1   r   rowr&   r&   r'   r     s   $zSupabaseVectorStore.delete)r   N)r   r   r   r   r   r   r   r   r   r   r   r   )r   r   )NN)
r+   r,   r-   r.   r/   r0   r1   r   r   r2   )NNr   r    r   N)rC   rD   r+   r2   r   r   r-   rE   r   rF   r   rG   r   r   r   r   r/   r0   r1   r   r   rH   )rA   rL   r   rM   r/   r2   r   r2   )rN   N)
rO   r   rP   r   rQ   rR   r1   r   r   rM   )
r   rZ   rP   r   rQ   rR   r1   r   r   rM   )
rO   r   rP   r   rQ   rR   r1   r   r   r_   )rO   rZ   rQ   rR   r   ra   )NNN)rO   rZ   rP   r   rQ   rR   re   rG   rf   rg   r   r_   )
rO   rZ   rP   r   rQ   rR   re   rG   r   r   r)   )r+   r,   r-   r   r   rM   )r   r   r   r   rA   rL   r   rM   r/   r2   r   r   r1   r   r   r2   )rN   r   r   )r   rZ   rP   r   r   r   r   r   r1   r   r   rM   )rO   r   rP   r   r   r   r   r   r1   r   r   rM   )r/   r0   r1   r   r   r   )__name__
__module____qualname____doc__r(   propertyr*   rB   classmethodrK   r?   rY   rW   r`   rd   r]   r   staticmethodr<   rJ   r   r   r   r&   r&   r&   r'   r      sd    ?
#
B&(-?r   )
__future__r   r5   r   	itertoolsr   typingr   r   r   r   r   r	   r
   r   r   numpyr   Zlangchain_core.documentsr   Zlangchain_core.embeddingsr   Zlangchain_core.vectorstoresr   Z&langchain_community.vectorstores.utilsr   r!   r   r&   r&   r&   r'   <module>   s    ,