pub struct HnswIndex { /* private fields */ }Expand description
HNSW vector index backed by hnsw_rs.
Each collective gets its own HnswIndex instance, providing
complete data isolation between collectives.
§Persistence Strategy
Metadata (ID mappings, deleted set) is persisted to a JSON .hnsw.meta
file. The graph itself is rebuilt from redb embeddings on open, because
hnsw_rs::HnswIo::load_hnsw has lifetime constraints that create
self-referential struct issues. The graph dump files (via file_dump)
are saved for future optimization but not currently loaded.
Implementations§
Source§impl HnswIndex
impl HnswIndex
Sourcepub fn new(dimension: usize, config: &HnswConfig) -> Self
pub fn new(dimension: usize, config: &HnswConfig) -> Self
Creates a new empty HNSW index.
§Arguments
dimension- Expected embedding dimension (validated on insert)config- HNSW tuning parameters
Sourcepub fn insert_experience(
&self,
exp_id: ExperienceId,
embedding: &[f32],
) -> Result<()>
pub fn insert_experience( &self, exp_id: ExperienceId, embedding: &[f32], ) -> Result<()>
Inserts an experience embedding into the index.
Assigns a new internal usize ID and records the mapping. If the ExperienceId is already present, this is a no-op.
Sourcepub fn delete_experience(&self, exp_id: ExperienceId) -> Result<()>
pub fn delete_experience(&self, exp_id: ExperienceId) -> Result<()>
Marks an experience as deleted in the index.
The vector remains in the graph but is excluded from search results via filtered search. Returns Ok even if the experience is not in the index (idempotent).
Sourcepub fn search_experiences(
&self,
query: &[f32],
k: usize,
ef_search: usize,
) -> Result<Vec<(ExperienceId, f32)>>
pub fn search_experiences( &self, query: &[f32], k: usize, ef_search: usize, ) -> Result<Vec<(ExperienceId, f32)>>
Searches for the k nearest experiences, excluding deleted ones.
Returns (ExperienceId, distance) pairs sorted by distance
ascending (closest first). Distance is cosine distance:
0.0 = identical, 2.0 = opposite.
Sourcepub fn contains(&self, exp_id: ExperienceId) -> bool
pub fn contains(&self, exp_id: ExperienceId) -> bool
Returns true if the given experience is in the index (and not deleted).
Sourcepub fn active_count(&self) -> usize
pub fn active_count(&self) -> usize
Returns the number of active (non-deleted) vectors.
Sourcepub fn total_count(&self) -> usize
pub fn total_count(&self) -> usize
Returns the total number of vectors (including deleted).
Sourcepub fn restore_deleted_set(&self, deleted_exp_ids: &[String]) -> Result<()>
pub fn restore_deleted_set(&self, deleted_exp_ids: &[String]) -> Result<()>
Restores the deleted set from persisted metadata.
Called during PulseDB::open() after rebuilding the graph from redb.
Accepts ExperienceId UUID strings and maps them to the current
internal IDs (which may differ from the previous session’s IDs
after a rebuild).
Sourcepub fn save_to_dir(&self, dir: &Path, name: &str) -> Result<()>
pub fn save_to_dir(&self, dir: &Path, name: &str) -> Result<()>
Saves index metadata to a JSON file.
Creates {dir}/{name}.hnsw.meta with ID mappings and deleted set.
Also attempts to save the HNSW graph via file_dump for future
optimization (graph loading is not yet implemented due to lifetime
constraints in hnsw_rs).
Sourcepub fn rebuild_from_embeddings(
dimension: usize,
config: &HnswConfig,
embeddings: Vec<(ExperienceId, Vec<f32>)>,
) -> Result<Self>
pub fn rebuild_from_embeddings( dimension: usize, config: &HnswConfig, embeddings: Vec<(ExperienceId, Vec<f32>)>, ) -> Result<Self>
Rebuilds an index from a set of embeddings.
Used during PulseDB::open() to reconstruct the HNSW graph
from embeddings stored in redb (the source of truth).
Trait Implementations§
Source§impl VectorIndex for HnswIndex
impl VectorIndex for HnswIndex
Source§fn insert(&self, id: usize, embedding: &[f32]) -> Result<()>
fn insert(&self, id: usize, embedding: &[f32]) -> Result<()>
Source§fn insert_batch(&self, items: &[(&Vec<f32>, usize)]) -> Result<()>
fn insert_batch(&self, items: &[(&Vec<f32>, usize)]) -> Result<()>
Source§fn search(
&self,
query: &[f32],
k: usize,
ef_search: usize,
) -> Result<Vec<(usize, f32)>>
fn search( &self, query: &[f32], k: usize, ef_search: usize, ) -> Result<Vec<(usize, f32)>>
Source§fn search_filtered(
&self,
query: &[f32],
k: usize,
ef_search: usize,
filter: &(dyn Fn(&usize) -> bool + Sync),
) -> Result<Vec<(usize, f32)>>
fn search_filtered( &self, query: &[f32], k: usize, ef_search: usize, filter: &(dyn Fn(&usize) -> bool + Sync), ) -> Result<Vec<(usize, f32)>>
Source§fn is_deleted(&self, id: usize) -> bool
fn is_deleted(&self, id: usize) -> bool
Auto Trait Implementations§
impl !Freeze for HnswIndex
impl !RefUnwindSafe for HnswIndex
impl Send for HnswIndex
impl Sync for HnswIndex
impl Unpin for HnswIndex
impl UnsafeUnpin for HnswIndex
impl !UnwindSafe for HnswIndex
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 more