vectra-client 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,536 @@
1
+ ---
2
+ layout: page
3
+ title: Real-World Examples
4
+ permalink: /examples/real-world/
5
+ ---
6
+
7
+ # Real-World Examples
8
+
9
+ Production-ready examples demonstrating Vectra in real-world scenarios.
10
+
11
+ ## E-Commerce Product Search
12
+
13
+ Semantic product search with filtering, caching, and performance optimization.
14
+
15
+ ```ruby
16
+ require "vectra"
17
+
18
+ class ProductSearchService
19
+ def initialize
20
+ @client = Vectra.pinecone(
21
+ api_key: ENV["PINECONE_API_KEY"],
22
+ environment: "us-east-1"
23
+ )
24
+
25
+ # Performance optimizations
26
+ @cache = Vectra::Cache.new(ttl: 600, max_size: 5000)
27
+ @cached_client = Vectra::CachedClient.new(@client, cache: @cache)
28
+
29
+ # Resilience patterns
30
+ @rate_limiter = Vectra::RateLimiter.new(requests_per_second: 100)
31
+ @circuit_breaker = Vectra::CircuitBreaker.new(
32
+ name: "product-search",
33
+ failure_threshold: 5,
34
+ recovery_timeout: 60
35
+ )
36
+ end
37
+
38
+ def search(query:, category: nil, price_range: nil, limit: 20)
39
+ query_embedding = generate_embedding(query)
40
+
41
+ filter = {}
42
+ filter[:category] = category if category
43
+ filter[:price_min] = price_range[:min] if price_range&.dig(:min)
44
+ filter[:price_max] = price_range[:max] if price_range&.dig(:max)
45
+
46
+ @rate_limiter.acquire do
47
+ @circuit_breaker.call do
48
+ @cached_client.query(
49
+ index: "products",
50
+ vector: query_embedding,
51
+ top_k: limit,
52
+ filter: filter,
53
+ include_metadata: true
54
+ )
55
+ end
56
+ end
57
+ rescue Vectra::RateLimitError => e
58
+ # Handle rate limiting gracefully
59
+ Rails.logger.warn("Rate limit hit: #{e.retry_after}s")
60
+ sleep(e.retry_after || 1)
61
+ retry
62
+ rescue Vectra::CircuitBreakerOpenError
63
+ # Fallback to cached results or alternative search
64
+ fallback_search(query, category)
65
+ end
66
+
67
+ private
68
+
69
+ def generate_embedding(text)
70
+ # Use your embedding model (OpenAI, sentence-transformers, etc.)
71
+ OpenAI::Client.new.embeddings(
72
+ parameters: { model: "text-embedding-ada-002", input: text }
73
+ )["data"][0]["embedding"]
74
+ end
75
+
76
+ def fallback_search(query, category)
77
+ # Fallback to database search or cached results
78
+ Product.where("name ILIKE ?", "%#{query}%")
79
+ .where(category: category)
80
+ .limit(20)
81
+ end
82
+ end
83
+
84
+ # Usage
85
+ service = ProductSearchService.new
86
+ results = service.search(
87
+ query: "wireless headphones with noise cancellation",
88
+ category: "Electronics",
89
+ price_range: { min: 50, max: 200 }
90
+ )
91
+
92
+ results.each do |product|
93
+ puts "#{product.metadata[:name]} - $#{product.metadata[:price]}"
94
+ end
95
+ ```
96
+
97
+ ## RAG Chatbot with Streaming
98
+
99
+ Retrieval-Augmented Generation chatbot with streaming responses and error handling.
100
+
101
+ ```ruby
102
+ require "vectra"
103
+
104
+ class RAGChatbot
105
+ def initialize
106
+ @vectra_client = Vectra.qdrant(
107
+ host: ENV["QDRANT_HOST"],
108
+ api_key: ENV["QDRANT_API_KEY"]
109
+ )
110
+
111
+ @llm_client = OpenAI::Client.new
112
+ @streaming = Vectra::Streaming.new(@vectra_client)
113
+
114
+ # Monitoring
115
+ Vectra::Instrumentation::Sentry.setup! if defined?(Sentry)
116
+ Vectra::Logging.setup!(output: "log/chatbot.json.log")
117
+ end
118
+
119
+ def chat(user_message:, conversation_id:, &block)
120
+ # 1. Retrieve relevant context
121
+ context = retrieve_context(user_message, limit: 5)
122
+
123
+ # 2. Build prompt with context
124
+ prompt = build_prompt(user_message, context)
125
+
126
+ # 3. Stream LLM response
127
+ stream_llm_response(prompt, conversation_id, &block)
128
+
129
+ # 4. Log interaction
130
+ log_interaction(user_message, context, conversation_id)
131
+ end
132
+
133
+ private
134
+
135
+ def retrieve_context(query, limit:)
136
+ query_embedding = generate_embedding(query)
137
+
138
+ results = @streaming.query_each(
139
+ index: "knowledge_base",
140
+ vector: query_embedding,
141
+ top_k: limit,
142
+ batch_size: 10,
143
+ include_metadata: true
144
+ ) do |batch|
145
+ # Process in batches for memory efficiency
146
+ batch
147
+ end
148
+
149
+ results.map { |r| r.metadata[:content] }.join("\n\n")
150
+ end
151
+
152
+ def build_prompt(user_message, context)
153
+ <<~PROMPT
154
+ You are a helpful assistant. Use the following context to answer the question.
155
+
156
+ Context:
157
+ #{context}
158
+
159
+ Question: #{user_message}
160
+
161
+ Answer:
162
+ PROMPT
163
+ end
164
+
165
+ def stream_llm_response(prompt, conversation_id, &block)
166
+ @llm_client.chat(
167
+ parameters: {
168
+ model: "gpt-4",
169
+ messages: [{ role: "user", content: prompt }],
170
+ stream: proc { |chunk, _bytesize|
171
+ block.call(chunk) if block
172
+ }
173
+ }
174
+ )
175
+ end
176
+
177
+ def log_interaction(user_message, context, conversation_id)
178
+ Vectra::Logging.log_info(
179
+ "Chat interaction",
180
+ conversation_id: conversation_id,
181
+ query_length: user_message.length,
182
+ context_snippets: context.split("\n\n").size
183
+ )
184
+ end
185
+
186
+ def generate_embedding(text)
187
+ # Embedding generation
188
+ @llm_client.embeddings(
189
+ parameters: { model: "text-embedding-ada-002", input: text }
190
+ )["data"][0]["embedding"]
191
+ end
192
+ end
193
+
194
+ # Usage with streaming
195
+ chatbot = RAGChatbot.new
196
+
197
+ chatbot.chat(
198
+ user_message: "How do I implement authentication in Rails?",
199
+ conversation_id: "conv-123"
200
+ ) do |chunk|
201
+ print chunk.dig("choices", 0, "delta", "content")
202
+ end
203
+ ```
204
+
205
+ ## Multi-Tenant SaaS Application
206
+
207
+ SaaS application with tenant isolation, audit logging, and health monitoring.
208
+
209
+ ```ruby
210
+ require "vectra"
211
+
212
+ class TenantDocumentService
213
+ def initialize(tenant_id:)
214
+ @tenant_id = tenant_id
215
+ @client = Vectra.pgvector(
216
+ connection_url: ENV["DATABASE_URL"],
217
+ pool_size: 10
218
+ )
219
+
220
+ # Audit logging for compliance
221
+ @audit = Vectra::AuditLog.new(
222
+ output: "log/audit.json.log",
223
+ enabled: true
224
+ )
225
+
226
+ # Health monitoring
227
+ @health_checker = Vectra::AggregateHealthCheck.new(
228
+ primary: @client
229
+ )
230
+ end
231
+
232
+ def index_document(document_id:, content:, metadata: {})
233
+ embedding = generate_embedding(content)
234
+
235
+ result = @client.upsert(
236
+ index: "documents",
237
+ vectors: [{
238
+ id: document_id,
239
+ values: embedding,
240
+ metadata: metadata.merge(tenant_id: @tenant_id)
241
+ }],
242
+ namespace: "tenant-#{@tenant_id}"
243
+ )
244
+
245
+ # Audit log
246
+ @audit.log_data_modification(
247
+ user_id: current_user&.id,
248
+ operation: "upsert",
249
+ index: "documents",
250
+ record_count: 1
251
+ )
252
+
253
+ result
254
+ end
255
+
256
+ def search_documents(query:, limit: 20)
257
+ query_embedding = generate_embedding(query)
258
+
259
+ # Ensure tenant isolation via namespace
260
+ results = @client.query(
261
+ index: "documents",
262
+ vector: query_embedding,
263
+ top_k: limit,
264
+ namespace: "tenant-#{@tenant_id}",
265
+ filter: { tenant_id: @tenant_id }, # Double protection
266
+ include_metadata: true
267
+ )
268
+
269
+ # Audit log
270
+ @audit.log_access(
271
+ user_id: current_user&.id,
272
+ operation: "query",
273
+ index: "documents",
274
+ result_count: results.size
275
+ )
276
+
277
+ results
278
+ end
279
+
280
+ def health_status
281
+ @health_checker.check_all
282
+ end
283
+
284
+ private
285
+
286
+ def generate_embedding(text)
287
+ # Your embedding generation
288
+ end
289
+ end
290
+
291
+ # Usage per tenant
292
+ tenant_service = TenantDocumentService.new(tenant_id: "acme-corp")
293
+
294
+ # Index document (isolated to tenant)
295
+ tenant_service.index_document(
296
+ document_id: "doc-123",
297
+ content: "Important business document...",
298
+ metadata: { title: "Q4 Report", category: "Finance" }
299
+ )
300
+
301
+ # Search (only returns tenant's documents)
302
+ results = tenant_service.search_documents(query: "financial report")
303
+
304
+ # Health check
305
+ health = tenant_service.health_status
306
+ puts "System healthy: #{health[:overall_healthy]}"
307
+ ```
308
+
309
+ ## High-Performance Batch Processing
310
+
311
+ Processing large datasets with async batch operations and progress tracking.
312
+
313
+ ```ruby
314
+ require "vectra"
315
+
316
+ class DocumentIndexer
317
+ def initialize
318
+ @client = Vectra.pinecone(
319
+ api_key: ENV["PINECONE_API_KEY"],
320
+ environment: "us-east-1"
321
+ )
322
+
323
+ @batch_client = Vectra::Batch.new(@client)
324
+ end
325
+
326
+ def index_large_dataset(documents, concurrency: 4)
327
+ total = documents.size
328
+ processed = 0
329
+ errors = []
330
+
331
+ # Convert to vectors
332
+ vectors = documents.map do |doc|
333
+ {
334
+ id: doc[:id],
335
+ values: generate_embedding(doc[:content]),
336
+ metadata: doc[:metadata]
337
+ }
338
+ end
339
+
340
+ # Process in async batches
341
+ result = @batch_client.upsert_async(
342
+ index: "documents",
343
+ vectors: vectors,
344
+ concurrency: concurrency,
345
+ on_progress: proc { |success, failed, total|
346
+ processed = success + failed
347
+ progress = (processed.to_f / total * 100).round(1)
348
+ puts "Progress: #{progress}% (#{processed}/#{total})"
349
+ },
350
+ on_error: proc { |error, vector|
351
+ errors << { id: vector[:id], error: error.message }
352
+ }
353
+ )
354
+
355
+ {
356
+ success: result[:success],
357
+ failed: result[:failed],
358
+ errors: errors,
359
+ total: total
360
+ }
361
+ end
362
+
363
+ private
364
+
365
+ def generate_embedding(text)
366
+ # Embedding generation
367
+ end
368
+ end
369
+
370
+ # Usage
371
+ indexer = DocumentIndexer.new
372
+
373
+ # Index 10,000 documents with 4 concurrent workers
374
+ result = indexer.index_large_dataset(
375
+ large_document_array,
376
+ concurrency: 4
377
+ )
378
+
379
+ puts "Indexed: #{result[:success]}"
380
+ puts "Failed: #{result[:failed]}"
381
+ puts "Errors: #{result[:errors].size}"
382
+ ```
383
+
384
+ ## Production-Ready Configuration
385
+
386
+ Complete production setup with all monitoring, resilience, and performance features.
387
+
388
+ ```ruby
389
+ # config/initializers/vectra.rb
390
+ require "vectra"
391
+
392
+ Vectra.configure do |config|
393
+ config.provider = :pinecone
394
+ config.api_key = Rails.application.credentials.dig(:vectra, :api_key)
395
+ config.environment = ENV["PINECONE_ENVIRONMENT"] || "us-east-1"
396
+
397
+ # Performance
398
+ config.cache_enabled = true
399
+ config.cache_ttl = 600
400
+ config.cache_max_size = 10000
401
+ config.async_concurrency = 4
402
+ config.batch_size = 100
403
+
404
+ # Resilience
405
+ config.max_retries = 3
406
+ config.retry_delay = 1
407
+ config.timeout = 30
408
+
409
+ # Logging
410
+ config.logger = Rails.logger
411
+ end
412
+
413
+ # Setup monitoring
414
+ if defined?(Sentry)
415
+ Vectra::Instrumentation::Sentry.setup!
416
+ end
417
+
418
+ if defined?(Honeybadger)
419
+ Vectra::Instrumentation::Honeybadger.setup!
420
+ end
421
+
422
+ # Setup structured logging
423
+ Vectra::Logging.setup!(
424
+ output: Rails.root.join("log", "vectra.json.log"),
425
+ app: Rails.application.class.module_parent_name,
426
+ env: Rails.env
427
+ )
428
+
429
+ # Setup audit logging
430
+ Vectra::AuditLogging.setup!(
431
+ output: Rails.root.join("log", "audit.json.log"),
432
+ enabled: Rails.env.production?,
433
+ app: Rails.application.class.module_parent_name,
434
+ env: Rails.env
435
+ )
436
+
437
+ # Global rate limiter
438
+ $vectra_rate_limiter = Vectra::RateLimiter.new(
439
+ requests_per_second: ENV.fetch("VECTRA_RATE_LIMIT", 100).to_i,
440
+ burst_size: ENV.fetch("VECTRA_BURST_SIZE", 200).to_i
441
+ )
442
+
443
+ # Global circuit breaker
444
+ $vectra_circuit_breaker = Vectra::CircuitBreaker.new(
445
+ name: "vectra-main",
446
+ failure_threshold: 5,
447
+ recovery_timeout: 60
448
+ )
449
+
450
+ # Application helper
451
+ module VectraHelper
452
+ def vectra_client
453
+ @vectra_client ||= begin
454
+ client = Vectra::Client.new
455
+ cached = Vectra::CachedClient.new(client)
456
+ cached
457
+ end
458
+ end
459
+
460
+ def safe_vectra_query(**args)
461
+ $vectra_rate_limiter.acquire do
462
+ $vectra_circuit_breaker.call do
463
+ vectra_client.query(**args)
464
+ end
465
+ end
466
+ rescue Vectra::CircuitBreakerOpenError
467
+ # Fallback logic
468
+ Rails.logger.error("Circuit breaker open, using fallback")
469
+ fallback_search(args)
470
+ rescue Vectra::RateLimitError => e
471
+ Rails.logger.warn("Rate limit: #{e.retry_after}s")
472
+ sleep(e.retry_after || 1)
473
+ retry
474
+ end
475
+ end
476
+ ```
477
+
478
+ ## Best Practices
479
+
480
+ ### 1. Always Use Caching for Frequent Queries
481
+
482
+ ```ruby
483
+ cache = Vectra::Cache.new(ttl: 600, max_size: 10000)
484
+ cached_client = Vectra::CachedClient.new(client, cache: cache)
485
+ ```
486
+
487
+ ### 2. Implement Rate Limiting
488
+
489
+ ```ruby
490
+ limiter = Vectra::RateLimiter.new(requests_per_second: 100)
491
+ limiter.acquire { client.query(...) }
492
+ ```
493
+
494
+ ### 3. Use Circuit Breaker for Resilience
495
+
496
+ ```ruby
497
+ breaker = Vectra::CircuitBreaker.new(failure_threshold: 5)
498
+ breaker.call { client.query(...) }
499
+ ```
500
+
501
+ ### 4. Enable Monitoring
502
+
503
+ ```ruby
504
+ Vectra::Instrumentation::Sentry.setup!
505
+ Vectra::Logging.setup!(output: "log/vectra.json.log")
506
+ ```
507
+
508
+ ### 5. Audit Critical Operations
509
+
510
+ ```ruby
511
+ audit = Vectra::AuditLog.new(output: "log/audit.json.log")
512
+ audit.log_access(user_id: user.id, operation: "query", index: "docs")
513
+ ```
514
+
515
+ ### 6. Use Streaming for Large Queries
516
+
517
+ ```ruby
518
+ streaming = Vectra::Streaming.new(client)
519
+ streaming.query_each(index: "docs", vector: vec, batch_size: 100) do |batch|
520
+ process_batch(batch)
521
+ end
522
+ ```
523
+
524
+ ### 7. Health Checks in Production
525
+
526
+ ```ruby
527
+ health = client.health_check(include_stats: true)
528
+ raise "Unhealthy" unless health.healthy?
529
+ ```
530
+
531
+ ## Next Steps
532
+
533
+ - [Comprehensive Demo](../examples/) - Full feature demonstration
534
+ - [Performance Guide](../guides/performance/) - Optimization strategies
535
+ - [Monitoring Guide](../guides/monitoring/) - Production monitoring
536
+ - [Security Guide](../guides/security/) - Security best practices
Binary file
@@ -138,6 +138,56 @@ run YourApp
138
138
 
139
139
  ## Grafana Dashboard
140
140
 
141
+ ### Live Dashboard Preview
142
+
143
+ Vectra includes a comprehensive Grafana dashboard with 11 professional panels for monitoring all aspects of your vector database operations:
144
+
145
+ <div class="tma-dashboard-showcase">
146
+ <div class="tma-dashboard-showcase__image">
147
+ <img src="{{ site.baseurl }}/grafana_final.png" alt="Vectra Grafana Dashboard - Real-time monitoring of vector database operations" class="tma-dashboard-screenshot">
148
+ </div>
149
+ <div class="tma-dashboard-showcase__features">
150
+ <h4>Dashboard Features</h4>
151
+ <ul>
152
+ <li><strong>Real-time Metrics:</strong> Request rate, latency, error tracking</li>
153
+ <li><strong>Performance Monitoring:</strong> P50, P95, P99 latency percentiles</li>
154
+ <li><strong>Cache Analytics:</strong> Hit ratio and performance metrics</li>
155
+ <li><strong>Provider Insights:</strong> Multi-provider comparison and distribution</li>
156
+ <li><strong>Connection Pooling:</strong> pgvector pool status and utilization</li>
157
+ <li><strong>Visual Analytics:</strong> Time series, pie charts, bar gauges</li>
158
+ </ul>
159
+ <div class="tma-dashboard-showcase__actions">
160
+ <a href="https://github.com/stokry/vectra/tree/main/examples#grafana-dashboard" class="tma-button tma-button--primary" target="_blank" rel="noopener">
161
+ Get Dashboard JSON →
162
+ </a>
163
+ <a href="https://github.com/stokry/vectra/blob/main/examples/GRAFANA_QUICKSTART.md" class="tma-button tma-button--secondary" target="_blank" rel="noopener">
164
+ Quick Start Guide →
165
+ </a>
166
+ </div>
167
+ </div>
168
+ </div>
169
+
170
+ ### Quick Setup
171
+
172
+ Get started in 5 minutes:
173
+
174
+ 1. **Start Prometheus Exporter:**
175
+ ```bash
176
+ gem install prometheus-client
177
+ ruby examples/prometheus-exporter.rb
178
+ ```
179
+
180
+ 2. **Import Dashboard:**
181
+ - Sign up at [grafana.com](https://grafana.com) (free tier available)
182
+ - Add Prometheus data source
183
+ - Import `examples/grafana-dashboard.json`
184
+
185
+ 3. **View Metrics:**
186
+ - Dashboard populates with real-time data
187
+ - Perfect for monitoring and screenshots
188
+
189
+ See the [Quick Start Guide](https://github.com/stokry/vectra/blob/main/examples/GRAFANA_QUICKSTART.md) for detailed setup instructions.
190
+
141
191
  ### Dashboard JSON Template
142
192
 
143
193
  Save as `vectra-dashboard.json` and import into Grafana: