Qdrant + FastEmbed with Rust #1
So none, I repeat none of this is “AI” generated!
(The racing car image started off from a real photo of mine!) . Let’s get that out of the way first and learn how to do the Rust code so that we can use the FastEmbed crate to create our own embeddings to put into Qdrant

https://qdrant.tech/documentation/frameworks
Framework Integrations
I have put together the following useful notes on how to do embeddings for Qdrant using Rust with the FastEmbed crate ‘for generating vector embeddings, reranking locally’. This saves money on tokens, many tutorials use OpenAI for doing the embeddings!

Qdrant stores the embeddings for semantic retrieval, think “recommendation” or “similarity search”. The Qdrant docs are great, the FastEmbed docs are great, but we need to weave the 2 things together, that’s the purpose of this article.
(In a future article – called “part 2” – I will show how to do chunking, but for now let’s focus on creating the embeddings and getting them into Qdrant).
The code
Dependencies (Cargo.toml)
[dependencies]
dotenvy = "0.15.7"
fastembed = "5.8.1"
qdrant-client = "1.16.0"
serde_json = "1.0.149"
tokio = { version = "1.49.0", features = ["macros", "rt-multi-thread"] }
The “difficult” part is linking the examples from Qdrant for making a client and a collection to the FastEmbed examples on how to do embeddings.
Embedding Model Choice
In the example code I used EmbeddingModel::AllMiniLML6V2 but you can choose whichever one you desire, based on the variants offered to you from the EmbeddingModel enum.
Supported Models:
https://github.com/Anush008/fastembed-rs?tab=readme-ov-file#models
Support the project if you have the means ππ»
Prepare the ‘Points’
Most of the code will seem relatively straightforward to work out, especially from the IDE hints, but this is the key part you won’t find.
Line 43, we create our Vec of PointStruct where Vec is the Rust standard library type and PointStruct is a Qdrant type provided by the Qdrant client crate.
// Prepare points with embeddings and corresponding documents as payload
let points: Vec<PointStruct> = embeddings
.into_iter()
.enumerate()
.filter(|(id, _)| !documents[*id].is_empty())
.map(|(id, vector)| {
let payload: Payload = serde_json::json!({ "document": documents[id] })
.try_into()
.unwrap();
PointStruct::new(id as u64, vector, payload)
})
.collect();
documents[ ] ββ
ββ same index β (vector + payload) β PointStruct
embeddings[ ] ββ
Weβre strapping on the appropriate document to the id + embedding
Note the filter line?
Only keep the embeddings that have a real document attached, we skip the empty ones.
Also, note the * to deref the id?
Necessary because Rust doesnβt auto-deref tuple elements in closures.
Then, with map, we take a pair and turn it into a single “thing” that contains three bits of data, ready for the upsert to Qdrant!

Links:
https://qdrant.tech/documentation/fastembed/fastembed-semantic-search/
https://qdrant.tech/documentation/fastembed
https://crates.io/crates/fastembed
Massive thanks to Anush for making the FastEmbed crate!
If you liked this article and want to read part 2, here it is:

