diff --git a/libs/core/langchain_core/indexing/base_index.py b/libs/core/langchain_core/indexing/base_index.py index 588c8c13536..d5597a2d5e0 100644 --- a/libs/core/langchain_core/indexing/base_index.py +++ b/libs/core/langchain_core/indexing/base_index.py @@ -18,6 +18,7 @@ from typing import ( from langchain_core._api import beta from langchain_core.documents.base import BaseMedia from langchain_core.indexing.base import DeleteResponse, UpsertResponse +from langchain_core.runnables import run_in_executor from langchain_core.utils import abatch_iterate, batch_iterate @@ -153,6 +154,12 @@ class BaseIndex(Generic[T]): .. versionadded:: 0.2.11 """ + return await run_in_executor( + None, + self.upsert, + items, + **kwargs, + ) @abc.abstractmethod def get_by_ids( @@ -169,31 +176,3 @@ class BaseIndex(Generic[T]): /, ) -> DeleteResponse: """Delete items by id.""" - - # Delete and get are part of the READ/WRITE interface. - # They do not take advantage of indexes on the content. - # However, all the indexers ARE assumed to have the capability to index - # on metadata if they implement the delete_by_query and get_by_query methods. - # @abc.abstractmethod - # def get_by_query( - # self, - # *, - # filter: Optional[Union[List[Dict[str, Any], Dict[str, Any]]]] = None, - # limit: Optional[int] = None, - # offset: Optional[int] = None, - # sort: Optional[Union[Sort, List[Sort]]] = None, - # **kwargs: Any, - # ) -> Iterable[T]: - # """Get items by query.""" - # - # @abc.abstractmethod - # def delete_by_query( - # self, - # *, - # filter: Optional[Union[List[Dict[str, Any], Dict[str, Any]]]] = None, - # limit: Optional[int] = None, - # offset: Optional[int] = None, - # sort: Optional[Union[Sort, List[Sort]]] = None, - # **kwargs: Any, - # ) -> Iterable[DeleteResponse]: - # """Delete items by query.""" diff --git a/libs/core/tests/unit_tests/example_selectors/test_similarity.py b/libs/core/tests/unit_tests/example_selectors/test_similarity.py index 2cd50ca8dd2..d9009f7bf1b 100644 --- a/libs/core/tests/unit_tests/example_selectors/test_similarity.py +++ b/libs/core/tests/unit_tests/example_selectors/test_similarity.py @@ -1,4 +1,4 @@ -from typing import Any, Iterable, List, Optional, cast +from typing import Any, Iterable, List, Optional, Sequence, cast from langchain_core.documents import Document from langchain_core.embeddings import Embeddings, FakeEmbeddings @@ -6,6 +6,7 @@ from langchain_core.example_selectors import ( MaxMarginalRelevanceExampleSelector, SemanticSimilarityExampleSelector, ) +from langchain_core.indexing.base import DeleteResponse from langchain_core.vectorstores import VectorStore @@ -31,6 +32,16 @@ class DummyVectorStore(VectorStore): self.metadatas.extend(metadatas) return ["dummy_id"] + def get_by_ids(self, ids: Sequence[str], /) -> List[Document]: + raise NotImplementedError() + + def delete_by_ids( + self, + ids: Sequence[str], + /, + ) -> DeleteResponse: + raise NotImplementedError() + def similarity_search( self, query: str, k: int = 4, **kwargs: Any ) -> List[Document]: diff --git a/libs/core/tests/unit_tests/indexing/test_indexing.py b/libs/core/tests/unit_tests/indexing/test_indexing.py index f56293c369a..ad0a0fc1240 100644 --- a/libs/core/tests/unit_tests/indexing/test_indexing.py +++ b/libs/core/tests/unit_tests/indexing/test_indexing.py @@ -6,7 +6,7 @@ from typing import ( Iterator, Sequence, ) -from unittest.mock import MagicMock, patch, AsyncMock +from unittest.mock import AsyncMock, MagicMock, patch import pytest import pytest_asyncio diff --git a/libs/core/tests/unit_tests/vectorstores/test_vectorstore.py b/libs/core/tests/unit_tests/vectorstores/test_vectorstore.py index dc4955e70a2..6c1c6e101b2 100644 --- a/libs/core/tests/unit_tests/vectorstores/test_vectorstore.py +++ b/libs/core/tests/unit_tests/vectorstores/test_vectorstore.py @@ -7,7 +7,7 @@ from typing_extensions import TypedDict from langchain_core.documents import Document from langchain_core.embeddings import Embeddings -from langchain_core.indexing.base import UpsertResponse +from langchain_core.indexing.base import DeleteResponse, UpsertResponse from langchain_core.vectorstores import VectorStore @@ -68,6 +68,18 @@ class CustomSyncVectorStore(VectorStore): def get_by_ids(self, ids: Sequence[str], /) -> List[Document]: return [self.store[id] for id in ids if id in self.store] + def delete_by_ids( + self, + ids: Sequence[str], + /, + ) -> DeleteResponse: + for id_ in ids: + self.store.pop(id_, None) + return { + "succeeded": ids, + "failed": [], + } + def from_texts( # type: ignore cls, texts: List[str],