use allama::mock::MockEmbeddingProvider;
use allama::prelude::*;
use allama::{ChunkedEmbeddingProgress, EmbeddingInputType, EmbeddingResponse};
use futures_util::StreamExt;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let provider = MockEmbeddingProvider::new([
Ok(EmbeddingResponse::new(vec![
vec![0.1, 0.2, 0.3],
vec![0.4, 0.5, 0.6],
])),
Ok(EmbeddingResponse::new(vec![vec![0.7, 0.8, 0.9]])),
Ok(EmbeddingResponse::new(vec![vec![1.0], vec![2.0]])),
Ok(EmbeddingResponse::new(vec![vec![3.0]])),
Ok(EmbeddingResponse::new(vec![vec![0.5, 0.5]])),
Ok(EmbeddingResponse::new(vec![vec![1.0], vec![2.0]])),
Err(Error::rate_limited("slow down")),
Ok(EmbeddingResponse::new(vec![vec![3.0], vec![4.0]])),
Ok(EmbeddingResponse::new(vec![vec![5.0]])),
]);
let request = EmbeddingRequest::new("demo-embedding-model")
.inputs(["hello world", "embedding demo"])
.dimensions(3);
for (index, vector) in provider
.embed(&request)
.await?
.embeddings
.iter()
.enumerate()
{
println!("embedding[{index}] = {vector:?}");
}
let single = provider
.embed_input("demo-embedding-model", "quick one-shot")
.await?;
println!("single-input vector: {single:?}");
let batch = EmbeddingRequest::new("demo-embedding-model").inputs(["a", "b", "c"]);
let combined = provider.embed_chunked(&batch, 2).await?;
println!("chunked vectors: {:?}", combined.embeddings);
let search = EmbeddingRequest::new("demo-embedding-model")
.input("Which language is simple?")
.input_type(EmbeddingInputType::Query);
let response = provider.embed(&search).await?;
println!(
"query vector: {:?} ({} warnings)",
response.embeddings[0],
response.warnings.len()
);
let corpus = EmbeddingRequest::new("demo-embedding-model").inputs(["a", "b", "c", "d", "e"]);
let mut stored: Vec<Vec<f32>> = Vec::new();
let mut next = 0;
while next < corpus.inputs.len() {
let mut rest = corpus.clone();
rest.inputs.drain(..next);
let mut chunks = std::pin::pin!(provider.embed_chunks(&rest, 2));
while let Some(chunk) = chunks.next().await {
match chunk {
Ok(chunk) => {
println!(
"stored inputs {}..{}",
next + chunk.offset,
next + chunk.end()
);
stored.extend(chunk.response.embeddings);
}
Err(err) if err.is_retryable() => {
let progress = ChunkedEmbeddingProgress::from_error(&err)
.expect("a chunked call attaches its progress");
println!(
"chunk failed ({err}); resuming at input {}",
next + progress.completed_inputs
);
}
Err(err) => return Err(err.into()),
}
}
next = stored.len();
}
println!("indexed {} vectors", stored.len());
Ok(())
}