ollama-ruby 0.9.0 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +34 -0
- data/bin/ollama_chat +245 -228
- data/lib/ollama/dto.rb +4 -0
- data/lib/ollama/utils/fetcher.rb +8 -0
- data/lib/ollama/version.rb +1 -1
- data/ollama-ruby.gemspec +5 -5
- data/spec/ollama/documents_spec.rb +6 -5
- data/spec/ollama/options_spec.rb +4 -0
- data/spec/ollama/utils/colorize_texts_spec.rb +13 -0
- data/spec/ollama/utils/fetcher_spec.rb +27 -5
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2a82c4fc1db4e92e628d0e3a84525273f2ee3bd994f34185c742f0dab1d9b78
|
4
|
+
data.tar.gz: b77caa026511e2bc49bdf3d2e3782cc6a1edd1f60161f1301efbc927dc2d3cba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ea50f6c8fd275365b52b4c7047abc627079804dd7db61120dbbcf2c6b3f3fddf1946a46508fbb0bc26d0d7284d3b23f4f934b7c418bc91799417a5c2b72332c
|
7
|
+
data.tar.gz: cef39db9d4eb0ee160c53c4e522a158942c3532203f46d50ee88af2c1f3f36aac0030087e71864045c4979018be4891329155ad0e8863c4e8c52080ba3e28f3f
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,39 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
## 2024-10-20 v0.9.2
|
4
|
+
|
5
|
+
* Added SourceParsing module and update parse_source method to use it:
|
6
|
+
+ Added `SourceParsing` module with `parse_source` method that handles
|
7
|
+
different file types (e.g. HTML, XML, CSV, RSS)
|
8
|
+
+ Added `parse_csv` method to `SourceParsing` module
|
9
|
+
+ Updated `parse_source` method in main file to include new functionality
|
10
|
+
* Add colorize texts spec for Ollama::Utils::ColorizeTexts to test its
|
11
|
+
functionality.
|
12
|
+
* Added test for expected output of `documents.tags`
|
13
|
+
* Add test for empty Ollama options:
|
14
|
+
+ Added test case for `Ollama::Options` being empty
|
15
|
+
* Display (embedding) model options in info output
|
16
|
+
* Only show `collection_stats` if embedding is performed
|
17
|
+
* Add empty? method to DTO class:
|
18
|
+
+ Added `empty?` method to `Ollama::DTO` class using `to_hash.empty?`
|
19
|
+
+ Method is used to check if the object's hash representation is empty.
|
20
|
+
|
21
|
+
## 2024-10-19 v0.9.1
|
22
|
+
|
23
|
+
* Fixing string interpolation in `import_source` method:
|
24
|
+
+ Changed result to use `#{}` instead of `%{}` for string interpolation
|
25
|
+
* Move `pull_model_unless_present` method:
|
26
|
+
+ Moved the method before other methods
|
27
|
+
* Moved Switch classes and `setup_switches` method into Switches module:
|
28
|
+
+ Moved the classes and method into a new module
|
29
|
+
* Utils::Fetcher: Normalize URL in fetcher utility:
|
30
|
+
+ Added `normalize_url` method to class Ollama::Utils::Fetcher
|
31
|
+
+ Normalizes URL by decoding URI components, removing anchors, and escaping special characters
|
32
|
+
+ `excon` method now calls `normalize_url` on the provided URL
|
33
|
+
+ Added specs for `normalize_url` in `fetcher_spec.rb`
|
34
|
+
* Remove Ollama top level Namespace b/c we include it from `ollama_chat`:
|
35
|
+
+ Removed the top-level namespace
|
36
|
+
|
3
37
|
## 2024-10-18 v0.9.0
|
4
38
|
|
5
39
|
* Add document policy chooser and modify embedding/importing/summarizing
|
data/bin/ollama_chat
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'ollama'
|
4
4
|
include Ollama
|
5
|
+
include Tins::GO
|
5
6
|
require 'term/ansicolor'
|
6
7
|
include Term::ANSIColor
|
7
|
-
include Tins::GO
|
8
8
|
require 'reline'
|
9
9
|
require 'reverse_markdown'
|
10
10
|
require 'complex_config'
|
@@ -108,7 +108,7 @@ class OllamaChatConfig
|
|
108
108
|
end
|
109
109
|
|
110
110
|
class FollowChat
|
111
|
-
include
|
111
|
+
include Handlers::Concern
|
112
112
|
include Term::ANSIColor
|
113
113
|
|
114
114
|
def initialize(messages:, markdown: false, voice: nil, output: $stdout)
|
@@ -164,114 +164,142 @@ class FollowChat
|
|
164
164
|
end
|
165
165
|
end
|
166
166
|
|
167
|
-
module
|
168
|
-
|
167
|
+
module Switches
|
168
|
+
module CheckSwitch
|
169
|
+
extend Tins::Concern
|
169
170
|
|
170
|
-
|
171
|
-
|
172
|
-
|
171
|
+
included do
|
172
|
+
alias_method :on?, :value
|
173
|
+
end
|
173
174
|
|
174
|
-
|
175
|
-
|
176
|
-
|
175
|
+
def off?
|
176
|
+
!on?
|
177
|
+
end
|
177
178
|
|
178
|
-
|
179
|
-
|
179
|
+
def show
|
180
|
+
puts @msg[value]
|
181
|
+
end
|
180
182
|
end
|
181
|
-
end
|
182
183
|
|
183
|
-
class Switch
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
184
|
+
class Switch
|
185
|
+
def initialize(name, msg:, config: $config)
|
186
|
+
@value = [ false, true ].include?(config) ? config : !!config.send("#{name}?")
|
187
|
+
@msg = msg
|
188
|
+
end
|
188
189
|
|
189
|
-
|
190
|
+
attr_reader :value
|
190
191
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
192
|
+
def set(value, show: false)
|
193
|
+
@value = !!value
|
194
|
+
show && self.show
|
195
|
+
end
|
196
|
+
|
197
|
+
def toggle(show: true)
|
198
|
+
@value = !@value
|
199
|
+
show && self.show
|
200
|
+
end
|
195
201
|
|
196
|
-
|
197
|
-
@value = !@value
|
198
|
-
show && self.show
|
202
|
+
include CheckSwitch
|
199
203
|
end
|
200
204
|
|
201
|
-
|
202
|
-
|
205
|
+
class CombinedSwitch
|
206
|
+
def initialize(value:, msg:)
|
207
|
+
@value = value
|
208
|
+
@msg = msg
|
209
|
+
end
|
203
210
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
@msg = msg
|
208
|
-
end
|
211
|
+
def value
|
212
|
+
@value.()
|
213
|
+
end
|
209
214
|
|
210
|
-
|
211
|
-
@value.()
|
215
|
+
include CheckSwitch
|
212
216
|
end
|
213
217
|
|
214
|
-
|
215
|
-
|
218
|
+
def setup_switches
|
219
|
+
$markdown = Switch.new(
|
220
|
+
:markdown,
|
221
|
+
msg: {
|
222
|
+
true => "Using #{italic{'ANSI'}} markdown to output content.",
|
223
|
+
false => "Using plaintext for outputting content.",
|
224
|
+
}
|
225
|
+
)
|
216
226
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
)
|
227
|
+
$stream = Switch.new(
|
228
|
+
:stream,
|
229
|
+
msg: {
|
230
|
+
true => "Streaming enabled.",
|
231
|
+
false => "Streaming disabled.",
|
232
|
+
}
|
233
|
+
)
|
225
234
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
235
|
+
$voice = Switch.new(
|
236
|
+
:stream,
|
237
|
+
msg: {
|
238
|
+
true => "Voice output enabled.",
|
239
|
+
false => "Voice output disabled.",
|
240
|
+
},
|
241
|
+
config: $config.voice
|
242
|
+
)
|
233
243
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
)
|
244
|
+
$embedding_enabled = Switch.new(
|
245
|
+
:embedding_enabled,
|
246
|
+
msg: {
|
247
|
+
true => "Embedding enabled.",
|
248
|
+
false => "Embedding disabled.",
|
249
|
+
}
|
250
|
+
)
|
242
251
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
252
|
+
$embedding_paused = Switch.new(
|
253
|
+
:embedding_paused,
|
254
|
+
msg: {
|
255
|
+
true => "Embedding paused.",
|
256
|
+
false => "Embedding resumed.",
|
257
|
+
}
|
258
|
+
)
|
250
259
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
260
|
+
$embedding = CombinedSwitch.new(
|
261
|
+
value: -> { $embedding_enabled.on? && $embedding_paused.off? },
|
262
|
+
msg: {
|
263
|
+
true => "Embedding is currently performed.",
|
264
|
+
false => "Embedding is currently not performed.",
|
265
|
+
}
|
266
|
+
)
|
258
267
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
268
|
+
$location = Switch.new(
|
269
|
+
:location,
|
270
|
+
msg: {
|
271
|
+
true => "Location and localtime enabled.",
|
272
|
+
false => "Location and localtime disabled.",
|
273
|
+
},
|
274
|
+
config: $config.location.enabled
|
275
|
+
)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
include Switches
|
266
279
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
280
|
+
def pull_model_unless_present(model, options, retried = false)
|
281
|
+
ollama.show(name: model) { |response|
|
282
|
+
puts "Model #{bold{model}} with architecture "\
|
283
|
+
"#{response.model_info['general.architecture']} found."
|
284
|
+
if system = response.system
|
285
|
+
puts "Configured model system prompt is:\n#{italic { system }}"
|
286
|
+
return system
|
287
|
+
else
|
288
|
+
return
|
289
|
+
end
|
290
|
+
}
|
291
|
+
rescue Errors::NotFoundError
|
292
|
+
puts "Model #{bold{model}} not found locally, attempting to pull it from remote now…"
|
293
|
+
ollama.pull(name: model)
|
294
|
+
if retried
|
295
|
+
exit 1
|
296
|
+
else
|
297
|
+
retried = true
|
298
|
+
retry
|
299
|
+
end
|
300
|
+
rescue Errors::Error => e
|
301
|
+
warn "Caught #{e.class} while pulling model: #{e} => Exiting."
|
302
|
+
exit 1
|
275
303
|
end
|
276
304
|
|
277
305
|
def search_web(query, n = nil)
|
@@ -282,7 +310,7 @@ def search_web(query, n = nil)
|
|
282
310
|
n < 1 and n = 1
|
283
311
|
query = URI.encode_uri_component(query)
|
284
312
|
url = "https://www.duckduckgo.com/html/?q=#{query}"
|
285
|
-
|
313
|
+
Utils::Fetcher.get(url, debug: $config.debug) do |tmp|
|
286
314
|
result = []
|
287
315
|
doc = Nokogiri::HTML(tmp)
|
288
316
|
doc.css('.results_links').each do |link|
|
@@ -303,38 +331,13 @@ def search_web(query, n = nil)
|
|
303
331
|
end
|
304
332
|
end
|
305
333
|
|
306
|
-
def pull_model_unless_present(model, options, retried = false)
|
307
|
-
ollama.show(name: model) { |response|
|
308
|
-
puts "Model #{bold{model}} with architecture "\
|
309
|
-
"#{response.model_info['general.architecture']} found."
|
310
|
-
if system = response.system
|
311
|
-
puts "Configured model system prompt is:\n#{italic { system }}"
|
312
|
-
return system
|
313
|
-
else
|
314
|
-
return
|
315
|
-
end
|
316
|
-
}
|
317
|
-
rescue Errors::NotFoundError
|
318
|
-
puts "Model #{bold{model}} not found locally, attempting to pull it from remote now…"
|
319
|
-
ollama.pull(name: model)
|
320
|
-
if retried
|
321
|
-
exit 1
|
322
|
-
else
|
323
|
-
retried = true
|
324
|
-
retry
|
325
|
-
end
|
326
|
-
rescue Errors::Error => e
|
327
|
-
warn "Caught #{e.class} while pulling model: #{e} => Exiting."
|
328
|
-
exit 1
|
329
|
-
end
|
330
|
-
|
331
334
|
def load_conversation(filename)
|
332
335
|
unless File.exist?(filename)
|
333
336
|
puts "File #{filename} doesn't exist. Choose another filename."
|
334
337
|
return
|
335
338
|
end
|
336
339
|
File.open(filename, 'r') do |output|
|
337
|
-
return JSON(output.read).map {
|
340
|
+
return JSON(output.read).map { Message.from_hash(_1) }
|
338
341
|
end
|
339
342
|
end
|
340
343
|
|
@@ -372,113 +375,120 @@ def list_conversation(messages, last = nil)
|
|
372
375
|
end
|
373
376
|
end
|
374
377
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
378
|
+
module SourceParsing
|
379
|
+
def parse_source(source_io)
|
380
|
+
case source_io&.content_type
|
381
|
+
when 'text/html'
|
382
|
+
reverse_markdown(source_io.read)
|
383
|
+
when 'text/xml'
|
384
|
+
if source_io.readline =~ %r(^\s*<rss\s)
|
385
|
+
source_io.rewind
|
386
|
+
return parse_rss(source_io)
|
387
|
+
end
|
388
|
+
source_io.rewind
|
389
|
+
source_io.read
|
390
|
+
when 'text/csv' # TODO
|
391
|
+
parse_csv(source_io)
|
392
|
+
when 'application/rss+xml'
|
393
|
+
parse_rss(source_io)
|
394
|
+
when 'application/atom+xml'
|
395
|
+
parse_atom(source_io)
|
396
|
+
when 'application/postscript'
|
397
|
+
ps_read(source_io)
|
398
|
+
when 'application/pdf'
|
399
|
+
pdf_read(source_io)
|
400
|
+
when %r(\Aapplication/(json|ld\+json|x-ruby|x-perl|x-gawk|x-python|x-javascript|x-c?sh|x-dosexec|x-shellscript|x-tex|x-latex|x-lyx|x-bibtex)), %r(\Atext/), nil
|
401
|
+
source_io.read
|
402
|
+
else
|
403
|
+
STDERR.puts "Cannot embed #{source_io&.content_type} document."
|
404
|
+
return
|
405
|
+
end
|
406
|
+
end
|
383
407
|
|
384
|
-
def
|
385
|
-
|
386
|
-
|
387
|
-
|
408
|
+
def parse_csv(source_io)
|
409
|
+
result = +''
|
410
|
+
CSV.table(File.new(source_io), col_sep: ?,).each do |row|
|
411
|
+
next if row.fields.select(&:present?).size == 0
|
412
|
+
result << row.map { |pair|
|
413
|
+
pair.compact.map { _1.to_s.strip } * ': ' if pair.last.present?
|
414
|
+
}.select(&:present?).map { _1.prepend(' ') } * ?\n
|
415
|
+
result << "\n\n"
|
416
|
+
end
|
417
|
+
result
|
418
|
+
end
|
388
419
|
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
420
|
+
def parse_rss(source_io)
|
421
|
+
feed = RSS::Parser.parse(source_io, false, false)
|
422
|
+
title = <<~EOT
|
423
|
+
# #{feed&.channel&.title}
|
393
424
|
|
394
|
-
|
425
|
+
EOT
|
426
|
+
feed.items.inject(title) do |text, item|
|
427
|
+
text << <<~EOT
|
428
|
+
## [#{item&.title}](#{item&.link})
|
395
429
|
|
396
|
-
|
430
|
+
updated on #{item&.pubDate}
|
397
431
|
|
398
|
-
|
432
|
+
#{reverse_markdown(item&.description)}
|
433
|
+
|
434
|
+
EOT
|
435
|
+
end
|
399
436
|
end
|
400
|
-
end
|
401
437
|
|
402
|
-
def parse_atom(source_io)
|
403
|
-
|
404
|
-
|
405
|
-
|
438
|
+
def parse_atom(source_io)
|
439
|
+
feed = RSS::Parser.parse(source_io, false, false)
|
440
|
+
title = <<~EOT
|
441
|
+
# #{feed.title.content}
|
406
442
|
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
443
|
+
EOT
|
444
|
+
feed.items.inject(title) do |text, item|
|
445
|
+
text << <<~EOT
|
446
|
+
## [#{item&.title&.content}](#{item&.link&.href})
|
411
447
|
|
412
|
-
|
448
|
+
updated on #{item&.updated&.content}
|
413
449
|
|
414
|
-
|
450
|
+
#{reverse_markdown(item&.content&.content)}
|
415
451
|
|
416
|
-
|
452
|
+
EOT
|
453
|
+
end
|
417
454
|
end
|
418
|
-
end
|
419
455
|
|
420
|
-
def pdf_read(io)
|
421
|
-
|
422
|
-
|
423
|
-
end
|
456
|
+
def pdf_read(io)
|
457
|
+
reader = PDF::Reader.new(io)
|
458
|
+
reader.pages.inject(+'') { |result, page| result << page.text }
|
459
|
+
end
|
424
460
|
|
425
|
-
def ps_read(io)
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
461
|
+
def ps_read(io)
|
462
|
+
gs = `which gs`.chomp
|
463
|
+
if gs.present?
|
464
|
+
Tempfile.create do |tmp|
|
465
|
+
IO.popen("#{gs} -q -sDEVICE=pdfwrite -sOutputFile=#{tmp.path} -", 'wb') do |gs_io|
|
466
|
+
until io.eof?
|
467
|
+
buffer = io.read(1 << 17)
|
468
|
+
IO.select(nil, [ gs_io ], nil)
|
469
|
+
gs_io.write buffer
|
470
|
+
end
|
471
|
+
gs_io.close
|
472
|
+
File.open(tmp.path, 'rb') do |pdf|
|
473
|
+
pdf_read(pdf)
|
474
|
+
end
|
438
475
|
end
|
439
476
|
end
|
477
|
+
else
|
478
|
+
STDERR.puts "Cannot convert #{io&.content_type} whith ghostscript, gs not in path."
|
440
479
|
end
|
441
|
-
else
|
442
|
-
STDERR.puts "Cannot convert #{io&.content_type} whith ghostscript, gs not in path."
|
443
480
|
end
|
444
|
-
end
|
445
481
|
|
446
|
-
def
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
return parse_rss(source_io)
|
454
|
-
end
|
455
|
-
source_io.rewind
|
456
|
-
source_io.read
|
457
|
-
when 'text/csv'
|
458
|
-
result = +''
|
459
|
-
CSV.table(File.new(source_io), col_sep: ?,).each do |row|
|
460
|
-
next if row.fields.select(&:present?).size == 0
|
461
|
-
result << row.map { |pair|
|
462
|
-
pair.compact.map { _1.to_s.strip } * ': ' if pair.last.present?
|
463
|
-
}.select(&:present?).map { _1.prepend(' ') } * ?\n
|
464
|
-
result << "\n\n"
|
465
|
-
end
|
466
|
-
result
|
467
|
-
when 'application/rss+xml'
|
468
|
-
parse_rss(source_io)
|
469
|
-
when 'application/atom+xml'
|
470
|
-
parse_atom(source_io)
|
471
|
-
when 'application/postscript'
|
472
|
-
ps_read(source_io)
|
473
|
-
when 'application/pdf'
|
474
|
-
pdf_read(source_io)
|
475
|
-
when %r(\Aapplication/(json|ld\+json|x-ruby|x-perl|x-gawk|x-python|x-javascript|x-c?sh|x-dosexec|x-shellscript|x-tex|x-latex|x-lyx|x-bibtex)), %r(\Atext/), nil
|
476
|
-
source_io.read
|
477
|
-
else
|
478
|
-
STDERR.puts "Cannot embed #{source_io&.content_type} document."
|
479
|
-
return
|
482
|
+
def reverse_markdown(html)
|
483
|
+
ReverseMarkdown.convert(
|
484
|
+
html,
|
485
|
+
unknown_tags: :bypass,
|
486
|
+
github_flavored: true,
|
487
|
+
tag_border: ''
|
488
|
+
)
|
480
489
|
end
|
481
490
|
end
|
491
|
+
include SourceParsing
|
482
492
|
|
483
493
|
def http_options(url)
|
484
494
|
options = {}
|
@@ -504,7 +514,7 @@ def fetch_source(source, &block)
|
|
504
514
|
source,
|
505
515
|
cache: $cache,
|
506
516
|
debug: $config.debug,
|
507
|
-
http_options: http_options(source)
|
517
|
+
http_options: http_options(Utils::Fetcher.normalize_url(source))
|
508
518
|
) do |tmp|
|
509
519
|
block.(tmp)
|
510
520
|
end
|
@@ -518,7 +528,7 @@ def fetch_source(source, &block)
|
|
518
528
|
raise "invalid source"
|
519
529
|
end
|
520
530
|
rescue => e
|
521
|
-
STDERR.puts "Cannot fetch source #{source.to_s.inspect}: #{e}\n#{e.backtrace * ?\n}"
|
531
|
+
STDERR.puts "Cannot fetch source #{source.to_s.inspect}: #{e.class} #{e}\n#{e.backtrace * ?\n}"
|
522
532
|
end
|
523
533
|
|
524
534
|
def add_image(images, source_io, source)
|
@@ -530,7 +540,8 @@ end
|
|
530
540
|
def import_source(source_io, source)
|
531
541
|
source = source.to_s
|
532
542
|
puts "Importing #{italic { source_io&.content_type }} document #{source.inspect} now."
|
533
|
-
|
543
|
+
source_content = parse_source(source_io)
|
544
|
+
"Imported #{source.inspect}:\n#{source_content}\n\n"
|
534
545
|
end
|
535
546
|
|
536
547
|
def import(source)
|
@@ -572,17 +583,17 @@ def embed_source(source_io, source, count: nil)
|
|
572
583
|
inputs = nil
|
573
584
|
case splitter_config.name
|
574
585
|
when 'Character'
|
575
|
-
splitter =
|
586
|
+
splitter = Documents::Splitters::Character.new(
|
576
587
|
chunk_size: splitter_config.chunk_size,
|
577
588
|
)
|
578
589
|
inputs = splitter.split(text)
|
579
590
|
when 'RecursiveCharacter'
|
580
|
-
splitter =
|
591
|
+
splitter = Documents::Splitters::RecursiveCharacter.new(
|
581
592
|
chunk_size: splitter_config.chunk_size,
|
582
593
|
)
|
583
594
|
inputs = splitter.split(text)
|
584
595
|
when 'Semantic'
|
585
|
-
splitter =
|
596
|
+
splitter = Documents::Splitters::Semantic.new(
|
586
597
|
ollama:, model: $config.embedding.model.name,
|
587
598
|
chunk_size: splitter_config.chunk_size,
|
588
599
|
)
|
@@ -597,7 +608,7 @@ def embed_source(source_io, source, count: nil)
|
|
597
608
|
inputs or return
|
598
609
|
source = source.to_s
|
599
610
|
if source.start_with?(?!)
|
600
|
-
source =
|
611
|
+
source = Utils::Width.truncate(
|
601
612
|
source[1..-1].gsub(/\W+/, ?_),
|
602
613
|
length: 10
|
603
614
|
)
|
@@ -662,7 +673,7 @@ end
|
|
662
673
|
def choose_model(cli_model, current_model)
|
663
674
|
models = ollama.tags.models.map(&:name).sort
|
664
675
|
model = if cli_model == ''
|
665
|
-
|
676
|
+
Utils::Chooser.choose(models) || current_model
|
666
677
|
else
|
667
678
|
cli_model || current_model
|
668
679
|
end
|
@@ -679,7 +690,7 @@ def choose_collection(current_collection)
|
|
679
690
|
collections = [ current_collection ] + $documents.collections
|
680
691
|
collections = collections.compact.map(&:to_s).uniq.sort
|
681
692
|
collections.unshift('[EXIT]').unshift('[NEW]')
|
682
|
-
collection =
|
693
|
+
collection = Utils::Chooser.choose(collections) || current_collection
|
683
694
|
case collection
|
684
695
|
when '[NEW]'
|
685
696
|
$documents.collection = ask?(prompt: "Enter name of the new collection: ")
|
@@ -703,7 +714,7 @@ def choose_document_policy
|
|
703
714
|
policies.first
|
704
715
|
end
|
705
716
|
policies.unshift('[EXIT]')
|
706
|
-
policy =
|
717
|
+
policy = Utils::Chooser.choose(policies)
|
707
718
|
case policy
|
708
719
|
when nil, '[EXIT]'
|
709
720
|
puts "Exiting chooser."
|
@@ -722,7 +733,6 @@ def collection_stats
|
|
722
733
|
puts <<~EOT
|
723
734
|
Current Collection
|
724
735
|
Name: #{bold{$documents.collection}}
|
725
|
-
Embedding model: #{bold{$embedding_model}}
|
726
736
|
#Embeddings: #{$documents.size}
|
727
737
|
#Tags: #{$documents.tags.size}
|
728
738
|
Tags: #{$documents.tags}
|
@@ -733,19 +743,19 @@ end
|
|
733
743
|
|
734
744
|
def configure_cache
|
735
745
|
if $opts[?M]
|
736
|
-
|
746
|
+
Documents::MemoryCache
|
737
747
|
else
|
738
748
|
Object.const_get($config.cache)
|
739
749
|
end
|
740
750
|
rescue => e
|
741
751
|
STDERR.puts "Caught #{e.class}: #{e} => Falling back to MemoryCache."
|
742
|
-
|
752
|
+
Documents::MemoryCache
|
743
753
|
end
|
744
754
|
|
745
755
|
def show_system_prompt
|
746
756
|
puts <<~EOT
|
747
757
|
Configured system prompt is:
|
748
|
-
#{
|
758
|
+
#{Utils::ANSIMarkdown.parse($system.to_s).gsub(/\n+\z/, '').full? || 'n/a'}
|
749
759
|
EOT
|
750
760
|
end
|
751
761
|
|
@@ -769,7 +779,7 @@ end
|
|
769
779
|
|
770
780
|
def change_system_prompt(messages, default)
|
771
781
|
prompts = $config.system_prompts.attribute_names.compact
|
772
|
-
chosen =
|
782
|
+
chosen = Utils::Chooser.choose(prompts)
|
773
783
|
system = if chosen
|
774
784
|
$config.system_prompts.send(chosen)
|
775
785
|
else
|
@@ -779,16 +789,23 @@ def change_system_prompt(messages, default)
|
|
779
789
|
end
|
780
790
|
|
781
791
|
def change_voice
|
782
|
-
chosen =
|
792
|
+
chosen = Utils::Chooser.choose($config.voice.list)
|
783
793
|
$current_voice = chosen.full? || $config.voice.default
|
784
794
|
end
|
785
795
|
|
786
796
|
def info
|
787
797
|
puts "Current model is #{bold{$model}}."
|
788
|
-
|
798
|
+
if $model_options.present?
|
799
|
+
puts " Options: #{JSON.pretty_generate($model_options).gsub(/(?<!\A)^/, ' ')}"
|
800
|
+
end
|
789
801
|
$embedding.show
|
790
802
|
if $embedding.on?
|
803
|
+
puts "Embedding model is #{bold{$embedding_model}}"
|
804
|
+
if $embedding_model_options.present?
|
805
|
+
puts " Options: #{JSON.pretty_generate($embedding_model_options).gsub(/(?<!\A)^/, ' ')}"
|
806
|
+
end
|
791
807
|
puts "Text splitter is #{bold{$config.embedding.splitter.name}}."
|
808
|
+
collection_stats
|
792
809
|
end
|
793
810
|
puts "Documents database cache is #{$documents.nil? ? 'n/a' : bold{$documents.cache.class}}"
|
794
811
|
$markdown.show
|
@@ -891,12 +908,12 @@ $opts[?h] and usage
|
|
891
908
|
$opts[?V] and version
|
892
909
|
|
893
910
|
base_url = $opts[?u] || $config.url
|
894
|
-
$ollama
|
911
|
+
$ollama = Client.new(base_url:, debug: $config.debug)
|
895
912
|
|
896
913
|
$document_policy = $config.document_policy
|
897
914
|
$model = choose_model($opts[?m], $config.model.name)
|
898
|
-
|
899
|
-
model_system = pull_model_unless_present($model,
|
915
|
+
$model_options = Options[$config.model.options]
|
916
|
+
model_system = pull_model_unless_present($model, $model_options)
|
900
917
|
messages = []
|
901
918
|
$embedding_enabled.set($config.embedding.enabled && !$opts[?E])
|
902
919
|
|
@@ -907,15 +924,15 @@ else
|
|
907
924
|
if $opts[?s] == ??
|
908
925
|
change_system_prompt(messages, default)
|
909
926
|
else
|
910
|
-
system =
|
927
|
+
system = Utils::FileArgument.get_file_argument($opts[?s], default:)
|
911
928
|
system.present? and set_system_prompt(messages, system)
|
912
929
|
end
|
913
930
|
end
|
914
931
|
|
915
932
|
if $embedding.on?
|
916
933
|
$embedding_model = $config.embedding.model.name
|
917
|
-
embedding_model_options = Options[$config.embedding.model.options]
|
918
|
-
pull_model_unless_present($embedding_model, embedding_model_options)
|
934
|
+
$embedding_model_options = Options[$config.embedding.model.options]
|
935
|
+
pull_model_unless_present($embedding_model, $embedding_model_options)
|
919
936
|
collection = $opts[?C] || $config.embedding.collection
|
920
937
|
$documents = Documents.new(
|
921
938
|
ollama:,
|
@@ -957,7 +974,7 @@ else
|
|
957
974
|
end
|
958
975
|
|
959
976
|
if redis_expiring_url = $config.redis.expiring.url?
|
960
|
-
$cache =
|
977
|
+
$cache = Documents::RedisCache.new(
|
961
978
|
prefix: 'Expiring-',
|
962
979
|
url: redis_expiring_url,
|
963
980
|
ex: $config.redis.expiring.ex,
|
@@ -1051,7 +1068,7 @@ loop do
|
|
1051
1068
|
when 'clear'
|
1052
1069
|
loop do
|
1053
1070
|
tags = $documents.tags.add('[EXIT]').add('[ALL]')
|
1054
|
-
tag =
|
1071
|
+
tag = Utils::Chooser.choose(tags, prompt: 'Clear? %s')
|
1055
1072
|
case tag
|
1056
1073
|
when nil, '[EXIT]'
|
1057
1074
|
puts "Exiting chooser."
|
@@ -1154,7 +1171,7 @@ loop do
|
|
1154
1171
|
messages << Message.new(role: 'user', content:, images: images.dup)
|
1155
1172
|
images.clear
|
1156
1173
|
handler = FollowChat.new(messages:, markdown: $markdown.on?, voice: ($current_voice if $voice.on?))
|
1157
|
-
ollama.chat(model: $model, messages:, options
|
1174
|
+
ollama.chat(model: $model, messages:, options: $model_options, stream: $stream.on?, &handler)
|
1158
1175
|
|
1159
1176
|
if $embedding.on? && !records.empty?
|
1160
1177
|
puts "", records.map { |record|
|
data/lib/ollama/dto.rb
CHANGED
data/lib/ollama/utils/fetcher.rb
CHANGED
@@ -38,6 +38,13 @@ class Ollama::Utils::Fetcher
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
def self.normalize_url(url)
|
42
|
+
url = url.to_s
|
43
|
+
url = URI.decode_uri_component(url)
|
44
|
+
url = url.sub(/#.*/, '')
|
45
|
+
URI::Parser.new.escape(url).to_s
|
46
|
+
end
|
47
|
+
|
41
48
|
def self.read(filename, &block)
|
42
49
|
if File.exist?(filename)
|
43
50
|
File.open(filename) do |file|
|
@@ -80,6 +87,7 @@ class Ollama::Utils::Fetcher
|
|
80
87
|
private
|
81
88
|
|
82
89
|
def excon(url, **options)
|
90
|
+
url = self.class.normalize_url(url)
|
83
91
|
Excon.new(url, options.merge(@http_options))
|
84
92
|
end
|
85
93
|
|
data/lib/ollama/version.rb
CHANGED
data/ollama-ruby.gemspec
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: ollama-ruby 0.9.
|
2
|
+
# stub: ollama-ruby 0.9.2 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "ollama-ruby".freeze
|
6
|
-
s.version = "0.9.
|
6
|
+
s.version = "0.9.2".freeze
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
9
9
|
s.require_paths = ["lib".freeze]
|
10
10
|
s.authors = ["Florian Frank".freeze]
|
11
|
-
s.date = "2024-10-
|
11
|
+
s.date = "2024-10-20"
|
12
12
|
s.description = "Library that allows interacting with the Ollama API".freeze
|
13
13
|
s.email = "flori@ping.de".freeze
|
14
14
|
s.executables = ["ollama_console".freeze, "ollama_chat".freeze, "ollama_update".freeze, "ollama_cli".freeze]
|
15
15
|
s.extra_rdoc_files = ["README.md".freeze, "lib/ollama.rb".freeze, "lib/ollama/client.rb".freeze, "lib/ollama/client/command.rb".freeze, "lib/ollama/client/doc.rb".freeze, "lib/ollama/commands/chat.rb".freeze, "lib/ollama/commands/copy.rb".freeze, "lib/ollama/commands/create.rb".freeze, "lib/ollama/commands/delete.rb".freeze, "lib/ollama/commands/embed.rb".freeze, "lib/ollama/commands/embeddings.rb".freeze, "lib/ollama/commands/generate.rb".freeze, "lib/ollama/commands/ps.rb".freeze, "lib/ollama/commands/pull.rb".freeze, "lib/ollama/commands/push.rb".freeze, "lib/ollama/commands/show.rb".freeze, "lib/ollama/commands/tags.rb".freeze, "lib/ollama/documents.rb".freeze, "lib/ollama/documents/cache/common.rb".freeze, "lib/ollama/documents/cache/memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_backed_memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_cache.rb".freeze, "lib/ollama/documents/splitters/character.rb".freeze, "lib/ollama/documents/splitters/semantic.rb".freeze, "lib/ollama/dto.rb".freeze, "lib/ollama/errors.rb".freeze, "lib/ollama/handlers.rb".freeze, "lib/ollama/handlers/collector.rb".freeze, "lib/ollama/handlers/concern.rb".freeze, "lib/ollama/handlers/dump_json.rb".freeze, "lib/ollama/handlers/dump_yaml.rb".freeze, "lib/ollama/handlers/markdown.rb".freeze, "lib/ollama/handlers/nop.rb".freeze, "lib/ollama/handlers/print.rb".freeze, "lib/ollama/handlers/progress.rb".freeze, "lib/ollama/handlers/say.rb".freeze, "lib/ollama/handlers/single.rb".freeze, "lib/ollama/image.rb".freeze, "lib/ollama/message.rb".freeze, "lib/ollama/options.rb".freeze, "lib/ollama/response.rb".freeze, "lib/ollama/tool.rb".freeze, "lib/ollama/tool/function.rb".freeze, "lib/ollama/tool/function/parameters.rb".freeze, "lib/ollama/tool/function/parameters/property.rb".freeze, "lib/ollama/utils/ansi_markdown.rb".freeze, "lib/ollama/utils/cache_fetcher.rb".freeze, "lib/ollama/utils/chooser.rb".freeze, "lib/ollama/utils/colorize_texts.rb".freeze, "lib/ollama/utils/fetcher.rb".freeze, "lib/ollama/utils/file_argument.rb".freeze, "lib/ollama/utils/math.rb".freeze, "lib/ollama/utils/tags.rb".freeze, "lib/ollama/utils/width.rb".freeze, "lib/ollama/version.rb".freeze]
|
16
|
-
s.files = [".envrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_cli".freeze, "bin/ollama_console".freeze, "bin/ollama_update".freeze, "config/redis.conf".freeze, "docker-compose.yml".freeze, "lib/ollama.rb".freeze, "lib/ollama/client.rb".freeze, "lib/ollama/client/command.rb".freeze, "lib/ollama/client/doc.rb".freeze, "lib/ollama/commands/chat.rb".freeze, "lib/ollama/commands/copy.rb".freeze, "lib/ollama/commands/create.rb".freeze, "lib/ollama/commands/delete.rb".freeze, "lib/ollama/commands/embed.rb".freeze, "lib/ollama/commands/embeddings.rb".freeze, "lib/ollama/commands/generate.rb".freeze, "lib/ollama/commands/ps.rb".freeze, "lib/ollama/commands/pull.rb".freeze, "lib/ollama/commands/push.rb".freeze, "lib/ollama/commands/show.rb".freeze, "lib/ollama/commands/tags.rb".freeze, "lib/ollama/documents.rb".freeze, "lib/ollama/documents/cache/common.rb".freeze, "lib/ollama/documents/cache/memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_backed_memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_cache.rb".freeze, "lib/ollama/documents/splitters/character.rb".freeze, "lib/ollama/documents/splitters/semantic.rb".freeze, "lib/ollama/dto.rb".freeze, "lib/ollama/errors.rb".freeze, "lib/ollama/handlers.rb".freeze, "lib/ollama/handlers/collector.rb".freeze, "lib/ollama/handlers/concern.rb".freeze, "lib/ollama/handlers/dump_json.rb".freeze, "lib/ollama/handlers/dump_yaml.rb".freeze, "lib/ollama/handlers/markdown.rb".freeze, "lib/ollama/handlers/nop.rb".freeze, "lib/ollama/handlers/print.rb".freeze, "lib/ollama/handlers/progress.rb".freeze, "lib/ollama/handlers/say.rb".freeze, "lib/ollama/handlers/single.rb".freeze, "lib/ollama/image.rb".freeze, "lib/ollama/message.rb".freeze, "lib/ollama/options.rb".freeze, "lib/ollama/response.rb".freeze, "lib/ollama/tool.rb".freeze, "lib/ollama/tool/function.rb".freeze, "lib/ollama/tool/function/parameters.rb".freeze, "lib/ollama/tool/function/parameters/property.rb".freeze, "lib/ollama/utils/ansi_markdown.rb".freeze, "lib/ollama/utils/cache_fetcher.rb".freeze, "lib/ollama/utils/chooser.rb".freeze, "lib/ollama/utils/colorize_texts.rb".freeze, "lib/ollama/utils/fetcher.rb".freeze, "lib/ollama/utils/file_argument.rb".freeze, "lib/ollama/utils/math.rb".freeze, "lib/ollama/utils/tags.rb".freeze, "lib/ollama/utils/width.rb".freeze, "lib/ollama/version.rb".freeze, "ollama-ruby.gemspec".freeze, "spec/assets/embeddings.json".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/prompt.txt".freeze, "spec/ollama/client/doc_spec.rb".freeze, "spec/ollama/client_spec.rb".freeze, "spec/ollama/commands/chat_spec.rb".freeze, "spec/ollama/commands/copy_spec.rb".freeze, "spec/ollama/commands/create_spec.rb".freeze, "spec/ollama/commands/delete_spec.rb".freeze, "spec/ollama/commands/embed_spec.rb".freeze, "spec/ollama/commands/embeddings_spec.rb".freeze, "spec/ollama/commands/generate_spec.rb".freeze, "spec/ollama/commands/ps_spec.rb".freeze, "spec/ollama/commands/pull_spec.rb".freeze, "spec/ollama/commands/push_spec.rb".freeze, "spec/ollama/commands/show_spec.rb".freeze, "spec/ollama/commands/tags_spec.rb".freeze, "spec/ollama/documents/memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_backed_memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_cache_spec.rb".freeze, "spec/ollama/documents/splitters/character_spec.rb".freeze, "spec/ollama/documents/splitters/semantic_spec.rb".freeze, "spec/ollama/documents_spec.rb".freeze, "spec/ollama/handlers/collector_spec.rb".freeze, "spec/ollama/handlers/dump_json_spec.rb".freeze, "spec/ollama/handlers/dump_yaml_spec.rb".freeze, "spec/ollama/handlers/markdown_spec.rb".freeze, "spec/ollama/handlers/nop_spec.rb".freeze, "spec/ollama/handlers/print_spec.rb".freeze, "spec/ollama/handlers/progress_spec.rb".freeze, "spec/ollama/handlers/say_spec.rb".freeze, "spec/ollama/handlers/single_spec.rb".freeze, "spec/ollama/image_spec.rb".freeze, "spec/ollama/message_spec.rb".freeze, "spec/ollama/options_spec.rb".freeze, "spec/ollama/tool_spec.rb".freeze, "spec/ollama/utils/ansi_markdown_spec.rb".freeze, "spec/ollama/utils/cache_fetcher_spec.rb".freeze, "spec/ollama/utils/fetcher_spec.rb".freeze, "spec/ollama/utils/file_argument_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/ollama/utils/width_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
|
16
|
+
s.files = [".envrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_cli".freeze, "bin/ollama_console".freeze, "bin/ollama_update".freeze, "config/redis.conf".freeze, "docker-compose.yml".freeze, "lib/ollama.rb".freeze, "lib/ollama/client.rb".freeze, "lib/ollama/client/command.rb".freeze, "lib/ollama/client/doc.rb".freeze, "lib/ollama/commands/chat.rb".freeze, "lib/ollama/commands/copy.rb".freeze, "lib/ollama/commands/create.rb".freeze, "lib/ollama/commands/delete.rb".freeze, "lib/ollama/commands/embed.rb".freeze, "lib/ollama/commands/embeddings.rb".freeze, "lib/ollama/commands/generate.rb".freeze, "lib/ollama/commands/ps.rb".freeze, "lib/ollama/commands/pull.rb".freeze, "lib/ollama/commands/push.rb".freeze, "lib/ollama/commands/show.rb".freeze, "lib/ollama/commands/tags.rb".freeze, "lib/ollama/documents.rb".freeze, "lib/ollama/documents/cache/common.rb".freeze, "lib/ollama/documents/cache/memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_backed_memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_cache.rb".freeze, "lib/ollama/documents/splitters/character.rb".freeze, "lib/ollama/documents/splitters/semantic.rb".freeze, "lib/ollama/dto.rb".freeze, "lib/ollama/errors.rb".freeze, "lib/ollama/handlers.rb".freeze, "lib/ollama/handlers/collector.rb".freeze, "lib/ollama/handlers/concern.rb".freeze, "lib/ollama/handlers/dump_json.rb".freeze, "lib/ollama/handlers/dump_yaml.rb".freeze, "lib/ollama/handlers/markdown.rb".freeze, "lib/ollama/handlers/nop.rb".freeze, "lib/ollama/handlers/print.rb".freeze, "lib/ollama/handlers/progress.rb".freeze, "lib/ollama/handlers/say.rb".freeze, "lib/ollama/handlers/single.rb".freeze, "lib/ollama/image.rb".freeze, "lib/ollama/message.rb".freeze, "lib/ollama/options.rb".freeze, "lib/ollama/response.rb".freeze, "lib/ollama/tool.rb".freeze, "lib/ollama/tool/function.rb".freeze, "lib/ollama/tool/function/parameters.rb".freeze, "lib/ollama/tool/function/parameters/property.rb".freeze, "lib/ollama/utils/ansi_markdown.rb".freeze, "lib/ollama/utils/cache_fetcher.rb".freeze, "lib/ollama/utils/chooser.rb".freeze, "lib/ollama/utils/colorize_texts.rb".freeze, "lib/ollama/utils/fetcher.rb".freeze, "lib/ollama/utils/file_argument.rb".freeze, "lib/ollama/utils/math.rb".freeze, "lib/ollama/utils/tags.rb".freeze, "lib/ollama/utils/width.rb".freeze, "lib/ollama/version.rb".freeze, "ollama-ruby.gemspec".freeze, "spec/assets/embeddings.json".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/prompt.txt".freeze, "spec/ollama/client/doc_spec.rb".freeze, "spec/ollama/client_spec.rb".freeze, "spec/ollama/commands/chat_spec.rb".freeze, "spec/ollama/commands/copy_spec.rb".freeze, "spec/ollama/commands/create_spec.rb".freeze, "spec/ollama/commands/delete_spec.rb".freeze, "spec/ollama/commands/embed_spec.rb".freeze, "spec/ollama/commands/embeddings_spec.rb".freeze, "spec/ollama/commands/generate_spec.rb".freeze, "spec/ollama/commands/ps_spec.rb".freeze, "spec/ollama/commands/pull_spec.rb".freeze, "spec/ollama/commands/push_spec.rb".freeze, "spec/ollama/commands/show_spec.rb".freeze, "spec/ollama/commands/tags_spec.rb".freeze, "spec/ollama/documents/memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_backed_memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_cache_spec.rb".freeze, "spec/ollama/documents/splitters/character_spec.rb".freeze, "spec/ollama/documents/splitters/semantic_spec.rb".freeze, "spec/ollama/documents_spec.rb".freeze, "spec/ollama/handlers/collector_spec.rb".freeze, "spec/ollama/handlers/dump_json_spec.rb".freeze, "spec/ollama/handlers/dump_yaml_spec.rb".freeze, "spec/ollama/handlers/markdown_spec.rb".freeze, "spec/ollama/handlers/nop_spec.rb".freeze, "spec/ollama/handlers/print_spec.rb".freeze, "spec/ollama/handlers/progress_spec.rb".freeze, "spec/ollama/handlers/say_spec.rb".freeze, "spec/ollama/handlers/single_spec.rb".freeze, "spec/ollama/image_spec.rb".freeze, "spec/ollama/message_spec.rb".freeze, "spec/ollama/options_spec.rb".freeze, "spec/ollama/tool_spec.rb".freeze, "spec/ollama/utils/ansi_markdown_spec.rb".freeze, "spec/ollama/utils/cache_fetcher_spec.rb".freeze, "spec/ollama/utils/colorize_texts_spec.rb".freeze, "spec/ollama/utils/fetcher_spec.rb".freeze, "spec/ollama/utils/file_argument_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/ollama/utils/width_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
|
17
17
|
s.homepage = "https://github.com/flori/ollama-ruby".freeze
|
18
18
|
s.licenses = ["MIT".freeze]
|
19
19
|
s.rdoc_options = ["--title".freeze, "Ollama-ruby - Interacting with the Ollama API".freeze, "--main".freeze, "README.md".freeze]
|
20
20
|
s.required_ruby_version = Gem::Requirement.new("~> 3.1".freeze)
|
21
21
|
s.rubygems_version = "3.5.18".freeze
|
22
22
|
s.summary = "Interacting with the Ollama API".freeze
|
23
|
-
s.test_files = ["spec/ollama/client/doc_spec.rb".freeze, "spec/ollama/client_spec.rb".freeze, "spec/ollama/commands/chat_spec.rb".freeze, "spec/ollama/commands/copy_spec.rb".freeze, "spec/ollama/commands/create_spec.rb".freeze, "spec/ollama/commands/delete_spec.rb".freeze, "spec/ollama/commands/embed_spec.rb".freeze, "spec/ollama/commands/embeddings_spec.rb".freeze, "spec/ollama/commands/generate_spec.rb".freeze, "spec/ollama/commands/ps_spec.rb".freeze, "spec/ollama/commands/pull_spec.rb".freeze, "spec/ollama/commands/push_spec.rb".freeze, "spec/ollama/commands/show_spec.rb".freeze, "spec/ollama/commands/tags_spec.rb".freeze, "spec/ollama/documents/memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_backed_memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_cache_spec.rb".freeze, "spec/ollama/documents/splitters/character_spec.rb".freeze, "spec/ollama/documents/splitters/semantic_spec.rb".freeze, "spec/ollama/documents_spec.rb".freeze, "spec/ollama/handlers/collector_spec.rb".freeze, "spec/ollama/handlers/dump_json_spec.rb".freeze, "spec/ollama/handlers/dump_yaml_spec.rb".freeze, "spec/ollama/handlers/markdown_spec.rb".freeze, "spec/ollama/handlers/nop_spec.rb".freeze, "spec/ollama/handlers/print_spec.rb".freeze, "spec/ollama/handlers/progress_spec.rb".freeze, "spec/ollama/handlers/say_spec.rb".freeze, "spec/ollama/handlers/single_spec.rb".freeze, "spec/ollama/image_spec.rb".freeze, "spec/ollama/message_spec.rb".freeze, "spec/ollama/options_spec.rb".freeze, "spec/ollama/tool_spec.rb".freeze, "spec/ollama/utils/ansi_markdown_spec.rb".freeze, "spec/ollama/utils/cache_fetcher_spec.rb".freeze, "spec/ollama/utils/fetcher_spec.rb".freeze, "spec/ollama/utils/file_argument_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/ollama/utils/width_spec.rb".freeze, "spec/spec_helper.rb".freeze]
|
23
|
+
s.test_files = ["spec/ollama/client/doc_spec.rb".freeze, "spec/ollama/client_spec.rb".freeze, "spec/ollama/commands/chat_spec.rb".freeze, "spec/ollama/commands/copy_spec.rb".freeze, "spec/ollama/commands/create_spec.rb".freeze, "spec/ollama/commands/delete_spec.rb".freeze, "spec/ollama/commands/embed_spec.rb".freeze, "spec/ollama/commands/embeddings_spec.rb".freeze, "spec/ollama/commands/generate_spec.rb".freeze, "spec/ollama/commands/ps_spec.rb".freeze, "spec/ollama/commands/pull_spec.rb".freeze, "spec/ollama/commands/push_spec.rb".freeze, "spec/ollama/commands/show_spec.rb".freeze, "spec/ollama/commands/tags_spec.rb".freeze, "spec/ollama/documents/memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_backed_memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_cache_spec.rb".freeze, "spec/ollama/documents/splitters/character_spec.rb".freeze, "spec/ollama/documents/splitters/semantic_spec.rb".freeze, "spec/ollama/documents_spec.rb".freeze, "spec/ollama/handlers/collector_spec.rb".freeze, "spec/ollama/handlers/dump_json_spec.rb".freeze, "spec/ollama/handlers/dump_yaml_spec.rb".freeze, "spec/ollama/handlers/markdown_spec.rb".freeze, "spec/ollama/handlers/nop_spec.rb".freeze, "spec/ollama/handlers/print_spec.rb".freeze, "spec/ollama/handlers/progress_spec.rb".freeze, "spec/ollama/handlers/say_spec.rb".freeze, "spec/ollama/handlers/single_spec.rb".freeze, "spec/ollama/image_spec.rb".freeze, "spec/ollama/message_spec.rb".freeze, "spec/ollama/options_spec.rb".freeze, "spec/ollama/tool_spec.rb".freeze, "spec/ollama/utils/ansi_markdown_spec.rb".freeze, "spec/ollama/utils/cache_fetcher_spec.rb".freeze, "spec/ollama/utils/colorize_texts_spec.rb".freeze, "spec/ollama/utils/fetcher_spec.rb".freeze, "spec/ollama/utils/file_argument_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/ollama/utils/width_spec.rb".freeze, "spec/spec_helper.rb".freeze]
|
24
24
|
|
25
25
|
s.specification_version = 4
|
26
26
|
|
@@ -60,16 +60,16 @@ RSpec.describe Ollama::Documents do
|
|
60
60
|
expect(ollama).to receive(:embed).
|
61
61
|
with(model:, input: [ 'foo' ], options: nil).
|
62
62
|
and_return(double(embeddings: [ [ 0.1 ] ]))
|
63
|
-
expect(documents.add('foo', tags: %
|
63
|
+
expect(documents.add('foo', tags: %w[ test ])).to eq documents
|
64
64
|
expect(ollama).to receive(:embed).
|
65
65
|
with(model:, input: 'foo', options: nil).
|
66
66
|
and_return(double(embeddings: [ [ 0.1 ] ]))
|
67
|
-
records = documents.find('foo', tags: %
|
67
|
+
records = documents.find('foo', tags: %w[ nix ])
|
68
68
|
expect(records).to eq []
|
69
69
|
expect(ollama).to receive(:embed).
|
70
70
|
with(model:, input: 'foo', options: nil).
|
71
71
|
and_return(double(embeddings: [ [ 0.1 ] ]))
|
72
|
-
records = documents.find('foo', tags: %
|
72
|
+
records = documents.find('foo', tags: %w[ test ])
|
73
73
|
expect(records).to eq [
|
74
74
|
Ollama::Documents::Record[text: 'foo', embedding: [ 0.1 ], similarity: 1.0 ]
|
75
75
|
]
|
@@ -135,8 +135,9 @@ RSpec.describe Ollama::Documents do
|
|
135
135
|
expect(ollama).to receive(:embed).
|
136
136
|
with(model:, input: %w[ bar ], options: nil).
|
137
137
|
and_return(double(embeddings: [ [ 0.1 ] ]))
|
138
|
-
expect(documents.add('foo', tags: %
|
139
|
-
expect(documents.add('bar', tags: %
|
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 ]
|
140
141
|
expect {
|
141
142
|
documents.clear tags: 'test'
|
142
143
|
}.to change { documents.size }.from(2).to(1)
|
data/spec/ollama/options_spec.rb
CHANGED
@@ -13,6 +13,10 @@ RSpec.describe Ollama::Options do
|
|
13
13
|
expect(options).to be_a described_class
|
14
14
|
end
|
15
15
|
|
16
|
+
it 'can be empty' do
|
17
|
+
expect(described_class.new).to be_empty
|
18
|
+
end
|
19
|
+
|
16
20
|
it 'can be used to cast hashes' do
|
17
21
|
expect(described_class[{
|
18
22
|
penalize_newline: true,
|
@@ -0,0 +1,13 @@
|
|
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
|
@@ -19,7 +19,7 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'can #get with streaming' do
|
22
|
-
stub_request(:get,
|
22
|
+
stub_request(:get, url).
|
23
23
|
with(headers: fetcher.headers).
|
24
24
|
to_return(
|
25
25
|
status: 200,
|
@@ -37,7 +37,7 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
37
37
|
fetcher = described_class.new(
|
38
38
|
http_options: { ssl_verify_peer: false }
|
39
39
|
).expose
|
40
|
-
stub_request(:get,
|
40
|
+
stub_request(:get, url).
|
41
41
|
with(headers: fetcher.headers).
|
42
42
|
to_return(
|
43
43
|
status: 200,
|
@@ -45,7 +45,7 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
45
45
|
headers: { 'Content-Type' => 'text/plain' },
|
46
46
|
)
|
47
47
|
expect(Excon).to receive(:new).with(
|
48
|
-
|
48
|
+
url,
|
49
49
|
hash_including(ssl_verify_peer: false)
|
50
50
|
).and_call_original
|
51
51
|
fetcher.get(url) do |tmp|
|
@@ -56,7 +56,7 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
it 'can #get and fallback from streaming' do
|
59
|
-
stub_request(:get,
|
59
|
+
stub_request(:get, url).
|
60
60
|
with(headers: fetcher.headers).
|
61
61
|
to_return(
|
62
62
|
{ status: 501 },
|
@@ -74,9 +74,10 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
74
74
|
end
|
75
75
|
|
76
76
|
it 'can #get and finally fail' do
|
77
|
-
stub_request(:get,
|
77
|
+
stub_request(:get, url).
|
78
78
|
with(headers: fetcher.headers).
|
79
79
|
to_return(status: 500)
|
80
|
+
expect(STDERR).to receive(:puts).with(/cannot.*get.*#{url}/i)
|
80
81
|
fetcher.get(url) do |tmp|
|
81
82
|
expect(tmp).to be_a StringIO
|
82
83
|
expect(tmp.read).to eq ''
|
@@ -106,10 +107,31 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
106
107
|
|
107
108
|
it 'can .execute and fail' do
|
108
109
|
expect(IO).to receive(:popen).and_raise StandardError
|
110
|
+
expect(STDERR).to receive(:puts).with(/cannot.*execute.*foobar/i)
|
109
111
|
described_class.execute('foobar') do |file|
|
110
112
|
expect(file).to be_a StringIO
|
111
113
|
expect(file.read).to be_empty
|
112
114
|
expect(file.content_type).to eq 'text/plain'
|
113
115
|
end
|
114
116
|
end
|
117
|
+
|
118
|
+
describe '.normalize_url' do
|
119
|
+
it 'can handle umlauts' do
|
120
|
+
expect(described_class.normalize_url('https://foo.de/bär')).to eq(
|
121
|
+
'https://foo.de/b%C3%A4r'
|
122
|
+
)
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'can handle escaped umlauts' do
|
126
|
+
expect(described_class.normalize_url('https://foo.de/b%C3%A4r')).to eq(
|
127
|
+
'https://foo.de/b%C3%A4r'
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'can remove #anchors' do
|
132
|
+
expect(described_class.normalize_url('https://foo.de#bar')).to eq(
|
133
|
+
'https://foo.de'
|
134
|
+
)
|
135
|
+
end
|
136
|
+
end
|
115
137
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ollama-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Frank
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-10-
|
11
|
+
date: 2024-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gem_hadar
|
@@ -516,6 +516,7 @@ files:
|
|
516
516
|
- spec/ollama/tool_spec.rb
|
517
517
|
- spec/ollama/utils/ansi_markdown_spec.rb
|
518
518
|
- spec/ollama/utils/cache_fetcher_spec.rb
|
519
|
+
- spec/ollama/utils/colorize_texts_spec.rb
|
519
520
|
- spec/ollama/utils/fetcher_spec.rb
|
520
521
|
- spec/ollama/utils/file_argument_spec.rb
|
521
522
|
- spec/ollama/utils/tags_spec.rb
|
@@ -585,6 +586,7 @@ test_files:
|
|
585
586
|
- spec/ollama/tool_spec.rb
|
586
587
|
- spec/ollama/utils/ansi_markdown_spec.rb
|
587
588
|
- spec/ollama/utils/cache_fetcher_spec.rb
|
589
|
+
- spec/ollama/utils/colorize_texts_spec.rb
|
588
590
|
- spec/ollama/utils/fetcher_spec.rb
|
589
591
|
- spec/ollama/utils/file_argument_spec.rb
|
590
592
|
- spec/ollama/utils/tags_spec.rb
|