Skip to main content

Documentation Index

Fetch the complete documentation index at: https://cognis.vasanth.xyz/llms.txt

Use this file to discover all available pages before exploring further.

Cognis ships six vector stores (in-memory, FAISS, Chroma, Qdrant, Pinecone, Weaviate). Adding a seventh is a self-contained task. This page covers the shape.

What you’ll add

  • A new module under crates/cognis-rag/src/vectorstore/<name>.rs (or a directory for larger backends).
  • A struct implementing VectorStore, plus a <Name>Builder for hosted backends.
  • A feature flag in crates/cognis-rag/Cargo.toml (vectorstore-<name>).
  • Tests with mocked HTTP if hosted, or in-process if local.
  • An example under examples/retrieval/.
  • Documentation entries in Embeddings and vector stores and Feature flags.

The trait

use std::collections::HashMap;
use serde_json::Value;

#[async_trait]
pub trait VectorStore: Send + Sync {
    async fn add_texts(
        &mut self,
        texts: Vec<String>,
        metadata: Option<Vec<HashMap<String, Value>>>,
    ) -> Result<Vec<String>>;

    async fn add_vectors(
        &mut self,
        vectors: Vec<Vec<f32>>,
        texts: Vec<String>,
        metadata: Option<Vec<HashMap<String, Value>>>,
    ) -> Result<Vec<String>>;

    async fn similarity_search(&self, query: &str, k: usize) -> Result<Vec<SearchResult>>;
    async fn similarity_search_by_vector(&self, query_vector: Vec<f32>, k: usize) -> Result<Vec<SearchResult>>;

    /// Default fallback: searches top `k * 4`, then filters in-process. Override
    /// when your backend supports native metadata filters (Qdrant, Pinecone, …).
    async fn similarity_search_with_filter(&self, query: &str, k: usize, filter: &Filter) -> Result<Vec<SearchResult>>;

    async fn delete(&mut self, ids: Vec<String>) -> Result<()>;

    fn len(&self) -> usize;
    fn is_empty(&self) -> bool { self.len() == 0 }
}
SearchResult is { id, text, score, metadata }. add_texts returns the IDs the store assigned; add_vectors is the lower-level entry when the caller has already paid the embedding cost. For backends that don’t natively support a method, provide a sensible fallback (similarity_search_with_filter has one already) and document the difference.

Step 1 — Build the struct

For a hosted backend:
// crates/cognis-rag/src/vectorstore/myvector.rs
use std::sync::Arc;
use async_trait::async_trait;
use crate::{Document, Embeddings, SearchResult, VectorStore, Filter};

pub struct MyVectorStore {
    embeddings: Arc<dyn Embeddings>,
    http: reqwest::Client,
    base_url: String,
    api_key: secrecy::SecretString,
    collection: String,
}

pub struct MyVectorStoreBuilder { /* … */ }

impl MyVectorStoreBuilder {
    pub fn new() -> Self { /* … */ todo!() }
    pub fn url(mut self, u: impl Into<String>) -> Self { /* … */ self }
    pub fn api_key(mut self, k: impl Into<String>) -> Self { /* … */ self }
    pub fn collection(mut self, c: impl Into<String>) -> Self { /* … */ self }
    pub fn embeddings(mut self, e: Arc<dyn Embeddings>) -> Self { /* … */ self }
    pub fn build(self) -> cognis_core::Result<MyVectorStore> { /* … */ todo!() }
}

#[async_trait]
impl VectorStore for MyVectorStore {
    // 6 methods. Map to your backend's REST / gRPC API.
}
For local stores (FAISS-style), there’s no HTTP — the struct holds the index and the embedder.

Step 2 — Feature flag

# crates/cognis-rag/Cargo.toml
[features]
vectorstore-myvector = ["dep:reqwest", "dep:secrecy"]

# Update the all-vectorstores grouping:
all-vectorstores = [
    "vectorstore-chroma",
    "vectorstore-qdrant",
    "vectorstore-pinecone",
    "vectorstore-weaviate",
    "vectorstore-faiss",
    "vectorstore-myvector",
]
In crates/cognis-rag/src/lib.rs:
#[cfg(feature = "vectorstore-myvector")]
pub use vectorstore::myvector::{MyVectorStore, MyVectorStoreBuilder};
The cognis umbrella does not auto-glob from cognis_rag — it explicitly lists the types it re-exports at the top level. Add your types to the relevant pub use cognis_rag::{...} block in crates/cognis/src/lib.rs so users get cognis::MyVectorStore without an extra import. Existing entries there (e.g. InMemoryVectorStore, Filter) are the template.

Step 3 — Tests

Mocked HTTP for hosted; in-process tests for local.
// crates/cognis-rag/src/vectorstore/myvector.rs
#[cfg(test)]
mod tests {
    use super::*;
    use crate::FakeEmbeddings;

    #[tokio::test]
    async fn add_then_search() {
        // Use `wiremock` for HTTP backends, or build the local index in-process.
    }
}
Make sure tests cover:
  • add_texts followed by similarity_search returns the right docs.
  • delete actually removes — a search after delete shouldn’t find the deleted ids.
  • similarity_search_with_filter either filters or falls back gracefully (and the doc page says which).
  • Error paths — what happens when the service is down, returns 5xx, or the collection doesn’t exist.

Step 4 — Add an example

// examples/retrieval/myvector_basics.rs
use std::sync::Arc;
use cognis::prelude::*;
use cognis_rag::{Embeddings, FakeEmbeddings, MyVectorStoreBuilder, VectorStore};

#[tokio::main]
async fn main() -> Result<()> {
    let emb: Arc<dyn Embeddings> = Arc::new(FakeEmbeddings::new(8));
    let mut store = MyVectorStoreBuilder::new()
        .url(std::env::var("MYVECTOR_URL").unwrap_or_else(|_| "http://localhost:6334".into()))
        .api_key(std::env::var("MYVECTOR_API_KEY").unwrap_or_default())
        .collection("demo")
        .embeddings(emb)
        .build()?;

    store.add_texts(vec!["hello".into(), "world".into()], None).await?;
    let hits = store.similarity_search("greeting", 2).await?;
    println!("{:#?}", hits);
    Ok(())
}
Register in crates/examples/Cargo.toml with a name like retrieval_myvector_basics.

Step 5 — Update docs

Step 6 — PR

Title: feat(rag): add MyVectorStore. Description should mention:
  • The backend’s public docs.
  • Feature flag name.
  • Whether similarity_search_with_filter is native or an in-process fallback.
  • Anything not yet supported.

See also

Adding a provider

Same shape, different domain.

cognis-rag reference

Trait surface and existing implementations.