smithery.ai

semantic-search

Implement and debug semantic/vector search with model2vec-rs and sqlite-vec. Use for embedding generation, vector queries, hybrid search, or RRF fusion.

First seen Apr 12, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 3,647 B
  • docs SUMMARY.md 175 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

Semantic Search Implementation

Architecture

┌─────────────────────────────────────┐
│         Search Query                │
└─────────────┬───────────────────────┘
              │
    ┌─────────┴─────────┐
    │                   │
┌───▼───┐         ┌─────▼─────┐
│ FTS5  │         │model2vec  │
│(text) │         │(embedding)│
└───┬───┘         └─────┬─────┘
    │                   │
    │              ┌────▼────┐
    │              │sqlite-vec│
    │              │ (vector) │
    │              └────┬────┘
    │                   │
    └─────────┬─────────┘
              │
        ┌─────▼─────┐
        │ RRF Fusion│
        │  (k=60)   │
        └───────────┘

Key Components

Embedder (src/embed.rs)

use model2vec_rs::model::StaticModel;

const MODEL_ID: &str = "minishlab/potion-base-32M";

pub struct Embedder {
    model: StaticModel,
}

impl Embedder {
    pub fn new() -> Result<Self> {
        let model = StaticModel::from_pretrained(MODEL_ID, None, None, None)?;
        Ok(Self { model })
    }

    pub fn embed_query(&self, text: &str) -> Result<Vec<f32>> {
        let embeddings = self.model.encode(&[text.to_string()]);
        Ok(embeddings.into_iter().next().unwrap())
    }

    pub fn dimension(&self) -> usize {
        512  // Potion-base-32M outputs 512 dimensions
    }
}

Vector Search (src/db/mod.rs)

// sqlite-vec query for similarity search
let sql = r#"
    SELECT d.*, v.distance
    FROM documents_vec v
    JOIN documents d ON d.id = v.id
    WHERE v.embedding MATCH ?1
      AND k = ?2
    ORDER BY v.distance
"#;

// Convert embedding to bytes for sqlite-vec
let embedding_bytes: Vec<u8> = embedding
    .iter()
    .flat_map(|f| f.to_le_bytes())
    .collect();

RRF Fusion

fn rrf_fusion(fts: &[Result], vec: &[Result], k: f32, limit: usize) -> Vec<Result> {
    let mut scores: HashMap<String, f32> = HashMap::new();

    for (rank, result) in fts.iter().enumerate() {
        *scores.entry(result.id.clone()).or_default() += 1.0 / (k + rank as f32 + 1.0);
    }
    for (rank, result) in vec.iter().enumerate() {
        *scores.entry(result.id.clone()).or_default() += 1.0 / (k + rank as f32 + 1.0);
    }

    // Sort by combined score descending
    let mut results: Vec<_> = scores.into_iter().collect();
    results.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
    results.truncate(limit);
    results
}

Search Modes

Mode Flag Description
Hybrid --mode hybrid FTS5 + vector with RRF (default)
Text --mode text FTS5 only (fast, keyword match)
Semantic --mode semantic Vector only (meaning-based)

Debugging

Check embedding dimensions

assert_eq!(embedding.len(), 512); // Potion-base-32M

Verify sqlite-vec loaded

SELECT vec_version();

Test vector distance

SELECT vec_distance_L2(embedding, ?1) FROM documents_vec LIMIT 1;