ollama-ruby 0.9.0 → 0.9.2
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/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
|