vectra-client 1.1.2 → 1.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -16
- data/docs/api/cheatsheet.md +30 -0
- data/docs/api/methods.md +88 -0
- data/lib/vectra/client.rb +151 -1
- 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: c2ed5842cd4c611fd0c140abc8925a2d13577c4f2094dbc71c7b2772aceda9e4
|
|
4
|
+
data.tar.gz: da3005805b97d5b36c632d3e2c34ad9a3966eb65b09ce2f5f84911858c2d34d5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bb3324f260afb42c5e03356f8d09c902571fcaddc39969541c918523c4ebadbdb8dadf35764d9d04cce2b308ee4aa18d9f7c3266690a1a728ceeecb9908a3622
|
|
7
|
+
data.tar.gz: adca9a174757547d1306dbaa727069fa1954a8dc40b101c1cb378bfb3663c94ad7ec0a35082ea578ef4dd4a7ab53477bdfde6dd258623c83e161eb8c6cff2b42
|
data/CHANGELOG.md
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v1.1.4](https://github.com/stokry/vectra/tree/v1.1.4) (2026-01-20)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/stokry/vectra/compare/v1.1.3...v1.1.4)
|
|
6
|
+
|
|
7
|
+
- Add `Client#valid?` – non-raising validation (returns true/false)
|
|
8
|
+
- Add `Client#for_tenant` – multi-tenant block helper for namespace isolation
|
|
9
|
+
|
|
10
|
+
## [v1.1.3](https://github.com/stokry/vectra/tree/v1.1.3) (2026-01-20)
|
|
11
|
+
|
|
12
|
+
[Full Changelog](https://github.com/stokry/vectra/compare/v1.1.2...v1.1.3)
|
|
13
|
+
|
|
14
|
+
## [v1.1.2](https://github.com/stokry/vectra/tree/v1.1.2) (2026-01-19)
|
|
15
|
+
|
|
16
|
+
[Full Changelog](https://github.com/stokry/vectra/compare/v1.1.1...v1.1.2)
|
|
17
|
+
|
|
3
18
|
## [v1.1.1](https://github.com/stokry/vectra/tree/v1.1.1) (2026-01-15)
|
|
4
19
|
|
|
5
20
|
[Full Changelog](https://github.com/stokry/vectra/compare/v1.1.0...v1.1.1)
|
|
6
21
|
|
|
7
|
-
### Added
|
|
8
|
-
- **Text Search Support** - New `text_search` method for keyword-only search without requiring embeddings
|
|
9
|
-
- Qdrant: BM25 text search
|
|
10
|
-
- Weaviate: BM25 text search via GraphQL
|
|
11
|
-
- pgvector: PostgreSQL full-text search (`to_tsvector`, `plainto_tsquery`, `ts_rank`)
|
|
12
|
-
- Memory: Simple keyword matching (for testing)
|
|
13
|
-
- Raises `UnsupportedFeatureError` for Pinecone (use sparse vectors instead)
|
|
14
|
-
- **Documentation Search** - Added search functionality to documentation site with `simple-jekyll-search`
|
|
15
|
-
- Client-side search with fuzzy matching
|
|
16
|
-
- Search index auto-generated from all documentation pages
|
|
17
|
-
- Responsive search UI in navigation
|
|
18
|
-
|
|
19
|
-
### Changed
|
|
20
|
-
- Updated API documentation to include `text_search` method in overview and cheatsheet
|
|
21
|
-
- Enhanced documentation with text search examples and use cases
|
|
22
|
-
|
|
23
22
|
## [v1.1.0](https://github.com/stokry/vectra/tree/v1.1.0) (2026-01-15)
|
|
24
23
|
|
|
25
24
|
[Full Changelog](https://github.com/stokry/vectra/compare/v1.0.8...v1.1.0)
|
data/docs/api/cheatsheet.md
CHANGED
|
@@ -51,6 +51,36 @@ client.query(vector: query_embedding, top_k: 10)
|
|
|
51
51
|
|
|
52
52
|
In a Rails app with `config/vectra.yml` generated by `rails generate vectra:index`, if that YAML file contains only one entry, `Vectra::Client.new` will automatically use that entry's `index` (and `namespace`, if present) as defaults.
|
|
53
53
|
|
|
54
|
+
### Temporary defaults (block-scoped)
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
client.with_defaults(index: "products", namespace: "tenant-2") do |c|
|
|
58
|
+
c.upsert(vectors: [...])
|
|
59
|
+
c.query(vector: query_embedding, top_k: 10)
|
|
60
|
+
end
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Validate client config & capabilities
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
client.validate!
|
|
67
|
+
client.validate!(require_default_index: true)
|
|
68
|
+
client.validate!(features: [:text_search])
|
|
69
|
+
|
|
70
|
+
# Non-raising: returns true/false
|
|
71
|
+
client.valid?
|
|
72
|
+
client.valid?(require_default_index: true)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Multi-tenant (for_tenant)
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
client.for_tenant("acme", namespace_prefix: "tenant_") do |c|
|
|
79
|
+
c.upsert(vectors: [...])
|
|
80
|
+
c.query(vector: query_embedding, top_k: 10)
|
|
81
|
+
end
|
|
82
|
+
```
|
|
83
|
+
|
|
54
84
|
### Upsert
|
|
55
85
|
|
|
56
86
|
```ruby
|
data/docs/api/methods.md
CHANGED
|
@@ -426,6 +426,94 @@ After the block finishes (even if it raises), the previous `config.timeout` valu
|
|
|
426
426
|
|
|
427
427
|
---
|
|
428
428
|
|
|
429
|
+
### `client.validate!(require_default_index: false, require_default_namespace: false, features: [])`
|
|
430
|
+
|
|
431
|
+
Validate the client configuration and (optionally) your defaults and provider feature support.
|
|
432
|
+
|
|
433
|
+
This is useful in boot-time checks (Rails initializers), health endpoints, and CI.
|
|
434
|
+
|
|
435
|
+
**Parameters:**
|
|
436
|
+
- `require_default_index` (Boolean) - Require `client.default_index` to be set
|
|
437
|
+
- `require_default_namespace` (Boolean) - Require `client.default_namespace` to be set
|
|
438
|
+
- `features` (Array<Symbol> or Symbol) - Provider features (methods) that must be supported (e.g. `:text_search`)
|
|
439
|
+
|
|
440
|
+
**Returns:** `Vectra::Client` (self)
|
|
441
|
+
|
|
442
|
+
**Raises:** `Vectra::ConfigurationError` when validation fails
|
|
443
|
+
|
|
444
|
+
**Example:**
|
|
445
|
+
```ruby
|
|
446
|
+
# Ensure client is configured
|
|
447
|
+
client.validate!
|
|
448
|
+
|
|
449
|
+
# Ensure calls can omit index:
|
|
450
|
+
client.validate!(require_default_index: true)
|
|
451
|
+
|
|
452
|
+
# Ensure provider supports text_search:
|
|
453
|
+
client.validate!(features: [:text_search])
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
### `client.with_defaults(index: ..., namespace: ...) { ... }`
|
|
459
|
+
|
|
460
|
+
Temporarily override the client's **default index and/or namespace** inside a block.
|
|
461
|
+
|
|
462
|
+
Unlike `with_index_and_namespace`, this helper accepts keyword arguments and only overrides what you pass.
|
|
463
|
+
|
|
464
|
+
**Returns:** Block result
|
|
465
|
+
|
|
466
|
+
**Example:**
|
|
467
|
+
```ruby
|
|
468
|
+
client.with_defaults(index: "products", namespace: "tenant-2") do |c|
|
|
469
|
+
c.upsert(vectors: [...]) # uses products/tenant-2
|
|
470
|
+
c.query(vector: embedding, top_k: 10)
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
# Previous defaults are restored after the block.
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
---
|
|
477
|
+
|
|
478
|
+
### `client.valid?(require_default_index: false, require_default_namespace: false, features: [])`
|
|
479
|
+
|
|
480
|
+
Non-raising validation. Returns `true` if the client passes `validate!`, `false` otherwise. Accepts the same options as `validate!`.
|
|
481
|
+
|
|
482
|
+
**Returns:** `Boolean`
|
|
483
|
+
|
|
484
|
+
**Example:**
|
|
485
|
+
```ruby
|
|
486
|
+
next unless client.valid?
|
|
487
|
+
client.upsert(vectors: [...])
|
|
488
|
+
|
|
489
|
+
# With same options as validate!
|
|
490
|
+
client.valid?(require_default_index: true)
|
|
491
|
+
client.valid?(features: [:text_search])
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
### `client.for_tenant(tenant_id, namespace_prefix: "tenant_") { ... }`
|
|
497
|
+
|
|
498
|
+
Multi-tenant block helper. Temporarily sets the default namespace to `"#{namespace_prefix}#{tenant_id}"`, yields the client, then restores the previous namespace. `tenant_id` can be a string, symbol, or anything responding to `to_s`.
|
|
499
|
+
|
|
500
|
+
**Parameters:**
|
|
501
|
+
- `tenant_id` (String, Symbol, #to_s) - Tenant identifier
|
|
502
|
+
- `namespace_prefix` (String) - Prefix for namespace (default: `"tenant_"`)
|
|
503
|
+
|
|
504
|
+
**Returns:** Block result
|
|
505
|
+
|
|
506
|
+
**Example:**
|
|
507
|
+
```ruby
|
|
508
|
+
client.for_tenant("acme", namespace_prefix: "tenant_") do |c|
|
|
509
|
+
c.upsert(vectors: [...])
|
|
510
|
+
c.query(vector: embedding, top_k: 10)
|
|
511
|
+
end
|
|
512
|
+
# All operations use namespace "tenant_acme"; previous default restored after block.
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
429
517
|
### `client.health_check`
|
|
430
518
|
|
|
431
519
|
Detailed health check with provider-specific information.
|
data/lib/vectra/client.rb
CHANGED
|
@@ -44,6 +44,9 @@ module Vectra
|
|
|
44
44
|
|
|
45
45
|
attr_reader :config, :provider, :default_index, :default_namespace
|
|
46
46
|
|
|
47
|
+
DEFAULT_UNSET = Object.new.freeze
|
|
48
|
+
private_constant :DEFAULT_UNSET
|
|
49
|
+
|
|
47
50
|
class << self
|
|
48
51
|
# Get the global middleware stack
|
|
49
52
|
#
|
|
@@ -621,6 +624,67 @@ module Vectra
|
|
|
621
624
|
result
|
|
622
625
|
end
|
|
623
626
|
|
|
627
|
+
# Validate the client configuration and provider capabilities.
|
|
628
|
+
#
|
|
629
|
+
# This is a convenience wrapper around `config.validate!` that can also
|
|
630
|
+
# validate your defaults and provider feature support.
|
|
631
|
+
#
|
|
632
|
+
# @param require_default_index [Boolean] require default index to be set
|
|
633
|
+
# @param require_default_namespace [Boolean] require default namespace to be set
|
|
634
|
+
# @param features [Array<Symbol>, Symbol] provider features (methods) required, e.g. :text_search
|
|
635
|
+
# @return [true]
|
|
636
|
+
# @raise [ConfigurationError] when client is misconfigured
|
|
637
|
+
#
|
|
638
|
+
# @example Basic validation
|
|
639
|
+
# client.validate! # => client
|
|
640
|
+
#
|
|
641
|
+
# @example Ensure you can call methods without passing index:
|
|
642
|
+
# client.validate!(require_default_index: true)
|
|
643
|
+
#
|
|
644
|
+
# @example Ensure provider supports text search:
|
|
645
|
+
# client.validate!(features: [:text_search])
|
|
646
|
+
#
|
|
647
|
+
def validate!(require_default_index: false, require_default_namespace: false, features: [])
|
|
648
|
+
errors = []
|
|
649
|
+
|
|
650
|
+
append_client_config_errors(errors)
|
|
651
|
+
append_client_provider_errors(errors)
|
|
652
|
+
append_client_default_errors(
|
|
653
|
+
errors,
|
|
654
|
+
require_default_index: require_default_index,
|
|
655
|
+
require_default_namespace: require_default_namespace
|
|
656
|
+
)
|
|
657
|
+
append_client_feature_errors(errors, features: features)
|
|
658
|
+
|
|
659
|
+
raise ConfigurationError, client_validation_message(errors) if errors.any?
|
|
660
|
+
|
|
661
|
+
self
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
# Non-raising validation. Returns true if client passes validate!, false otherwise.
|
|
665
|
+
#
|
|
666
|
+
# Accepts the same options as validate!.
|
|
667
|
+
#
|
|
668
|
+
# @param require_default_index [Boolean] require default index to be set
|
|
669
|
+
# @param require_default_namespace [Boolean] require default namespace to be set
|
|
670
|
+
# @param features [Array<Symbol>, Symbol] provider features required, e.g. :text_search
|
|
671
|
+
# @return [Boolean]
|
|
672
|
+
#
|
|
673
|
+
# @example
|
|
674
|
+
# next unless client.valid?
|
|
675
|
+
# client.upsert(vectors: [...])
|
|
676
|
+
#
|
|
677
|
+
def valid?(require_default_index: false, require_default_namespace: false, features: [])
|
|
678
|
+
validate!(
|
|
679
|
+
require_default_index: require_default_index,
|
|
680
|
+
require_default_namespace: require_default_namespace,
|
|
681
|
+
features: features
|
|
682
|
+
)
|
|
683
|
+
true
|
|
684
|
+
rescue ConfigurationError
|
|
685
|
+
false
|
|
686
|
+
end
|
|
687
|
+
|
|
624
688
|
# Chainable query builder
|
|
625
689
|
#
|
|
626
690
|
# @api public
|
|
@@ -786,6 +850,52 @@ module Vectra
|
|
|
786
850
|
@default_namespace = namespace if @default_namespace.nil? && namespace.is_a?(String) && !namespace.empty?
|
|
787
851
|
end
|
|
788
852
|
|
|
853
|
+
def append_client_config_errors(errors)
|
|
854
|
+
config.validate!
|
|
855
|
+
rescue ConfigurationError, UnsupportedProviderError => e
|
|
856
|
+
errors << e.message
|
|
857
|
+
end
|
|
858
|
+
|
|
859
|
+
def append_client_provider_errors(errors)
|
|
860
|
+
errors << "Provider is not initialized" if provider.nil?
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
def append_client_default_errors(errors, require_default_index:, require_default_namespace:)
|
|
864
|
+
append_default_index_error(errors) if require_default_index
|
|
865
|
+
append_default_namespace_error(errors) if require_default_namespace
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
def append_default_index_error(errors)
|
|
869
|
+
if default_index.nil? || (default_index.respond_to?(:empty?) && default_index.empty?)
|
|
870
|
+
errors << "Default index is not set (pass `index:` to Vectra::Client.new, or set it via config/vectra.yml in Rails)"
|
|
871
|
+
elsif !default_index.is_a?(String)
|
|
872
|
+
errors << "Default index must be a String"
|
|
873
|
+
end
|
|
874
|
+
end
|
|
875
|
+
|
|
876
|
+
def append_default_namespace_error(errors)
|
|
877
|
+
if default_namespace.nil? || (default_namespace.respond_to?(:empty?) && default_namespace.empty?)
|
|
878
|
+
errors << "Default namespace is not set (pass `namespace:` to Vectra::Client.new, or set it via config/vectra.yml in Rails)"
|
|
879
|
+
elsif !default_namespace.is_a?(String)
|
|
880
|
+
errors << "Default namespace must be a String"
|
|
881
|
+
end
|
|
882
|
+
end
|
|
883
|
+
|
|
884
|
+
def append_client_feature_errors(errors, features:)
|
|
885
|
+
return if provider.nil?
|
|
886
|
+
|
|
887
|
+
Array(features).compact.each do |feature|
|
|
888
|
+
method = feature.to_sym
|
|
889
|
+
next if provider.respond_to?(method)
|
|
890
|
+
|
|
891
|
+
errors << "Provider does not support `#{method}`"
|
|
892
|
+
end
|
|
893
|
+
end
|
|
894
|
+
|
|
895
|
+
def client_validation_message(errors)
|
|
896
|
+
"Client validation failed:\n- #{errors.join("\n- ")}"
|
|
897
|
+
end
|
|
898
|
+
|
|
789
899
|
def validate_index!(index)
|
|
790
900
|
raise ValidationError, "Index name cannot be nil" if index.nil?
|
|
791
901
|
raise ValidationError, "Index name must be a string" unless index.is_a?(String)
|
|
@@ -908,7 +1018,47 @@ module Vectra
|
|
|
908
1018
|
end
|
|
909
1019
|
end
|
|
910
1020
|
|
|
911
|
-
|
|
1021
|
+
# Temporarily override default index and/or namespace within a block.
|
|
1022
|
+
#
|
|
1023
|
+
# Unlike `with_index_and_namespace`, this method accepts keyword arguments
|
|
1024
|
+
# and only overrides the values you pass.
|
|
1025
|
+
#
|
|
1026
|
+
# @param index [String, nil] temporary index name (omit to keep current)
|
|
1027
|
+
# @param namespace [String, nil] temporary namespace (omit to keep current)
|
|
1028
|
+
# @yield [Client] yields self with overridden defaults
|
|
1029
|
+
# @return [Object] block result
|
|
1030
|
+
def with_defaults(index: DEFAULT_UNSET, namespace: DEFAULT_UNSET)
|
|
1031
|
+
previous_index = @default_index
|
|
1032
|
+
previous_namespace = @default_namespace
|
|
1033
|
+
|
|
1034
|
+
@default_index = index unless index.equal?(DEFAULT_UNSET)
|
|
1035
|
+
@default_namespace = namespace unless namespace.equal?(DEFAULT_UNSET)
|
|
1036
|
+
|
|
1037
|
+
yield self
|
|
1038
|
+
ensure
|
|
1039
|
+
@default_index = previous_index
|
|
1040
|
+
@default_namespace = previous_namespace
|
|
1041
|
+
end
|
|
1042
|
+
|
|
1043
|
+
# Multi-tenant block helper: temporarily sets default namespace to +"#{namespace_prefix}#{tenant_id}"+.
|
|
1044
|
+
#
|
|
1045
|
+
# @param tenant_id [String, Symbol, #to_s] tenant identifier
|
|
1046
|
+
# @param namespace_prefix [String] prefix for namespace (default: "tenant_")
|
|
1047
|
+
# @yield [Client] yields self with overridden namespace
|
|
1048
|
+
# @return [Object] block result
|
|
1049
|
+
#
|
|
1050
|
+
# @example
|
|
1051
|
+
# client.for_tenant("acme", namespace_prefix: "tenant_") do |c|
|
|
1052
|
+
# c.upsert(vectors: [...])
|
|
1053
|
+
# c.query(vector: emb, top_k: 10)
|
|
1054
|
+
# end
|
|
1055
|
+
#
|
|
1056
|
+
def for_tenant(tenant_id, namespace_prefix: "tenant_")
|
|
1057
|
+
ns = "#{namespace_prefix}#{tenant_id}"
|
|
1058
|
+
with_namespace(ns) { yield self }
|
|
1059
|
+
end
|
|
1060
|
+
|
|
1061
|
+
public :with_index, :with_namespace, :with_index_and_namespace, :with_defaults, :with_timeout, :for_tenant
|
|
912
1062
|
end
|
|
913
1063
|
# rubocop:enable Metrics/ClassLength
|
|
914
1064
|
end
|
data/lib/vectra/version.rb
CHANGED