ollama-ruby 0.12.1 → 0.13.0
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/.yardopts +1 -0
- data/CHANGES.md +6 -0
- data/README.md +2 -2
- data/Rakefile +4 -5
- data/bin/ollama_chat +19 -18
- data/lib/ollama/client/command.rb +2 -2
- data/lib/ollama/version.rb +1 -1
- data/lib/ollama.rb +0 -4
- data/ollama-ruby.gemspec +11 -12
- metadata +26 -88
- data/lib/ollama/documents/cache/common.rb +0 -36
- data/lib/ollama/documents/cache/memory_cache.rb +0 -44
- data/lib/ollama/documents/cache/records.rb +0 -87
- data/lib/ollama/documents/cache/redis_backed_memory_cache.rb +0 -39
- data/lib/ollama/documents/cache/redis_cache.rb +0 -68
- data/lib/ollama/documents/cache/sqlite_cache.rb +0 -215
- data/lib/ollama/documents/splitters/character.rb +0 -72
- data/lib/ollama/documents/splitters/semantic.rb +0 -91
- data/lib/ollama/documents.rb +0 -184
- data/lib/ollama/utils/colorize_texts.rb +0 -65
- data/lib/ollama/utils/math.rb +0 -48
- data/lib/ollama/utils/tags.rb +0 -67
- data/spec/assets/embeddings.json +0 -1
- data/spec/ollama/documents/cache/memory_cache_spec.rb +0 -97
- data/spec/ollama/documents/cache/redis_backed_memory_cache_spec.rb +0 -118
- data/spec/ollama/documents/cache/redis_cache_spec.rb +0 -121
- data/spec/ollama/documents/cache/sqlite_cache_spec.rb +0 -141
- data/spec/ollama/documents/splitters/character_spec.rb +0 -110
- data/spec/ollama/documents/splitters/semantic_spec.rb +0 -56
- data/spec/ollama/documents_spec.rb +0 -162
- data/spec/ollama/utils/colorize_texts_spec.rb +0 -13
- data/spec/ollama/utils/tags_spec.rb +0 -53
@@ -1,121 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Ollama::Documents::RedisCache do
|
4
|
-
let :prefix do
|
5
|
-
'test-'
|
6
|
-
end
|
7
|
-
|
8
|
-
let :cache do
|
9
|
-
described_class.new prefix:, url: 'something'
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'can be instantiated' do
|
13
|
-
expect(cache).to be_a described_class
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'defaults to nil object_class' do
|
17
|
-
expect(cache.object_class).to be_nil
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'can be configured with object_class' do
|
21
|
-
object_class = Class.new(JSON::GenericObject)
|
22
|
-
cache = described_class.new(prefix:, url: 'something', object_class:)
|
23
|
-
expect(cache.object_class).to eq object_class
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'raises ArgumentError if url is missing' do
|
27
|
-
expect {
|
28
|
-
described_class.new prefix:, url: nil
|
29
|
-
}.to raise_error ArgumentError
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'test redis interactions' do
|
33
|
-
let :redis do
|
34
|
-
double('Redis')
|
35
|
-
end
|
36
|
-
|
37
|
-
before do
|
38
|
-
allow_any_instance_of(described_class).to receive(:redis).and_return(redis)
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'has Redis client' do
|
42
|
-
expect(cache.redis).to eq redis
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'can get a key' do
|
46
|
-
key = 'foo'
|
47
|
-
expect(redis).to receive(:get).with(prefix + key).and_return '"some_json"'
|
48
|
-
expect(cache[key]).to eq 'some_json'
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'can set a value for a key' do
|
52
|
-
key, value = 'foo', { test: true }
|
53
|
-
expect(redis).to receive(:set).with(prefix + key, JSON(value), ex: nil)
|
54
|
-
cache[key] = value
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'can set a value for a key with ttl' do
|
58
|
-
cache = described_class.new prefix:, url: 'something', ex: 3_600
|
59
|
-
key, value = 'foo', { test: true }
|
60
|
-
expect(redis).to receive(:set).with(prefix + key, JSON(value), ex: 3_600)
|
61
|
-
cache[key] = value
|
62
|
-
expect(redis).to receive(:ttl).with(prefix + key).and_return 3_600
|
63
|
-
expect(cache.ttl(key)).to eq 3_600
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'can determine if key exists' do
|
67
|
-
key = 'foo'
|
68
|
-
expect(redis).to receive(:exists?).with(prefix + key).and_return(false, true)
|
69
|
-
expect(cache.key?('foo')).to eq false
|
70
|
-
expect(cache.key?('foo')).to eq true
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'can delete' do
|
74
|
-
key = 'foo'
|
75
|
-
expect(redis).to receive(:del).with(prefix + key)
|
76
|
-
cache.delete(key)
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'can iterate over keys, values' do
|
80
|
-
key, value = 'foo', { 'test' => true }
|
81
|
-
expect(redis).to receive(:set).with(prefix + key, JSON(value), ex: nil)
|
82
|
-
cache[key] = value
|
83
|
-
expect(redis).to receive(:scan_each).with(match: "#{prefix}*").
|
84
|
-
and_yield("#{prefix}foo")
|
85
|
-
expect(redis).to receive(:get).with(prefix + key).and_return(JSON(test: true))
|
86
|
-
cache.each do |k, v|
|
87
|
-
expect(k).to eq prefix + key
|
88
|
-
expect(v).to eq value
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'returns size' do
|
93
|
-
expect(redis).to receive(:scan_each).with(match: "#{prefix}*").
|
94
|
-
and_yield("#{prefix}foo").
|
95
|
-
and_yield("#{prefix}bar").
|
96
|
-
and_yield("#{prefix}baz")
|
97
|
-
expect(cache.size).to eq 3
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'can clear' do
|
101
|
-
expect(redis).to receive(:scan_each).with(match: 'test-*').and_yield(
|
102
|
-
'test-foo'
|
103
|
-
)
|
104
|
-
expect(redis).to receive(:del).with('test-foo')
|
105
|
-
expect(cache.clear).to eq cache
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'can iterate over keys under a prefix' do
|
109
|
-
expect(redis).to receive(:scan_each).with(match: 'test-*')
|
110
|
-
cache.to_a
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'can compute prefix with pre' do
|
114
|
-
expect(cache.pre('foo')).to eq 'test-foo'
|
115
|
-
end
|
116
|
-
|
117
|
-
it 'can remove prefix with unpre' do
|
118
|
-
expect(cache.unpre('test-foo')).to eq 'foo'
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
@@ -1,141 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Ollama::Documents::SQLiteCache do
|
4
|
-
let :prefix do
|
5
|
-
'test-'
|
6
|
-
end
|
7
|
-
|
8
|
-
let :test_value do
|
9
|
-
{
|
10
|
-
key: 'test',
|
11
|
-
text: 'test text',
|
12
|
-
norm: 0.5,
|
13
|
-
source: 'for-test.txt',
|
14
|
-
tags: %w[ test ],
|
15
|
-
embedding: [ 0.5 ] * 1_024,
|
16
|
-
}
|
17
|
-
end
|
18
|
-
|
19
|
-
let :cache do
|
20
|
-
described_class.new prefix:
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'can be instantiated' do
|
24
|
-
expect(cache).to be_a described_class
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'defaults to :memory: mode' do
|
28
|
-
expect(cache.filename).to eq ':memory:'
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'can be switchted to file mode' do
|
32
|
-
expect(SQLite3::Database).to receive(:new).with('foo.sqlite').
|
33
|
-
and_return(double.as_null_object)
|
34
|
-
cache = described_class.new prefix:, filename: 'foo.sqlite'
|
35
|
-
expect(cache.filename).to eq 'foo.sqlite'
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'can get/set a key' do
|
39
|
-
key, value = 'foo', test_value
|
40
|
-
queried_value = nil
|
41
|
-
expect {
|
42
|
-
cache[key] = value
|
43
|
-
}.to change {
|
44
|
-
queried_value = cache[key]
|
45
|
-
}.from(nil).to(Ollama::Documents::Record[value])
|
46
|
-
expect(queried_value.embedding).to eq [ 0.5 ] * 1_024
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'can determine if key exists' do
|
50
|
-
key, value = 'foo', test_value
|
51
|
-
expect {
|
52
|
-
cache[key] = value
|
53
|
-
}.to change {
|
54
|
-
cache.key?(key)
|
55
|
-
}.from(false).to(true)
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'can set key with different prefixes' do
|
59
|
-
key, value = 'foo', test_value
|
60
|
-
expect {
|
61
|
-
cache[key] = value
|
62
|
-
}.to change {
|
63
|
-
cache.size
|
64
|
-
}.from(0).to(1)
|
65
|
-
cache2 = cache.dup
|
66
|
-
cache2.prefix = 'test2-'
|
67
|
-
expect {
|
68
|
-
cache2[key] = value
|
69
|
-
}.to change {
|
70
|
-
cache2.size
|
71
|
-
}.from(0).to(1)
|
72
|
-
expect(cache.size).to eq 1
|
73
|
-
s = 0
|
74
|
-
cache.full_each { s += 1 }
|
75
|
-
expect(s).to eq 2
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'can delete' do
|
79
|
-
key, value = 'foo', test_value
|
80
|
-
expect(cache.delete(key)).to be_falsy
|
81
|
-
cache[key] = value
|
82
|
-
expect {
|
83
|
-
expect(cache.delete(key)).to be_truthy
|
84
|
-
}.to change {
|
85
|
-
cache.key?(key)
|
86
|
-
}.from(true).to(false)
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'returns size' do
|
90
|
-
key, value = 'foo', test_value
|
91
|
-
expect {
|
92
|
-
cache[key] = value
|
93
|
-
}.to change {
|
94
|
-
cache.size
|
95
|
-
}.from(0).to(1)
|
96
|
-
end
|
97
|
-
|
98
|
-
it 'can convert_to_vector' do
|
99
|
-
vector = [ 23.0, 666.0 ]
|
100
|
-
expect(cache.convert_to_vector(vector)).to eq vector
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'can clear' do
|
104
|
-
key, value = 'foo', { embedding: [ 0.5 ] * 1_024 }
|
105
|
-
cache[key] = value
|
106
|
-
expect {
|
107
|
-
expect(cache.clear).to eq cache
|
108
|
-
}.to change {
|
109
|
-
cache.size
|
110
|
-
}.from(1).to(0)
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'can clear for tags' do
|
114
|
-
key, value = 'foo', { tags: %w[ foo ], embedding: [ 0.5 ] * 1_024 }
|
115
|
-
cache[key] = value
|
116
|
-
key, value = 'bar', { embedding: [ 0.5 ] * 1_024 }
|
117
|
-
cache[key] = value
|
118
|
-
expect {
|
119
|
-
expect(cache.clear_for_tags(%w[ #foo ])).to eq cache
|
120
|
-
}.to change {
|
121
|
-
cache.size
|
122
|
-
}.from(2).to(1)
|
123
|
-
expect(cache).not_to be_key 'foo'
|
124
|
-
expect(cache).to be_key 'bar'
|
125
|
-
end
|
126
|
-
|
127
|
-
it 'can return tags' do
|
128
|
-
key, value = 'foo', { tags: %w[ foo ], embedding: [ 0.5 ] * 1_024 }
|
129
|
-
cache[key] = value
|
130
|
-
key, value = 'bar', { tags: %w[ bar baz ], embedding: [ 0.5 ] * 1_024 }
|
131
|
-
cache[key] = value
|
132
|
-
tags = cache.tags
|
133
|
-
expect(tags).to be_a Ollama::Utils::Tags
|
134
|
-
expect(tags.to_a).to eq %w[ bar baz foo ]
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'can iterate over keys under a prefix' do
|
138
|
-
cache['foo'] = test_value
|
139
|
-
expect(cache.to_a).to eq [ [ 'test-foo', Ollama::Documents::Record[test_value] ] ]
|
140
|
-
end
|
141
|
-
end
|
@@ -1,110 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Ollama::Documents::Splitters::Character do
|
4
|
-
let :splitter do
|
5
|
-
described_class.new chunk_size: 23, combining_string: ''
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'can be instantiated' do
|
9
|
-
expect(splitter).to be_a described_class
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'can split' do
|
13
|
-
text = [ ?A * 10 ] * 10 * "\n\n"
|
14
|
-
result = splitter.split(text)
|
15
|
-
expect(result.count).to eq 5
|
16
|
-
expect(result.to_a.join('')).to eq ?A * 100
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'can split combining with separation' do
|
20
|
-
splitter = described_class.new chunk_size: 25, include_separator: false,
|
21
|
-
combining_string: ?X
|
22
|
-
text = [ ?A * 10 ] * 10 * "\n\n"
|
23
|
-
result = splitter.split(text)
|
24
|
-
expect(result.count).to eq 5
|
25
|
-
expect(result.to_a.join(?B)).to eq\
|
26
|
-
"AAAAAAAAAAXAAAAAAAAAAXBAAAAAAAAAAAAAAAAAAAAXBAAAAAAAAAAAAAAAAAAAAXB"\
|
27
|
-
"AAAAAAAAAAAAAAAAAAAAXBAAAAAAAAAAAAAAAAAAAAX"
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'can split including separator' do
|
31
|
-
splitter = described_class.new chunk_size: 25, include_separator: true,
|
32
|
-
combining_string: ''
|
33
|
-
text = [ ?A * 10 ] * 10 * "\n\n"
|
34
|
-
result = splitter.split(text)
|
35
|
-
expect(result.count).to eq 5
|
36
|
-
expect(result.to_a.join('')).to eq text
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'cannot split' do
|
40
|
-
text = [ ?A * 10 ] * 10 * "\n"
|
41
|
-
result = splitter.split(text)
|
42
|
-
expect(result.count).to eq 1
|
43
|
-
expect(result.to_a.join('').count(?A)).to eq text.count(?A)
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'cannot split2' do
|
47
|
-
text = ?A * 25
|
48
|
-
result = splitter.split(text)
|
49
|
-
expect(result.count).to eq 1
|
50
|
-
expect(result.to_a.join('')).to eq ?A * 25
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'can split sentences' do
|
54
|
-
text = "foo.foo. bar!bar! baz?baz? quux.\nquux."
|
55
|
-
splitter = described_class.new(separator: /[.!?]\s*(?:\b|\z)/, chunk_size: 2)
|
56
|
-
result = splitter.split(text)
|
57
|
-
expect(result.to_a).to eq %w[ foo foo bar bar baz baz quux quux ]
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
RSpec.describe Ollama::Documents::Splitters::RecursiveCharacter do
|
62
|
-
let :splitter do
|
63
|
-
described_class.new chunk_size: 23, combining_string: ''
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'can be instantiated' do
|
67
|
-
expect(splitter).to be_a described_class
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'can split' do
|
71
|
-
text = [ ?A * 10 ] * 10 * "\n\n"
|
72
|
-
result = splitter.split(text)
|
73
|
-
expect(result.count).to eq 5
|
74
|
-
expect(result.to_a.join('')).to eq ?A * 100
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'cannot split' do
|
78
|
-
splitter = described_class.new chunk_size: 23, include_separator: true,
|
79
|
-
separators: described_class::DEFAULT_SEPARATORS[0..-2]
|
80
|
-
text = ?A * 25
|
81
|
-
result = splitter.split(text)
|
82
|
-
expect(result.count).to eq 1
|
83
|
-
expect(result.to_a.join('')).to eq ?A * 25
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'can split including separator' do
|
87
|
-
splitter = described_class.new chunk_size: 25, include_separator: true,
|
88
|
-
combining_string: ''
|
89
|
-
text = [ ?A * 10 ] * 10 * "\n\n"
|
90
|
-
result = splitter.split(text)
|
91
|
-
expect(result.count).to eq 5
|
92
|
-
expect(result.to_a.join('')).to eq text
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'can split single newline as well' do
|
96
|
-
text = [ ?A * 10 ] * 10 * "\n"
|
97
|
-
result = splitter.split(text)
|
98
|
-
expect(result.count).to eq 5
|
99
|
-
expect(result.to_a.join('')).to eq ?A * 100
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'can split single newline as well including separator' do
|
103
|
-
splitter = described_class.new chunk_size: 25, include_separator: true,
|
104
|
-
combining_string: ''
|
105
|
-
text = [ ?A * 10 ] * 10 * "\n"
|
106
|
-
result = splitter.split(text)
|
107
|
-
expect(result.count).to eq 5
|
108
|
-
expect(result.to_a.join('')).to eq text
|
109
|
-
end
|
110
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Ollama::Documents::Splitters::Semantic do
|
4
|
-
let :ollama do
|
5
|
-
double('Ollama::Client')
|
6
|
-
end
|
7
|
-
|
8
|
-
let :splitter do
|
9
|
-
described_class.new ollama:, model: 'mxbai-embed-large'
|
10
|
-
end
|
11
|
-
|
12
|
-
let :embeddings do
|
13
|
-
JSON(File.read(asset('embeddings.json')))
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'can be instantiated' do
|
17
|
-
expect(splitter).to be_a described_class
|
18
|
-
end
|
19
|
-
|
20
|
-
before do
|
21
|
-
allow(ollama).to receive(:embed).and_return(double(embeddings:))
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'can split with breakpoint :percentile' do
|
25
|
-
text = ([ "A" * 10 ] * 3 + [ "B" * 10 ] * 3 + [ "A" * 10 ] * 3) * ". "
|
26
|
-
result = splitter.split(text, breakpoint: :percentile, percentile: 75)
|
27
|
-
expect(result.count).to eq 3
|
28
|
-
expect(result.to_a.join('').count(?A)).to eq text.count(?A)
|
29
|
-
expect(result.to_a.join('').count(?B)).to eq text.count(?B)
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'can split with breakpoint :percentile' do
|
33
|
-
described_class.new ollama:, model: 'mxbai-embed-large', chunk_size: 50
|
34
|
-
text = ([ "A" * 10 ] * 6 + [ "B" * 10 ] * 3 + [ "A" * 10 ] * 3) * ". "
|
35
|
-
result = splitter.split(text, breakpoint: :percentile, percentile: 75)
|
36
|
-
expect(result.count).to eq 4
|
37
|
-
expect(result.to_a.join('').count(?A)).to eq text.count(?A)
|
38
|
-
expect(result.to_a.join('').count(?B)).to eq text.count(?B)
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'can split with breakpoint :standard_deviation' do
|
42
|
-
text = ([ "A" * 10 ] * 3 + [ "B" * 10 ] * 3 + [ "A" * 10 ] * 3) * ". "
|
43
|
-
result = splitter.split(text, breakpoint: :standard_deviation, percentage: 100)
|
44
|
-
expect(result.count).to eq 3
|
45
|
-
expect(result.to_a.join('').count(?A)).to eq text.count(?A)
|
46
|
-
expect(result.to_a.join('').count(?B)).to eq text.count(?B)
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'can split with breakpoint :interquartile' do
|
50
|
-
text = ([ "A" * 10 ] * 3 + [ "B" * 10 ] * 3 + [ "A" * 10 ] * 3) * ". "
|
51
|
-
result = splitter.split(text, breakpoint: :interquartile, percentage: 75)
|
52
|
-
expect(result.count).to eq 3
|
53
|
-
expect(result.to_a.join('').count(?A)).to eq text.count(?A)
|
54
|
-
expect(result.to_a.join('').count(?B)).to eq text.count(?B)
|
55
|
-
end
|
56
|
-
end
|
@@ -1,162 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Ollama::Documents do
|
4
|
-
let :ollama do
|
5
|
-
double('Ollama::Client')
|
6
|
-
end
|
7
|
-
|
8
|
-
let :model do
|
9
|
-
'mxbai-embed-large'
|
10
|
-
end
|
11
|
-
|
12
|
-
let :documents do
|
13
|
-
described_class.new ollama:, model:
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'can be instantiated' do
|
17
|
-
expect(documents).to be_a described_class
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'no texts can be added to it' do
|
21
|
-
expect(documents.add([])).to eq documents
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'texts can be added to it' do
|
25
|
-
expect(ollama).to receive(:embed).
|
26
|
-
with(model:, input: %w[ foo bar ], options: nil).
|
27
|
-
and_return(double(embeddings: [ [ 0.1 ], [ 0.2 ] ]))
|
28
|
-
expect(documents.add(%w[ foo bar ])).to eq documents
|
29
|
-
expect(documents.exist?('foo')).to eq true
|
30
|
-
expect(documents.exist?('bar')).to eq true
|
31
|
-
expect(documents['foo']).to be_a Ollama::Documents::Record
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'a text can be added to it' do
|
35
|
-
expect(ollama).to receive(:embed).
|
36
|
-
with(model:, input: %w[ foo ], options: nil).
|
37
|
-
and_return(double(embeddings: [ [ 0.1 ] ]))
|
38
|
-
expect(documents << 'foo').to eq documents
|
39
|
-
expect(documents.exist?('foo')).to eq true
|
40
|
-
expect(documents.exist?('bar')).to eq false
|
41
|
-
expect(documents['foo']).to be_a Ollama::Documents::Record
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'can find strings' do
|
45
|
-
expect(ollama).to receive(:embed).
|
46
|
-
with(model:, input: [ 'foo' ], options: nil).
|
47
|
-
and_return(double(embeddings: [ [ 0.1 ] ]))
|
48
|
-
expect(documents << 'foo').to eq documents
|
49
|
-
expect(ollama).to receive(:embed).
|
50
|
-
with(model:, input: 'foo', options: nil).
|
51
|
-
and_return(double(embeddings: [ [ 0.1 ] ]))
|
52
|
-
records = documents.find('foo')
|
53
|
-
expect(records).to eq [
|
54
|
-
Ollama::Documents::Record[text: 'foo', embedding: [ 0.1 ], similarity: 1.0 ]
|
55
|
-
]
|
56
|
-
expect(records[0].to_s).to eq '#<Ollama::Documents::Record "foo" 1.0>'
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'can find only tagged strings' do
|
60
|
-
expect(ollama).to receive(:embed).
|
61
|
-
with(model:, input: [ 'foo' ], options: nil).
|
62
|
-
and_return(double(embeddings: [ [ 0.1 ] ]))
|
63
|
-
expect(documents.add('foo', tags: %w[ test ])).to eq documents
|
64
|
-
expect(ollama).to receive(:embed).
|
65
|
-
with(model:, input: 'foo', options: nil).
|
66
|
-
and_return(double(embeddings: [ [ 0.1 ] ]))
|
67
|
-
records = documents.find('foo', tags: %w[ nix ])
|
68
|
-
expect(records).to eq []
|
69
|
-
expect(ollama).to receive(:embed).
|
70
|
-
with(model:, input: 'foo', options: nil).
|
71
|
-
and_return(double(embeddings: [ [ 0.1 ] ]))
|
72
|
-
records = documents.find('foo', tags: %w[ test ])
|
73
|
-
expect(records).to eq [
|
74
|
-
Ollama::Documents::Record[text: 'foo', embedding: [ 0.1 ], similarity: 1.0 ]
|
75
|
-
]
|
76
|
-
expect(records[0].to_s).to eq '#<Ollama::Documents::Record "foo" #test 1.0>'
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'can find strings conditionally' do
|
80
|
-
expect(ollama).to receive(:embed).
|
81
|
-
with(model:, input: [ 'foobar' ], options: nil).
|
82
|
-
and_return(double(embeddings: [ [ 0.01 ] ]))
|
83
|
-
expect(ollama).to receive(:embed).
|
84
|
-
with(model:, input: [ 'foo' ], options: nil).
|
85
|
-
and_return(double(embeddings: [ [ 0.1 ] ]))
|
86
|
-
expect(documents << 'foobar').to eq documents
|
87
|
-
expect(documents << 'foo').to eq documents
|
88
|
-
expect(ollama).to receive(:embed).at_least(:once).
|
89
|
-
with(model:, input: 'foo', options: nil).
|
90
|
-
and_return(double(embeddings: [ [ 0.1 ] ]))
|
91
|
-
records = documents.find_where('foo', text_count: 1)
|
92
|
-
expect(records).to eq [
|
93
|
-
Ollama::Documents::Record[text: 'foo', embedding: [ 0.1 ], similarity: 1.0 ],
|
94
|
-
]
|
95
|
-
records = documents.find_where('foo', text_size: 3)
|
96
|
-
expect(records).to eq [
|
97
|
-
Ollama::Documents::Record[text: 'foo', embedding: [ 0.1 ], similarity: 1.0 ],
|
98
|
-
]
|
99
|
-
records = documents.find_where('foo')
|
100
|
-
expect(records).to eq [
|
101
|
-
Ollama::Documents::Record[text: 'foo', embedding: [ 0.1 ], similarity: 1.0 ],
|
102
|
-
Ollama::Documents::Record[text: 'foobar', embedding: [ 0.1 ], similarity: 1.0 ],
|
103
|
-
]
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
context 'it uses cache' do
|
108
|
-
before do
|
109
|
-
allow(ollama).to receive(:embed).
|
110
|
-
with(model:, input: %w[ foo ], options: nil).
|
111
|
-
and_return(double(embeddings: [ [ 0.1 ] ]))
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'can delete texts' do
|
115
|
-
expect(documents << 'foo').to eq documents
|
116
|
-
expect {
|
117
|
-
documents.delete('foo')
|
118
|
-
}.to change { documents.exist?('foo') }.from(true).to(false)
|
119
|
-
end
|
120
|
-
|
121
|
-
it 'tracks size' do
|
122
|
-
expect {
|
123
|
-
expect(documents << 'foo').to eq documents
|
124
|
-
}.to change { documents.size }.from(0).to(1)
|
125
|
-
end
|
126
|
-
|
127
|
-
it 'can clear texts' do
|
128
|
-
expect(documents << 'foo').to eq documents
|
129
|
-
expect {
|
130
|
-
documents.clear
|
131
|
-
}.to change { documents.size }.from(1).to(0)
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'can clear texts with tags' do
|
135
|
-
expect(ollama).to receive(:embed).
|
136
|
-
with(model:, input: %w[ bar ], options: nil).
|
137
|
-
and_return(double(embeddings: [ [ 0.1 ] ]))
|
138
|
-
expect(documents.add('foo', tags: %w[ test ])).to eq documents
|
139
|
-
expect(documents.add('bar', tags: %w[ test2 ])).to eq documents
|
140
|
-
expect(documents.tags.to_a).to eq %w[ test test2 ]
|
141
|
-
expect {
|
142
|
-
documents.clear tags: 'test'
|
143
|
-
}.to change { documents.size }.from(2).to(1)
|
144
|
-
expect {
|
145
|
-
documents.clear tags: :test2
|
146
|
-
}.to change { documents.size }.from(1).to(0)
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'returns collections' do
|
150
|
-
expect(documents.collections).to eq [ :default ]
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'can change collection' do
|
154
|
-
expect(documents.instance_eval { @cache }).to receive(:prefix=).
|
155
|
-
with(/#@collection/).and_call_original
|
156
|
-
expect { documents.collection = :new_collection }.
|
157
|
-
to change { documents.collection }.
|
158
|
-
from(:default).
|
159
|
-
to(:new_collection)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Ollama::Utils::ColorizeTexts do
|
4
|
-
it 'colorizes texts' do
|
5
|
-
ct = described_class.new(%w[ foo bar ])
|
6
|
-
colored = ct.to_s
|
7
|
-
uncolored = Term::ANSIColor.uncolor(ct.to_s)
|
8
|
-
expect(colored.size).to be > uncolored.size
|
9
|
-
expect(uncolored).to eq(
|
10
|
-
"foo\n#3 \n\nbar\n#3 \n\n"
|
11
|
-
)
|
12
|
-
end
|
13
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Ollama::Utils::Tags do
|
4
|
-
it 'can be instantiated' do
|
5
|
-
expect(described_class.new).to be_a described_class
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'can contain unique tags and is sorted' do
|
9
|
-
tags = described_class.new(%w[ bar foo ])
|
10
|
-
expect(tags.to_a).to eq %w[ bar foo ]
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'can contain unique tags with leading # characters and is sorted' do
|
14
|
-
tags = described_class.new(%w[ #bar ##foo ])
|
15
|
-
expect(tags.to_a).to eq %w[ bar foo ]
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'tags can be added to it' do
|
19
|
-
tags = described_class.new([ 'foo' ])
|
20
|
-
tags.add 'bar'
|
21
|
-
expect(tags.to_a).to eq %w[ bar foo ]
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'can increase in size' do
|
25
|
-
tags = described_class.new
|
26
|
-
expect { tags.add 'foo' }.to change { tags.size }.from(0).to(1)
|
27
|
-
expect { tags.add 'bar' }.to change { tags.size }.from(1).to(2)
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'can be cleared' do
|
31
|
-
tags = described_class.new([ 'foo', 'bar' ])
|
32
|
-
expect { tags.clear }.to change { tags.size }.from(2).to(0)
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'tags can be empty' do
|
36
|
-
tags = described_class.new([ 'foo' ])
|
37
|
-
expect { tags.clear }.to change { tags.empty? }.from(false).to(true)
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'can be output nicely' do
|
41
|
-
expect(described_class.new(%w[ #foo bar ]).to_s).to eq '#bar #foo'
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'can be output nicely with links to source' do
|
45
|
-
tags = described_class.new([ 'foo' ], source: 'https://foo.example.com')
|
46
|
-
tags.add 'bar', source: '/path/to/bar.html'
|
47
|
-
expect(tags.to_a).to eq %w[ bar foo ]
|
48
|
-
tags.all? { expect(_1).to be_a(Ollama::Utils::Tags::Tag) }
|
49
|
-
expect(tags.to_s).to eq(
|
50
|
-
"\e]8;;file:///path/to/bar.html\e\\#bar\e]8;;\e\\ \e]8;;https://foo.example.com\e\\#foo\e]8;;\e\\"
|
51
|
-
)
|
52
|
-
end
|
53
|
-
end
|