citadeldb-haystack 2.0.0__tar.gz → 2.2.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.
@@ -5,6 +5,7 @@
5
5
  *~
6
6
  .DS_Store
7
7
  site/public/
8
+ site/data/release.json
8
9
  site/static/wasm/*.wasm
9
10
  site/static/wasm/*.js
10
11
  /notes/
@@ -0,0 +1,132 @@
1
+ Metadata-Version: 2.5
2
+ Name: citadeldb-haystack
3
+ Version: 2.2.0
4
+ Summary: Haystack document store backed by Citadel: encrypted at rest, with deletes that destroy the key
5
+ Project-URL: Homepage, https://citadeldb.dev
6
+ Project-URL: Repository, https://github.com/yp3y5akh0v/citadel
7
+ Author: Yuriy Peysakhov
8
+ License-Expression: Apache-2.0
9
+ Keywords: document-store,encryption,haystack,rag,vector-store
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Database
14
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
+ Requires-Python: >=3.10
16
+ Requires-Dist: citadeldb<3,>=2.2
17
+ Requires-Dist: haystack-ai<4,>=2.9
18
+ Provides-Extra: test
19
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'test'
20
+ Requires-Dist: pytest>=8; extra == 'test'
21
+ Description-Content-Type: text/markdown
22
+
23
+ # citadeldb-haystack
24
+
25
+ A [Haystack](https://github.com/deepset-ai/haystack) `DocumentStore` backed by
26
+ [Citadel](https://citadeldb.dev). Encrypted at rest, embedded in your process, and deletes
27
+ that destroy the key, not just the row.
28
+
29
+ ```
30
+ pip install citadeldb-haystack sentence-transformers
31
+ ```
32
+
33
+ Requires `citadeldb>=2.2,<3` and `haystack-ai>=2.9,<4`. Set `CITADEL_KEY` before
34
+ running the example. The embedding model downloads on first use and runs locally.
35
+
36
+ ```python
37
+ from haystack import Document
38
+ from haystack.components.embedders import SentenceTransformersTextEmbedder
39
+ from haystack.utils import Secret
40
+ from citadeldb_haystack import CitadelDocumentStore
41
+
42
+ embedder = SentenceTransformersTextEmbedder(model="sentence-transformers/all-mpnet-base-v2")
43
+ store = CitadelDocumentStore(
44
+ "corpus.cdl",
45
+ Secret.from_env_var("CITADEL_KEY"),
46
+ embedder=embedder,
47
+ dim=768,
48
+ embedding_similarity_function="cosine",
49
+ )
50
+ store.write_documents([
51
+ Document(id="d1", content="The deployment failed because the disk was full.",
52
+ meta={"chapter": "intro"}),
53
+ ])
54
+ store.filter_documents({"field": "meta.chapter", "operator": "==", "value": "intro"})
55
+ ```
56
+
57
+ `dim` defaults to 768 and must match your embedding model.
58
+ `embedding_similarity_function` is `"cosine"` or `"dot_product"` and is persisted
59
+ with the store. It defaults to Haystack's `"dot_product"`; choose `"cosine"`
60
+ explicitly when that is what produced the supplied vectors.
61
+ Embedders exposing `model_id`, `model`, or `model_name` record that identity automatically,
62
+ in that order. For a custom component without any of those attributes, pass a stable
63
+ `model_id=` explicitly; Citadel refuses to guess from the Python class name.
64
+
65
+ ## Pipeline serialization
66
+
67
+ Use a Haystack environment-variable `Secret` for pipeline serialization. Literal
68
+ passphrases cannot be serialized:
69
+
70
+ ```python
71
+ CitadelDocumentStore(
72
+ "literal.cdl", "literal-passphrase", embedder=embedder, dim=768
73
+ ).to_dict()
74
+ # ValueError: Cannot serialize token-based secret.
75
+
76
+ CitadelDocumentStore(
77
+ "corpus.cdl", Secret.from_env_var("CITADEL_KEY"), embedder=embedder, dim=768,
78
+ embedding_similarity_function="cosine",
79
+ ).to_dict()
80
+ # {... "key": {"type": "env_var", "env_vars": ["CITADEL_KEY"], ...}}
81
+ ```
82
+
83
+ Use `Secret.from_env_var` for any store that goes into a saved pipeline.
84
+
85
+ ## Deletes destroy the key
86
+
87
+ Every document is sealed under its own key. Deleting destroys that key and removes the
88
+ row. Pre-erasure backups or snapshots containing keys, and exported plaintext, are outside
89
+ that erasure.
90
+
91
+ ```python
92
+ store.delete_documents(["d1"])
93
+ store.delete_all() # returns the number erased
94
+ ```
95
+
96
+ `DuplicatePolicy.NONE` is treated as `FAIL`: duplicate ids are rejected.
97
+
98
+ ## Retrieval
99
+
100
+ ```python
101
+ embedder.warm_up()
102
+ query_embedding = embedder.run(text="Why did the release break?")["embedding"]
103
+
104
+ store.embedding_retrieval(
105
+ query_embedding,
106
+ top_k=5,
107
+ filters={"field": "meta.chapter", "operator": "==", "value": "intro"},
108
+ scale_score=False,
109
+ return_embedding=False,
110
+ )
111
+ ```
112
+
113
+ Filters use Haystack's evaluator.
114
+ Top-level `AND` string equalities, including nested paths such as `meta.person.name`,
115
+ are passed to Citadel as payload filters. Other predicates filter ranked candidates; the
116
+ search window expands until `top_k` matches survive or the region is exhausted.
117
+
118
+ ## Notes
119
+
120
+ The store requires a Haystack text embedder. Documents that arrive without a vector are
121
+ embedded with it, while vectors already supplied by the pipeline are stored as-is. Pass the
122
+ same model to the pipeline and store so both paths remain in one vector space. The store warms
123
+ the embedder lazily before its first model call and includes its configuration in pipeline
124
+ serialization.
125
+
126
+ Citadel is embedded and one process owns the file. A path already open on this thread,
127
+ under the same passphrase, is shared, so this can sit on the same database as another
128
+ Citadel adapter; construct them on the same thread.
129
+
130
+ ## License
131
+
132
+ Apache-2.0
@@ -0,0 +1,110 @@
1
+ # citadeldb-haystack
2
+
3
+ A [Haystack](https://github.com/deepset-ai/haystack) `DocumentStore` backed by
4
+ [Citadel](https://citadeldb.dev). Encrypted at rest, embedded in your process, and deletes
5
+ that destroy the key, not just the row.
6
+
7
+ ```
8
+ pip install citadeldb-haystack sentence-transformers
9
+ ```
10
+
11
+ Requires `citadeldb>=2.2,<3` and `haystack-ai>=2.9,<4`. Set `CITADEL_KEY` before
12
+ running the example. The embedding model downloads on first use and runs locally.
13
+
14
+ ```python
15
+ from haystack import Document
16
+ from haystack.components.embedders import SentenceTransformersTextEmbedder
17
+ from haystack.utils import Secret
18
+ from citadeldb_haystack import CitadelDocumentStore
19
+
20
+ embedder = SentenceTransformersTextEmbedder(model="sentence-transformers/all-mpnet-base-v2")
21
+ store = CitadelDocumentStore(
22
+ "corpus.cdl",
23
+ Secret.from_env_var("CITADEL_KEY"),
24
+ embedder=embedder,
25
+ dim=768,
26
+ embedding_similarity_function="cosine",
27
+ )
28
+ store.write_documents([
29
+ Document(id="d1", content="The deployment failed because the disk was full.",
30
+ meta={"chapter": "intro"}),
31
+ ])
32
+ store.filter_documents({"field": "meta.chapter", "operator": "==", "value": "intro"})
33
+ ```
34
+
35
+ `dim` defaults to 768 and must match your embedding model.
36
+ `embedding_similarity_function` is `"cosine"` or `"dot_product"` and is persisted
37
+ with the store. It defaults to Haystack's `"dot_product"`; choose `"cosine"`
38
+ explicitly when that is what produced the supplied vectors.
39
+ Embedders exposing `model_id`, `model`, or `model_name` record that identity automatically,
40
+ in that order. For a custom component without any of those attributes, pass a stable
41
+ `model_id=` explicitly; Citadel refuses to guess from the Python class name.
42
+
43
+ ## Pipeline serialization
44
+
45
+ Use a Haystack environment-variable `Secret` for pipeline serialization. Literal
46
+ passphrases cannot be serialized:
47
+
48
+ ```python
49
+ CitadelDocumentStore(
50
+ "literal.cdl", "literal-passphrase", embedder=embedder, dim=768
51
+ ).to_dict()
52
+ # ValueError: Cannot serialize token-based secret.
53
+
54
+ CitadelDocumentStore(
55
+ "corpus.cdl", Secret.from_env_var("CITADEL_KEY"), embedder=embedder, dim=768,
56
+ embedding_similarity_function="cosine",
57
+ ).to_dict()
58
+ # {... "key": {"type": "env_var", "env_vars": ["CITADEL_KEY"], ...}}
59
+ ```
60
+
61
+ Use `Secret.from_env_var` for any store that goes into a saved pipeline.
62
+
63
+ ## Deletes destroy the key
64
+
65
+ Every document is sealed under its own key. Deleting destroys that key and removes the
66
+ row. Pre-erasure backups or snapshots containing keys, and exported plaintext, are outside
67
+ that erasure.
68
+
69
+ ```python
70
+ store.delete_documents(["d1"])
71
+ store.delete_all() # returns the number erased
72
+ ```
73
+
74
+ `DuplicatePolicy.NONE` is treated as `FAIL`: duplicate ids are rejected.
75
+
76
+ ## Retrieval
77
+
78
+ ```python
79
+ embedder.warm_up()
80
+ query_embedding = embedder.run(text="Why did the release break?")["embedding"]
81
+
82
+ store.embedding_retrieval(
83
+ query_embedding,
84
+ top_k=5,
85
+ filters={"field": "meta.chapter", "operator": "==", "value": "intro"},
86
+ scale_score=False,
87
+ return_embedding=False,
88
+ )
89
+ ```
90
+
91
+ Filters use Haystack's evaluator.
92
+ Top-level `AND` string equalities, including nested paths such as `meta.person.name`,
93
+ are passed to Citadel as payload filters. Other predicates filter ranked candidates; the
94
+ search window expands until `top_k` matches survive or the region is exhausted.
95
+
96
+ ## Notes
97
+
98
+ The store requires a Haystack text embedder. Documents that arrive without a vector are
99
+ embedded with it, while vectors already supplied by the pipeline are stored as-is. Pass the
100
+ same model to the pipeline and store so both paths remain in one vector space. The store warms
101
+ the embedder lazily before its first model call and includes its configuration in pipeline
102
+ serialization.
103
+
104
+ Citadel is embedded and one process owns the file. A path already open on this thread,
105
+ under the same passphrase, is shared, so this can sit on the same database as another
106
+ Citadel adapter; construct them on the same thread.
107
+
108
+ ## License
109
+
110
+ Apache-2.0
@@ -18,8 +18,8 @@ classifiers = [
18
18
  "Topic :: Database",
19
19
  "Topic :: Scientific/Engineering :: Artificial Intelligence",
20
20
  ]
21
- # The precomputed vector needs the `embedding` field added in citadeldb 2.0.
22
- dependencies = ["citadeldb>=2.0,<3", "haystack-ai>=2.9,<4"]
21
+ # Reads the expanded AtomHit scoring fields added in citadeldb 2.2.
22
+ dependencies = ["citadeldb>=2.2,<3", "haystack-ai>=2.9,<4"]
23
23
 
24
24
  [project.optional-dependencies]
25
25
  test = ["pytest>=8", "pytest-asyncio>=0.23"]