gonzalo_vector/lib.rs
1//! Vector-search capability layer for gonzalo.
2//!
3//! Provides the [`VectorIndex`] trait (and its exact in-memory implementation
4//! [`MemoryVectorIndex`]) plus the [`Embedder`] seam so caliban-side model
5//! providers and gonzalo-hosted embedders share a single interface.
6//!
7//! All index operations are async so remote / approximate backends can be
8//! added in later milestones without breaking callers.
9
10pub mod index;
11pub use index::MemoryVectorIndex;
12
13#[cfg(feature = "hnsw")]
14pub mod hnsw;
15#[cfg(feature = "hnsw")]
16pub use hnsw::HnswVectorIndex;
17
18use async_trait::async_trait;
19use gonzalo_core::{KeyPrefix, RecordKey, Result};
20
21// ---------------------------------------------------------------------------
22// Embedder
23// ---------------------------------------------------------------------------
24
25/// Turns text into an embedding vector.
26///
27/// The default deployment delegates this to the caller (caliban, which talks
28/// to model providers); gonzalo can also host its own embedder. This trait
29/// is the seam for both.
30#[async_trait]
31pub trait Embedder: Send + Sync {
32 async fn embed(&self, text: &str) -> Result<Vec<f32>>;
33}
34
35// ---------------------------------------------------------------------------
36// Match
37// ---------------------------------------------------------------------------
38
39/// One search hit: the record key and its similarity score (cosine, in
40/// `[-1.0, 1.0]`; higher is more similar).
41#[derive(Debug, Clone, PartialEq)]
42pub struct Match {
43 pub key: RecordKey,
44 pub score: f32,
45}
46
47// ---------------------------------------------------------------------------
48// VectorIndex
49// ---------------------------------------------------------------------------
50
51/// A vector index keyed by [`RecordKey`].
52///
53/// Async so remote / approximate backends can implement it later; the
54/// in-memory impl ([`MemoryVectorIndex`]) is exact brute-force cosine kNN.
55#[async_trait]
56pub trait VectorIndex: Send + Sync {
57 /// Insert or replace the vector for `key`.
58 async fn upsert(&self, key: RecordKey, vector: Vec<f32>) -> Result<()>;
59
60 /// Remove `key` if present (no error if absent).
61 async fn remove(&self, key: &RecordKey) -> Result<()>;
62
63 /// Return the top-`k` matches to `query`, restricted to keys matching
64 /// `filter`, ordered by descending score.
65 async fn query(&self, query: &[f32], k: usize, filter: &KeyPrefix) -> Result<Vec<Match>>;
66}