ollama-ruby 0.2.0 → 0.3.1
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 +66 -0
- data/README.md +15 -13
- data/Rakefile +5 -3
- data/bin/ollama_chat +158 -74
- data/bin/ollama_cli +68 -0
- data/bin/ollama_console +7 -2
- data/lib/ollama/documents/memory_cache.rb +4 -2
- data/lib/ollama/documents/redis_cache.rb +4 -3
- data/lib/ollama/documents.rb +30 -5
- data/lib/ollama/utils/file_argument.rb +16 -0
- data/lib/ollama/utils/tags.rb +4 -0
- data/lib/ollama/utils/width.rb +16 -1
- data/lib/ollama/version.rb +1 -1
- data/lib/ollama.rb +1 -0
- data/ollama-ruby.gemspec +11 -10
- data/spec/ollama/documents/redis_cache_spec.rb +8 -0
- data/spec/ollama/documents_spec.rb +42 -0
- metadata +27 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0e3428486bf4d60d1e4a64574a9c04bb41da5a5fe76b5f4bc37c5f089221cf3
|
4
|
+
data.tar.gz: 0a2f6f5269c97b22493400448204116aebef642273c024aee474a38741dfdce5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fd8db76a1cad30ba41af287e1abb77a102913f09f1648c9fbaf89f5e3bf4f3dace4a39cc6b72da456b633eb42d331b356134aecc196b112c7f94215177b4023
|
7
|
+
data.tar.gz: 4541a1e93c2714b786cb21b5e401ffc48a08e05c39bfac860e8cdd275a447bbc7db0b6cf80fee5f459f86734320a90362418a50f4174d53ece4e1a9d2f1dc647
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,71 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
## 2024-09-12 v0.3.1
|
4
|
+
|
5
|
+
* Update dependencies and date in gemspec files:
|
6
|
+
- Updated `complex_config` dependency to '~> 0.22'
|
7
|
+
* Refactor FollowChat#eval_stats to add bold eval rates
|
8
|
+
* Improve formatting in eval_stats using bold and color for better
|
9
|
+
readability.
|
10
|
+
* Update import_document and add_image methods to handle nil values
|
11
|
+
correctly.
|
12
|
+
* Update width method in utils/width.rb to use uncolor when checking line
|
13
|
+
length.
|
14
|
+
* Refactor eval stats output in FollowChat class
|
15
|
+
- Add indentation to eval stats output for better readability
|
16
|
+
* FollowChat evaluation stats refactored
|
17
|
+
- Removed hardcoded eval_stats hash and replaced with method call
|
18
|
+
`eval_stats(response)`
|
19
|
+
- Added new method `eval_stats(response)` to calculate evaluation statistics
|
20
|
+
- Calculates eval duration, prompt eval duration, total duration, and load
|
21
|
+
duration
|
22
|
+
- Adds eval count, prompt eval count, eval rate, and prompt eval rate
|
23
|
+
* Use default to_s tree representation of config.
|
24
|
+
* Update complex_config dependency to ~> 0.21, >= 0.21.1 in Rakefile
|
25
|
+
* Update complex_config dependency to ~> 0.21, >= 0.21.1 in
|
26
|
+
ollama-ruby.gemspec
|
27
|
+
* Update dependencies and configuration display
|
28
|
+
* Update 'complex_config' dependency to '~> 0.21'
|
29
|
+
* Change OllamaChatConfig to display configuration as a tree instead of yaml
|
30
|
+
* Improve /web search command
|
31
|
+
* Update infobar dependency to ~> 0.8
|
32
|
+
* Update /web command to summarize web sources as well as importing them
|
33
|
+
directly
|
34
|
+
* Add /clobber command to clear conversation messages and collection
|
35
|
+
* Refactor Ollama chat configuration and summary generation.
|
36
|
+
* Update `OllamaChatConfig` to use `prompts.system` instead of `system`.
|
37
|
+
* Introduce `prompts.summarize` config as template for generating abstract
|
38
|
+
summaries.
|
39
|
+
* Replace hardcoded summary generation with call to `prompts.summarize`.
|
40
|
+
* Display /help for all unknown chat commands starting wit `/`
|
41
|
+
|
42
|
+
## 2024-09-05 v0.3.0
|
43
|
+
|
44
|
+
* **New Features**
|
45
|
+
* Created new file `ollama_cli` with Ollama CLI functionality.
|
46
|
+
* Added executable `ollama_cli` to s.executables in ollama-ruby.gemspec.
|
47
|
+
* Added `find_where` method in `documents.rb` to filter records by text size
|
48
|
+
and count.
|
49
|
+
* Added test for `find_where` method in `documents_spec.rb`.
|
50
|
+
* Features for `ollama_chat`
|
51
|
+
* Added `found_texts_count` option to `OllamaChatConfig`.
|
52
|
+
* Implemented `parse_rss` method for RSS feeds and `parse_atom` method
|
53
|
+
for Atom feeds.
|
54
|
+
* Added links to titles in RSS feed item summaries and Atom feed item
|
55
|
+
summaries.
|
56
|
+
* Updated `parse_source` method to handle different content types,
|
57
|
+
including HTML, XML, and RSS/Atom feeds.
|
58
|
+
* Added `/web [n] query` command to search web and return n or 1 results
|
59
|
+
in chat interface.
|
60
|
+
* **Improvements**
|
61
|
+
* Improved validation for system prompts
|
62
|
+
* Extracted file argument handling into a separate module and method
|
63
|
+
* Added default value for config or model system prompt
|
64
|
+
* Improved input validation for `system_prompt` path
|
65
|
+
* Updated collection clearing logic to accept optional tags parameter
|
66
|
+
* Updated `Tags` class to overload `to_a` method for converting to array of
|
67
|
+
strings
|
68
|
+
|
3
69
|
## 2024-09-03 v0.2.0
|
4
70
|
|
5
71
|
### Changes
|
data/README.md
CHANGED
@@ -152,19 +152,21 @@ subject - the young, blue-eyed cat.
|
|
152
152
|
The following commands can be given inside the chat, if prefixed by a `/`:
|
153
153
|
|
154
154
|
```
|
155
|
-
/paste
|
156
|
-
/markdown
|
157
|
-
/list
|
158
|
-
/clear
|
159
|
-
/
|
160
|
-
/
|
161
|
-
/
|
162
|
-
/
|
163
|
-
/
|
164
|
-
/
|
165
|
-
/
|
166
|
-
/
|
167
|
-
/
|
155
|
+
/paste to paste content
|
156
|
+
/markdown toggle markdown output
|
157
|
+
/list list the messages of the conversation
|
158
|
+
/clear clear the conversation messages
|
159
|
+
/clobber clear conversation messages and collection
|
160
|
+
/pop [n] pop the last n exchanges, defaults to 1
|
161
|
+
/model change the model
|
162
|
+
/regenerate the last answer message
|
163
|
+
/collection clear [tag]|stats|change|new clear or show stats of current collection
|
164
|
+
/summarize source summarize the URL/file source's content
|
165
|
+
/web [n] query query web search & return n or 1 results
|
166
|
+
/save filename store conversation messages
|
167
|
+
/load filename load conversation messages
|
168
|
+
/quit to quit
|
169
|
+
/help to view this help
|
168
170
|
```
|
169
171
|
|
170
172
|
### ollama\_console
|
data/Rakefile
CHANGED
@@ -18,12 +18,13 @@ GemHadar do
|
|
18
18
|
'.utilsrc', '.rspec', *Dir.glob('.github/**/*', File::FNM_DOTMATCH)
|
19
19
|
readme 'README.md'
|
20
20
|
|
21
|
-
executables << 'ollama_console' << 'ollama_chat' <<
|
21
|
+
executables << 'ollama_console' << 'ollama_chat' <<
|
22
|
+
'ollama_update' << 'ollama_cli'
|
22
23
|
|
23
24
|
required_ruby_version '~> 3.1'
|
24
25
|
|
25
26
|
dependency 'excon', '~> 0.111'
|
26
|
-
dependency 'infobar', '~> 0.
|
27
|
+
dependency 'infobar', '~> 0.8'
|
27
28
|
dependency 'term-ansicolor', '~> 1.11'
|
28
29
|
dependency 'kramdown-parser-gfm', '~> 1.1'
|
29
30
|
dependency 'terminal-table', '~> 3.0'
|
@@ -33,9 +34,10 @@ GemHadar do
|
|
33
34
|
dependency 'sorted_set', '~> 1.0'
|
34
35
|
dependency 'mime-types', '~> 3.0'
|
35
36
|
dependency 'reverse_markdown', '~> 2.0'
|
36
|
-
dependency 'complex_config', '~> 0.
|
37
|
+
dependency 'complex_config', '~> 0.22'
|
37
38
|
dependency 'search_ui', '~> 0.0'
|
38
39
|
dependency 'amatch', '~> 0.4.1'
|
40
|
+
dependency 'pdf-reader', '~> 2.0'
|
39
41
|
development_dependency 'all_images', '~> 0.4'
|
40
42
|
development_dependency 'rspec', '~> 3.2'
|
41
43
|
development_dependency 'utils'
|
data/bin/ollama_chat
CHANGED
@@ -12,6 +12,8 @@ require 'complex_config'
|
|
12
12
|
require 'fileutils'
|
13
13
|
require 'uri'
|
14
14
|
require 'nokogiri'
|
15
|
+
require 'rss'
|
16
|
+
require 'pdf/reader'
|
15
17
|
|
16
18
|
class OllamaChatConfig
|
17
19
|
include ComplexConfig
|
@@ -24,7 +26,12 @@ class OllamaChatConfig
|
|
24
26
|
name: <%= ENV.fetch('OLLAMA_CHAT_MODEL', 'llama3.1') %>
|
25
27
|
options:
|
26
28
|
num_ctx: 8192
|
27
|
-
|
29
|
+
prompts:
|
30
|
+
system: <%= ENV.fetch('OLLAMA_CHAT_SYSTEM', 'null') %>
|
31
|
+
summarize: |
|
32
|
+
Generate an abstract summary of the content in this document:
|
33
|
+
|
34
|
+
%s
|
28
35
|
voice: Samantha
|
29
36
|
markdown: true
|
30
37
|
embedding:
|
@@ -36,6 +43,7 @@ class OllamaChatConfig
|
|
36
43
|
prompt: 'Represent this sentence for searching relevant passages: %s'
|
37
44
|
collection: <%= ENV.fetch('OLLAMA_CHAT_COLLECTION', 'ollama_chat') %>
|
38
45
|
found_texts_size: 4096
|
46
|
+
found_texts_count: null
|
39
47
|
splitter:
|
40
48
|
name: RecursiveCharacter
|
41
49
|
chunk_size: 1024
|
@@ -47,7 +55,7 @@ class OllamaChatConfig
|
|
47
55
|
|
48
56
|
def initialize(filename = nil)
|
49
57
|
@filename = filename || default_path
|
50
|
-
@config = Provider.config(@filename)
|
58
|
+
@config = Provider.config(@filename, '⚙️')
|
51
59
|
retried = false
|
52
60
|
rescue ConfigurationFileMissing
|
53
61
|
if @filename == default_path && !retried
|
@@ -112,19 +120,28 @@ class FollowChat
|
|
112
120
|
@say.call(response)
|
113
121
|
end
|
114
122
|
if response.done
|
115
|
-
@output.puts
|
116
|
-
eval_stats = {
|
117
|
-
eval_duration: Tins::Duration.new(response.eval_duration / 1e9),
|
118
|
-
eval_count: response.eval_count,
|
119
|
-
prompt_eval_duration: Tins::Duration.new(response.prompt_eval_duration / 1e9),
|
120
|
-
prompt_eval_count: response.prompt_eval_count,
|
121
|
-
total_duration: Tins::Duration.new(response.total_duration / 1e9),
|
122
|
-
load_duration: Tins::Duration.new(response.load_duration / 1e9),
|
123
|
-
}.map { _1 * '=' } * ' '
|
124
|
-
@output.puts '📊 ' + color(111) { Utils::Width.wrap(eval_stats, percentage: 90) }
|
123
|
+
@output.puts "", eval_stats(response)
|
125
124
|
end
|
126
125
|
self
|
127
126
|
end
|
127
|
+
|
128
|
+
def eval_stats(response)
|
129
|
+
eval_duration = response.eval_duration / 1e9
|
130
|
+
prompt_eval_duration = response.prompt_eval_duration / 1e9
|
131
|
+
stats_text = {
|
132
|
+
eval_duration: Tins::Duration.new(eval_duration),
|
133
|
+
eval_count: response.eval_count,
|
134
|
+
eval_rate: bold { "%.2f c/s" % (response.eval_count / eval_duration) } + color(111),
|
135
|
+
prompt_eval_duration: Tins::Duration.new(prompt_eval_duration),
|
136
|
+
prompt_eval_count: response.prompt_eval_count,
|
137
|
+
prompt_eval_rate: bold { "%.2f c/s" % (response.prompt_eval_count / prompt_eval_duration) } + color(111),
|
138
|
+
total_duration: Tins::Duration.new(response.total_duration / 1e9),
|
139
|
+
load_duration: Tins::Duration.new(response.load_duration / 1e9),
|
140
|
+
}.map { _1 * '=' } * ' '
|
141
|
+
'📊 ' + color(111) {
|
142
|
+
Utils::Width.wrap(stats_text, percentage: 90).gsub(/(?<!\A)^/, ' ')
|
143
|
+
}
|
144
|
+
end
|
128
145
|
end
|
129
146
|
|
130
147
|
def search_web(query, n = 5)
|
@@ -153,7 +170,8 @@ end
|
|
153
170
|
|
154
171
|
def pull_model_unless_present(model, options, retried = false)
|
155
172
|
ollama.show(name: model) { |response|
|
156
|
-
puts "Model #{bold{model}} with architecture
|
173
|
+
puts "Model #{bold{model}} with architecture "\
|
174
|
+
"#{response.model_info['general.architecture']} found."
|
157
175
|
if system = response.system
|
158
176
|
puts "Configured model system prompt is:\n#{italic { system }}"
|
159
177
|
return system
|
@@ -226,17 +244,77 @@ def list_conversation(messages, markdown)
|
|
226
244
|
end
|
227
245
|
end
|
228
246
|
|
247
|
+
def reverse_markdown(html)
|
248
|
+
ReverseMarkdown.convert(
|
249
|
+
html,
|
250
|
+
unknown_tags: :bypass,
|
251
|
+
github_flavored: true,
|
252
|
+
tag_border: ''
|
253
|
+
)
|
254
|
+
end
|
255
|
+
|
256
|
+
def parse_rss(source_io)
|
257
|
+
feed = RSS::Parser.parse(source_io, false, false)
|
258
|
+
title = <<~end
|
259
|
+
# #{feed&.channel&.title}
|
260
|
+
|
261
|
+
end
|
262
|
+
feed.items.inject(title) do |text, item|
|
263
|
+
text << <<~end
|
264
|
+
## [#{item&.title}](#{item&.link})
|
265
|
+
|
266
|
+
updated on #{item&.pubDate}
|
267
|
+
|
268
|
+
#{reverse_markdown(item&.description)}
|
269
|
+
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def parse_atom(source_io)
|
275
|
+
feed = RSS::Parser.parse(source_io, false, false)
|
276
|
+
title = <<~end
|
277
|
+
# #{feed.title.content}
|
278
|
+
|
279
|
+
end
|
280
|
+
feed.items.inject(title) do |text, item|
|
281
|
+
text << <<~end
|
282
|
+
## [#{item&.title&.content}](#{item&.link&.href})
|
283
|
+
|
284
|
+
updated on #{item&.updated&.content}
|
285
|
+
|
286
|
+
#{reverse_markdown(item&.content&.content)}
|
287
|
+
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
229
292
|
def parse_source(source_io)
|
230
|
-
case source_io&.content_type
|
231
|
-
when 'html'
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
293
|
+
case source_io&.content_type
|
294
|
+
when 'text/html'
|
295
|
+
reverse_markdown(source_io.read)
|
296
|
+
when 'text/xml'
|
297
|
+
if source_io.readline =~ %r(^\s*<rss\s)
|
298
|
+
source_io.rewind
|
299
|
+
return parse_rss(source_io)
|
300
|
+
end
|
301
|
+
source_io.rewind
|
302
|
+
source_io.read
|
303
|
+
when %r(\Atext/)
|
239
304
|
source_io.read
|
305
|
+
when 'application/rss+xml'
|
306
|
+
parse_rss(source_io)
|
307
|
+
when 'application/atom+xml'
|
308
|
+
parse_atom(source_io)
|
309
|
+
when 'application/json'
|
310
|
+
source_io.read
|
311
|
+
when 'application/pdf'
|
312
|
+
reader = PDF::Reader.new(source_io)
|
313
|
+
result = +''
|
314
|
+
reader.pages.each do |page|
|
315
|
+
result << page.text
|
316
|
+
end
|
317
|
+
result
|
240
318
|
else
|
241
319
|
STDERR.puts "Cannot import #{source_io&.content_type} document."
|
242
320
|
return
|
@@ -248,7 +326,7 @@ def import_document(source_io, source)
|
|
248
326
|
STDOUT.puts "Embedding disabled, I won't import any documents, try: /summarize"
|
249
327
|
return
|
250
328
|
end
|
251
|
-
|
329
|
+
puts "Importing #{italic { source_io&.content_type }} document #{source.to_s.inspect}."
|
252
330
|
text = parse_source(source_io) or return
|
253
331
|
text.downcase!
|
254
332
|
splitter_config = $config.embedding.splitter
|
@@ -276,7 +354,7 @@ def import_document(source_io, source)
|
|
276
354
|
end
|
277
355
|
|
278
356
|
def add_image(images, source_io, source)
|
279
|
-
STDERR.puts "Adding #{source_io
|
357
|
+
STDERR.puts "Adding #{source_io&.content_type} image #{source.to_s.inspect}."
|
280
358
|
image = Image.for_io(source_io, path: source.to_s)
|
281
359
|
(images << image).uniq!
|
282
360
|
end
|
@@ -301,16 +379,12 @@ rescue => e
|
|
301
379
|
end
|
302
380
|
|
303
381
|
def summarize(source)
|
304
|
-
puts
|
382
|
+
puts "Now summarizing #{source.to_s.inspect}."
|
305
383
|
source_content =
|
306
384
|
fetch_source(source) do |source_io|
|
307
385
|
parse_source(source_io) or return
|
308
386
|
end
|
309
|
-
|
310
|
-
# Generate an abstract summary of the content in this document:
|
311
|
-
|
312
|
-
#{source_content}
|
313
|
-
end
|
387
|
+
$config.prompts.summarize % source_content
|
314
388
|
end
|
315
389
|
|
316
390
|
def parse_content(content, images)
|
@@ -327,7 +401,7 @@ def parse_content(content, images)
|
|
327
401
|
case source_io&.content_type&.media_type
|
328
402
|
when 'image'
|
329
403
|
add_image(images, source_io, source)
|
330
|
-
when 'text'
|
404
|
+
when 'text', 'application'
|
331
405
|
import_document(source_io, source)
|
332
406
|
else
|
333
407
|
STDERR.puts(
|
@@ -391,19 +465,21 @@ end
|
|
391
465
|
|
392
466
|
def display_chat_help
|
393
467
|
puts <<~end
|
394
|
-
/paste
|
395
|
-
/markdown
|
396
|
-
/list
|
397
|
-
/clear
|
398
|
-
/
|
399
|
-
/
|
400
|
-
/
|
401
|
-
/
|
402
|
-
/
|
403
|
-
/
|
404
|
-
/
|
405
|
-
/
|
406
|
-
/
|
468
|
+
/paste to paste content
|
469
|
+
/markdown toggle markdown output
|
470
|
+
/list list the messages of the conversation
|
471
|
+
/clear clear the conversation messages
|
472
|
+
/clobber clear conversation messages and collection
|
473
|
+
/pop [n] pop the last n exchanges, defaults to 1
|
474
|
+
/model change the model
|
475
|
+
/regenerate the last answer message
|
476
|
+
/collection clear [tag]|stats|change|new clear or show stats of current collection
|
477
|
+
/summarize source summarize the URL/file source's content
|
478
|
+
/web [n] query query web search & return n or 1 results
|
479
|
+
/save filename store conversation messages
|
480
|
+
/load filename load conversation messages
|
481
|
+
/quit to quit
|
482
|
+
/help to view this help
|
407
483
|
end
|
408
484
|
end
|
409
485
|
|
@@ -436,8 +512,7 @@ $config = config.config
|
|
436
512
|
|
437
513
|
opts[?h] and usage
|
438
514
|
|
439
|
-
puts "Configuration read from #{config.filename.inspect} is:"
|
440
|
-
y $config.to_h
|
515
|
+
puts "Configuration read from #{config.filename.inspect} is:", $config
|
441
516
|
|
442
517
|
base_url = opts[?u] || $config.url
|
443
518
|
$ollama = Client.new(base_url:, debug: $config.debug)
|
@@ -475,7 +550,7 @@ if $config.embedding.enabled
|
|
475
550
|
File.expand_path(doc)
|
476
551
|
end
|
477
552
|
end
|
478
|
-
|
553
|
+
puts "Collection #{bold{collection}}: Adding #{document_list.size} documents…"
|
479
554
|
document_list.each_slice(25) do |docs|
|
480
555
|
docs.each do |doc|
|
481
556
|
fetch_source(doc) do |doc_io|
|
@@ -497,23 +572,16 @@ markdown = set_markdown($config.markdown)
|
|
497
572
|
if opts[?c]
|
498
573
|
messages.concat load_conversation(opts[?c])
|
499
574
|
else
|
500
|
-
system =
|
501
|
-
|
502
|
-
system = File.read(system_prompt_file)
|
503
|
-
end
|
504
|
-
system ||= $config.system
|
505
|
-
|
506
|
-
if system
|
575
|
+
if system = Ollama::Utils::FileArgument.
|
576
|
+
get_file_argument(opts[?s], default: $config.prompts.system? || model_system)
|
507
577
|
messages << Message.new(role: 'system', content: system)
|
508
578
|
puts "Configured system prompt is:\n#{italic { system }}"
|
509
|
-
elsif model_system.present?
|
510
|
-
puts "Using model system prompt."
|
511
579
|
end
|
512
580
|
end
|
513
581
|
|
514
582
|
puts "\nType /help to display the chat help."
|
515
583
|
|
516
|
-
images
|
584
|
+
images = []
|
517
585
|
loop do
|
518
586
|
parse_content = true
|
519
587
|
input_prompt = bold { color(172) { message_type(images) + " user" } } + bold { "> " }
|
@@ -526,7 +594,7 @@ loop do
|
|
526
594
|
when %r(^/quit$)
|
527
595
|
puts "Goodbye."
|
528
596
|
exit 0
|
529
|
-
when %r(^/markdown)
|
597
|
+
when %r(^/markdown$)
|
530
598
|
markdown = set_markdown(!markdown)
|
531
599
|
next
|
532
600
|
when %r(^/list$)
|
@@ -536,11 +604,23 @@ loop do
|
|
536
604
|
messages.clear
|
537
605
|
puts "Cleared messages."
|
538
606
|
next
|
539
|
-
when %r(^/
|
540
|
-
|
607
|
+
when %r(^/clobber$)
|
608
|
+
messages.clear
|
609
|
+
$documents.clear
|
610
|
+
puts "Cleared messages and collection."
|
611
|
+
next
|
612
|
+
when %r(^/collection\s+(clear|stats|change|new)(?:\s+(.+))?$)
|
613
|
+
command, arg = $1, $2
|
614
|
+
case command
|
541
615
|
when 'clear'
|
542
|
-
|
543
|
-
|
616
|
+
tags = arg.present? ? arg.sub(/\A#*/, '') : nil
|
617
|
+
if tags
|
618
|
+
$documents.clear(tags:)
|
619
|
+
puts "Cleared tag ##{tags} from collection #{bold{collection}}."
|
620
|
+
else
|
621
|
+
$documents.clear
|
622
|
+
puts "Cleared collection #{bold{collection}}."
|
623
|
+
end
|
544
624
|
when 'stats'
|
545
625
|
collection_stats
|
546
626
|
when 'change'
|
@@ -571,13 +651,19 @@ loop do
|
|
571
651
|
when %r(^/summarize\s+(.+))
|
572
652
|
parse_content = false
|
573
653
|
content = summarize($1) or next
|
574
|
-
when %r(^/web\s+(?:(\d+)\s+)(.+)
|
575
|
-
parse_content
|
576
|
-
urls
|
654
|
+
when %r(^/web\s+(?:(\d+)\s+)?(.+))
|
655
|
+
parse_content = false
|
656
|
+
urls = search_web($2, $1.to_i)
|
657
|
+
urls.each do |url|
|
658
|
+
fetch_source(url) do |url_io|
|
659
|
+
import_document(url_io, url)
|
660
|
+
end
|
661
|
+
end
|
662
|
+
urls_summarized = urls.map { summarize(_1) }
|
577
663
|
content = <<~end
|
578
|
-
Answer the the query #{$2.inspect} using these sources:
|
664
|
+
Answer the the query #{$2.inspect} using these sources and summaries:
|
579
665
|
|
580
|
-
#{urls *
|
666
|
+
#{urls.zip(urls_summarized).map { |u, s| "%s as \n:%s" % [ u, s ] } * "\n\n"}
|
581
667
|
end
|
582
668
|
when %r(^/save\s+(.+)$)
|
583
669
|
save_conversation($1, messages)
|
@@ -587,7 +673,7 @@ loop do
|
|
587
673
|
messages = load_conversation($1)
|
588
674
|
puts "Loaded conversation from #$1."
|
589
675
|
next
|
590
|
-
when %r(^/
|
676
|
+
when %r(^/)
|
591
677
|
display_chat_help
|
592
678
|
next
|
593
679
|
when nil, ''
|
@@ -602,15 +688,13 @@ loop do
|
|
602
688
|
end
|
603
689
|
|
604
690
|
if $config.embedding.enabled && content
|
605
|
-
records = $documents.
|
691
|
+
records = $documents.find_where(
|
606
692
|
content.downcase,
|
607
693
|
tags:,
|
608
|
-
prompt:
|
694
|
+
prompt: $config.embedding.model.prompt?,
|
695
|
+
text_size: $config.embedding.found_texts_size?,
|
696
|
+
text_count: $config.embedding.found_texts_count?,
|
609
697
|
)
|
610
|
-
s, found_texts_size = 0, $config.embedding.found_texts_size
|
611
|
-
records = records.take_while {
|
612
|
-
(s += _1.text.size) <= found_texts_size
|
613
|
-
}
|
614
698
|
found_texts = records.map(&:text)
|
615
699
|
unless found_texts.empty?
|
616
700
|
content += "\nConsider these chunks for your answer:\n"\
|
data/bin/ollama_cli
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'ollama'
|
4
|
+
include Ollama
|
5
|
+
include Ollama::Utils::FileArgument
|
6
|
+
require 'tins'
|
7
|
+
include Tins::GO
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
def usage
|
11
|
+
puts <<~end
|
12
|
+
#{File.basename($0)} [OPTIONS]
|
13
|
+
|
14
|
+
-u URL the ollama base url, OLLAMA_URL
|
15
|
+
-m MODEL the ollama model to chat with, OLLAMA_MODEL
|
16
|
+
-M OPTIONS the ollama model options to use, OLLAMA_MODEL_OPTIONS
|
17
|
+
-s SYSTEM the system prompt to use as a file, OLLAMA_SYSTEM
|
18
|
+
-p PROMPT the user prompt to use as a file, OLLAMA_PROMPT
|
19
|
+
-H HANDLER the handler to use for the response, defaults to Print
|
20
|
+
-S use streaming for generation
|
21
|
+
-h this help
|
22
|
+
|
23
|
+
end
|
24
|
+
exit 0
|
25
|
+
end
|
26
|
+
|
27
|
+
opts = go 'u:m:M:s:p:H:Sh', defaults: { ?H => 'Print', ?M => '{}' }
|
28
|
+
|
29
|
+
opts[?h] and usage
|
30
|
+
|
31
|
+
base_url = opts[?u] || ENV['OLLAMA_URL'] || 'http://%s' % ENV.fetch('OLLAMA_HOST')
|
32
|
+
model = opts[?m] || ENV.fetch('OLLAMA_MODEL', 'llama3.1')
|
33
|
+
options = Ollama::Options.from_hash(JSON(
|
34
|
+
get_file_argument(opts[?M], default: ENV['OLLAMA_MODEL_OPTIONS'])
|
35
|
+
))
|
36
|
+
system = get_file_argument(opts[?s], default: ENV['OLLAMA_SYSTEM'])
|
37
|
+
prompt = get_file_argument(opts[?p], default: ENV['OLLAMA_PROMPT'])
|
38
|
+
|
39
|
+
if prompt.nil?
|
40
|
+
prompt = STDIN.read
|
41
|
+
elsif c = prompt.scan('%s').size
|
42
|
+
case c
|
43
|
+
when 0
|
44
|
+
when 1
|
45
|
+
prompt = prompt % STDIN.read
|
46
|
+
else
|
47
|
+
STDERR.puts "Found more than one plaeceholder %s. => Ignoring."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if ENV['DEBUG'].to_i == 1
|
52
|
+
puts <<~EOT
|
53
|
+
base_url = #{base_url.inspect}
|
54
|
+
model = #{model.inspect}
|
55
|
+
system = #{system.inspect}
|
56
|
+
prompt = #{prompt.inspect}
|
57
|
+
options = #{options.to_json}
|
58
|
+
EOT
|
59
|
+
end
|
60
|
+
|
61
|
+
Client.new(base_url:, read_timeout: 120).generate(
|
62
|
+
model:,
|
63
|
+
system:,
|
64
|
+
prompt:,
|
65
|
+
options:,
|
66
|
+
stream: !!opts[?S],
|
67
|
+
&Object.const_get(opts[?H])
|
68
|
+
)
|
data/bin/ollama_console
CHANGED
@@ -5,8 +5,13 @@ include Ollama
|
|
5
5
|
require 'irb'
|
6
6
|
require 'irb/history'
|
7
7
|
|
8
|
-
base_url
|
9
|
-
|
8
|
+
def base_url
|
9
|
+
ENV['OLLAMA_URL'] || 'http://%s' % ENV.fetch('OLLAMA_HOST')
|
10
|
+
end
|
11
|
+
|
12
|
+
def ollama
|
13
|
+
$ollama ||= Client.new(base_url:)
|
14
|
+
end
|
10
15
|
IRB.setup nil
|
11
16
|
IRB.conf[:MAIN_CONTEXT] = IRB::Irb.new.context
|
12
17
|
IRB.conf[:HISTORY_FILE] = File.join(ENV.fetch('HOME'), '.ollama_console-history')
|
@@ -13,7 +13,10 @@ class Ollama::Documents::RedisCache
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def [](key)
|
16
|
-
|
16
|
+
value = redis.get(pre(key))
|
17
|
+
unless value.nil?
|
18
|
+
JSON(value, object_class: Ollama::Documents::Record)
|
19
|
+
end
|
17
20
|
end
|
18
21
|
|
19
22
|
def []=(key, value)
|
@@ -45,8 +48,6 @@ class Ollama::Documents::RedisCache
|
|
45
48
|
end
|
46
49
|
include Enumerable
|
47
50
|
|
48
|
-
private
|
49
|
-
|
50
51
|
def pre(key)
|
51
52
|
[ @prefix, key ].join
|
52
53
|
end
|
data/lib/ollama/documents.rb
CHANGED
@@ -12,6 +12,7 @@ require 'ollama/documents/splitters/semantic'
|
|
12
12
|
|
13
13
|
class Ollama::Documents
|
14
14
|
include Ollama::Utils::Math
|
15
|
+
include Ollama::Utils::Width
|
15
16
|
|
16
17
|
class Record < JSON::GenericObject
|
17
18
|
def to_s
|
@@ -42,7 +43,7 @@ class Ollama::Documents
|
|
42
43
|
def add(inputs, batch_size: 10, source: nil, tags: [])
|
43
44
|
inputs = Array(inputs)
|
44
45
|
tags = Ollama::Utils::Tags.new(tags)
|
45
|
-
source and tags.add File.basename(source)
|
46
|
+
source and tags.add File.basename(source).gsub(/\?.*/, '')
|
46
47
|
inputs.map! { |i|
|
47
48
|
text = i.respond_to?(:read) ? i.read : i.to_s
|
48
49
|
text
|
@@ -51,7 +52,7 @@ class Ollama::Documents
|
|
51
52
|
inputs.empty? and return self
|
52
53
|
batches = inputs.each_slice(batch_size).
|
53
54
|
with_infobar(
|
54
|
-
label: "Add #{tags}",
|
55
|
+
label: "Add #{truncate(tags.to_s, percentage: 25)}",
|
55
56
|
total: inputs.size
|
56
57
|
)
|
57
58
|
batches.each do |batch|
|
@@ -87,8 +88,18 @@ class Ollama::Documents
|
|
87
88
|
@cache.size
|
88
89
|
end
|
89
90
|
|
90
|
-
def clear
|
91
|
-
|
91
|
+
def clear(tags: nil)
|
92
|
+
if tags
|
93
|
+
tags = Ollama::Utils::Tags.new(Array(tags)).to_a
|
94
|
+
@cache.each do |key, record|
|
95
|
+
if (tags & record.tags).size >= 1
|
96
|
+
@cache.delete(@cache.unpre(key))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
else
|
100
|
+
@cache.clear
|
101
|
+
end
|
102
|
+
self
|
92
103
|
end
|
93
104
|
|
94
105
|
def find(string, tags: nil, prompt: nil)
|
@@ -96,7 +107,7 @@ class Ollama::Documents
|
|
96
107
|
needle_norm = norm(needle)
|
97
108
|
records = @cache
|
98
109
|
if tags
|
99
|
-
tags = Ollama::Utils::Tags.new(tags)
|
110
|
+
tags = Ollama::Utils::Tags.new(tags).to_a
|
100
111
|
records = records.select { |_key, record| (tags & record.tags).size >= 1 }
|
101
112
|
end
|
102
113
|
records = records.sort_by { |key, record|
|
@@ -111,6 +122,20 @@ class Ollama::Documents
|
|
111
122
|
records.transpose.last&.reverse.to_a
|
112
123
|
end
|
113
124
|
|
125
|
+
def find_where(string, text_size: nil, text_count: nil, **opts)
|
126
|
+
records = find(string, **opts)
|
127
|
+
size, count = 0, 0
|
128
|
+
records.take_while do |record|
|
129
|
+
if text_size and (size += record.text.size) > text_size
|
130
|
+
next false
|
131
|
+
end
|
132
|
+
if text_count and (count += 1) > text_count
|
133
|
+
next false
|
134
|
+
end
|
135
|
+
true
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
114
139
|
def collections
|
115
140
|
case @cache
|
116
141
|
when MemoryCache
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Ollama::Utils::FileArgument
|
2
|
+
module_function
|
3
|
+
|
4
|
+
def get_file_argument(prompt, default: nil)
|
5
|
+
if prompt.present? && prompt.size < 2 ** 15 &&
|
6
|
+
File.basename(prompt).size < 2 ** 8 &&
|
7
|
+
File.exist?(prompt)
|
8
|
+
then
|
9
|
+
File.read(prompt)
|
10
|
+
elsif prompt.present?
|
11
|
+
prompt
|
12
|
+
else
|
13
|
+
default
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/ollama/utils/tags.rb
CHANGED
data/lib/ollama/utils/width.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'tins/terminal'
|
2
2
|
|
3
3
|
module Ollama::Utils::Width
|
4
|
+
include Term::ANSIColor
|
5
|
+
|
4
6
|
module_function
|
5
7
|
|
6
8
|
def width(percentage: 100.0)
|
@@ -12,11 +14,24 @@ module Ollama::Utils::Width
|
|
12
14
|
raise ArgumentError, "either pass percentage or length argument"
|
13
15
|
percentage and length ||= width(percentage:)
|
14
16
|
text.gsub(/(?<!\n)\n(?!\n)/, ' ').lines.map do |line|
|
15
|
-
if length >= 1 && line.length > length
|
17
|
+
if length >= 1 && uncolor { line }.length > length
|
16
18
|
line.gsub(/(.{1,#{length}})(\s+|$)/, "\\1\n").strip
|
17
19
|
else
|
18
20
|
line.strip
|
19
21
|
end
|
20
22
|
end * ?\n
|
21
23
|
end
|
24
|
+
|
25
|
+
def truncate(text, percentage: nil, length: nil, ellipsis: ?…)
|
26
|
+
percentage.nil? ^ length.nil? or
|
27
|
+
raise ArgumentError, "either pass percentage or length argument"
|
28
|
+
percentage and length ||= width(percentage:)
|
29
|
+
if length < 1
|
30
|
+
+''
|
31
|
+
elsif text.size > length
|
32
|
+
text[0, length - 1] + ?…
|
33
|
+
else
|
34
|
+
text
|
35
|
+
end
|
36
|
+
end
|
22
37
|
end
|
data/lib/ollama/version.rb
CHANGED
data/lib/ollama.rb
CHANGED
data/ollama-ruby.gemspec
CHANGED
@@ -1,36 +1,36 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: ollama-ruby 0.
|
2
|
+
# stub: ollama-ruby 0.3.1 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "ollama-ruby".freeze
|
6
|
-
s.version = "0.
|
6
|
+
s.version = "0.3.1".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-09-
|
11
|
+
s.date = "2024-09-12"
|
12
12
|
s.description = "Library that allows interacting with the Ollama API".freeze
|
13
13
|
s.email = "flori@ping.de".freeze
|
14
|
-
s.executables = ["ollama_console".freeze, "ollama_chat".freeze, "ollama_update".freeze]
|
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/memory_cache.rb".freeze, "lib/ollama/documents/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/chooser.rb".freeze, "lib/ollama/utils/colorize_texts.rb".freeze, "lib/ollama/utils/fetcher.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_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/memory_cache.rb".freeze, "lib/ollama/documents/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/chooser.rb".freeze, "lib/ollama/utils/colorize_texts.rb".freeze, "lib/ollama/utils/fetcher.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/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_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/fetcher_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
|
14
|
+
s.executables = ["ollama_console".freeze, "ollama_chat".freeze, "ollama_update".freeze, "ollama_cli".freeze]
|
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/memory_cache.rb".freeze, "lib/ollama/documents/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/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/memory_cache.rb".freeze, "lib/ollama/documents/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/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/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_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/fetcher_spec.rb".freeze, "spec/ollama/utils/tags_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
|
-
s.rubygems_version = "3.5.
|
21
|
+
s.rubygems_version = "3.5.18".freeze
|
22
22
|
s.summary = "Interacting with the Ollama API".freeze
|
23
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_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/fetcher_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/spec_helper.rb".freeze]
|
24
24
|
|
25
25
|
s.specification_version = 4
|
26
26
|
|
27
|
-
s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 1.17.
|
27
|
+
s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 1.17.1".freeze])
|
28
28
|
s.add_development_dependency(%q<all_images>.freeze, ["~> 0.4".freeze])
|
29
29
|
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.2".freeze])
|
30
30
|
s.add_development_dependency(%q<utils>.freeze, [">= 0".freeze])
|
31
31
|
s.add_development_dependency(%q<webmock>.freeze, [">= 0".freeze])
|
32
32
|
s.add_runtime_dependency(%q<excon>.freeze, ["~> 0.111".freeze])
|
33
|
-
s.add_runtime_dependency(%q<infobar>.freeze, ["~> 0.
|
33
|
+
s.add_runtime_dependency(%q<infobar>.freeze, ["~> 0.8".freeze])
|
34
34
|
s.add_runtime_dependency(%q<term-ansicolor>.freeze, ["~> 1.11".freeze])
|
35
35
|
s.add_runtime_dependency(%q<kramdown-parser-gfm>.freeze, ["~> 1.1".freeze])
|
36
36
|
s.add_runtime_dependency(%q<terminal-table>.freeze, ["~> 3.0".freeze])
|
@@ -40,7 +40,8 @@ Gem::Specification.new do |s|
|
|
40
40
|
s.add_runtime_dependency(%q<sorted_set>.freeze, ["~> 1.0".freeze])
|
41
41
|
s.add_runtime_dependency(%q<mime-types>.freeze, ["~> 3.0".freeze])
|
42
42
|
s.add_runtime_dependency(%q<reverse_markdown>.freeze, ["~> 2.0".freeze])
|
43
|
-
s.add_runtime_dependency(%q<complex_config>.freeze, ["~> 0.
|
43
|
+
s.add_runtime_dependency(%q<complex_config>.freeze, ["~> 0.22".freeze])
|
44
44
|
s.add_runtime_dependency(%q<search_ui>.freeze, ["~> 0.0".freeze])
|
45
45
|
s.add_runtime_dependency(%q<amatch>.freeze, ["~> 0.4.1".freeze])
|
46
|
+
s.add_runtime_dependency(%q<pdf-reader>.freeze, ["~> 2.0".freeze])
|
46
47
|
end
|
@@ -74,5 +74,13 @@ RSpec.describe Ollama::Documents::RedisCache do
|
|
74
74
|
expect(redis).to receive(:scan_each).with(match: 'test-*')
|
75
75
|
redis_cache.to_a
|
76
76
|
end
|
77
|
+
|
78
|
+
it 'can compute prefix with pre' do
|
79
|
+
expect(redis_cache.pre('foo')).to eq 'test-foo'
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'can remove prefix with unpre' do
|
83
|
+
expect(redis_cache.unpre('test-foo')).to eq 'foo'
|
84
|
+
end
|
77
85
|
end
|
78
86
|
end
|
@@ -76,6 +76,34 @@ RSpec.describe Ollama::Documents do
|
|
76
76
|
expect(records[0].to_s).to eq '#<Ollama::Documents::Record "foo" #test 1.0>'
|
77
77
|
end
|
78
78
|
|
79
|
+
it 'can find strings conditionally' do
|
80
|
+
allow(ollama).to receive(:embed).
|
81
|
+
with(model:, input: [ 'foobar' ], options: nil).
|
82
|
+
and_return(double(embeddings: [ [ 0.01 ] ]))
|
83
|
+
allow(ollama).to receive(:embed).
|
84
|
+
with(model:, input: [ 'foo' ], options: nil).
|
85
|
+
and_return(double(embeddings: [ [ 0.1 ] ]))
|
86
|
+
expect(documents << 'foobar').to eq documents
|
87
|
+
expect(documents << 'foo').to eq documents
|
88
|
+
expect(ollama).to receive(:embed).at_least(:once).
|
89
|
+
with(model:, input: 'foo', options: nil).
|
90
|
+
and_return(double(embeddings: [ [ 0.1 ] ]))
|
91
|
+
records = documents.find_where('foo', text_count: 1)
|
92
|
+
expect(records).to eq [
|
93
|
+
Ollama::Documents::Record[text: 'foo', embedding: [ 0.1 ], similarity: 1.0 ],
|
94
|
+
]
|
95
|
+
records = documents.find_where('foo', text_size: 3)
|
96
|
+
expect(records).to eq [
|
97
|
+
Ollama::Documents::Record[text: 'foo', embedding: [ 0.1 ], similarity: 1.0 ],
|
98
|
+
]
|
99
|
+
records = documents.find_where('foo')
|
100
|
+
expect(records).to eq [
|
101
|
+
Ollama::Documents::Record[text: 'foo', embedding: [ 0.1 ], similarity: 1.0 ],
|
102
|
+
Ollama::Documents::Record[text: 'foobar', embedding: [ 0.1 ], similarity: 1.0 ],
|
103
|
+
]
|
104
|
+
end
|
105
|
+
|
106
|
+
|
79
107
|
context 'it uses cache' do
|
80
108
|
before do
|
81
109
|
allow(ollama).to receive(:embed).
|
@@ -103,6 +131,20 @@ RSpec.describe Ollama::Documents do
|
|
103
131
|
}.to change { documents.size }.from(1).to(0)
|
104
132
|
end
|
105
133
|
|
134
|
+
it 'can clear texts with tags' do
|
135
|
+
allow(ollama).to receive(:embed).
|
136
|
+
with(model:, input: %w[ bar ], options: nil).
|
137
|
+
and_return(double(embeddings: [ [ 0.1 ] ]))
|
138
|
+
expect(documents.add('foo', tags: %i[ test ])).to eq documents
|
139
|
+
expect(documents.add('bar', tags: %i[ test2 ])).to eq documents
|
140
|
+
expect {
|
141
|
+
documents.clear tags: 'test'
|
142
|
+
}.to change { documents.size }.from(2).to(1)
|
143
|
+
expect {
|
144
|
+
documents.clear tags: :test2
|
145
|
+
}.to change { documents.size }.from(1).to(0)
|
146
|
+
end
|
147
|
+
|
106
148
|
it 'returns collections' do
|
107
149
|
expect(documents.collections).to eq [ :default ]
|
108
150
|
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.
|
4
|
+
version: 0.3.1
|
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-09-
|
11
|
+
date: 2024-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gem_hadar
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.17.
|
19
|
+
version: 1.17.1
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.17.
|
26
|
+
version: 1.17.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: all_images
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0.
|
103
|
+
version: '0.8'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0.
|
110
|
+
version: '0.8'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: term-ansicolor
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -240,14 +240,14 @@ dependencies:
|
|
240
240
|
requirements:
|
241
241
|
- - "~>"
|
242
242
|
- !ruby/object:Gem::Version
|
243
|
-
version: '0.
|
243
|
+
version: '0.22'
|
244
244
|
type: :runtime
|
245
245
|
prerelease: false
|
246
246
|
version_requirements: !ruby/object:Gem::Requirement
|
247
247
|
requirements:
|
248
248
|
- - "~>"
|
249
249
|
- !ruby/object:Gem::Version
|
250
|
-
version: '0.
|
250
|
+
version: '0.22'
|
251
251
|
- !ruby/object:Gem::Dependency
|
252
252
|
name: search_ui
|
253
253
|
requirement: !ruby/object:Gem::Requirement
|
@@ -276,12 +276,27 @@ dependencies:
|
|
276
276
|
- - "~>"
|
277
277
|
- !ruby/object:Gem::Version
|
278
278
|
version: 0.4.1
|
279
|
+
- !ruby/object:Gem::Dependency
|
280
|
+
name: pdf-reader
|
281
|
+
requirement: !ruby/object:Gem::Requirement
|
282
|
+
requirements:
|
283
|
+
- - "~>"
|
284
|
+
- !ruby/object:Gem::Version
|
285
|
+
version: '2.0'
|
286
|
+
type: :runtime
|
287
|
+
prerelease: false
|
288
|
+
version_requirements: !ruby/object:Gem::Requirement
|
289
|
+
requirements:
|
290
|
+
- - "~>"
|
291
|
+
- !ruby/object:Gem::Version
|
292
|
+
version: '2.0'
|
279
293
|
description: Library that allows interacting with the Ollama API
|
280
294
|
email: flori@ping.de
|
281
295
|
executables:
|
282
296
|
- ollama_console
|
283
297
|
- ollama_chat
|
284
298
|
- ollama_update
|
299
|
+
- ollama_cli
|
285
300
|
extensions: []
|
286
301
|
extra_rdoc_files:
|
287
302
|
- README.md
|
@@ -331,6 +346,7 @@ extra_rdoc_files:
|
|
331
346
|
- lib/ollama/utils/chooser.rb
|
332
347
|
- lib/ollama/utils/colorize_texts.rb
|
333
348
|
- lib/ollama/utils/fetcher.rb
|
349
|
+
- lib/ollama/utils/file_argument.rb
|
334
350
|
- lib/ollama/utils/math.rb
|
335
351
|
- lib/ollama/utils/tags.rb
|
336
352
|
- lib/ollama/utils/width.rb
|
@@ -343,6 +359,7 @@ files:
|
|
343
359
|
- README.md
|
344
360
|
- Rakefile
|
345
361
|
- bin/ollama_chat
|
362
|
+
- bin/ollama_cli
|
346
363
|
- bin/ollama_console
|
347
364
|
- bin/ollama_update
|
348
365
|
- config/redis.conf
|
@@ -393,6 +410,7 @@ files:
|
|
393
410
|
- lib/ollama/utils/chooser.rb
|
394
411
|
- lib/ollama/utils/colorize_texts.rb
|
395
412
|
- lib/ollama/utils/fetcher.rb
|
413
|
+
- lib/ollama/utils/file_argument.rb
|
396
414
|
- lib/ollama/utils/math.rb
|
397
415
|
- lib/ollama/utils/tags.rb
|
398
416
|
- lib/ollama/utils/width.rb
|
@@ -460,7 +478,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
460
478
|
- !ruby/object:Gem::Version
|
461
479
|
version: '0'
|
462
480
|
requirements: []
|
463
|
-
rubygems_version: 3.5.
|
481
|
+
rubygems_version: 3.5.18
|
464
482
|
signing_key:
|
465
483
|
specification_version: 4
|
466
484
|
summary: Interacting with the Ollama API
|