vectra-client 1.0.7 → 1.0.8
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/docs/api/cheatsheet.md +43 -0
- data/docs/api/methods.md +30 -6
- data/lib/vectra/active_record.rb +52 -1
- data/lib/vectra/cache.rb +49 -0
- data/lib/vectra/client.rb +77 -13
- data/lib/vectra/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '05778206f66d4e2ead830f5b7c5885f6336b46d36af696f3df5a56eb26163c5f'
|
|
4
|
+
data.tar.gz: 1ae5814cd10df006ecf5568f34e457400b072ecc8a06dbf85a4e4f5b94120fb9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d25889a4626c9caa9edf7ccc285c849799de87cf38a8a7a6f56a49edb46da592b28bc0232960e2612fd0d9199e990c21bd5fe6b88f15351d8ff38c73bd7afc84
|
|
7
|
+
data.tar.gz: d4ef355089814ed4caf8c61e216b9554f23035df12be72a65c778b3230bd2a32f16ecf4c50de3bc33e40dc323f1aee83d7a891ad962bec105585c8bc6b30902b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v1.0.8](https://github.com/stokry/vectra/tree/v1.0.8) (2026-01-14)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/stokry/vectra/compare/v1.0.7...v1.0.8)
|
|
6
|
+
|
|
3
7
|
## [v1.0.7](https://github.com/stokry/vectra/tree/v1.0.7) (2026-01-14)
|
|
4
8
|
|
|
5
9
|
[Full Changelog](https://github.com/stokry/vectra/compare/v1.0.6...v1.0.7)
|
data/docs/api/cheatsheet.md
CHANGED
|
@@ -34,6 +34,21 @@ client = Vectra.pgvector(connection_url: ENV['DATABASE_URL'])
|
|
|
34
34
|
client = Vectra.memory # In-memory (testing only)
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
You can also set a **default index and namespace**:
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
client = Vectra::Client.new(
|
|
41
|
+
provider: :qdrant,
|
|
42
|
+
host: 'http://localhost:6333',
|
|
43
|
+
index: 'products',
|
|
44
|
+
namespace: 'tenant-1'
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Now index and namespace can be omitted
|
|
48
|
+
client.upsert(vectors: [...])
|
|
49
|
+
client.query(vector: query_embedding, top_k: 10)
|
|
50
|
+
```
|
|
51
|
+
|
|
37
52
|
### Upsert
|
|
38
53
|
|
|
39
54
|
```ruby
|
|
@@ -225,6 +240,22 @@ vector.normalize! # Mutates values
|
|
|
225
240
|
client.upsert(index: 'documents', vectors: [vector])
|
|
226
241
|
```
|
|
227
242
|
|
|
243
|
+
### Embedding Cache Helper
|
|
244
|
+
|
|
245
|
+
```ruby
|
|
246
|
+
cache = Vectra::Cache.new(ttl: 600, max_size: 1000)
|
|
247
|
+
|
|
248
|
+
embedding = Vectra::Embeddings.fetch(
|
|
249
|
+
cache: cache,
|
|
250
|
+
model_name: "Product",
|
|
251
|
+
id: product.id,
|
|
252
|
+
input: product.description,
|
|
253
|
+
field: :description
|
|
254
|
+
) do
|
|
255
|
+
EmbeddingService.generate(product.description)
|
|
256
|
+
end
|
|
257
|
+
```
|
|
258
|
+
|
|
228
259
|
---
|
|
229
260
|
|
|
230
261
|
## Batch Operations
|
|
@@ -318,6 +349,18 @@ results.each do |doc|
|
|
|
318
349
|
end
|
|
319
350
|
```
|
|
320
351
|
|
|
352
|
+
### Reindex All Records
|
|
353
|
+
|
|
354
|
+
```ruby
|
|
355
|
+
# Reindex all documents that already have embeddings
|
|
356
|
+
processed = Document.reindex_vectors(
|
|
357
|
+
scope: Document.where.not(embedding: nil),
|
|
358
|
+
batch_size: 500
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
puts "Reindexed #{processed} documents"
|
|
362
|
+
```
|
|
363
|
+
|
|
321
364
|
---
|
|
322
365
|
|
|
323
366
|
## Error Handling
|
data/docs/api/methods.md
CHANGED
|
@@ -43,7 +43,7 @@ client = Vectra::Client.new(
|
|
|
43
43
|
Upsert vectors into an index. If a vector with the same ID exists, it will be updated.
|
|
44
44
|
|
|
45
45
|
**Parameters:**
|
|
46
|
-
- `index` (String) - Index/collection name
|
|
46
|
+
- `index` (String) - Index/collection name (uses client's default index when omitted)
|
|
47
47
|
- `vectors` (Array<Hash, Vector>) - Array of vector hashes or Vector objects
|
|
48
48
|
- `namespace` (String, optional) - Namespace
|
|
49
49
|
|
|
@@ -77,7 +77,7 @@ result = client.upsert(
|
|
|
77
77
|
Search for similar vectors using cosine similarity.
|
|
78
78
|
|
|
79
79
|
**Parameters:**
|
|
80
|
-
- `index` (String) - Index/collection name
|
|
80
|
+
- `index` (String) - Index/collection name (uses client's default index when omitted)
|
|
81
81
|
- `vector` (Array<Float>) - Query vector
|
|
82
82
|
- `top_k` (Integer) - Number of results (default: 10)
|
|
83
83
|
- `namespace` (String, optional) - Namespace
|
|
@@ -152,7 +152,7 @@ results = client.hybrid_search(
|
|
|
152
152
|
Fetch vectors by their IDs.
|
|
153
153
|
|
|
154
154
|
**Parameters:**
|
|
155
|
-
- `index` (String) - Index/collection name
|
|
155
|
+
- `index` (String) - Index/collection name (uses client's default index when omitted)
|
|
156
156
|
- `ids` (Array<String>) - Array of vector IDs
|
|
157
157
|
- `namespace` (String, optional) - Namespace
|
|
158
158
|
|
|
@@ -176,7 +176,7 @@ vectors['doc-1'].metadata # => { 'title' => 'Hello' }
|
|
|
176
176
|
Update a vector's metadata or values.
|
|
177
177
|
|
|
178
178
|
**Parameters:**
|
|
179
|
-
- `index` (String) - Index/collection name
|
|
179
|
+
- `index` (String) - Index/collection name (uses client's default index when omitted)
|
|
180
180
|
- `id` (String) - Vector ID
|
|
181
181
|
- `metadata` (Hash, optional) - New metadata (merged with existing)
|
|
182
182
|
- `values` (Array<Float>, optional) - New vector values
|
|
@@ -202,7 +202,7 @@ client.update(
|
|
|
202
202
|
Delete vectors.
|
|
203
203
|
|
|
204
204
|
**Parameters:**
|
|
205
|
-
- `index` (String) - Index/collection name
|
|
205
|
+
- `index` (String) - Index/collection name (uses client's default index when omitted)
|
|
206
206
|
- `ids` (Array<String>, optional) - Vector IDs to delete
|
|
207
207
|
- `namespace` (String, optional) - Namespace
|
|
208
208
|
- `filter` (Hash, optional) - Delete by metadata filter
|
|
@@ -231,7 +231,7 @@ client.delete(index: 'documents', delete_all: true)
|
|
|
231
231
|
Get index statistics.
|
|
232
232
|
|
|
233
233
|
**Parameters:**
|
|
234
|
-
- `index` (String) - Index/collection name
|
|
234
|
+
- `index` (String) - Index/collection name (uses client's default index when omitted)
|
|
235
235
|
- `namespace` (String, optional) - Namespace
|
|
236
236
|
|
|
237
237
|
**Returns:** `Hash` with statistics:
|
|
@@ -571,6 +571,30 @@ end
|
|
|
571
571
|
|
|
572
572
|
---
|
|
573
573
|
|
|
574
|
+
### `Model.reindex_vectors(scope: all, batch_size: 1000, on_progress: nil)`
|
|
575
|
+
|
|
576
|
+
Reindex all records for a model into the configured vector index.
|
|
577
|
+
|
|
578
|
+
**Parameters:**
|
|
579
|
+
- `scope` (ActiveRecord::Relation) - Records to reindex (default: `Model.all`)
|
|
580
|
+
- `batch_size` (Integer) - Number of records per batch (default: 1000)
|
|
581
|
+
- `on_progress` (Proc, optional) - Progress callback, receives a hash with `:processed` and `:total`
|
|
582
|
+
|
|
583
|
+
**Returns:** `Integer` - Number of records processed
|
|
584
|
+
|
|
585
|
+
**Example:**
|
|
586
|
+
```ruby
|
|
587
|
+
# Reindex all products with embeddings
|
|
588
|
+
processed = Product.reindex_vectors(
|
|
589
|
+
scope: Product.where.not(embedding: nil),
|
|
590
|
+
batch_size: 500
|
|
591
|
+
)
|
|
592
|
+
|
|
593
|
+
puts "Reindexed #{processed} products"
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
---
|
|
597
|
+
|
|
574
598
|
## Error Handling
|
|
575
599
|
|
|
576
600
|
Vectra defines specific error types:
|
data/lib/vectra/active_record.rb
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
require "active_support/concern"
|
|
4
4
|
|
|
5
|
-
# Ensure Client and
|
|
5
|
+
# Ensure Client and supporting classes are loaded (for Rails autoloading compatibility)
|
|
6
6
|
require_relative "client" unless defined?(Vectra::Client)
|
|
7
|
+
require_relative "batch" unless defined?(Vectra::Batch)
|
|
7
8
|
|
|
8
9
|
module Vectra
|
|
9
10
|
# ActiveRecord integration for vector embeddings
|
|
@@ -26,6 +27,7 @@ module Vectra
|
|
|
26
27
|
# # Search similar documents
|
|
27
28
|
# results = Document.vector_search([0.1, 0.2, ...], limit: 10)
|
|
28
29
|
#
|
|
30
|
+
# rubocop:disable Metrics/ModuleLength
|
|
29
31
|
module ActiveRecord
|
|
30
32
|
extend ActiveSupport::Concern
|
|
31
33
|
|
|
@@ -86,6 +88,54 @@ module Vectra
|
|
|
86
88
|
end
|
|
87
89
|
end
|
|
88
90
|
|
|
91
|
+
# Reindex all vectors for this model using current configuration.
|
|
92
|
+
#
|
|
93
|
+
# @param scope [ActiveRecord::Relation] records to reindex (default: all)
|
|
94
|
+
# @param batch_size [Integer] number of records per batch
|
|
95
|
+
# @param on_progress [Proc, nil] optional callback called after each batch
|
|
96
|
+
# Receives a hash with :processed and :total keys (and any other stats from Batch)
|
|
97
|
+
#
|
|
98
|
+
# @return [Integer] number of records processed
|
|
99
|
+
def reindex_vectors(scope: all, batch_size: 1_000, on_progress: nil)
|
|
100
|
+
config = _vectra_config
|
|
101
|
+
client = vectra_client
|
|
102
|
+
batch = Vectra::Batch.new(client)
|
|
103
|
+
|
|
104
|
+
processed = 0
|
|
105
|
+
|
|
106
|
+
scope.in_batches(of: batch_size).each do |relation|
|
|
107
|
+
records = relation.to_a
|
|
108
|
+
|
|
109
|
+
vectors = records.map do |record|
|
|
110
|
+
vector = record.send(config[:attribute])
|
|
111
|
+
next if vector.nil?
|
|
112
|
+
|
|
113
|
+
metadata = config[:metadata_fields].each_with_object({}) do |field, hash|
|
|
114
|
+
hash[field.to_s] = record.send(field) if record.respond_to?(field)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
{
|
|
118
|
+
id: "#{config[:index]}_#{record.id}",
|
|
119
|
+
values: vector,
|
|
120
|
+
metadata: metadata
|
|
121
|
+
}
|
|
122
|
+
end.compact
|
|
123
|
+
|
|
124
|
+
next if vectors.empty?
|
|
125
|
+
|
|
126
|
+
batch.upsert_async(
|
|
127
|
+
index: config[:index],
|
|
128
|
+
vectors: vectors,
|
|
129
|
+
namespace: nil,
|
|
130
|
+
on_progress: on_progress
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
processed += vectors.size
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
processed
|
|
137
|
+
end
|
|
138
|
+
|
|
89
139
|
# Search vectors
|
|
90
140
|
#
|
|
91
141
|
# @api private
|
|
@@ -195,4 +245,5 @@ module Vectra
|
|
|
195
245
|
"#{self.class._vectra_config[:index]}_#{id}"
|
|
196
246
|
end
|
|
197
247
|
end
|
|
248
|
+
# rubocop:enable Metrics/ModuleLength
|
|
198
249
|
end
|
data/lib/vectra/cache.rb
CHANGED
|
@@ -258,4 +258,53 @@ module Vectra
|
|
|
258
258
|
"#{index}:f:#{id}:#{namespace || 'default'}"
|
|
259
259
|
end
|
|
260
260
|
end
|
|
261
|
+
|
|
262
|
+
# Helper for caching embeddings based on model, record ID and input text.
|
|
263
|
+
#
|
|
264
|
+
# @example
|
|
265
|
+
# cache = Vectra::Cache.new(ttl: 600, max_size: 1000)
|
|
266
|
+
#
|
|
267
|
+
# embedding = Vectra::Embeddings.fetch(
|
|
268
|
+
# cache: cache,
|
|
269
|
+
# model_name: "Product",
|
|
270
|
+
# id: product.id,
|
|
271
|
+
# input: product.description,
|
|
272
|
+
# field: :description
|
|
273
|
+
# ) do
|
|
274
|
+
# EmbeddingService.generate(product.description)
|
|
275
|
+
# end
|
|
276
|
+
#
|
|
277
|
+
module Embeddings
|
|
278
|
+
module_function
|
|
279
|
+
|
|
280
|
+
# Build a stable cache key for an embedding.
|
|
281
|
+
#
|
|
282
|
+
# @param model_name [String] model class name (e.g. "Product")
|
|
283
|
+
# @param id [Integer, String] record ID
|
|
284
|
+
# @param input [String] raw input used for embedding
|
|
285
|
+
# @param field [Symbol, String, nil] optional field name
|
|
286
|
+
#
|
|
287
|
+
# @return [String] cache key
|
|
288
|
+
def cache_key(model_name:, id:, input:, field: nil)
|
|
289
|
+
field_part = field ? field.to_s : "default"
|
|
290
|
+
base = "#{model_name}:#{field_part}:#{id}:#{input}"
|
|
291
|
+
digest = Digest::SHA256.hexdigest(base)[0, 32]
|
|
292
|
+
"emb:#{model_name}:#{field_part}:#{digest}"
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Fetch an embedding from cache or compute and store it.
|
|
296
|
+
#
|
|
297
|
+
# @param cache [Vectra::Cache] cache instance
|
|
298
|
+
# @param model_name [String] model class name
|
|
299
|
+
# @param id [Integer, String] record ID
|
|
300
|
+
# @param input [String] input used for embedding
|
|
301
|
+
# @param field [Symbol, String, nil] optional field name
|
|
302
|
+
#
|
|
303
|
+
# @yield block that computes the embedding when not cached
|
|
304
|
+
# @return [Object] cached or computed embedding
|
|
305
|
+
def fetch(cache:, model_name:, id:, input:, field: nil, &block)
|
|
306
|
+
key = cache_key(model_name: model_name, id: id, input: input, field: field)
|
|
307
|
+
cache.fetch(key, &block)
|
|
308
|
+
end
|
|
309
|
+
end
|
|
261
310
|
end
|
data/lib/vectra/client.rb
CHANGED
|
@@ -40,7 +40,7 @@ module Vectra
|
|
|
40
40
|
class Client
|
|
41
41
|
include Vectra::HealthCheck
|
|
42
42
|
|
|
43
|
-
attr_reader :config, :provider
|
|
43
|
+
attr_reader :config, :provider, :default_index, :default_namespace
|
|
44
44
|
|
|
45
45
|
# Initialize a new Client
|
|
46
46
|
#
|
|
@@ -49,17 +49,21 @@ module Vectra
|
|
|
49
49
|
# @param environment [String, nil] environment/region
|
|
50
50
|
# @param host [String, nil] custom host URL
|
|
51
51
|
# @param options [Hash] additional options
|
|
52
|
+
# @option options [String] :index default index name
|
|
53
|
+
# @option options [String] :namespace default namespace
|
|
52
54
|
def initialize(provider: nil, api_key: nil, environment: nil, host: nil, **options)
|
|
53
55
|
@config = build_config(provider, api_key, environment, host, options)
|
|
54
56
|
@config.validate!
|
|
55
57
|
@provider = build_provider
|
|
58
|
+
@default_index = options[:index]
|
|
59
|
+
@default_namespace = options[:namespace]
|
|
56
60
|
end
|
|
57
61
|
|
|
58
62
|
# Upsert vectors into an index
|
|
59
63
|
#
|
|
60
|
-
# @param index [String] the index/collection name
|
|
61
64
|
# @param vectors [Array<Hash, Vector>] vectors to upsert
|
|
62
|
-
# @param
|
|
65
|
+
# @param index [String, nil] the index/collection name (falls back to client's default)
|
|
66
|
+
# @param namespace [String, nil] optional namespace (provider-specific, falls back to client's default)
|
|
63
67
|
# @return [Hash] upsert response with :upserted_count
|
|
64
68
|
#
|
|
65
69
|
# @example Upsert vectors
|
|
@@ -71,7 +75,9 @@ module Vectra
|
|
|
71
75
|
# ]
|
|
72
76
|
# )
|
|
73
77
|
#
|
|
74
|
-
def upsert(
|
|
78
|
+
def upsert(vectors:, index: nil, namespace: nil)
|
|
79
|
+
index ||= default_index
|
|
80
|
+
namespace ||= default_namespace
|
|
75
81
|
validate_index!(index)
|
|
76
82
|
validate_vectors!(vectors)
|
|
77
83
|
|
|
@@ -130,6 +136,10 @@ module Vectra
|
|
|
130
136
|
# Handle positional argument for index in non-builder case
|
|
131
137
|
index = index_arg if index_arg && index.nil?
|
|
132
138
|
|
|
139
|
+
# Fall back to default index/namespace when not provided
|
|
140
|
+
index ||= default_index
|
|
141
|
+
namespace ||= default_namespace
|
|
142
|
+
|
|
133
143
|
# Backwards-compatible path: perform query immediately
|
|
134
144
|
validate_index!(index)
|
|
135
145
|
validate_query_vector!(vector)
|
|
@@ -157,16 +167,18 @@ module Vectra
|
|
|
157
167
|
|
|
158
168
|
# Fetch vectors by IDs
|
|
159
169
|
#
|
|
160
|
-
# @param index [String] the index/collection name
|
|
161
170
|
# @param ids [Array<String>] vector IDs to fetch
|
|
162
|
-
# @param
|
|
171
|
+
# @param index [String, nil] the index/collection name (falls back to client's default)
|
|
172
|
+
# @param namespace [String, nil] optional namespace (falls back to client's default)
|
|
163
173
|
# @return [Hash<String, Vector>] hash of ID to Vector
|
|
164
174
|
#
|
|
165
175
|
# @example Fetch vectors
|
|
166
176
|
# vectors = client.fetch(index: 'my-index', ids: ['vec1', 'vec2'])
|
|
167
177
|
# vectors['vec1'].values # => [0.1, 0.2, 0.3]
|
|
168
178
|
#
|
|
169
|
-
def fetch(
|
|
179
|
+
def fetch(ids:, index: nil, namespace: nil)
|
|
180
|
+
index ||= default_index
|
|
181
|
+
namespace ||= default_namespace
|
|
170
182
|
validate_index!(index)
|
|
171
183
|
validate_ids!(ids)
|
|
172
184
|
|
|
@@ -182,8 +194,8 @@ module Vectra
|
|
|
182
194
|
|
|
183
195
|
# Update a vector's metadata or values
|
|
184
196
|
#
|
|
185
|
-
# @param index [String] the index/collection name
|
|
186
197
|
# @param id [String] vector ID
|
|
198
|
+
# @param index [String, nil] the index/collection name (falls back to client's default)
|
|
187
199
|
# @param metadata [Hash, nil] new metadata (merged with existing)
|
|
188
200
|
# @param values [Array<Float>, nil] new vector values
|
|
189
201
|
# @param namespace [String, nil] optional namespace
|
|
@@ -196,7 +208,9 @@ module Vectra
|
|
|
196
208
|
# metadata: { category: 'updated' }
|
|
197
209
|
# )
|
|
198
210
|
#
|
|
199
|
-
def update(
|
|
211
|
+
def update(id:, index: nil, metadata: nil, values: nil, namespace: nil)
|
|
212
|
+
index ||= default_index
|
|
213
|
+
namespace ||= default_namespace
|
|
200
214
|
validate_index!(index)
|
|
201
215
|
validate_id!(id)
|
|
202
216
|
|
|
@@ -236,7 +250,9 @@ module Vectra
|
|
|
236
250
|
# @example Delete all
|
|
237
251
|
# client.delete(index: 'my-index', delete_all: true)
|
|
238
252
|
#
|
|
239
|
-
def delete(index
|
|
253
|
+
def delete(index: nil, ids: nil, namespace: nil, filter: nil, delete_all: false)
|
|
254
|
+
index ||= default_index
|
|
255
|
+
namespace ||= default_namespace
|
|
240
256
|
validate_index!(index)
|
|
241
257
|
|
|
242
258
|
if ids.nil? && filter.nil? && !delete_all
|
|
@@ -280,7 +296,8 @@ module Vectra
|
|
|
280
296
|
# info = client.describe_index(index: 'my-index')
|
|
281
297
|
# puts info[:dimension]
|
|
282
298
|
#
|
|
283
|
-
def describe_index(index:)
|
|
299
|
+
def describe_index(index: nil)
|
|
300
|
+
index ||= default_index
|
|
284
301
|
validate_index!(index)
|
|
285
302
|
provider.describe_index(index: index)
|
|
286
303
|
end
|
|
@@ -295,7 +312,9 @@ module Vectra
|
|
|
295
312
|
# stats = client.stats(index: 'my-index')
|
|
296
313
|
# puts "Total vectors: #{stats[:total_vector_count]}"
|
|
297
314
|
#
|
|
298
|
-
def stats(index
|
|
315
|
+
def stats(index: nil, namespace: nil)
|
|
316
|
+
index ||= default_index
|
|
317
|
+
namespace ||= default_namespace
|
|
299
318
|
validate_index!(index)
|
|
300
319
|
provider.stats(index: index, namespace: namespace)
|
|
301
320
|
end
|
|
@@ -359,7 +378,8 @@ module Vectra
|
|
|
359
378
|
# namespaces = client.list_namespaces(index: 'documents')
|
|
360
379
|
# namespaces.each { |ns| puts "Namespace: #{ns}" }
|
|
361
380
|
#
|
|
362
|
-
def list_namespaces(index:)
|
|
381
|
+
def list_namespaces(index: nil)
|
|
382
|
+
index ||= default_index
|
|
363
383
|
validate_index!(index)
|
|
364
384
|
stats_data = provider.stats(index: index)
|
|
365
385
|
namespaces = stats_data[:namespaces] || {}
|
|
@@ -408,6 +428,8 @@ module Vectra
|
|
|
408
428
|
#
|
|
409
429
|
def hybrid_search(index:, vector:, text:, alpha: 0.5, top_k: 10, namespace: nil,
|
|
410
430
|
filter: nil, include_values: false, include_metadata: true)
|
|
431
|
+
index ||= default_index
|
|
432
|
+
namespace ||= default_namespace
|
|
411
433
|
validate_index!(index)
|
|
412
434
|
validate_query_vector!(vector)
|
|
413
435
|
raise ValidationError, "Text query cannot be nil or empty" if text.nil? || text.empty?
|
|
@@ -671,6 +693,48 @@ module Vectra
|
|
|
671
693
|
config.logger.debug("[Vectra] #{message}")
|
|
672
694
|
config.logger.debug("[Vectra] #{data.inspect}") if data
|
|
673
695
|
end
|
|
696
|
+
|
|
697
|
+
# Temporarily override default index within a block.
|
|
698
|
+
#
|
|
699
|
+
# @param index [String] temporary index name
|
|
700
|
+
# @yield [Client] yields self with overridden index
|
|
701
|
+
# @return [Object] block result
|
|
702
|
+
def with_index(index)
|
|
703
|
+
previous = @default_index
|
|
704
|
+
@default_index = index
|
|
705
|
+
yield self
|
|
706
|
+
ensure
|
|
707
|
+
@default_index = previous
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
# Temporarily override default namespace within a block.
|
|
711
|
+
#
|
|
712
|
+
# @param namespace [String] temporary namespace
|
|
713
|
+
# @yield [Client] yields self with overridden namespace
|
|
714
|
+
# @return [Object] block result
|
|
715
|
+
def with_namespace(namespace)
|
|
716
|
+
previous = @default_namespace
|
|
717
|
+
@default_namespace = namespace
|
|
718
|
+
yield self
|
|
719
|
+
ensure
|
|
720
|
+
@default_namespace = previous
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
# Temporarily override both index and namespace within a block.
|
|
724
|
+
#
|
|
725
|
+
# @param index [String] temporary index name
|
|
726
|
+
# @param namespace [String] temporary namespace
|
|
727
|
+
# @yield [Client] yields self with overridden index and namespace
|
|
728
|
+
# @return [Object] block result
|
|
729
|
+
def with_index_and_namespace(index, namespace)
|
|
730
|
+
with_index(index) do
|
|
731
|
+
with_namespace(namespace) do
|
|
732
|
+
yield self
|
|
733
|
+
end
|
|
734
|
+
end
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
public :with_index, :with_namespace, :with_index_and_namespace
|
|
674
738
|
end
|
|
675
739
|
# rubocop:enable Metrics/ClassLength
|
|
676
740
|
end
|
data/lib/vectra/version.rb
CHANGED