Module zep_python.langchain

Expand source code
from zep_python.langchain.history import ZepChatMessageHistory
from zep_python.langchain.vectorstore import ZepVectorStore

__all__ = [
    "ZepChatMessageHistory",
    "ZepVectorStore",
]

Sub-modules

zep_python.langchain.history
zep_python.langchain.vectorstore

Classes

class ZepChatMessageHistory (session_id: str, zep_client: Optional[ZepClient] = None, api_url: Optional[str] = 'https://api.getzep.com', api_key: Optional[str] = None, memory_type: Optional[str] = None, ai_prefix: Optional[str] = None, human_prefix: Optional[str] = None, summary_instruction: Optional[str] = None)

LangChain Chat message history that uses Zep as a backend.

Attributes

session_id : str
The unique identifier of the session.
zep_client : ZepClient
The Zep client used for making API requests. Pass in this rather than the API key and URL.
api_url : str
The Zep API service URL. Not required if using Zep Cloud.
api_key : str
The Zep API key. Not required if using Zep Open Source.
memory_type : str
The type of memory to use. Can be "perpetual", "summary_retrieval", or "message_window". Defaults to "perpetual".
summary_instruction : Optional[str]
Additional instructions for generating dialog summaries.
Expand source code
class ZepChatMessageHistory(BaseChatMessageHistory):
    """
    LangChain Chat message history that uses Zep as a backend.

    Attributes
    ----------
    session_id : str
        The unique identifier of the session.
    zep_client : ZepClient
        The Zep client used for making API requests.
        Pass in this rather than the API key and URL.
    api_url : str
        The Zep API service URL. Not required if using Zep Cloud.
    api_key : str
        The Zep API key. Not required if using Zep Open Source.
    memory_type : str
        The type of memory to use. Can be "perpetual", "summary_retrieval",
        or "message_window". Defaults to "perpetual".
    summary_instruction : Optional[str]
        Additional instructions for generating dialog summaries.
    """

    def __init__(
        self,
        session_id: str,
        zep_client: Optional[ZepClient] = None,
        api_url: Optional[str] = API_URL,
        api_key: Optional[str] = None,
        memory_type: Optional[str] = None,
        ai_prefix: Optional[str] = None,
        human_prefix: Optional[str] = None,
        summary_instruction: Optional[str] = None,
    ) -> None:
        if zep_client is None:
            self._client = ZepClient(api_url=api_url, api_key=api_key)
        else:
            self._client = zep_client

        self.session_id = session_id
        self.memory_type = memory_type or "perpetual"

        self.ai_prefix = ai_prefix or "ai"
        self.human_prefix = human_prefix or "human"
        self.summary_instruction = summary_instruction

    @property
    def messages(self) -> List[BaseMessage]:  # type: ignore
        """Retrieve messages from Zep memory"""

        zep_memory: Optional[Memory] = self._get_memory()
        if not zep_memory:
            return []

        messages: List[BaseMessage] = []
        # Extract facts and summary, if present, and messages
        if zep_memory.facts:
            messages.append(SystemMessage(content="\n".join(zep_memory.facts)))

        if zep_memory.summary:
            if len(zep_memory.summary.content) > 0:
                messages.append(SystemMessage(content=zep_memory.summary.content))

        if zep_memory.messages:
            for msg in zep_memory.messages:
                metadata = {
                    "uuid": msg.uuid,
                    "created_at": msg.created_at,
                    "token_count": msg.token_count,
                    "metadata": msg.metadata,
                }
                message_class = AIMessage if msg.role == "ai" else HumanMessage
                messages.append(
                    message_class(content=msg.content, additional_kwargs=metadata)
                )

        return messages

    @property
    def zep_messages(self) -> Union[List[Message], None]:
        """Retrieve summary from Zep memory"""
        zep_memory: Optional[Memory] = self._get_memory()
        if not zep_memory:
            return []

        return zep_memory.messages

    @property
    def zep_summary(self) -> Optional[str]:
        """Retrieve summary from Zep memory"""
        zep_memory: Optional[Memory] = self._get_memory()
        if not zep_memory or not zep_memory.summary:
            return None

        return zep_memory.summary.content

    def _get_memory(self) -> Optional[Memory]:
        """Retrieve memory from Zep"""
        try:
            zep_memory: Memory = self._client.memory.get_memory(
                self.session_id, self.memory_type
            )
        except NotFoundError:
            logger.warning(
                f"Session {self.session_id} not found in Zep. Returning None"
            )
            return None
        return zep_memory

    def add_user_message(  # type: ignore
        self, message: str, metadata: Optional[Dict[str, Any]] = None
    ) -> None:
        """Convenience method for adding a human message string to the store.

        Args:
            message: The string contents of a human message.
            metadata: Optional metadata to attach to the message.
        """
        from langchain_core.messages import HumanMessage

        self.add_message(HumanMessage(content=message), metadata=metadata)

    def add_ai_message(  # type: ignore
        self, message: str, metadata: Optional[Dict[str, Any]] = None
    ) -> None:
        """Convenience method for adding an AI message string to the store.

        Args:
            message: The string contents of an AI message.
            metadata: Optional metadata to attach to the message.
        """
        from langchain_core.messages import AIMessage

        self.add_message(AIMessage(content=message), metadata=metadata)

    def add_message(
        self, message: BaseMessage, metadata: Optional[Dict[str, Any]] = None
    ) -> None:
        """Append the message to the Zep memory history"""

        if message.content is None:
            raise ValueError("Message content cannot be None")

        if isinstance(message.content, list):
            raise ValueError("Message content cannot be a list")

        if message.type == "ai":
            message.name = self.ai_prefix
        elif message.type == "human":
            message.name = self.human_prefix

        zep_message = Message(
            content=message.content,
            # If name is not set, use type as role
            role=message.name or message.type,
            role_type=get_zep_message_role_type(message.type),
            metadata=metadata,
        )
        zep_memory = Memory(
            messages=[zep_message], summary_instruction=self.summary_instruction
        )

        self._client.memory.add_memory(self.session_id, zep_memory)

    def clear(self) -> None:
        """Clear session memory from Zep. Note that Zep is long-term storage for memory
        and this is not advised unless you have specific data retention requirements.
        """
        try:
            self._client.memory.delete_memory(self.session_id)
        except NotFoundError:
            logger.warning(
                f"Session {self.session_id} not found in Zep. Skipping delete."
            )

Ancestors

  • langchain_core.chat_history.BaseChatMessageHistory
  • abc.ABC

Instance variables

var messages : List[langchain_core.messages.base.BaseMessage]

Retrieve messages from Zep memory

Expand source code
@property
def messages(self) -> List[BaseMessage]:  # type: ignore
    """Retrieve messages from Zep memory"""

    zep_memory: Optional[Memory] = self._get_memory()
    if not zep_memory:
        return []

    messages: List[BaseMessage] = []
    # Extract facts and summary, if present, and messages
    if zep_memory.facts:
        messages.append(SystemMessage(content="\n".join(zep_memory.facts)))

    if zep_memory.summary:
        if len(zep_memory.summary.content) > 0:
            messages.append(SystemMessage(content=zep_memory.summary.content))

    if zep_memory.messages:
        for msg in zep_memory.messages:
            metadata = {
                "uuid": msg.uuid,
                "created_at": msg.created_at,
                "token_count": msg.token_count,
                "metadata": msg.metadata,
            }
            message_class = AIMessage if msg.role == "ai" else HumanMessage
            messages.append(
                message_class(content=msg.content, additional_kwargs=metadata)
            )

    return messages
var zep_messages : Optional[List[Message]]

Retrieve summary from Zep memory

Expand source code
@property
def zep_messages(self) -> Union[List[Message], None]:
    """Retrieve summary from Zep memory"""
    zep_memory: Optional[Memory] = self._get_memory()
    if not zep_memory:
        return []

    return zep_memory.messages
var zep_summary : Optional[str]

Retrieve summary from Zep memory

Expand source code
@property
def zep_summary(self) -> Optional[str]:
    """Retrieve summary from Zep memory"""
    zep_memory: Optional[Memory] = self._get_memory()
    if not zep_memory or not zep_memory.summary:
        return None

    return zep_memory.summary.content

Methods

def add_ai_message(self, message: str, metadata: Optional[Dict[str, Any]] = None) ‑> None

Convenience method for adding an AI message string to the store.

Args

message
The string contents of an AI message.
metadata
Optional metadata to attach to the message.
Expand source code
def add_ai_message(  # type: ignore
    self, message: str, metadata: Optional[Dict[str, Any]] = None
) -> None:
    """Convenience method for adding an AI message string to the store.

    Args:
        message: The string contents of an AI message.
        metadata: Optional metadata to attach to the message.
    """
    from langchain_core.messages import AIMessage

    self.add_message(AIMessage(content=message), metadata=metadata)
def add_message(self, message: BaseMessage, metadata: Optional[Dict[str, Any]] = None) ‑> None

Append the message to the Zep memory history

Expand source code
def add_message(
    self, message: BaseMessage, metadata: Optional[Dict[str, Any]] = None
) -> None:
    """Append the message to the Zep memory history"""

    if message.content is None:
        raise ValueError("Message content cannot be None")

    if isinstance(message.content, list):
        raise ValueError("Message content cannot be a list")

    if message.type == "ai":
        message.name = self.ai_prefix
    elif message.type == "human":
        message.name = self.human_prefix

    zep_message = Message(
        content=message.content,
        # If name is not set, use type as role
        role=message.name or message.type,
        role_type=get_zep_message_role_type(message.type),
        metadata=metadata,
    )
    zep_memory = Memory(
        messages=[zep_message], summary_instruction=self.summary_instruction
    )

    self._client.memory.add_memory(self.session_id, zep_memory)
def add_user_message(self, message: str, metadata: Optional[Dict[str, Any]] = None) ‑> None

Convenience method for adding a human message string to the store.

Args

message
The string contents of a human message.
metadata
Optional metadata to attach to the message.
Expand source code
def add_user_message(  # type: ignore
    self, message: str, metadata: Optional[Dict[str, Any]] = None
) -> None:
    """Convenience method for adding a human message string to the store.

    Args:
        message: The string contents of a human message.
        metadata: Optional metadata to attach to the message.
    """
    from langchain_core.messages import HumanMessage

    self.add_message(HumanMessage(content=message), metadata=metadata)
def clear(self) ‑> None

Clear session memory from Zep. Note that Zep is long-term storage for memory and this is not advised unless you have specific data retention requirements.

Expand source code
def clear(self) -> None:
    """Clear session memory from Zep. Note that Zep is long-term storage for memory
    and this is not advised unless you have specific data retention requirements.
    """
    try:
        self._client.memory.delete_memory(self.session_id)
    except NotFoundError:
        logger.warning(
            f"Session {self.session_id} not found in Zep. Skipping delete."
        )
class ZepVectorStore (collection_name: str, description: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None, zep_client: Optional[ZepClient] = None, api_url: Optional[str] = 'https://api.getzep.com', api_key: Optional[str] = None)

Zep VectorStore.

Provides methods for adding texts or documents to a Zep Collection, searching for similar documents, and deleting documents.

Search scores are calculated using cosine similarity normalized to [0, 1].

Args

collection_name : str
The name of the collection in the Zep store.
description : Optional[str]
The description of the collection.
metadata : Optional[Dict[str, Any]]
The metadata to associate with the collection.
zep_client : Optional[ZepClient]
The Zep client to use.
api_url : str
The URL of the Zep API. Defaults to "https://api.getzep.com". Not required if passing in a ZepClient.
api_key : Optional[str]
The API key for the Zep API. Not required if passing in a ZepClient.
Expand source code
class ZepVectorStore(VectorStore):
    """`Zep` VectorStore.

    Provides methods for adding texts or documents to a Zep Collection,
    searching for similar documents, and deleting documents.

    Search scores are calculated using cosine similarity normalized to [0, 1].

    Args:
        collection_name (str): The name of the collection in the Zep store.
        description (Optional[str]): The description of the collection.
        metadata (Optional[Dict[str, Any]]): The metadata to associate with the
            collection.
        zep_client (Optional[ZepClient]): The Zep client to use.
        api_url (str): The URL of the Zep API. Defaults to "https://api.getzep.com".
            Not required if passing in a ZepClient.
        api_key (Optional[str]): The API key for the Zep API.
            Not required if passing in a ZepClient.
    """

    def __init__(
        self,
        collection_name: str,
        description: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None,
        zep_client: Optional[ZepClient] = None,
        api_url: Optional[str] = API_URL,
        api_key: Optional[str] = None,
    ) -> None:
        super().__init__()
        if not collection_name:
            raise ValueError(
                "collection_name must be specified when using ZepVectorStore."
            )
        if zep_client is None:
            self._client = ZepClient(api_url=api_url, api_key=api_key)
        else:
            self._client = zep_client

        self.collection_name = collection_name
        self.c_description = description
        self.c_metadata = metadata

        self._collection = self._load_collection()

    def _load_collection(self) -> DocumentCollection:
        """
        Load the collection from the Zep backend.
        """

        try:
            collection = self._client.document.get_collection(self.collection_name)
        except NotFoundError:
            logger.info(
                f"Collection {self.collection_name} not found. Creating new collection."
            )
            collection = self._create_collection()

        return collection

    def _create_collection(self) -> DocumentCollection:
        """
        Create a new collection in the Zep backend.
        """
        collection = self._client.document.add_collection(
            name=self.collection_name,
            description=self.c_description,
            metadata=self.c_metadata,
        )
        return collection

    def _generate_documents_to_add(
        self,
        texts: Iterable[str],
        metadatas: Optional[List[Dict[Any, Any]]] = None,  # langchain spelling
        document_ids: Optional[List[str]] = None,
    ) -> List[ZepDocument]:
        documents: List[ZepDocument] = []
        for i, d in enumerate(texts):
            documents.append(
                ZepDocument(
                    content=d,
                    metadata=metadatas[i] if metadatas else None,
                    document_id=document_ids[i] if document_ids else None,
                )
            )
        return documents

    def add_texts(
        self,
        texts: Iterable[str],
        metadatas: Optional[List[Dict[str, Any]]] = None,  # langchain spelling
        document_ids: Optional[List[str]] = None,
        **kwargs: Any,
    ) -> List[str]:
        """Run more texts through the embeddings and add to the vectorstore.

        Args:
            texts: Iterable of strings to add to the vectorstore.
            metadatas: Optional list of metadatas associated with the texts.
            document_ids: Optional list of document ids associated with the texts.
            kwargs: vectorstore specific parameters

        Returns:
            List of ids from adding the texts into the vectorstore.
        """
        if not self._collection:
            raise ValueError(
                "collection should be an instance of a Zep DocumentCollection"
            )

        documents = self._generate_documents_to_add(texts, metadatas, document_ids)
        uuids = self._collection.add_documents(documents)

        return uuids

    async def aadd_texts(
        self,
        texts: Iterable[str],
        metadatas: Optional[List[Dict[str, Any]]] = None,  # langchain spelling
        document_ids: Optional[List[str]] = None,
        **kwargs: Any,
    ) -> List[str]:
        """Run more texts through the embeddings and add to the vectorstore."""
        if not self._collection:
            raise ValueError(
                "collection should be an instance of a Zep DocumentCollection"
            )

        documents = self._generate_documents_to_add(texts, metadatas, document_ids)
        uuids = await self._collection.aadd_documents(documents)

        return uuids

    def search(
        self,
        query: str,
        search_type: str,
        metadata_filter: Optional[Dict[str, Any]] = None,
        k: int = 3,
        **kwargs: Any,
    ) -> List[Document]:
        """Return docs most similar to query using specified search type."""
        if search_type == "similarity":
            return self.similarity_search(
                query, k=k, metadata=metadata_filter, **kwargs
            )
        elif search_type == "mmr":
            return self.max_marginal_relevance_search(
                query, k=k, metadata_filter=metadata_filter, **kwargs
            )
        else:
            raise ValueError(
                f"search_type of {search_type} not allowed. Expected "
                "search_type to be 'similarity' or 'mmr'."
            )

    async def asearch(
        self,
        query: str,
        search_type: str,
        metadata_filter: Optional[Dict[str, Any]] = None,
        k: int = 3,
        **kwargs: Any,
    ) -> List[Document]:
        """Return docs most similar to query using specified search type."""
        if search_type == "similarity":
            return await self.asimilarity_search(
                query, k=k, metadata=metadata_filter, **kwargs
            )
        elif search_type == "mmr":
            return await self.amax_marginal_relevance_search(
                query, k=k, metadata_filter=metadata_filter, **kwargs
            )
        else:
            raise ValueError(
                f"search_type of {search_type} not allowed. Expected "
                "search_type to be 'similarity' or 'mmr'."
            )

    def similarity_search(
        self,
        query: str,
        k: int = 4,
        metadata: Optional[Dict[str, Any]] = None,
        **kwargs: Any,
    ) -> List[Document]:
        """Return docs most similar to query."""

        results = self._similarity_search_with_relevance_scores(
            query, k=k, metadata_filter=metadata, **kwargs
        )
        return [doc for doc, _ in results]

    def similarity_search_with_score(
        self,
        query: str,
        k: int = 4,
        metadata: Optional[Dict[str, Any]] = None,
        **kwargs: Any,
    ) -> List[Tuple[Document, float]]:
        """Run similarity search with distance."""

        return self._similarity_search_with_relevance_scores(
            query, k=k, metadata_filter=metadata, **kwargs
        )

    def _similarity_search_with_relevance_scores(
        self,
        query: str,
        k: int = 4,
        metadata_filter: Optional[Dict[str, Any]] = None,
        **kwargs: Any,
    ) -> List[Tuple[Document, float]]:
        """
        Default similarity search with relevance scores.
        Return docs and relevance scores in the range [0, 1].

        0 is dissimilar, 1 is most similar.

        Args:
            query: input text
            k: Number of Documents to return. Defaults to 4.
            metadata_filter: Optional, metadata filter
            **kwargs: kwargs to be passed to similarity search. Should include:
                score_threshold: Optional, a floating point value between 0 to 1 and
                    filter the resulting set of retrieved docs

        Returns:
            List of Tuples of (doc, similarity_score)
        """

        if not self._collection:
            raise ValueError(
                "collection should be an instance of a Zep DocumentCollection"
            )

        results = self._collection.search(
            query, limit=k, metadata=metadata_filter, **kwargs
        )

        return [
            (
                Document(
                    page_content=doc.content,
                    metadata=doc.metadata or {},
                ),
                doc.score or 0.0,
            )
            for doc in results
        ]

    async def asimilarity_search_with_relevance_scores(
        self,
        query: str,
        k: int = 4,
        metadata_filter: Optional[Dict[str, Any]] = None,
        **kwargs: Any,
    ) -> List[Tuple[Document, float]]:
        """Return docs most similar to query."""

        if not self._collection:
            raise ValueError(
                "collection should be an instance of a Zep DocumentCollection"
            )

        results = await self._collection.asearch(
            query, limit=k, metadata=metadata_filter, **kwargs
        )

        return [
            (
                Document(
                    page_content=doc.content,
                    metadata=doc.metadata or {},
                ),
                doc.score or 0.0,
            )
            for doc in results
        ]

    async def asimilarity_search(
        self,
        query: str,
        k: int = 4,
        metadata: Optional[Dict[str, Any]] = None,
        **kwargs: Any,
    ) -> List[Document]:
        """Return docs most similar to query."""

        results = await self.asimilarity_search_with_relevance_scores(
            query, k, metadata_filter=metadata, **kwargs
        )

        return [doc for doc, _ in results]

    def max_marginal_relevance_search(  # type: ignore # ignore inconsistent override
        self,
        query: str,
        k: int = 4,
        fetch_k: int = 20,
        lambda_mult: float = 0.5,
        metadata_filter: Optional[Dict[str, Any]] = None,
    ) -> List[Document]:
        """Return docs selected using the maximal marginal relevance reranking.

        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: (Unsupported) 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.
            metadata_filter: Optional, metadata to filter the resulting set of retrieved
                docs
        Returns:
            List of Documents selected by maximal marginal relevance.

        NOTE: Zep automatically tunes the number of results returned by the search prior
        to reranking based on `k`. `fetch_k` is ignored.
        """

        if not self._collection:
            raise ValueError(
                "collection should be an instance of a Zep DocumentCollection"
            )

        results = self._collection.search(
            query,
            limit=k,
            metadata=metadata_filter,
            search_type="mmr",
            mmr_lambda=lambda_mult,
        )

        return [
            Document(page_content=d.content, metadata=d.metadata or {}) for d in results
        ]

    async def amax_marginal_relevance_search(
        self,
        query: str,
        k: int = 4,
        fetch_k: int = 20,
        lambda_mult: float = 0.5,
        metadata_filter: Optional[Dict[str, Any]] = None,
        **kwargs: Any,
    ) -> List[Document]:
        """Return docs selected using the maximal marginal relevance reranking.

        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: (Unsupported) 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.
            metadata_filter: Optional, metadata to filter the resulting set of retrieved
                docs
        Returns:
            List of Documents selected by maximal marginal relevance.

        NOTE: Zep automatically tunes the number of results returned by the
        search prior to reranking based on `k`. `fetch_k` is ignored.
        """

        if not self._collection:
            raise ValueError(
                "collection should be an instance of a Zep DocumentCollection"
            )

        results = await self._collection.asearch(
            query,
            limit=k,
            metadata=metadata_filter,
            search_type="mmr",
            mmr_lambda=lambda_mult,
        )

        return [
            Document(page_content=d.content, metadata=d.metadata or {}) for d in results
        ]

    @classmethod
    def from_texts(  # type: ignore # ignore inconsistent override
        cls,
        texts: List[str],
        collection_name: str,
        metadatas: Optional[List[dict]] = None,
        description: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None,
        zep_client: Optional[ZepClient] = None,
        api_url: Optional[str] = API_URL,
        api_key: Optional[str] = None,
        **kwargs: Any,
    ) -> ZepVectorStore:
        """
        Class method that returns a ZepVectorStore instance initialized from texts.

        If the collection does not exist, it will be created.

        Args:
            texts (List[str]): The list of texts to add to the vectorstore.
            collection_name (str): The name of the collection in the Zep store.
            metadatas (Optional[List[Dict[str, Any]]]): Optional list of metadata
               associated with the texts.
            description (Optional[str]): The description of the collection.
            metadata (Optional[Dict[str, Any]]): The metadata to associate with the
                collection.
            zep_client (Optional[ZepClient]): The Zep client to use.
            api_url (Optional[str]): The URL of the Zep API. Defaults to
                "https://api.getzep.com". Not required if passing in a ZepClient.
            api_key (Optional[str]): The API key for the Zep API. Not required if
                passing in a ZepClient.
            **kwargs: Additional parameters specific to the vectorstore.

        Returns:
            ZepVectorStore: An instance of ZepVectorStore.
        """
        vecstore = cls(
            collection_name,
            description=description,
            metadata=metadata,
            zep_client=zep_client,
            api_url=api_url,
            api_key=api_key,
        )
        vecstore.add_texts(texts, metadatas)

        return vecstore

    @classmethod
    async def afrom_texts(  # type: ignore # ignore inconsistent override
        cls,
        texts: List[str],
        collection_name: str,
        metadatas: Optional[List[dict]] = None,
        description: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None,
        zep_client: Optional[ZepClient] = None,
        api_url: Optional[str] = API_URL,
        api_key: Optional[str] = None,
        **kwargs: Any,
    ) -> ZepVectorStore:
        """
        Class method that asynchronously returns a ZepVectorStore instance
        initialized from texts.

        If the collection does not exist, it will be created.

        Args:
            texts (List[str]): The list of texts to add to the vectorstore.
            collection_name (str): The name of the collection in the Zep store.
            metadatas (Optional[List[Dict[str, Any]]]): Optional list of metadata
               associated with the texts.
            description (Optional[str]): The description of the collection.
            metadata (Optional[Dict[str, Any]]): The metadata to associate with the
                collection.
            zep_client (Optional[ZepClient]): The Zep client to use.
            api_url (Optional[str]): The URL of the Zep API. Defaults to
                "https://api.getzep.com". Not required if passing in a ZepClient.
            api_key (Optional[str]): The API key for the Zep API. Not required if
                passing in a ZepClient.
            **kwargs: Additional parameters specific to the vectorstore.

        Returns:
            ZepVectorStore: An instance of ZepVectorStore.
        """
        vecstore = cls(
            collection_name,
            description=description,
            metadata=metadata,
            zep_client=zep_client,
            api_url=api_url,
            api_key=api_key,
        )
        await vecstore.aadd_texts(texts, metadatas)
        return vecstore

    @classmethod
    def from_documents(  # type: ignore # ignore inconsistent override
        cls,
        documents: List[Document],
        **kwargs: Any,
    ) -> ZepVectorStore:
        """Return VectorStore initialized from documents."""
        texts = [d.page_content for d in documents]
        metadatas = [d.metadata for d in documents]
        return cls.from_texts(texts, metadatas=metadatas, **kwargs)

    @classmethod
    async def afrom_documents(  # type: ignore # ignore inconsistent override
        cls,
        documents: List[Document],
        **kwargs: Any,
    ) -> ZepVectorStore:
        """Asynchronously return VectorStore initialized from documents."""
        texts = [d.page_content for d in documents]
        metadatas = [d.metadata for d in documents]
        return await cls.afrom_texts(texts, metadatas=metadatas, **kwargs)

    def delete(self, ids: Optional[List[str]] = None, **kwargs: Any) -> None:
        """Delete by Zep vector UUIDs.

        Parameters
        ----------
        ids : Optional[List[str]]
            The UUIDs of the vectors to delete.

        Raises
        ------
        ValueError
            If no UUIDs are provided.
        """

        if ids is None or len(ids) == 0:
            raise ValueError("No uuids provided to delete.")

        if self._collection is None:
            raise ValueError("No collection name provided.")

        for u in ids:
            self._collection.delete_document(u)

Ancestors

  • langchain_core.vectorstores.VectorStore
  • abc.ABC

Static methods

async def afrom_documents(documents: List[Document], **kwargs: Any) ‑> ZepVectorStore

Asynchronously return VectorStore initialized from documents.

Expand source code
@classmethod
async def afrom_documents(  # type: ignore # ignore inconsistent override
    cls,
    documents: List[Document],
    **kwargs: Any,
) -> ZepVectorStore:
    """Asynchronously return VectorStore initialized from documents."""
    texts = [d.page_content for d in documents]
    metadatas = [d.metadata for d in documents]
    return await cls.afrom_texts(texts, metadatas=metadatas, **kwargs)
async def afrom_texts(texts: List[str], collection_name: str, metadatas: Optional[List[dict]] = None, description: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None, zep_client: Optional[ZepClient] = None, api_url: Optional[str] = 'https://api.getzep.com', api_key: Optional[str] = None, **kwargs: Any) ‑> ZepVectorStore

Class method that asynchronously returns a ZepVectorStore instance initialized from texts.

If the collection does not exist, it will be created.

Args

texts : List[str]
The list of texts to add to the vectorstore.
collection_name : str
The name of the collection in the Zep store.
metadatas : Optional[List[Dict[str, Any]]]
Optional list of metadata associated with the texts.
description : Optional[str]
The description of the collection.
metadata : Optional[Dict[str, Any]]
The metadata to associate with the collection.
zep_client : Optional[ZepClient]
The Zep client to use.
api_url : Optional[str]
The URL of the Zep API. Defaults to "https://api.getzep.com". Not required if passing in a ZepClient.
api_key : Optional[str]
The API key for the Zep API. Not required if passing in a ZepClient.
**kwargs
Additional parameters specific to the vectorstore.

Returns

ZepVectorStore
An instance of ZepVectorStore.
Expand source code
@classmethod
async def afrom_texts(  # type: ignore # ignore inconsistent override
    cls,
    texts: List[str],
    collection_name: str,
    metadatas: Optional[List[dict]] = None,
    description: Optional[str] = None,
    metadata: Optional[Dict[str, Any]] = None,
    zep_client: Optional[ZepClient] = None,
    api_url: Optional[str] = API_URL,
    api_key: Optional[str] = None,
    **kwargs: Any,
) -> ZepVectorStore:
    """
    Class method that asynchronously returns a ZepVectorStore instance
    initialized from texts.

    If the collection does not exist, it will be created.

    Args:
        texts (List[str]): The list of texts to add to the vectorstore.
        collection_name (str): The name of the collection in the Zep store.
        metadatas (Optional[List[Dict[str, Any]]]): Optional list of metadata
           associated with the texts.
        description (Optional[str]): The description of the collection.
        metadata (Optional[Dict[str, Any]]): The metadata to associate with the
            collection.
        zep_client (Optional[ZepClient]): The Zep client to use.
        api_url (Optional[str]): The URL of the Zep API. Defaults to
            "https://api.getzep.com". Not required if passing in a ZepClient.
        api_key (Optional[str]): The API key for the Zep API. Not required if
            passing in a ZepClient.
        **kwargs: Additional parameters specific to the vectorstore.

    Returns:
        ZepVectorStore: An instance of ZepVectorStore.
    """
    vecstore = cls(
        collection_name,
        description=description,
        metadata=metadata,
        zep_client=zep_client,
        api_url=api_url,
        api_key=api_key,
    )
    await vecstore.aadd_texts(texts, metadatas)
    return vecstore
def from_documents(documents: List[Document], **kwargs: Any) ‑> ZepVectorStore

Return VectorStore initialized from documents.

Expand source code
@classmethod
def from_documents(  # type: ignore # ignore inconsistent override
    cls,
    documents: List[Document],
    **kwargs: Any,
) -> ZepVectorStore:
    """Return VectorStore initialized from documents."""
    texts = [d.page_content for d in documents]
    metadatas = [d.metadata for d in documents]
    return cls.from_texts(texts, metadatas=metadatas, **kwargs)
def from_texts(texts: List[str], collection_name: str, metadatas: Optional[List[dict]] = None, description: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None, zep_client: Optional[ZepClient] = None, api_url: Optional[str] = 'https://api.getzep.com', api_key: Optional[str] = None, **kwargs: Any) ‑> ZepVectorStore

Class method that returns a ZepVectorStore instance initialized from texts.

If the collection does not exist, it will be created.

Args

texts : List[str]
The list of texts to add to the vectorstore.
collection_name : str
The name of the collection in the Zep store.
metadatas : Optional[List[Dict[str, Any]]]
Optional list of metadata associated with the texts.
description : Optional[str]
The description of the collection.
metadata : Optional[Dict[str, Any]]
The metadata to associate with the collection.
zep_client : Optional[ZepClient]
The Zep client to use.
api_url : Optional[str]
The URL of the Zep API. Defaults to "https://api.getzep.com". Not required if passing in a ZepClient.
api_key : Optional[str]
The API key for the Zep API. Not required if passing in a ZepClient.
**kwargs
Additional parameters specific to the vectorstore.

Returns

ZepVectorStore
An instance of ZepVectorStore.
Expand source code
@classmethod
def from_texts(  # type: ignore # ignore inconsistent override
    cls,
    texts: List[str],
    collection_name: str,
    metadatas: Optional[List[dict]] = None,
    description: Optional[str] = None,
    metadata: Optional[Dict[str, Any]] = None,
    zep_client: Optional[ZepClient] = None,
    api_url: Optional[str] = API_URL,
    api_key: Optional[str] = None,
    **kwargs: Any,
) -> ZepVectorStore:
    """
    Class method that returns a ZepVectorStore instance initialized from texts.

    If the collection does not exist, it will be created.

    Args:
        texts (List[str]): The list of texts to add to the vectorstore.
        collection_name (str): The name of the collection in the Zep store.
        metadatas (Optional[List[Dict[str, Any]]]): Optional list of metadata
           associated with the texts.
        description (Optional[str]): The description of the collection.
        metadata (Optional[Dict[str, Any]]): The metadata to associate with the
            collection.
        zep_client (Optional[ZepClient]): The Zep client to use.
        api_url (Optional[str]): The URL of the Zep API. Defaults to
            "https://api.getzep.com". Not required if passing in a ZepClient.
        api_key (Optional[str]): The API key for the Zep API. Not required if
            passing in a ZepClient.
        **kwargs: Additional parameters specific to the vectorstore.

    Returns:
        ZepVectorStore: An instance of ZepVectorStore.
    """
    vecstore = cls(
        collection_name,
        description=description,
        metadata=metadata,
        zep_client=zep_client,
        api_url=api_url,
        api_key=api_key,
    )
    vecstore.add_texts(texts, metadatas)

    return vecstore

Methods

async def aadd_texts(self, texts: Iterable[str], metadatas: Optional[List[Dict[str, Any]]] = None, document_ids: Optional[List[str]] = None, **kwargs: Any) ‑> List[str]

Run more texts through the embeddings and add to the vectorstore.

Expand source code
async def aadd_texts(
    self,
    texts: Iterable[str],
    metadatas: Optional[List[Dict[str, Any]]] = None,  # langchain spelling
    document_ids: Optional[List[str]] = None,
    **kwargs: Any,
) -> List[str]:
    """Run more texts through the embeddings and add to the vectorstore."""
    if not self._collection:
        raise ValueError(
            "collection should be an instance of a Zep DocumentCollection"
        )

    documents = self._generate_documents_to_add(texts, metadatas, document_ids)
    uuids = await self._collection.aadd_documents(documents)

    return uuids
def add_texts(self, texts: Iterable[str], metadatas: Optional[List[Dict[str, Any]]] = None, document_ids: Optional[List[str]] = None, **kwargs: Any) ‑> List[str]

Run more texts through the embeddings and add to the vectorstore.

Args

texts
Iterable of strings to add to the vectorstore.
metadatas
Optional list of metadatas associated with the texts.
document_ids
Optional list of document ids associated with the texts.
kwargs
vectorstore specific parameters

Returns

List of ids from adding the texts into the vectorstore.

Expand source code
def add_texts(
    self,
    texts: Iterable[str],
    metadatas: Optional[List[Dict[str, Any]]] = None,  # langchain spelling
    document_ids: Optional[List[str]] = None,
    **kwargs: Any,
) -> List[str]:
    """Run more texts through the embeddings and add to the vectorstore.

    Args:
        texts: Iterable of strings to add to the vectorstore.
        metadatas: Optional list of metadatas associated with the texts.
        document_ids: Optional list of document ids associated with the texts.
        kwargs: vectorstore specific parameters

    Returns:
        List of ids from adding the texts into the vectorstore.
    """
    if not self._collection:
        raise ValueError(
            "collection should be an instance of a Zep DocumentCollection"
        )

    documents = self._generate_documents_to_add(texts, metadatas, document_ids)
    uuids = self._collection.add_documents(documents)

    return uuids

Return docs selected using the maximal marginal relevance reranking.

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
(Unsupported) 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.
metadata_filter
Optional, metadata to filter the resulting set of retrieved docs

Returns

List of Documents selected by maximal marginal relevance. NOTE: Zep automatically tunes the number of results returned by the search prior to reranking based on k. fetch_k is ignored.

Expand source code
async def amax_marginal_relevance_search(
    self,
    query: str,
    k: int = 4,
    fetch_k: int = 20,
    lambda_mult: float = 0.5,
    metadata_filter: Optional[Dict[str, Any]] = None,
    **kwargs: Any,
) -> List[Document]:
    """Return docs selected using the maximal marginal relevance reranking.

    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: (Unsupported) 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.
        metadata_filter: Optional, metadata to filter the resulting set of retrieved
            docs
    Returns:
        List of Documents selected by maximal marginal relevance.

    NOTE: Zep automatically tunes the number of results returned by the
    search prior to reranking based on `k`. `fetch_k` is ignored.
    """

    if not self._collection:
        raise ValueError(
            "collection should be an instance of a Zep DocumentCollection"
        )

    results = await self._collection.asearch(
        query,
        limit=k,
        metadata=metadata_filter,
        search_type="mmr",
        mmr_lambda=lambda_mult,
    )

    return [
        Document(page_content=d.content, metadata=d.metadata or {}) for d in results
    ]
async def asearch(self, query: str, search_type: str, metadata_filter: Optional[Dict[str, Any]] = None, k: int = 3, **kwargs: Any) ‑> List[langchain_core.documents.base.Document]

Return docs most similar to query using specified search type.

Expand source code
async def asearch(
    self,
    query: str,
    search_type: str,
    metadata_filter: Optional[Dict[str, Any]] = None,
    k: int = 3,
    **kwargs: Any,
) -> List[Document]:
    """Return docs most similar to query using specified search type."""
    if search_type == "similarity":
        return await self.asimilarity_search(
            query, k=k, metadata=metadata_filter, **kwargs
        )
    elif search_type == "mmr":
        return await self.amax_marginal_relevance_search(
            query, k=k, metadata_filter=metadata_filter, **kwargs
        )
    else:
        raise ValueError(
            f"search_type of {search_type} not allowed. Expected "
            "search_type to be 'similarity' or 'mmr'."
        )

Return docs most similar to query.

Expand source code
async def asimilarity_search(
    self,
    query: str,
    k: int = 4,
    metadata: Optional[Dict[str, Any]] = None,
    **kwargs: Any,
) -> List[Document]:
    """Return docs most similar to query."""

    results = await self.asimilarity_search_with_relevance_scores(
        query, k, metadata_filter=metadata, **kwargs
    )

    return [doc for doc, _ in results]
async def asimilarity_search_with_relevance_scores(self, query: str, k: int = 4, metadata_filter: Optional[Dict[str, Any]] = None, **kwargs: Any) ‑> List[Tuple[langchain_core.documents.base.Document, float]]

Return docs most similar to query.

Expand source code
async def asimilarity_search_with_relevance_scores(
    self,
    query: str,
    k: int = 4,
    metadata_filter: Optional[Dict[str, Any]] = None,
    **kwargs: Any,
) -> List[Tuple[Document, float]]:
    """Return docs most similar to query."""

    if not self._collection:
        raise ValueError(
            "collection should be an instance of a Zep DocumentCollection"
        )

    results = await self._collection.asearch(
        query, limit=k, metadata=metadata_filter, **kwargs
    )

    return [
        (
            Document(
                page_content=doc.content,
                metadata=doc.metadata or {},
            ),
            doc.score or 0.0,
        )
        for doc in results
    ]
def delete(self, ids: Optional[List[str]] = None, **kwargs: Any) ‑> None

Delete by Zep vector UUIDs.

Parameters

ids : Optional[List[str]]
The UUIDs of the vectors to delete.

Raises

ValueError
If no UUIDs are provided.
Expand source code
def delete(self, ids: Optional[List[str]] = None, **kwargs: Any) -> None:
    """Delete by Zep vector UUIDs.

    Parameters
    ----------
    ids : Optional[List[str]]
        The UUIDs of the vectors to delete.

    Raises
    ------
    ValueError
        If no UUIDs are provided.
    """

    if ids is None or len(ids) == 0:
        raise ValueError("No uuids provided to delete.")

    if self._collection is None:
        raise ValueError("No collection name provided.")

    for u in ids:
        self._collection.delete_document(u)

Return docs selected using the maximal marginal relevance reranking.

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
(Unsupported) 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.
metadata_filter
Optional, metadata to filter the resulting set of retrieved docs

Returns

List of Documents selected by maximal marginal relevance. NOTE: Zep automatically tunes the number of results returned by the search prior to reranking based on k. fetch_k is ignored.

Expand source code
def max_marginal_relevance_search(  # type: ignore # ignore inconsistent override
    self,
    query: str,
    k: int = 4,
    fetch_k: int = 20,
    lambda_mult: float = 0.5,
    metadata_filter: Optional[Dict[str, Any]] = None,
) -> List[Document]:
    """Return docs selected using the maximal marginal relevance reranking.

    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: (Unsupported) 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.
        metadata_filter: Optional, metadata to filter the resulting set of retrieved
            docs
    Returns:
        List of Documents selected by maximal marginal relevance.

    NOTE: Zep automatically tunes the number of results returned by the search prior
    to reranking based on `k`. `fetch_k` is ignored.
    """

    if not self._collection:
        raise ValueError(
            "collection should be an instance of a Zep DocumentCollection"
        )

    results = self._collection.search(
        query,
        limit=k,
        metadata=metadata_filter,
        search_type="mmr",
        mmr_lambda=lambda_mult,
    )

    return [
        Document(page_content=d.content, metadata=d.metadata or {}) for d in results
    ]
def search(self, query: str, search_type: str, metadata_filter: Optional[Dict[str, Any]] = None, k: int = 3, **kwargs: Any) ‑> List[langchain_core.documents.base.Document]

Return docs most similar to query using specified search type.

Expand source code
def search(
    self,
    query: str,
    search_type: str,
    metadata_filter: Optional[Dict[str, Any]] = None,
    k: int = 3,
    **kwargs: Any,
) -> List[Document]:
    """Return docs most similar to query using specified search type."""
    if search_type == "similarity":
        return self.similarity_search(
            query, k=k, metadata=metadata_filter, **kwargs
        )
    elif search_type == "mmr":
        return self.max_marginal_relevance_search(
            query, k=k, metadata_filter=metadata_filter, **kwargs
        )
    else:
        raise ValueError(
            f"search_type of {search_type} not allowed. Expected "
            "search_type to be 'similarity' or 'mmr'."
        )

Return docs most similar to query.

Expand source code
def similarity_search(
    self,
    query: str,
    k: int = 4,
    metadata: Optional[Dict[str, Any]] = None,
    **kwargs: Any,
) -> List[Document]:
    """Return docs most similar to query."""

    results = self._similarity_search_with_relevance_scores(
        query, k=k, metadata_filter=metadata, **kwargs
    )
    return [doc for doc, _ in results]
def similarity_search_with_score(self, query: str, k: int = 4, metadata: Optional[Dict[str, Any]] = None, **kwargs: Any) ‑> List[Tuple[langchain_core.documents.base.Document, float]]

Run similarity search with distance.

Expand source code
def similarity_search_with_score(
    self,
    query: str,
    k: int = 4,
    metadata: Optional[Dict[str, Any]] = None,
    **kwargs: Any,
) -> List[Tuple[Document, float]]:
    """Run similarity search with distance."""

    return self._similarity_search_with_relevance_scores(
        query, k=k, metadata_filter=metadata, **kwargs
    )