faiss-haystack 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,146 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ volumes/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ .python-version
87
+
88
+ # pipenv
89
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
90
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
91
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
92
+ # install all needed dependencies.
93
+ #Pipfile.lock
94
+
95
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
96
+ __pypackages__/
97
+
98
+ # Celery stuff
99
+ celerybeat-schedule
100
+ celerybeat.pid
101
+
102
+ # SageMath parsed files
103
+ *.sage.py
104
+
105
+ # Environments
106
+ .env
107
+ .venv
108
+ env/
109
+ venv/
110
+ ENV/
111
+ env.bak/
112
+ venv.bak/
113
+
114
+ # Spyder project settings
115
+ .spyderproject
116
+ .spyproject
117
+
118
+ # Rope project settings
119
+ .ropeproject
120
+
121
+ # mkdocs documentation
122
+ /site
123
+
124
+ # mypy
125
+ .mypy_cache/
126
+ .dmypy.json
127
+ dmypy.json
128
+
129
+ # Pyre type checker
130
+ .pyre/
131
+
132
+ # IDEs
133
+ .vscode
134
+
135
+ # Docs generation artifacts
136
+ _readme_*.md
137
+ .idea
138
+
139
+ # macOS
140
+ .DS_Store
141
+
142
+ # http cache (requests-cache)
143
+ **/http_cache.sqlite
144
+
145
+ # ruff
146
+ .ruff_cache
@@ -0,0 +1,39 @@
1
+ Metadata-Version: 2.4
2
+ Name: faiss-haystack
3
+ Version: 1.0.0
4
+ Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/faiss#readme
5
+ Project-URL: Issues, https://github.com/deepset-ai/haystack-core-integrations/issues
6
+ Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/faiss
7
+ Author-email: Deepset <info@deepset.ai>
8
+ License-Expression: Apache-2.0
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: Implementation :: CPython
16
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: faiss-cpu>=1.8.0
19
+ Requires-Dist: haystack-ai>=2.24.0
20
+ Requires-Dist: numpy<2,>=1.22; python_version < '3.13'
21
+ Description-Content-Type: text/markdown
22
+
23
+ # faiss-haystack
24
+
25
+ This package provides a [FAISS](https://github.com/facebookresearch/faiss) document store for [Haystack](https://github.com/deepset-ai/haystack).
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ pip install faiss-haystack
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ```python
36
+ from haystack_integrations.document_stores.faiss import FAISSDocumentStore
37
+
38
+ document_store = FAISSDocumentStore(index_path="my_index")
39
+ ```
@@ -0,0 +1,17 @@
1
+ # faiss-haystack
2
+
3
+ This package provides a [FAISS](https://github.com/facebookresearch/faiss) document store for [Haystack](https://github.com/deepset-ai/haystack).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install faiss-haystack
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```python
14
+ from haystack_integrations.document_stores.faiss import FAISSDocumentStore
15
+
16
+ document_store = FAISSDocumentStore(index_path="my_index")
17
+ ```
@@ -0,0 +1,14 @@
1
+ loaders:
2
+ - modules:
3
+ - haystack_integrations.components.retrievers.faiss.embedding_retriever
4
+ - haystack_integrations.document_stores.faiss.document_store
5
+ search_path: [../src]
6
+ processors:
7
+ - type: filter
8
+ documented_only: true
9
+ skip_empty_modules: true
10
+ renderer:
11
+ description: FAISS integration for Haystack
12
+ id: integrations-faiss
13
+ filename: faiss.md
14
+ title: FAISS
@@ -0,0 +1,159 @@
1
+ [build-system]
2
+ requires = ["hatchling", "hatch-vcs"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "faiss-haystack"
7
+ dynamic = ["version"]
8
+ description = ''
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "Apache-2.0"
12
+ keywords = []
13
+ authors = [{ name = "Deepset", email = "info@deepset.ai" }]
14
+ classifiers = [
15
+ "License :: OSI Approved :: Apache Software License",
16
+ "Development Status :: 4 - Beta",
17
+ "Programming Language :: Python",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: Implementation :: CPython",
22
+ "Programming Language :: Python :: Implementation :: PyPy",
23
+ ]
24
+ dependencies = [
25
+ "haystack-ai>=2.24.0",
26
+ "faiss-cpu>=1.8.0",
27
+ "numpy>=1.22,<2; python_version < '3.13'",
28
+ ]
29
+
30
+ [project.urls]
31
+ Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/faiss#readme"
32
+ Issues = "https://github.com/deepset-ai/haystack-core-integrations/issues"
33
+ Source = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/faiss"
34
+
35
+ [tool.hatch.build.targets.wheel]
36
+ packages = ["src/haystack_integrations"]
37
+
38
+ [tool.hatch.version]
39
+ source = "vcs"
40
+ tag-pattern = 'integrations\/faiss-v(?P<version>.*)'
41
+
42
+ [tool.hatch.version.raw-options]
43
+ root = "../.."
44
+ git_describe_command = 'git describe --tags --match="integrations/faiss-v[0-9]*"'
45
+
46
+ [tool.hatch.envs.default]
47
+ installer = "uv"
48
+ dependencies = ["haystack-pydoc-tools", "ruff"]
49
+
50
+ [tool.hatch.envs.default.scripts]
51
+ docs = ["pydoc-markdown pydoc/config_docusaurus.yml"]
52
+ fmt = "ruff check --fix {args}; ruff format {args}"
53
+ fmt-check = "ruff check {args} && ruff format --check {args}"
54
+
55
+ [tool.hatch.envs.test]
56
+ dependencies = [
57
+ "pytest",
58
+ "pytest-cov",
59
+ "pytest-rerunfailures",
60
+ "mypy",
61
+ "pandas",
62
+ ]
63
+
64
+ [tool.hatch.envs.test.scripts]
65
+ unit = 'pytest -m "not integration" {args:tests}'
66
+ integration = 'pytest -m "integration" {args:tests}'
67
+ all = 'pytest {args:tests}'
68
+ cov-retry = 'pytest --cov=haystack_integrations --reruns 3 --reruns-delay 30 -x {args:tests}'
69
+
70
+ types = "mypy -p haystack_integrations.document_stores.faiss -p haystack_integrations.components.retrievers.faiss {args}"
71
+
72
+ [tool.mypy]
73
+ install_types = true
74
+ non_interactive = true
75
+ check_untyped_defs = true
76
+ disallow_incomplete_defs = true
77
+
78
+ [tool.hatch.metadata]
79
+ allow-direct-references = true
80
+
81
+ [tool.ruff]
82
+ line-length = 120
83
+
84
+ [tool.ruff.lint]
85
+ select = [
86
+ "A",
87
+ "ARG",
88
+ "B",
89
+ "C",
90
+ "DTZ",
91
+ "E",
92
+ "EM",
93
+ "F",
94
+ "FBT",
95
+ "I",
96
+ "ICN",
97
+ "ISC",
98
+ "N",
99
+ "PLC",
100
+ "PLE",
101
+ "PLR",
102
+ "PLW",
103
+ "Q",
104
+ "RUF",
105
+ "S",
106
+ "T",
107
+ "TID",
108
+ "UP",
109
+ "W",
110
+ "YTT",
111
+ ]
112
+ ignore = [
113
+ # Allow non-abstract empty methods in abstract base classes
114
+ "B027",
115
+ # Allow boolean positional values in function calls, like `dict.get(... True)`
116
+ "FBT003",
117
+ # Ignore checks for possible passwords
118
+ "S105",
119
+ "S106",
120
+ "S107",
121
+ # Ignore complexity
122
+ "C901",
123
+ "PLR0911",
124
+ "PLR0912",
125
+ "PLR0913",
126
+ "PLR0915",
127
+ # Ignore unused params
128
+ "ARG002",
129
+ # Allow assertions
130
+ "S101",
131
+ ]
132
+ exclude = ["example"]
133
+
134
+ [tool.ruff.lint.isort]
135
+ known-first-party = ["haystack_integrations"]
136
+
137
+ [tool.ruff.lint.flake8-tidy-imports]
138
+ ban-relative-imports = "parents"
139
+
140
+ [tool.ruff.lint.per-file-ignores]
141
+ # Tests can use magic values, assertions, and relative imports
142
+ "tests/**/*" = ["PLR2004", "S101", "TID252"]
143
+ "example/**/*" = ["T201"]
144
+
145
+ [tool.coverage.run]
146
+ source = ["haystack_integrations"]
147
+ branch = true
148
+ parallel = false
149
+
150
+
151
+ [tool.coverage.report]
152
+ omit = ["*/tests/*", "*/__init__.py"]
153
+ show_missing = true
154
+ exclude_lines = ["no cov", "if __name__ == .__main__.:", "if TYPE_CHECKING:"]
155
+
156
+
157
+ [tool.pytest.ini_options]
158
+ minversion = "6.0"
159
+ markers = ["integration: integration tests"]
@@ -0,0 +1,3 @@
1
+ # SPDX-FileCopyrightText: 2023-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
@@ -0,0 +1,3 @@
1
+ # SPDX-FileCopyrightText: 2023-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
@@ -0,0 +1,6 @@
1
+ # SPDX-FileCopyrightText: 2023-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ from .embedding_retriever import FAISSEmbeddingRetriever
5
+
6
+ __all__ = ["FAISSEmbeddingRetriever"]
@@ -0,0 +1,153 @@
1
+ # SPDX-FileCopyrightText: 2023-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from typing import Any
6
+
7
+ from haystack import component, default_from_dict, default_to_dict
8
+ from haystack.dataclasses import Document
9
+ from haystack.document_stores.types import FilterPolicy
10
+ from haystack.document_stores.types.filter_policy import apply_filter_policy
11
+
12
+ from haystack_integrations.document_stores.faiss import FAISSDocumentStore
13
+
14
+
15
+ @component
16
+ class FAISSEmbeddingRetriever:
17
+ """
18
+ Retrieves documents from the `FAISSDocumentStore`, based on their dense embeddings.
19
+
20
+ Example usage:
21
+ ```python
22
+ from haystack import Document, Pipeline
23
+ from haystack.components.embedders import SentenceTransformersTextEmbedder, SentenceTransformersDocumentEmbedder
24
+ from haystack.document_stores.types import DuplicatePolicy
25
+
26
+ from haystack_integrations.document_stores.faiss import FAISSDocumentStore
27
+ from haystack_integrations.components.retrievers.faiss import FAISSEmbeddingRetriever
28
+
29
+ document_store = FAISSDocumentStore(embedding_dim=768)
30
+
31
+ documents = [
32
+ Document(content="There are over 7,000 languages spoken around the world today."),
33
+ Document(content="Elephants have been observed to behave in a way that indicates a high level of intelligence."),
34
+ Document(content="In certain places, you can witness the phenomenon of bioluminescent waves."),
35
+ ]
36
+
37
+ document_embedder = SentenceTransformersDocumentEmbedder()
38
+ document_embedder.warm_up()
39
+ documents_with_embeddings = document_embedder.run(documents)["documents"]
40
+
41
+ document_store.write_documents(documents_with_embeddings, policy=DuplicatePolicy.OVERWRITE)
42
+
43
+ query_pipeline = Pipeline()
44
+ query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder())
45
+ query_pipeline.add_component("retriever", FAISSEmbeddingRetriever(document_store=document_store))
46
+ query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
47
+
48
+ query = "How many languages are there?"
49
+ res = query_pipeline.run({"text_embedder": {"text": query}})
50
+
51
+ assert res["retriever"]["documents"][0].content == "There are over 7,000 languages spoken around the world today."
52
+ ```
53
+ """ # noqa: E501
54
+
55
+ def __init__(
56
+ self,
57
+ *,
58
+ document_store: FAISSDocumentStore,
59
+ filters: dict[str, Any] | None = None,
60
+ top_k: int = 10,
61
+ filter_policy: str | FilterPolicy = FilterPolicy.REPLACE,
62
+ ):
63
+ """
64
+ :param document_store: An instance of `FAISSDocumentStore`.
65
+ :param filters: Filters applied to the retrieved Documents at initialisation time. At runtime, these are merged
66
+ with any runtime filters according to the `filter_policy`.
67
+ :param top_k: Maximum number of Documents to return.
68
+ :param filter_policy: Policy to determine how init-time and runtime filters are combined.
69
+ See `FilterPolicy` for details. Defaults to `FilterPolicy.REPLACE`.
70
+ :raises ValueError: If `document_store` is not an instance of `FAISSDocumentStore`.
71
+ """
72
+ if not isinstance(document_store, FAISSDocumentStore):
73
+ msg = "document_store must be an instance of FAISSDocumentStore"
74
+ raise ValueError(msg)
75
+
76
+ self.document_store = document_store
77
+ self.filters = filters or {}
78
+ self.top_k = top_k
79
+ self.filter_policy = (
80
+ filter_policy if isinstance(filter_policy, FilterPolicy) else FilterPolicy.from_str(filter_policy)
81
+ )
82
+
83
+ def to_dict(self) -> dict[str, Any]:
84
+ """
85
+ Serializes the component to a dictionary.
86
+
87
+ :returns: Dictionary with serialized data.
88
+ """
89
+ return default_to_dict(
90
+ self,
91
+ filters=self.filters,
92
+ top_k=self.top_k,
93
+ filter_policy=self.filter_policy.value,
94
+ document_store=self.document_store.to_dict(),
95
+ )
96
+
97
+ @classmethod
98
+ def from_dict(cls, data: dict[str, Any]) -> "FAISSEmbeddingRetriever":
99
+ """
100
+ Deserializes the component from a dictionary.
101
+
102
+ :param data: Dictionary to deserialize from.
103
+ :returns: Deserialized component.
104
+ """
105
+ doc_store_params = data["init_parameters"]["document_store"]
106
+ data["init_parameters"]["document_store"] = FAISSDocumentStore.from_dict(doc_store_params)
107
+ return default_from_dict(cls, data)
108
+
109
+ @component.output_types(documents=list[Document])
110
+ def run(
111
+ self,
112
+ query_embedding: list[float],
113
+ filters: dict[str, Any] | None = None,
114
+ top_k: int | None = None,
115
+ ) -> dict[str, list[Document]]:
116
+ """
117
+ Retrieve documents from the `FAISSDocumentStore`, based on their embeddings.
118
+
119
+ :param query_embedding: Embedding of the query.
120
+ :param filters: Filters applied to the retrieved Documents. The way runtime filters are applied depends on
121
+ the `filter_policy` chosen at retriever initialization. See init method docstring for more
122
+ details.
123
+ :param top_k: Maximum number of Documents to return. Overrides the value set at initialization.
124
+ :returns: A dictionary with the following keys:
125
+ - `documents`: List of `Document`s that are similar to `query_embedding`.
126
+ """
127
+ filters = apply_filter_policy(self.filter_policy, self.filters, filters)
128
+ top_k = top_k or self.top_k
129
+ docs = self.document_store.search(query_embedding=query_embedding, top_k=top_k, filters=filters)
130
+ return {"documents": docs}
131
+
132
+ @component.output_types(documents=list[Document])
133
+ async def run_async(
134
+ self,
135
+ query_embedding: list[float],
136
+ filters: dict[str, Any] | None = None,
137
+ top_k: int | None = None,
138
+ ) -> dict[str, list[Document]]:
139
+ """
140
+ Asynchronously retrieve documents from the `FAISSDocumentStore`, based on their embeddings.
141
+
142
+ Since FAISS search is CPU-bound and fully in-memory, this delegates directly to the synchronous
143
+ `run()` method. No I/O or network calls are involved.
144
+
145
+ :param query_embedding: Embedding of the query.
146
+ :param filters: Filters applied to the retrieved Documents. The way runtime filters are applied depends on
147
+ the `filter_policy` chosen at retriever initialization. See init method docstring for more
148
+ details.
149
+ :param top_k: Maximum number of Documents to return. Overrides the value set at initialization.
150
+ :returns: A dictionary with the following keys:
151
+ - `documents`: List of `Document`s that are similar to `query_embedding`.
152
+ """
153
+ return self.run(query_embedding=query_embedding, filters=filters, top_k=top_k)
@@ -0,0 +1,3 @@
1
+ from .document_store import FAISSDocumentStore
2
+
3
+ __all__ = ["FAISSDocumentStore"]