1use casper_client::{
2 CasperClient,
3 CreateCollectionRequest,
4 InsertRequest,
5 SearchRequest,
6 BatchUpdateRequest,
7 BatchInsertOperation,
8 CreateHNSWIndexRequest,
9 HNSWIndexConfig,
10 CreatePqRequest,
11};
12
13#[tokio::main]
14async fn main() -> Result<(), Box<dyn std::error::Error>> {
15 let host = std::env::var("CASPER_HOST")
17 .unwrap_or_else(|_| "http://127.0.0.1".to_string());
18 let http_port: u16 = std::env::var("CASPER_HTTP_PORT")
19 .ok()
20 .and_then(|v| v.parse().ok())
21 .unwrap_or(8080);
22 let grpc_port: u16 = std::env::var("CASPER_GRPC_PORT")
23 .ok()
24 .and_then(|v| v.parse().ok())
25 .unwrap_or(50051);
26
27 let client = CasperClient::new(&host, http_port, grpc_port)?;
29
30 println!("Casper Vector Database Client Example");
31
32 println!("\nCreating collection...");
34 let create_request = CreateCollectionRequest {
35 dim: 128,
36 max_size: 10000,
37 };
38 client.create_collection("example_collection", create_request).await?;
39 println!("Collection 'example_collection' created successfully");
40
41 println!("\nInserting vectors...");
43 for i in 1..=5 {
44 let vector = generate_random_vector(128, i as f32);
45 let insert_request = InsertRequest {
46 id: i,
47 vector,
48 };
49 client.insert_vector("example_collection", insert_request).await?;
50 println!("Vector {} inserted", i);
51 }
52
53 println!("\nBatch inserting vectors...");
55 let mut inserts = Vec::new();
56 for i in 6..=10 {
57 let vector = generate_random_vector(128, i as f32);
58 inserts.push(BatchInsertOperation { id: i, vector });
59 }
60 let batch_request = BatchUpdateRequest { insert: inserts, delete: vec![] };
61 client.batch_update("example_collection", batch_request).await?;
62 println!("Batch insert completed");
63
64 println!("\nCreating HNSW index...");
66 let hnsw_request = CreateHNSWIndexRequest {
67 hnsw: HNSWIndexConfig {
68 metric: "inner-product".to_string(),
69 quantization: "f32".to_string(),
70 m: 16,
71 m0: 32,
72 ef_construction: 200,
73 pq_name: None,
74 },
75 normalization: Some(true),
76 };
77 client.create_hnsw_index("example_collection", hnsw_request).await?;
78 println!("HNSW index created");
79
80 println!("\nSearching for similar vectors...");
82 let query_vector = generate_random_vector(128, 1.0);
83 let search_request = SearchRequest {
84 vector: query_vector,
85 limit: Some(5),
86 };
87 let results = client.search("example_collection", 30, search_request).await?;
88
89 println!("Found {} similar vectors:", results.len());
90 for (i, result) in results.iter().enumerate() {
91 println!(" {}. ID: {}, Score: {:.4}", i + 1, result.id, result.score);
92 }
93
94 println!("\nGetting vector by ID...");
96 if let Some(vector) = client.get_vector("example_collection", 1).await? {
97 println!("Vector 1 retrieved: {} dimensions", vector.len());
98 } else {
99 println!("Vector 1 not found");
100 }
101
102 println!("\nDeleting vector...");
104 client.delete_vector("example_collection", casper_client::DeleteRequest { id: 10 }).await?;
105 println!("Vector 10 deleted");
106
107 println!("\nGetting collection information...");
109 let collection_info = client.get_collection("example_collection").await?;
110 println!("Collection info retrieved:");
111 println!(" - Name: {}", collection_info.name);
112 println!(" - Dimension: {}", collection_info.dimension);
113 println!(" - Mutable: {}", collection_info.mutable);
114 println!(" - Has index: {}", collection_info.has_index);
115 println!(" - Max size: {}", collection_info.max_size);
116 if let Some(index) = collection_info.index {
117 if let Some(hnsw) = index.hnsw {
118 println!(" - Index: HNSW");
119 println!(" - Metric: {}", hnsw.metric);
120 println!(" - Quantization: {}", hnsw.quantization);
121 println!(" - M: {}", hnsw.m);
122 println!(" - M0: {}", hnsw.m0);
123 println!(" - Ef construction: {}", hnsw.ef_construction);
124 println!(" - Normalization: {}", index.normalization);
125 } else {
126 println!(" - Index present (non-HNSW)");
127 }
128 }
129
130 println!("\nListing collections...");
132 let collections = client.list_collections().await?;
133 println!("Found {} collections:", collections.collections.len());
134 for collection in collections.collections {
135 println!(" - {} (dim: {}, size: {}, mutable: {}, has_index: {})",
136 collection.name,
137 collection.dimension,
138 collection.size,
139 collection.mutable,
140 collection.has_index);
141 }
142
143 println!("\nDeleting index...");
145 client.delete_index("example_collection").await?;
146 println!("Index deleted successfully");
147
148 println!("\nDeleting collection...");
150 client.delete_collection("example_collection").await?;
151 println!("Collection 'example_collection' deleted successfully");
152
153 println!("\nCreating matrices via gRPC...");
155
156 let dim = 3usize;
157 let m1_name = "example_matrix_1";
158 let m2_name = "example_matrix_2";
159
160 let m1_vectors: Vec<f32> = vec![
162 1.0, 2.0, 3.0,
163 4.0, 5.0, 6.0,
164 ];
165 let m2_vectors: Vec<f32> = vec![
166 0.1, 0.2, 0.3,
167 0.4, 0.5, 0.6,
168 ];
169
170 let res1 = client
171 .upload_matrix(m1_name, dim, m1_vectors.clone(), 6)
172 .await?;
173 println!("Uploaded matrix '{}' via gRPC: {}", m1_name, res1.message);
174
175 let res2 = client
176 .upload_matrix(m2_name, dim, m2_vectors.clone(), 6)
177 .await?;
178 println!("Uploaded matrix '{}' via gRPC: {}", m2_name, res2.message);
179
180 println!("\nListing matrices...");
181 let matrices = client.list_matrices().await?;
182 println!("Found {} matrices:", matrices.len());
183 for m in &matrices {
184 println!(
185 " - {} (dim: {}, len: {}, enabled: {})",
186 m.name, m.dim, m.len, m.enabled
187 );
188 }
189
190 println!("\nGetting matrix info individually...");
191 let info1 = client.get_matrix_info(m1_name).await?;
192 println!(
193 " - {}: dim={}, len={}, enabled={}",
194 info1.name, info1.dim, info1.len, info1.enabled
195 );
196 let info2 = client.get_matrix_info(m2_name).await?;
197 println!(
198 " - {}: dim={}, len={}, enabled={}",
199 info2.name, info2.dim, info2.len, info2.enabled
200 );
201
202 println!("\nCreating PQ...");
204 let pq_name = "example_pq";
205 let pq_request = CreatePqRequest {
208 dim: dim * 2, codebooks: vec![m1_name.to_string(), m2_name.to_string()],
210 };
211
212 match client.create_pq(pq_name, pq_request).await {
213 Ok(()) => println!("PQ '{}' created", pq_name),
214 Err(e) => {
215 println!("Failed to create PQ '{}': {}", pq_name, e);
216 }
217 }
218
219 println!("\nListing PQs...");
220 let pqs = client.list_pqs().await?;
221 println!("Found {} PQs:", pqs.len());
222 for pq in &pqs {
223 println!(
224 " - {} (dim: {}, codebooks: {:?}, enabled: {})",
225 pq.name, pq.dim, pq.codebooks, pq.enabled
226 );
227 }
228
229 println!("\nGetting PQ info individually...");
230 match client.get_pq(pq_name).await {
231 Ok(pq_info) => {
232 println!(
233 " - {}: dim={}, codebooks={:?}, enabled={}",
234 pq_info.name, pq_info.dim, pq_info.codebooks, pq_info.enabled
235 );
236 }
237 Err(e) => {
238 println!("Failed to get PQ '{}': {}", pq_name, e);
239 }
240 }
241
242 println!("\nDeleting PQ '{}'...", pq_name);
243 match client.delete_pq(pq_name).await {
244 Ok(()) => println!("PQ '{}' deleted", pq_name),
245 Err(e) => println!("Failed to delete PQ '{}': {}", pq_name, e),
246 }
247
248 println!("\nDeleting matrices '{}' and '{}'...", m1_name, m2_name);
250 client.delete_matrix(m1_name).await?;
251 client.delete_matrix(m2_name).await?;
252 println!("Matrices '{}' and '{}' deleted", m1_name, m2_name);
253
254 let matrices_after = client.list_matrices().await?;
255 println!("Matrices after deletion ({} total):", matrices_after.len());
256 for m in &matrices_after {
257 println!(
258 " - {} (dim: {}, len: {}, enabled: {})",
259 m.name, m.dim, m.len, m.enabled
260 );
261 }
262
263 println!("\nExample completed successfully!");
264 Ok(())
265}
266
267fn generate_random_vector(dim: usize, seed: f32) -> Vec<f32> {
269 use std::collections::hash_map::DefaultHasher;
270 use std::hash::{Hash, Hasher};
271
272 let mut vector = Vec::with_capacity(dim);
273 for i in 0..dim {
274 let mut hasher = DefaultHasher::new();
275 (seed * 1000.0 + i as f32).to_bits().hash(&mut hasher);
276 let hash = hasher.finish();
277 let value = (hash as f32 / u64::MAX as f32) * 2.0 - 1.0; vector.push(value);
279 }
280
281 let norm: f32 = vector.iter().map(|x| x * x).sum::<f32>().sqrt();
283 if norm > 0.0 {
284 for value in &mut vector {
285 *value /= norm;
286 }
287 }
288
289 vector
290}