Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungWe Built a CLI to Find Out If You’re Overpaying for Claude(24.09.2026 um 04:35 Uhr)
Sichere ProgrammierungMy own sandbox was killing my agent's shell, and the exit code hid it(24.09.2026 um 04:38 Uhr)
Sichere ProgrammierungHow three OSLabs engineers built a CLI to catch you overpaying Claude(24.09.2026 um 04:45 Uhr)
Sichere ProgrammierungBreaking CI Guards on Purpose to Prove They Can Fail(24.09.2026 um 05:00 Uhr)
IT Security NachrichtenLangfristige Updatefähigkeit als Pflicht(24.09.2026 um 05:03 Uhr)
Sichere ProgrammierungWe Built a CLI to Find Out If You’re Overpaying for Claude(24.09.2026 um 04:35 Uhr)
Sichere ProgrammierungMy own sandbox was killing my agent's shell, and the exit code hid it(24.09.2026 um 04:38 Uhr)
Sichere ProgrammierungHow three OSLabs engineers built a CLI to catch you overpaying Claude(24.09.2026 um 04:45 Uhr)
Sichere ProgrammierungBreaking CI Guards on Purpose to Prove They Can Fail(24.09.2026 um 05:00 Uhr)
IT Security NachrichtenLangfristige Updatefähigkeit als Pflicht(24.09.2026 um 05:03 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Build a Fast and Lightweight Rust Vector Search App with Rig & LanceDB

TL;DR: Build a powerful semantic search system in Rust using Rig and LanceDB. We'll guide you step-by-step through creating, storing, and searching vector embeddings efficiently with hands-on examples. Perfect for building RAG systems,…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

TL;DR: Build a powerful semantic search system in Rust using Rig and LanceDB. We'll guide you step-by-step through creating, storing, and searching vector embeddings efficiently with hands-on examples. Perfect for building RAG systems, semantic search engines, and more.






Introduction



Semantic search is transforming the way we find and understand information. Unlike traditional keyword search, it captures the intent behind your queries, offering a more nuanced retrieval process. However, building these systems can feel daunting, often involving complex embeddings, vector databases, and similarity search algorithms.



That's where LanceDB comes in.






Why LanceDB?



LanceDB is an open-source vector database tailored for AI applications and vector search. It provides:





  • Embedded Database: Works directly in your application without needing external servers.


  • High Performance: Leverages Arrow format for efficient data storage and retrieval.


  • Scalable: Handles terabyte-scale datasets efficiently.


  • Vector Indexing: Supports both exact and approximate nearest neighbor searches out of the box.



Combined with Rig's embedding and LLM capabilities, you can create a powerful, efficient semantic search solution with minimal code.



Let's dive in!




You can find the full source code for this project in our GitHub repo.







Prerequisites



Before we begin, make sure you have:








Project Setup



To start, create a new Rust project:




cargo new vector_search
cd vector_search






Update your Cargo.toml to add the necessary dependencies:




[dependencies]
rig-core = "0.4.0"
rig-lancedb = "0.1.1"
lancedb = "0.10.0"
tokio = { version = "1.40.0", features = ["full"] }
anyhow = "1.0.89"
futures = "0.3.30"
serde = { version = "1.0.210", features = ["derive"] }
serde_json = "1.0.128"
arrow-array = "52.2.0"






Here’s a quick overview of each dependency:





  • rig-core and rig-lancedb: The core libraries for embedding generation and vector search.


  • lancedb: The embedded vector database.


  • tokio: Asynchronous runtime support.


  • arrow-array: To work with Arrow's columnar format, which LanceDB uses internally.

  • Others for error handling, serialization, and futures support.



Now, create a .env file to store your OpenAI API key:




echo "OPENAI_API_KEY=your_key_here" > .env









Building the Search System



We’ll break this into manageable steps. First, let’s create a utility function to handle data conversion between Rig's embeddings and LanceDB's format.



Create src/utils.rs:




use std::sync::Arc;
use arrow_array::{
types::Float64Type, ArrayRef, FixedSizeListArray,
RecordBatch, StringArray
};
use lancedb::arrow::arrow_schema::{DataType, Field, Fields, Schema};
use rig::embeddings::DocumentEmbeddings;

// Define the schema for our LanceDB table
pub fn schema(dims: usize) -> Schema {
Schema::new(Fields::from(vec![
Field::new("id", DataType::Utf8, false),
Field::new("content", DataType::Utf8, false),
Field::new(
"embedding",
DataType::FixedSizeList(
Arc::new(Field::new("item", DataType::Float64, true)),
dims as i32,
),
false,
),
]))
}






This schema function defines the structure of our table:





  • id: A unique identifier for each document.


  • content: The text content of the document.


  • embedding: The vector representation of the content.


  • dims parameter: Represents the size of embedding vectors (e.g., 1536 for OpenAI's ada-002 model).



Next, add the conversion function to convert DocumentEmbeddings into RecordBatch for LanceDB:




pub fn as_record_batch(
records: Vec<DocumentEmbeddings>,
dims: usize,
) -> Result<RecordBatch, lancedb::arrow::arrow_schema::ArrowError> {
let id = StringArray::from_iter_values(
records
.iter()
.flat_map(|record| (0..record.embeddings.len())
.map(|i| format!("{}-{i}", record.id)))
.collect::<Vec<_>>(),
);

let content = StringArray::from_iter_values(
records
.iter()
.flat_map(|record| {
record
.embeddings
.iter()
.map(|embedding| embedding.document.clone())
})
.collect::<Vec<_>>(),
);

let embedding = FixedSizeListArray::from_iter_primitive::<Float64Type, _, _>(
records
.into_iter()
.flat_map(|record| {
record
.embeddings
.into_iter()
.map(|embedding| embedding.vec.into_iter().map(Some).collect::<Vec<_>>())
.map(Some)
.collect::<Vec<_>>()
})
.collect::<Vec<_>>(),
dims as i32,
);

RecordBatch::try_from_iter(vec![
("id", Arc::new(id) as ArrayRef),
("content", Arc::new(content) as ArrayRef),
("embedding", Arc::new(embedding) as ArrayRef),
])
}






This function is crucial as it converts our Rust data structures into Arrow's columnar format, which LanceDB uses internally:




  1. Creates string arrays for IDs and content.

  2. Converts embeddings into fixed-size lists.

  3. Assembles everything into a RecordBatch.



With our utility functions ready, let’s build the main search functionality in src/main.rs. We’ll implement this step-by-step, explaining each part along the way.






Setting Up Dependencies



First, let’s import the required libraries:




use anyhow::Result;
use arrow_array::RecordBatchIterator;
use lancedb::{index::vector::IvfPqIndexBuilder, DistanceType};
use rig::{
embeddings::{DocumentEmbeddings, EmbeddingModel, EmbeddingsBuilder},
providers::openai::{Client, TEXT_EMBEDDING_ADA_002},
vector_store::VectorStoreIndex,
};
use rig_lancedb::{LanceDbVectorStore, SearchParams};
use serde::Deserialize;
use std::{env, sync::Arc};

mod utils;
use utils::{as_record_batch, schema};






These imports bring in:




  • Rig’s embedding and vector storage tools.

  • LanceDB’s database capabilities.

  • Arrow data structures for efficient processing.

  • Utilities for serialization, error handling, and async programming.






Defining Data Structures



We’ll create a simple struct to represent our search results:




#[derive(Debug, Deserialize)]
struct SearchResult {
content: String,
}






This struct maps to database records, representing the content we want to retrieve.






Generating Embeddings



Generating document embeddings is a core part of our system. Let’s implement this function:




async fn create_embeddings(client: &Client) -> Result<Vec<DocumentEmbeddings>> {
let model = client.embedding_model(TEXT_EMBEDDING_ADA_002);

// Set up dummy data to meet the 256 row requirement for IVF-PQ indexing
let dummy_doc = "Let there be light".to_string();
let dummy_docs = vec![dummy_doc; 256];

// Generate embeddings for the data
let embeddings = EmbeddingsBuilder::new(model)
// First add our real documents
.simple_document(
"doc1",
"Rust provides zero-cost abstractions and memory safety without garbage collection.",
)
.simple_document(
"doc2",
"Python emphasizes code readability with significant whitespace.",
)
// Add dummy documents to meet minimum requirement using enumerate to generate unique IDs
.simple_documents(
dummy_docs
.into_iter()
.enumerate()
.map(|(i, doc)| (format!("doc{}", i + 3), doc))
.collect(),
)
.build()
.await?;

Ok(embeddings)
}






This function handles:




  1. Initializing the OpenAI embedding model.

  2. Creating embeddings for our real documents.

  3. Adding dummy data to meet LanceDB’s indexing requirements.






Configuring the Vector Store



Now, let’s set up LanceDB and configure it with appropriate indexing and search parameters:




async fn setup_vector_store<M: EmbeddingModel>(
embeddings: Vec<DocumentEmbeddings>,
model: M,
) -> Result<LanceDbVectorStore<M>> {
// Initialize LanceDB
let db = lancedb::connect("data/lancedb-store").execute().await?;

// Drop the existing table if it exists - important for development
if db
.table_names()
.execute()
.await?
.contains(&"documents".to_string())
{
db.drop_table("documents").await?;
}

// Create table with embeddings
let record_batch = as_record_batch(embeddings, model.ndims())?;
let table = db
.create_table(
"documents",
RecordBatchIterator::new(vec![Ok(record_batch)], Arc::new(schema(model.ndims()))),
)
.execute()
.await?;

// Create an optimized vector index using IVF-PQ
table
.create_index(
&["embedding"],
lancedb::index::Index::IvfPq(
IvfPqIndexBuilder::default().distance_type(DistanceType::Cosine),
),
)
.execute()
.await?;

// Configure search parameters
let search_params = SearchParams::default().distance_type(DistanceType::Cosine);

// Create and return vector store
Ok(LanceDbVectorStore::new(table, model, "id", search_params).await?)
}






This setup function:




  1. Connects to the LanceDB database.

  2. Manages table creation and deletion.

  3. Sets up vector indexing for efficient similarity search.






Putting It All Together



Finally, the main function orchestrates the entire process:




#[tokio::main]
async fn main() -> Result<()> {
// Initialize OpenAI client
let openai_api_key = env::var("OPENAI_API_KEY").expect("OPENAI_API_KEY not set");
let openai_client = Client::new(&openai_api_key);
let model = openai_client.embedding_model(TEXT_EMBEDDING_ADA_002);

// Create embeddings (includes both real and dummy documents)
let embeddings = create_embeddings(&openai_client).await?;
println!("Created embeddings for {} documents", embeddings.len());

// Set up vector store
let store = setup_vector_store(embeddings, model).await?;
println!("Vector store initialized successfully");

// Perform a semantic search
let query = "Tell me about safe programming languages";
let results = store.top_n::<SearchResult>(query, 2).await?;

println!("\nSearch Results for: {}\n", query);
for (score, id, result) in results {
println!(
"Score: {:.4}\nID: {}\nContent: {}\n",
score, id, result.content
);
}

Ok(())
}









Understanding Vector Search Methods



Vector search systems need to balance accuracy and performance, especially as datasets grow. LanceDB provides two approaches to handle this: Exact Nearest Neighbor (ENN) and Approximate Nearest Neighbor (ANN) searches.






ENN vs ANN





  1. Exact Nearest Neighbor (ENN):




    • Searches exhaustively across all vectors.

    • Guarantees finding the true nearest neighbors.

    • Works well for small datasets.

    • No minimum data requirement.

    • Slower, but more accurate.




  2. Approximate Nearest Neighbor (ANN):




    • Uses indexing to speed up searches (like IVF-PQ).

    • Returns approximate results.

    • Suited for larger datasets.

    • Faster but slightly less accurate.








Choosing the Right Approach



Use ENN when:




  • Dataset is small (< 1,000 vectors).

  • Exact matches are crucial.

  • Performance isn’t a major concern.



Use ANN when:




  • Dataset is larger.

  • You can tolerate minor approximations.

  • Fast search speed is needed.



In our tutorial, we use ANN for scalability. For smaller datasets, ENN will be more suitable.




Tip: Start with ENN during development. Transition to ANN as your data and performance needs grow. Check out the ENN example.







Running the System



To run the project:




cargo run






Expected output:




Created embeddings for 258 documents
Vector store initialized successfully

Search Results for: Tell me about safe programming languages

Score: 0.3982
ID: doc2-0
Content: Python emphasizes code readability with significant whitespace.

Score: 0.4369
ID: doc1-0
Content: Rust provides zero-cost abstractions and memory safety without garbage collection.









Next Steps



If you’re ready to build more with Rig, here are some practical examples:






1. Build a RAG System



Want to give your LLM access to custom knowledge? Check out our tutorial on Building a RAG System with Rig in Under 100 Lines of Code.






2. Create an AI Agent



Ready to build more interactive AI applications? See our Agent Example.






3. Join the Community








Stay Connected



I’m always excited to hear from developers! If you’re interested in Rust, LLMs, or building intelligent assistants, join our Discord. Let’s build something amazing together!



And don’t forget: Build something with Rig, share your feedback, and get a chance to win $100.



Ad Astra,


Tachi


Co-Founder @ Playgrounds Analytics



This tutorial is part of our "Build with Rig" series. Follow our Website for more.

SOC Incident Playbook: Remote Code Execution (RCE) Defense
title: Detect Exploitation - Build a Fast and Lightweight Rust Vector Search App with Rig & LanceDB
id: 9323d7ad-4a28-4588-9507-a789123e3a7f
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-24
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-24"
        description = "YARA Signature for "
    strings:
        $str = "Build a Fast and Lightweight R" ascii wide
    condition:
        any of them
}
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Kognitive Analyse für identifizierte Bedrohung: Erhöhte Bedrohungslage im Bereich Build a Fast and Lightweight Rust Vector.... Basierend auf 368k Vektor-Korrelationen werden sofortige Isolationsmaßnahmen für betroffene Endpunkte empfohlen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
🔗 Semantisch verwandte Zero-Days MariaDB 11.7 VEC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Build a Fast and Lightweight Rust Vector Search App with Rig & LanceDB

Thematisch verwandte Begriffe: Build, Fast, Lightweight, Rust · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-96676 | A vulnerability was identified in Fast FAC1900R 20190827_2.0.2. The impa…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel TTP ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick