Class: HTM::EmbeddingService
- Inherits:
-
Object
- Object
- HTM::EmbeddingService
- Defined in:
- lib/htm/embedding_service.rb
Overview
Embedding Service - Processes and validates vector embeddings
This service wraps the configured embedding generator and provides:
-
Response validation
-
Dimension handling (padding/truncation)
-
Error handling and logging
-
Storage formatting
-
Circuit breaker protection for external LLM failures
The actual LLM call is delegated to HTM.configuration.embedding_generator
Class Method Summary collapse
-
.circuit_breaker ⇒ HTM::CircuitBreaker
Get or create the circuit breaker for embedding service.
-
.format_for_storage(embedding) ⇒ String
Format embedding for database storage.
-
.generate(text) ⇒ Hash
Generate embedding with validation and processing.
-
.max_dimension ⇒ Integer
Maximum embedding dimension (configurable, default 2000).
-
.pad_embedding(embedding) ⇒ Array<Float>
Pad embedding to max_dimension with zeros.
-
.reset_circuit_breaker! ⇒ void
Reset the circuit breaker (useful for testing).
-
.validate_embedding!(embedding) ⇒ Object
Validate embedding response format.
Class Method Details
.circuit_breaker ⇒ HTM::CircuitBreaker
Get or create the circuit breaker for embedding service
35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/htm/embedding_service.rb', line 35 def circuit_breaker config = HTM.configuration @circuit_breaker_mutex.synchronize do @circuit_breaker ||= HTM::CircuitBreaker.new( name: 'embedding_service', failure_threshold: config.circuit_breaker_failure_threshold, reset_timeout: config.circuit_breaker_reset_timeout, half_open_max_calls: config.circuit_breaker_half_open_max_calls ) end end |
.format_for_storage(embedding) ⇒ String
Format embedding for database storage
149 150 151 |
# File 'lib/htm/embedding_service.rb', line 149 def self.format_for_storage() "[#{.join(',')}]" end |
.generate(text) ⇒ Hash
Generate embedding with validation and processing
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/htm/embedding_service.rb', line 70 def self.generate(text) # Use circuit breaker to protect against cascading failures = circuit_breaker.call do HTM.configuration..call(text) end # Validate response () # Get actual dimension actual_dimension = .length # Check dimension limit max_dim = max_dimension if actual_dimension > max_dim HTM.logger.warn "EmbeddingService: Embedding dimension #{actual_dimension} exceeds max #{max_dim}, truncating" = [0...max_dim] actual_dimension = max_dim end # Pad to max dimensions for consistent storage = () # Format for database storage storage_string = format_for_storage() { embedding: , dimension: actual_dimension, storage_embedding: storage_string, storage_dimension: max_dim } rescue HTM::CircuitBreakerOpenError, HTM::EmbeddingError raise rescue StandardError => e HTM.logger.error "EmbeddingService: Failed to generate embedding: #{e.}" raise HTM::EmbeddingError, "Embedding generation failed: #{e.}" end |
.max_dimension ⇒ Integer
Maximum embedding dimension (configurable, default 2000)
27 28 29 |
# File 'lib/htm/embedding_service.rb', line 27 def max_dimension HTM.configuration. end |
.pad_embedding(embedding) ⇒ Array<Float>
Pad embedding to max_dimension with zeros
137 138 139 140 141 142 |
# File 'lib/htm/embedding_service.rb', line 137 def self.() max_dim = max_dimension return if .length >= max_dim + Array.new(max_dim - .length, 0.0) end |
.reset_circuit_breaker! ⇒ void
This method returns an undefined value.
Reset the circuit breaker (useful for testing)
51 52 53 54 55 |
# File 'lib/htm/embedding_service.rb', line 51 def reset_circuit_breaker! @circuit_breaker_mutex.synchronize do @circuit_breaker&.reset! end end |
.validate_embedding!(embedding) ⇒ Object
Validate embedding response format
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/htm/embedding_service.rb', line 114 def self.() unless .is_a?(Array) raise HTM::EmbeddingError, "Embedding must be an Array, got #{.class}" end if .empty? raise HTM::EmbeddingError, "Embedding array is empty" end unless .all?(Numeric) raise HTM::EmbeddingError, "Embedding must contain only numeric values" end # Check for NaN or Infinity return unless .any? { |v| (v.respond_to?(:nan?) && v.nan?) || (v.respond_to?(:infinite?) && v.infinite?) } raise HTM::EmbeddingError, "Embedding contains NaN or Infinity values" end |