pub struct SemanticMemory<E, V>where
E: Embedder,
V: VectorStore,{ /* private fields */ }Expand description
Embedder + VectorStore + Namespace bundle.
The embedder produces vectors at add and search time; the vector
store holds them. Both must agree on dimension() — checked at
construction.
Implementations§
Source§impl<E, V> SemanticMemory<E, V>where
E: Embedder,
V: VectorStore,
impl<E, V> SemanticMemory<E, V>where
E: Embedder,
V: VectorStore,
Sourcepub fn new(
embedder: Arc<E>,
vector_store: Arc<V>,
namespace: Namespace,
) -> Result<Self>
pub fn new( embedder: Arc<E>, vector_store: Arc<V>, namespace: Namespace, ) -> Result<Self>
Construct from owned components, validating dimension parity.
Returns Error::Config if the embedder and vector store report
different dimensions.
Sourcepub async fn add(
&self,
ctx: &ExecutionContext,
document: Document,
) -> Result<()>
pub async fn add( &self, ctx: &ExecutionContext, document: Document, ) -> Result<()>
Embed document.content and add it to the vector store.
The embedder’s usage metadata (when surfaced) is dropped here —
callers that need to charge cost meters per-embed should use
the embedder directly and then call
VectorStore::add.
Sourcepub async fn add_batch(
&self,
ctx: &ExecutionContext,
documents: Vec<Document>,
) -> Result<()>
pub async fn add_batch( &self, ctx: &ExecutionContext, documents: Vec<Document>, ) -> Result<()>
Add many documents at once — uses Embedder::embed_batch to
amortise embedder calls then VectorStore::add_batch to
amortise index writes.
Returns Error::Config if the embedder produces a vector
count that doesn’t match the input documents — silent
truncation via zip would drop documents without surfacing
the embedder bug.
Sourcepub async fn delete(&self, ctx: &ExecutionContext, doc_id: &str) -> Result<()>
pub async fn delete(&self, ctx: &ExecutionContext, doc_id: &str) -> Result<()>
Delete a previously-indexed document by id.
Sourcepub async fn update(
&self,
ctx: &ExecutionContext,
doc_id: &str,
document: Document,
) -> Result<()>
pub async fn update( &self, ctx: &ExecutionContext, doc_id: &str, document: Document, ) -> Result<()>
Update a previously-indexed document. Re-embeds the document’s content via the embedder and asks the vector store to swap vector + metadata under the same id.
Sourcepub async fn search(
&self,
ctx: &ExecutionContext,
query: &str,
top_k: usize,
) -> Result<Vec<Document>>
pub async fn search( &self, ctx: &ExecutionContext, query: &str, top_k: usize, ) -> Result<Vec<Document>>
Embed query and search the vector store for the top top_k
matches.
Sourcepub async fn search_filtered(
&self,
ctx: &ExecutionContext,
query: &str,
top_k: usize,
filter: &VectorFilter,
) -> Result<Vec<Document>>
pub async fn search_filtered( &self, ctx: &ExecutionContext, query: &str, top_k: usize, filter: &VectorFilter, ) -> Result<Vec<Document>>
Embed query and search with a metadata filter. Backends
without filter support return Error::Config per the
VectorStore::search_filtered contract.
Sourcepub async fn search_with_rerank<R: Reranker>(
&self,
ctx: &ExecutionContext,
query: &str,
top_k: usize,
candidates: usize,
reranker: &R,
) -> Result<Vec<RerankedDocument>>
pub async fn search_with_rerank<R: Reranker>( &self, ctx: &ExecutionContext, query: &str, top_k: usize, candidates: usize, reranker: &R, ) -> Result<Vec<RerankedDocument>>
Two-stage retrieval: over-fetch candidates from the vector
store, then rerank down to top_k via the supplied
Reranker. The over-fetch factor is the operator’s lever
for trading recall against rerank latency — passing
candidates == top_k makes the reranker no-op-shaped, while
candidates >> top_k exposes more candidates to the
reranker’s scoring. Returns RerankedDocuments so callers
retain both the retrieval and rerank scores for explainability.
Sourcepub async fn count(
&self,
ctx: &ExecutionContext,
filter: Option<&VectorFilter>,
) -> Result<usize>
pub async fn count( &self, ctx: &ExecutionContext, filter: Option<&VectorFilter>, ) -> Result<usize>
Count documents in the bound namespace. Pass-through to
VectorStore::count — backends without count support
surface Error::Config.
Sourcepub async fn list(
&self,
ctx: &ExecutionContext,
filter: Option<&VectorFilter>,
limit: usize,
offset: usize,
) -> Result<Vec<Document>>
pub async fn list( &self, ctx: &ExecutionContext, filter: Option<&VectorFilter>, limit: usize, offset: usize, ) -> Result<Vec<Document>>
Enumerate documents in the bound namespace. Pass-through to
VectorStore::list — backends without enumeration
support surface Error::Config.
Trait Implementations§
Source§impl<E, V> SemanticMemoryBackend for SemanticMemory<E, V>where
E: Embedder,
V: VectorStore,
impl<E, V> SemanticMemoryBackend for SemanticMemory<E, V>where
E: Embedder,
V: VectorStore,
Source§fn namespace(&self) -> &Namespace
fn namespace(&self) -> &Namespace
Namespace. Tools and orchestration code
that route queries by tenant or scope read this to validate
the backend is wired to the expected slice without downcasting
to the concrete generic type.Source§fn dimension(&self) -> usize
fn dimension(&self) -> usize
Source§fn search<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
query: &'life2 str,
top_k: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<Document>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn search<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
query: &'life2 str,
top_k: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<Document>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
query and return the top top_k matches.Source§fn search_filtered<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
query: &'life2 str,
top_k: usize,
filter: &'life3 VectorFilter,
) -> Pin<Box<dyn Future<Output = Result<Vec<Document>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn search_filtered<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
query: &'life2 str,
top_k: usize,
filter: &'life3 VectorFilter,
) -> Pin<Box<dyn Future<Output = Result<Vec<Document>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
query, fetch candidates, push down filter if the
backend supports it; otherwise the underlying VectorStore
returns Error::Config.Source§fn add<'life0, 'life1, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
document: Document,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn add<'life0, 'life1, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
document: Document,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
document.content and add the document to the index.Source§fn add_batch<'life0, 'life1, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
documents: Vec<Document>,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn add_batch<'life0, 'life1, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
documents: Vec<Document>,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn delete<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
doc_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn delete<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
doc_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn update<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
doc_id: &'life2 str,
document: Document,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn update<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
doc_id: &'life2 str,
document: Document,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn search_with_rerank_dyn<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
query: &'life2 str,
top_k: usize,
candidates: usize,
reranker: &'life3 dyn Reranker,
) -> Pin<Box<dyn Future<Output = Result<Vec<RerankedDocument>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn search_with_rerank_dyn<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
query: &'life2 str,
top_k: usize,
candidates: usize,
reranker: &'life3 dyn Reranker,
) -> Pin<Box<dyn Future<Output = Result<Vec<RerankedDocument>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
candidates then rerank
down to top_k. The reranker is supplied as a trait object
so the backend trait stays object-safe (the concrete
SemanticMemory::search_with_rerank also accepts
monomorphic R: Reranker for users who prefer static
dispatch). Returns RerankedDocuments so callers can
inspect the reranker’s score alongside the retrieval score.Source§fn count<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
filter: Option<&'life2 VectorFilter>,
) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn count<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
filter: Option<&'life2 VectorFilter>,
) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
VectorStore::count — backends without count support
surface Error::Config.Source§fn list<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
filter: Option<&'life2 VectorFilter>,
limit: usize,
offset: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<Document>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn list<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ExecutionContext,
filter: Option<&'life2 VectorFilter>,
limit: usize,
offset: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<Document>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
VectorStore::list — backends without enumeration
support surface Error::Config.