1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//! Embedding-similarity vector store abstraction.
//!
//! [`VectorStore`] is the trait for K-nearest-neighbour lookup used by the
//! semantic cache tier. Callers embed a prompt with an [`EmbeddingProvider`]
//! and then query the store to find a previously cached response whose
//! prompt is sufficiently similar to the current one.
//!
//! # Built-in implementations
//!
//! | Type | Description |
//! |---|---|
//! | [`InMemoryVectorStore`] | Brute-force cosine similarity over a `DashMap`. Suitable for ≤10 k entries. |
//! | [`OpenDalVectorStore`] | Persists vectors as JSON entries via any OpenDAL backend (gated on `opendal-cache`). |
pub use InMemoryVectorStore;
pub use OpenDalVectorStore;
use HashMap;
use Future;
use Pin;
use SystemTime;
use crateResult;
use crate;
/// Metadata stored alongside each vector entry.
/// Return `true` if an entry carrying `entry_tenant` is visible to a query
/// scoped to `query_tenant`.
///
/// ~keep The rule is plain equality, including the `None` case: a tenant-less
/// ~keep query only matches tenant-less entries, and a tenant-scoped query only
/// ~keep matches that exact tenant. "`None` matches everything" was
/// ~keep deliberately rejected — it would re-open the cross-tenant leak this
/// ~keep filter exists to close, since any request that happened to omit a
/// ~keep tenant would then see every other tenant's entries.
pub
/// A single result returned by [`VectorStore::search`].
/// Pluggable vector store for the semantic cache tier.
///
/// All methods return pinned boxed futures so the trait is object-safe and can
/// be stored behind `Arc<dyn VectorStore>`.
///
/// # Implementing `VectorStore`
///
/// ```rust,ignore
/// use liter_llm::vectorstore::{VectorStore, VectorMatch, VectorMetadata};
/// use liter_llm::error::Result;
/// use std::future::Future;
/// use std::pin::Pin;
///
/// struct MyVectorStore;
///
/// impl VectorStore for MyVectorStore {
/// fn search<'a>(
/// &'a self,
/// query_vec: &'a [f32],
/// k: usize,
/// threshold: f32,
/// tenant_id: Option<&'a str>,
/// ) -> Pin<Box<dyn Future<Output = Vec<VectorMatch>> + Send + 'a>> {
/// Box::pin(async move { Vec::new() })
/// }
///
/// fn upsert<'a>(
/// &'a self,
/// id: String,
/// vec: Vec<f32>,
/// metadata: VectorMetadata,
/// ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
/// Box::pin(async move { Ok(()) })
/// }
///
/// fn delete<'a>(
/// &'a self,
/// id: &'a str,
/// ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
/// Box::pin(async move { Ok(()) })
/// }
///
/// fn dim(&self) -> usize { 1536 }
/// }
/// ```