pub struct EmbeddingStore { /* private fields */ }Expand description
Typed wrapper over a VectorStore backend for conversation message embeddings.
Constructed via EmbeddingStore::new (Qdrant URL + optional API key) or
EmbeddingStore::with_store (custom backend for testing).
Implementations§
Source§impl EmbeddingStore
impl EmbeddingStore
Sourcepub fn new(
url: &str,
api_key: Option<&str>,
pool: DbPool,
) -> Result<Self, MemoryError>
pub fn new( url: &str, api_key: Option<&str>, pool: DbPool, ) -> Result<Self, MemoryError>
Create a new EmbeddingStore connected to the given Qdrant URL with optional API key.
api_key is forwarded to QdrantOps::new. The pool is used for SQLite metadata
operations on the embeddings_metadata table (which must already exist via sqlx
migrations).
§Errors
Returns an error if the Qdrant client cannot be created.
Sourcepub fn new_sqlite(pool: DbPool) -> Self
pub fn new_sqlite(pool: DbPool) -> Self
Create a new EmbeddingStore backed by SQLite for vector storage.
Uses the same pool for both vector data and metadata. No external Qdrant required.
pub fn with_store(store: Box<dyn VectorStore>, pool: DbPool) -> Self
pub async fn health_check(&self) -> bool
Sourcepub async fn ensure_collection(
&self,
vector_size: u64,
) -> Result<(), MemoryError>
pub async fn ensure_collection( &self, vector_size: u64, ) -> Result<(), MemoryError>
Ensure the collection exists in Qdrant with the given vector size.
Idempotent: no-op if the collection already exists.
§Errors
Returns an error if Qdrant cannot be reached or collection creation fails.
Sourcepub async fn store_with_tool_context(
&self,
message_id: MessageId,
conversation_id: ConversationId,
role: &str,
vector: Vec<f32>,
kind: MessageKind,
model: &str,
chunk_index: u32,
tool_name: &str,
exit_code: Option<i32>,
timestamp: Option<&str>,
) -> Result<String, MemoryError>
pub async fn store_with_tool_context( &self, message_id: MessageId, conversation_id: ConversationId, role: &str, vector: Vec<f32>, kind: MessageKind, model: &str, chunk_index: u32, tool_name: &str, exit_code: Option<i32>, timestamp: Option<&str>, ) -> Result<String, MemoryError>
Store a vector in Qdrant with additional tool execution metadata as payload fields.
Metadata fields (tool_name, exit_code, timestamp) are stored as Qdrant payload
alongside the standard fields. This allows filtering and scoring by tool context
without corrupting the embedding vector with text prefixes.
§Errors
Returns an error if the Qdrant upsert or SQLite insert fails.
Sourcepub async fn store(
&self,
message_id: MessageId,
conversation_id: ConversationId,
role: &str,
vector: Vec<f32>,
kind: MessageKind,
model: &str,
chunk_index: u32,
) -> Result<String, MemoryError>
pub async fn store( &self, message_id: MessageId, conversation_id: ConversationId, role: &str, vector: Vec<f32>, kind: MessageKind, model: &str, chunk_index: u32, ) -> Result<String, MemoryError>
Store a vector in Qdrant and persist metadata to SQLite.
chunk_index is 0 for single-vector messages and increases for each chunk
when a long message is split into multiple embeddings.
Returns the UUID of the newly created Qdrant point.
§Errors
Returns an error if the Qdrant upsert or SQLite insert fails.
Sourcepub async fn store_with_category(
&self,
message_id: MessageId,
conversation_id: ConversationId,
role: &str,
vector: Vec<f32>,
kind: MessageKind,
model: &str,
chunk_index: u32,
category: Option<&str>,
) -> Result<String, MemoryError>
pub async fn store_with_category( &self, message_id: MessageId, conversation_id: ConversationId, role: &str, vector: Vec<f32>, kind: MessageKind, model: &str, chunk_index: u32, category: Option<&str>, ) -> Result<String, MemoryError>
Store a vector with an optional category tag in the Qdrant payload.
Identical to Self::store but adds a category field to the payload when provided.
Used by category-aware memory (#2428) to enable category-filtered recall.
Note: when category is None no category field is written to the Qdrant payload.
Memories stored before category-aware recall was enabled therefore won’t match a
category filter — this is intentional (no silent false-positives), but a backfill
pass is needed if retrospective categorization is desired.
§Errors
Returns an error if the Qdrant upsert or SQLite insert fails.
Sourcepub async fn search(
&self,
query_vector: &[f32],
limit: usize,
filter: Option<SearchFilter>,
) -> Result<Vec<SearchResult>, MemoryError>
pub async fn search( &self, query_vector: &[f32], limit: usize, filter: Option<SearchFilter>, ) -> Result<Vec<SearchResult>, MemoryError>
Search for similar vectors in Qdrant, returning up to limit results.
§Errors
Returns an error if the Qdrant search fails.
Sourcepub async fn collection_exists(&self, name: &str) -> Result<bool, MemoryError>
pub async fn collection_exists(&self, name: &str) -> Result<bool, MemoryError>
Check whether a named collection exists in the vector store.
§Errors
Returns an error if the store backend cannot be reached.
Sourcepub async fn ensure_named_collection(
&self,
name: &str,
vector_size: u64,
) -> Result<(), MemoryError>
pub async fn ensure_named_collection( &self, name: &str, vector_size: u64, ) -> Result<(), MemoryError>
Ensure a named collection exists in Qdrant with the given vector size.
§Errors
Returns an error if Qdrant cannot be reached or collection creation fails.
Sourcepub async fn store_to_collection(
&self,
collection: &str,
payload: Value,
vector: Vec<f32>,
) -> Result<String, MemoryError>
pub async fn store_to_collection( &self, collection: &str, payload: Value, vector: Vec<f32>, ) -> Result<String, MemoryError>
Store a vector in a named Qdrant collection with arbitrary payload.
Returns the UUID of the newly created point.
§Errors
Returns an error if the Qdrant upsert fails.
Sourcepub async fn upsert_to_collection(
&self,
collection: &str,
point_id: &str,
payload: Value,
vector: Vec<f32>,
) -> Result<(), MemoryError>
pub async fn upsert_to_collection( &self, collection: &str, point_id: &str, payload: Value, vector: Vec<f32>, ) -> Result<(), MemoryError>
Upsert a vector into a named collection, reusing an existing point ID.
Use this when updating an existing entity to avoid orphaned Qdrant points.
§Errors
Returns an error if the Qdrant upsert fails.
Sourcepub async fn search_collection(
&self,
collection: &str,
query_vector: &[f32],
limit: usize,
filter: Option<VectorFilter>,
) -> Result<Vec<ScoredVectorPoint>, MemoryError>
pub async fn search_collection( &self, collection: &str, query_vector: &[f32], limit: usize, filter: Option<VectorFilter>, ) -> Result<Vec<ScoredVectorPoint>, MemoryError>
Search a named Qdrant collection, returning scored points with payloads.
§Errors
Returns an error if the Qdrant search fails.
Sourcepub async fn scroll_all_entity_ids(
&self,
collection: &str,
) -> Result<Vec<(String, i64)>, MemoryError>
pub async fn scroll_all_entity_ids( &self, collection: &str, ) -> Result<Vec<(String, i64)>, MemoryError>
Enumerate (point_id, entity_id) pairs for all points in collection that carry
an entity_id_str payload field.
entity_id_str is a string mirror of the i64 entity_id written alongside the numeric
field at embedding time. The scroll API only surfaces string-typed payload values, so a
parallel string field is necessary for enumeration. Points missing entity_id_str
(written before this field was added) are silently skipped — they will gain the field on
the next merge_entity or store_entity_embedding call.
§Errors
Returns an error if the underlying scroll operation fails.
Sourcepub async fn delete_from_collection(
&self,
collection: &str,
ids: Vec<String>,
) -> Result<(), MemoryError>
pub async fn delete_from_collection( &self, collection: &str, ids: Vec<String>, ) -> Result<(), MemoryError>
Delete a set of points from a named collection by their Qdrant point IDs.
This is a thin wrapper over VectorStore::delete_by_ids for use by
the stale-embedding cleanup path in community.rs.
§Errors
Returns an error if the underlying delete operation fails.
Sourcepub async fn get_vectors_from_collection(
&self,
collection: &str,
point_ids: &[String],
) -> Result<HashMap<String, Vec<f32>>, MemoryError>
pub async fn get_vectors_from_collection( &self, collection: &str, point_ids: &[String], ) -> Result<HashMap<String, Vec<f32>>, MemoryError>
Retrieve raw vectors for the given Qdrant point IDs from collection.
Returns a map of point_id → embedding. Missing ids are silently dropped.
Returns an empty map when the backend does not support vector retrieval
(e.g. DbVectorStore / InMemoryVectorStore without an override).
§Errors
Returns an error if the underlying store returns a non-Unsupported error.
Sourcepub async fn get_vectors(
&self,
ids: &[MessageId],
) -> Result<HashMap<MessageId, Vec<f32>>, MemoryError>
pub async fn get_vectors( &self, ids: &[MessageId], ) -> Result<HashMap<MessageId, Vec<f32>>, MemoryError>
Fetch raw vectors for the given message IDs from the SQLite vector store.
Returns an empty map when using Qdrant backend (vectors not locally stored).
§Errors
Returns an error if the SQLite query fails.
Sourcepub async fn get_vectors_for_messages(
&self,
ids: &[MessageId],
) -> Result<HashMap<MessageId, Vec<f32>>, MemoryError>
pub async fn get_vectors_for_messages( &self, ids: &[MessageId], ) -> Result<HashMap<MessageId, Vec<f32>>, MemoryError>
Fetch embeddings for the given message IDs from the configured vector store.
Resolves message_id → qdrant_point_id via embeddings_metadata (filtering to
chunk_index = 0 so each message yields at most one vector), then retrieves the
vectors from the underlying VectorStore.
Returns a map from MessageId to embedding vector. Messages without an
embeddings_metadata row, or whose vector cannot be retrieved, are silently dropped.
When the backend returns crate::VectorStoreError::Unsupported, an empty map is
returned without error (matches Self::get_vectors_from_collection semantics).
§Errors
Returns an error if the SQLite metadata query or vector store retrieval fails.
Sourcepub async fn delete_by_message_ids(
&self,
ids: &[MessageId],
) -> Result<usize, MemoryError>
pub async fn delete_by_message_ids( &self, ids: &[MessageId], ) -> Result<usize, MemoryError>
Delete all Qdrant vectors associated with the given message IDs.
Resolves message_id → qdrant_point_id via the embeddings_metadata table,
then calls the underlying vector store’s delete_by_ids. The
embeddings_metadata rows are not removed here — the SQLite CASCADE on
messages handles that when the rows are hard-deleted later.
Returns the number of Qdrant point IDs targeted for deletion (may be less than
ids.len() when some messages have no embeddings).
§Errors
Returns MemoryError if the SQLite query or the vector store delete fails.
Sourcepub async fn has_embedding(
&self,
message_id: MessageId,
) -> Result<bool, MemoryError>
pub async fn has_embedding( &self, message_id: MessageId, ) -> Result<bool, MemoryError>
Check whether an embedding already exists for the given message ID.
§Errors
Returns an error if the SQLite query fails.
Sourcepub async fn is_epoch_current(
&self,
entity_name: &str,
qdrant_epoch: u64,
) -> Result<bool, MemoryError>
pub async fn is_epoch_current( &self, entity_name: &str, qdrant_epoch: u64, ) -> Result<bool, MemoryError>
Check whether a Qdrant embedding for entity_name is current by comparing the
Qdrant-side epoch against the epoch stored in graph_entities.
Returns true if the Qdrant embedding is up-to-date or if the entity no longer
exists in SQLite (embedding should be cleaned up separately).
§Errors
Returns an error if the SQLite query fails.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for EmbeddingStore
impl !RefUnwindSafe for EmbeddingStore
impl Send for EmbeddingStore
impl Sync for EmbeddingStore
impl Unpin for EmbeddingStore
impl UnsafeUnpin for EmbeddingStore
impl !UnwindSafe for EmbeddingStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request