-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support for different MetadataStores in VectorStore (#144)
Co-authored-by: Michał Pstrąg <[email protected]>
- Loading branch information
1 parent
a60cdfe
commit c1c019f
Showing
14 changed files
with
255 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
packages/ragbits-core/src/ragbits/core/metadata_stores/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import sys | ||
|
||
from ragbits.core.utils.config_handling import get_cls_from_config | ||
|
||
from .base import MetadataStore | ||
from .in_memory import InMemoryMetadataStore | ||
|
||
__all__ = ["InMemoryMetadataStore", "MetadataStore"] | ||
|
||
module = sys.modules[__name__] | ||
|
||
|
||
def get_metadata_store(metadata_store_config: dict | None) -> MetadataStore | None: | ||
""" | ||
Initializes and returns a MetadataStore object based on the provided configuration. | ||
Args: | ||
metadata_store_config: A dictionary containing configuration details for the MetadataStore. | ||
Returns: | ||
An instance of the specified MetadataStore class, initialized with the provided config | ||
(if any) or default arguments. | ||
""" | ||
if metadata_store_config is None: | ||
return None | ||
|
||
metadata_store_class = get_cls_from_config(metadata_store_config["type"], module) | ||
config = metadata_store_config.get("config", {}) | ||
|
||
return metadata_store_class(**config) |
32 changes: 32 additions & 0 deletions
32
packages/ragbits-core/src/ragbits/core/metadata_stores/base.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
|
||
class MetadataStore(ABC): | ||
""" | ||
An abstract class for metadata storage. Allows to store, query and retrieve metadata in form of key value pairs. | ||
""" | ||
|
||
@abstractmethod | ||
async def store(self, ids: list[str], metadatas: list[dict]) -> None: | ||
""" | ||
Store metadatas under ids in metadata store. | ||
Args: | ||
ids: list of unique ids of the entries | ||
metadatas: list of dicts with metadata. | ||
""" | ||
|
||
@abstractmethod | ||
async def get(self, ids: list[str]) -> list[dict]: | ||
""" | ||
Returns metadatas associated with a given ids. | ||
Args: | ||
ids: list of ids to use. | ||
Returns: | ||
List of metadata dicts associated with a given ids. | ||
Raises: | ||
MetadataNotFoundError: If the metadata is not found. | ||
""" |
8 changes: 8 additions & 0 deletions
8
packages/ragbits-core/src/ragbits/core/metadata_stores/exceptions.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class MetadataNotFoundError(Exception): | ||
""" | ||
Raised when metadata is not found in the metadata store | ||
""" | ||
|
||
def __init__(self, id: str) -> None: | ||
super().__init__(f"Metadata not found for {id} id.") | ||
self.id = id |
43 changes: 43 additions & 0 deletions
43
packages/ragbits-core/src/ragbits/core/metadata_stores/in_memory.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from ragbits.core.metadata_stores.base import MetadataStore | ||
from ragbits.core.metadata_stores.exceptions import MetadataNotFoundError | ||
|
||
|
||
class InMemoryMetadataStore(MetadataStore): | ||
""" | ||
Metadata Store implemented in memory | ||
""" | ||
|
||
def __init__(self) -> None: | ||
""" | ||
Constructs a new InMemoryMetadataStore instance. | ||
""" | ||
self._storage: dict[str, dict] = {} | ||
|
||
async def store(self, ids: list[str], metadatas: list[dict]) -> None: | ||
""" | ||
Store metadatas under ids in metadata store. | ||
Args: | ||
ids: list of unique ids of the entries | ||
metadatas: list of dicts with metadata. | ||
""" | ||
for _id, metadata in zip(ids, metadatas, strict=False): | ||
self._storage[_id] = metadata | ||
|
||
async def get(self, ids: list[str]) -> list[dict]: | ||
""" | ||
Returns metadatas associated with a given ids. | ||
Args: | ||
ids: list of ids to use. | ||
Returns: | ||
List of metadata dicts associated with a given ids. | ||
Raises: | ||
MetadataNotFoundError: If the metadata is not found. | ||
""" | ||
try: | ||
return [self._storage[_id] for _id in ids] | ||
except KeyError as exc: | ||
raise MetadataNotFoundError(*exc.args) from exc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
31 changes: 31 additions & 0 deletions
31
packages/ragbits-core/tests/unit/metadata_stores/test_in_memory.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import pytest | ||
|
||
from ragbits.core.metadata_stores.exceptions import MetadataNotFoundError | ||
from ragbits.core.metadata_stores.in_memory import InMemoryMetadataStore | ||
|
||
|
||
@pytest.fixture | ||
def metadata_store() -> InMemoryMetadataStore: | ||
return InMemoryMetadataStore() | ||
|
||
|
||
async def test_store(metadata_store: InMemoryMetadataStore) -> None: | ||
ids = ["id1", "id2"] | ||
metadatas = [{"key1": "value1"}, {"key2": "value2"}] | ||
await metadata_store.store(ids, metadatas) | ||
assert metadata_store._storage["id1"] == {"key1": "value1"} | ||
assert metadata_store._storage["id2"] == {"key2": "value2"} | ||
|
||
|
||
async def test_get(metadata_store: InMemoryMetadataStore) -> None: | ||
ids = ["id1", "id2"] | ||
metadatas = [{"key1": "value1"}, {"key2": "value2"}] | ||
await metadata_store.store(ids, metadatas) | ||
result = await metadata_store.get(ids) | ||
assert result == [{"key1": "value1"}, {"key2": "value2"}] | ||
|
||
|
||
async def test_get_metadata_not_found(metadata_store: InMemoryMetadataStore) -> None: | ||
ids = ["id1"] | ||
with pytest.raises(MetadataNotFoundError): | ||
await metadata_store.get(ids) |
Empty file.
Oops, something went wrong.