ollama_chat 0.0.118 → 0.0.119
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 +58 -0
- data/Rakefile +1 -1
- data/lib/ollama_chat/commands.rb +2 -1
- data/lib/ollama_chat/input_content.rb +1 -1
- data/lib/ollama_chat/ollama_chat_config/default_config.yml +4 -2
- data/lib/ollama_chat/prompt_management.rb +1 -1
- data/lib/ollama_chat/rag_handling.rb +9 -12
- data/lib/ollama_chat/session_management.rb +9 -7
- data/lib/ollama_chat/source_fetching.rb +33 -5
- data/lib/ollama_chat/utils/chooser.rb +1 -1
- data/lib/ollama_chat/version.rb +1 -1
- data/ollama_chat.gemspec +3 -3
- data/spec/ollama_chat/commands_spec.rb +5 -5
- data/spec/ollama_chat/input_content_spec.rb +10 -0
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a7b876b681130c1ff2ec672460bb04aa85ed095e9358dbdaa62d744f82d68720
|
|
4
|
+
data.tar.gz: 3f85175d15231880d45e8f192f9f9af47c861cb8f1475d2fe653309ca173ab1c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9cf60761b6ce28cb22873b30808d3398ffcefc9e9991fcf781621b4db8a8fed5fd6cca21de046d8bf2851dd60a7529cfa162125ca4ee567e32c09042f4dc4e81
|
|
7
|
+
data.tar.gz: a2f1e6210141a8f00c4b9428453c49e4e1673e51521f788dcec694cd2c2c9963542bd491618ec8d1a4bb3ad5788588ca3d2c7f51ed3b67b977eaac1b4a59115a
|
data/CHANGES.md
CHANGED
|
@@ -1,5 +1,63 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-09-14 v0.0.119
|
|
4
|
+
|
|
5
|
+
* **Word-boundary fuzzy matching in chooser**
|
|
6
|
+
* Pass `/\b/` as the word-boundary argument to `matcher.similar` in
|
|
7
|
+
`chooser.rb` to filter out partial-word hits, improving ranked results
|
|
8
|
+
for model names containing `/`, `-`, `:`, and `.` separators.
|
|
9
|
+
|
|
10
|
+
* **Parallel embedding via bounded thread pool**
|
|
11
|
+
* Add `concurrency: 3` under `embedding:` in `default_config.yml`.
|
|
12
|
+
* Add `bulk_embed_sources` to `source_fetching.rb` using a
|
|
13
|
+
`Tins::Limited` bounded thread pool with a `Mutex`-guarded results
|
|
14
|
+
array.
|
|
15
|
+
* Change `embed` to accept a `prompt:` kwarg (defaults to
|
|
16
|
+
`prompt(:embed)`) so worker threads share a single resolved template
|
|
17
|
+
instead of each hitting Sequel/SQLite.
|
|
18
|
+
* Replace `STDOUT.puts` with `infobar.puts` in `embed_source` to prevent
|
|
19
|
+
raw output from clobbering the progress bar in concurrent workers.
|
|
20
|
+
* Rewrite the `-p` pattern path in `commands.rb` embedding to build a
|
|
21
|
+
`{source => tags}` Hash and call `bulk_embed_sources`.
|
|
22
|
+
* Rewrite `update_collection` in `rag_handling.rb` to collect both
|
|
23
|
+
modified and new sources into a single Hash and issue one
|
|
24
|
+
`bulk_embed_sources` call instead of a sequential `embed` loop.
|
|
25
|
+
* Update `commands_spec.rb` to stub `bulk_embed_sources` returning an
|
|
26
|
+
array.
|
|
27
|
+
|
|
28
|
+
* **Speed up embedding generation**
|
|
29
|
+
* Implement batch processing in the ollama server.
|
|
30
|
+
|
|
31
|
+
* **Dependency updates**
|
|
32
|
+
* Update `documentrix` minimum version to **0.7.0** in `Rakefile` and
|
|
33
|
+
`ollama_chat.gemspec` to support improved embedding speed.
|
|
34
|
+
|
|
35
|
+
* **Improve session switching and duplication robustness**
|
|
36
|
+
* In `duplicate_session`, replaced defensive `session.lock?` check with a
|
|
37
|
+
direct `session.lock` call, since a freshly duplicated session is never
|
|
38
|
+
yet locked.
|
|
39
|
+
* In `change_session`, added `except_id: session.id` to `choose_session`
|
|
40
|
+
to prevent re-selecting the current session from the chooser.
|
|
41
|
+
* Track `previous_session` as a full object instead of just an ID,
|
|
42
|
+
enabling restoration on lock failure.
|
|
43
|
+
* On lock failure, restore `@session` to the previous session, re-acquire
|
|
44
|
+
its lock, and reset `name` to `??` so the next iteration opens the
|
|
45
|
+
interactive picker instead of retrying the same locked session.
|
|
46
|
+
* Log `previous_session_id` correctly in the "Session changed" info
|
|
47
|
+
message.
|
|
48
|
+
|
|
49
|
+
* **Formatting fix**
|
|
50
|
+
* Add space before `\`.
|
|
51
|
+
|
|
52
|
+
* **Fix `context_spook` returning `nil` instead of context**
|
|
53
|
+
* Reordered `STDOUT.puts` and `ctx.send("to_#{format.downcase}")` in
|
|
54
|
+
`context_spook` so the serialized context is the last expression in the
|
|
55
|
+
`if count > 0` branch, preventing `STDOUT.puts` from clobbering the
|
|
56
|
+
implicit return value.
|
|
57
|
+
* Added a regression spec in `input_content_spec.rb` that exercises the
|
|
58
|
+
`count > 0` path with a real file and `all: true`, asserting the return
|
|
59
|
+
value is a non-blank `String` containing the ingested file path.
|
|
60
|
+
|
|
3
61
|
## 2026-09-05 v0.0.118
|
|
4
62
|
|
|
5
63
|
* Documented the upgrade workflow in the README, adding an "Upgrading"
|
data/Rakefile
CHANGED
|
@@ -40,7 +40,7 @@ GemHadar do
|
|
|
40
40
|
|
|
41
41
|
dependency 'excon', '~> 1.0'
|
|
42
42
|
dependency 'ollama-ruby', '~> 1.23'
|
|
43
|
-
dependency 'documentrix', '>= 0.
|
|
43
|
+
dependency 'documentrix', '>= 0.7.0'
|
|
44
44
|
dependency 'unix_socks', '>= 0.4'
|
|
45
45
|
dependency 'rss', '~> 0.3'
|
|
46
46
|
dependency 'term-ansicolor', '~> 1.11'
|
data/lib/ollama_chat/commands.rb
CHANGED
|
@@ -883,7 +883,8 @@ module OllamaChat::Commands
|
|
|
883
883
|
if opts[?p]
|
|
884
884
|
all = opts.fetch(?a, false)
|
|
885
885
|
patterns = extract_patterns(arg)
|
|
886
|
-
|
|
886
|
+
sources = file_set_each(patterns, all:).map(&:to_s).to_h { [_1, tags] }
|
|
887
|
+
next bulk_embed_sources(sources) || :next
|
|
887
888
|
elsif arg
|
|
888
889
|
next embed(arg, tags:) || :next
|
|
889
890
|
else
|
|
@@ -106,8 +106,8 @@ module OllamaChat::InputContent
|
|
|
106
106
|
end
|
|
107
107
|
end
|
|
108
108
|
if count > 0
|
|
109
|
-
ctx.send("to_#{format.downcase}")
|
|
110
109
|
STDOUT.puts "✅ Ingesting context now."
|
|
110
|
+
ctx.send("to_#{format.downcase}")
|
|
111
111
|
else
|
|
112
112
|
STDERR.puts "❌ No files in context. ⇨ Cancelled."
|
|
113
113
|
end
|
|
@@ -478,10 +478,12 @@ embedding:
|
|
|
478
478
|
name: snowflake-arctic-embed:137m
|
|
479
479
|
embedding_length: 768
|
|
480
480
|
context_length: 2048
|
|
481
|
-
options:
|
|
481
|
+
options:
|
|
482
|
+
num_batch: 2048
|
|
482
483
|
# Retrieval prompt template:
|
|
483
484
|
prompt: 'Represent this sentence for searching relevant passages: %s'
|
|
484
|
-
batch_size:
|
|
485
|
+
batch_size: 500
|
|
486
|
+
concurrency: 3
|
|
485
487
|
database_filename: null # ':memory:'
|
|
486
488
|
collection: <%= OC::OLLAMA::CHAT::COLLECTION %>
|
|
487
489
|
found_texts_size: 16384
|
|
@@ -432,7 +432,7 @@ module OllamaChat::PromptManagement
|
|
|
432
432
|
end
|
|
433
433
|
|
|
434
434
|
if orphans.any?
|
|
435
|
-
STDOUT.puts "\n#{orphans.count} orphaned prompt(s) "\
|
|
435
|
+
STDOUT.puts "\n#{orphans.count} orphaned prompt(s) " \
|
|
436
436
|
"(no longer in default config):\n"
|
|
437
437
|
orphans.each { |p| STDOUT.puts " • #{bold{p.name}} in #{italic{p.context}}" }
|
|
438
438
|
STDOUT.puts
|
|
@@ -184,12 +184,13 @@ module OllamaChat::RAGHandling
|
|
|
184
184
|
#
|
|
185
185
|
# @return [String] a newline-separated string of embedding result messages.
|
|
186
186
|
def update_collection(collection)
|
|
187
|
+
results = []
|
|
187
188
|
switch_collection(collection) do
|
|
188
189
|
unless col = database_collection?(collection)
|
|
189
190
|
STDERR.puts "❌ Collection #{collection.inspect} not found in database."
|
|
190
|
-
return
|
|
191
|
+
return ''
|
|
191
192
|
end
|
|
192
|
-
|
|
193
|
+
sources = {}
|
|
193
194
|
seen = {}
|
|
194
195
|
@documents.each_record do |record|
|
|
195
196
|
source = @documents.normalize_source(record.source) or next
|
|
@@ -199,24 +200,20 @@ module OllamaChat::RAGHandling
|
|
|
199
200
|
infobar.puts "Source #{source.to_s.inspect} is unmodified. => Skipping."
|
|
200
201
|
next
|
|
201
202
|
end
|
|
202
|
-
|
|
203
|
+
sources[source] = record.tags_set
|
|
203
204
|
@documents.source_remove(source)
|
|
204
|
-
r = embed(source, tags:) or next
|
|
205
|
-
results << r
|
|
206
205
|
end
|
|
207
206
|
|
|
208
207
|
if patterns = col.patterns.full?
|
|
209
|
-
all_file_set(patterns).
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
r = embed(file.to_s, tags: []) or next
|
|
213
|
-
results << r
|
|
214
|
-
end
|
|
208
|
+
new_sources = all_file_set(patterns).map(&:to_s).reject { seen.key?(_1) }
|
|
209
|
+
new_sources.each { seen[_1] = true }
|
|
210
|
+
new_sources.each { sources[_1] = [] }
|
|
215
211
|
end
|
|
216
212
|
|
|
213
|
+
results.concat(bulk_embed_sources(sources))
|
|
217
214
|
log(:info, "Collection updated", data: { collection:, sources_updated: results.size })
|
|
218
|
-
results * "\n"
|
|
219
215
|
end
|
|
216
|
+
results * ?\n
|
|
220
217
|
end
|
|
221
218
|
|
|
222
219
|
# Extracts and normalizes file patterns from a shell-style string.
|
|
@@ -219,8 +219,7 @@ module OllamaChat::SessionManagement
|
|
|
219
219
|
@session = session.duplicate
|
|
220
220
|
set_previous_session_on_change(old_session.id)
|
|
221
221
|
session.update(name:)
|
|
222
|
-
session.lock
|
|
223
|
-
"Could not lock session #{session.id} #{session.errors.full?(:inspect)}"
|
|
222
|
+
session.lock
|
|
224
223
|
confirm?(
|
|
225
224
|
prompt: "🔔 Clear messages of duplicated session? (y/n) ",
|
|
226
225
|
yes: /\Ay/i
|
|
@@ -537,9 +536,9 @@ module OllamaChat::SessionManagement
|
|
|
537
536
|
# @param name [String] the name or ID of the session to switch to
|
|
538
537
|
def change_session(name)
|
|
539
538
|
name.full? or name = ??
|
|
540
|
-
|
|
539
|
+
previous_session = nil
|
|
541
540
|
loop do
|
|
542
|
-
if chosen_session = choose_session(name, allow_new: true)
|
|
541
|
+
if chosen_session = choose_session(name, except_id: session.id, allow_new: true)
|
|
543
542
|
if chosen_session.nil? || chosen_session == session
|
|
544
543
|
confirm?(
|
|
545
544
|
prompt: "\n⏎ Same session chosen, Press any key to continue (%s). ",
|
|
@@ -548,7 +547,7 @@ module OllamaChat::SessionManagement
|
|
|
548
547
|
break
|
|
549
548
|
end
|
|
550
549
|
session_close
|
|
551
|
-
|
|
550
|
+
previous_session = session
|
|
552
551
|
@session = chosen_session
|
|
553
552
|
if session.lock?
|
|
554
553
|
messages.read_conversation_jsonl(session.messages.to_s)
|
|
@@ -563,10 +562,13 @@ module OllamaChat::SessionManagement
|
|
|
563
562
|
set_default_persona_name(session.default_persona_name.full? || :none)
|
|
564
563
|
set_current_system_prompt(session.current_system_prompt.full? || 'default')
|
|
565
564
|
session_apply
|
|
566
|
-
log(:info, "Session changed", data: { session_id: session.id, name: session.name, previous_session_id: })
|
|
565
|
+
log(:info, "Session changed", data: { session_id: session.id, name: session.name, previous_session_id: previous_session&.id })
|
|
567
566
|
info_session
|
|
568
567
|
break
|
|
569
568
|
else
|
|
569
|
+
@session = previous_session
|
|
570
|
+
@session.lock
|
|
571
|
+
name = ??
|
|
570
572
|
confirm?(
|
|
571
573
|
prompt: "\n⏎ Session locked: could not switch, Press any key to continue (%s). ",
|
|
572
574
|
timeout: 3
|
|
@@ -579,7 +581,7 @@ module OllamaChat::SessionManagement
|
|
|
579
581
|
end
|
|
580
582
|
end
|
|
581
583
|
ensure
|
|
582
|
-
set_previous_session_on_change(
|
|
584
|
+
set_previous_session_on_change(previous_session&.id)
|
|
583
585
|
session_sync
|
|
584
586
|
end
|
|
585
587
|
|
|
@@ -185,7 +185,7 @@ module OllamaChat::SourceFetching
|
|
|
185
185
|
def embed_source(source_io, source, tags: [], count: nil)
|
|
186
186
|
@embedding.on? or return parse_source(source_io)
|
|
187
187
|
unless @documents.source_modified?(source)
|
|
188
|
-
|
|
188
|
+
infobar.puts "Source #{source.to_s.inspect} already up-to-date. => Skipping."
|
|
189
189
|
log(:info, "Source up-to-date", data: { source: source.to_s })
|
|
190
190
|
return
|
|
191
191
|
end
|
|
@@ -225,9 +225,9 @@ module OllamaChat::SourceFetching
|
|
|
225
225
|
chunks: inputs.size
|
|
226
226
|
})
|
|
227
227
|
if count
|
|
228
|
-
|
|
228
|
+
infobar.puts '%u. %s' % [ count, m ]
|
|
229
229
|
else
|
|
230
|
-
|
|
230
|
+
infobar.puts m
|
|
231
231
|
end
|
|
232
232
|
source = source.to_s
|
|
233
233
|
command = false
|
|
@@ -253,10 +253,14 @@ module OllamaChat::SourceFetching
|
|
|
253
253
|
#
|
|
254
254
|
# @param source [String] The source identifier which can be a command, URL,
|
|
255
255
|
# or file path
|
|
256
|
+
# @param tags [Array<String>] Tags to apply to the embedded source
|
|
257
|
+
# @param prompt [#to_s] The prompt template to format the result with
|
|
258
|
+
# (defaults to `prompt(:embed)`)
|
|
256
259
|
#
|
|
257
260
|
# @return [String, nil] The formatted embedding result or summary message, or
|
|
258
261
|
# nil if the operation fails
|
|
259
|
-
def embed(source, tags: [])
|
|
262
|
+
def embed(source, tags: [], prompt: prompt(:embed))
|
|
263
|
+
prompt = prompt.to_s
|
|
260
264
|
@embedding.on? or return
|
|
261
265
|
fetch_source(source) do |source_io|
|
|
262
266
|
content = parse_source(source_io)
|
|
@@ -264,7 +268,31 @@ module OllamaChat::SourceFetching
|
|
|
264
268
|
source_io.rewind
|
|
265
269
|
embed_source(source_io, source, tags:) or return
|
|
266
270
|
end
|
|
267
|
-
prompt
|
|
271
|
+
prompt.to_s % { source:, collection: }
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Embeds multiple sources concurrently using a bounded thread pool.
|
|
275
|
+
#
|
|
276
|
+
# @param sources_tags [Hash{String => Array}] mapping of source identifier
|
|
277
|
+
# to the tags array to apply to that source
|
|
278
|
+
# @return [Array<String>] results from each successful embed call
|
|
279
|
+
def bulk_embed_sources(sources_tags)
|
|
280
|
+
return sources_tags.map { |s, tags| embed(s, tags:) }.compact if
|
|
281
|
+
sources_tags.size <= 1 or config.embedding.concurrency <= 1
|
|
282
|
+
|
|
283
|
+
results = []
|
|
284
|
+
mutex = Mutex.new
|
|
285
|
+
prompt = prompt(:embed)
|
|
286
|
+
Tins::Limited.new(config.embedding.concurrency, name: 'embed').process do |l|
|
|
287
|
+
sources_tags.each do |s, tags|
|
|
288
|
+
l.execute do
|
|
289
|
+
r = embed(s, prompt:, tags:)
|
|
290
|
+
mutex.synchronize { results << r } if r
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
l.stop
|
|
294
|
+
end
|
|
295
|
+
results
|
|
268
296
|
end
|
|
269
297
|
|
|
270
298
|
private
|
|
@@ -51,7 +51,7 @@ module OllamaChat::Utils::Chooser
|
|
|
51
51
|
matches = entries.map { |n|
|
|
52
52
|
[
|
|
53
53
|
n,
|
|
54
|
-
-matcher.similar(n.ask_and_send_or_self(:value).to_s.downcase)
|
|
54
|
+
-matcher.similar(n.ask_and_send_or_self(:value).to_s.downcase, /\b/)
|
|
55
55
|
]
|
|
56
56
|
}.select { |_, s| s < 0 }.sort_by(&:last).map(&:first)
|
|
57
57
|
matches.empty? and matches = entries
|
data/lib/ollama_chat/version.rb
CHANGED
data/ollama_chat.gemspec
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: ollama_chat 0.0.
|
|
2
|
+
# stub: ollama_chat 0.0.119 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "ollama_chat".freeze
|
|
6
|
-
s.version = "0.0.
|
|
6
|
+
s.version = "0.0.119".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]
|
|
@@ -35,7 +35,7 @@ Gem::Specification.new do |s|
|
|
|
35
35
|
s.add_development_dependency(%q<utils>.freeze, [">= 0".freeze])
|
|
36
36
|
s.add_runtime_dependency(%q<excon>.freeze, ["~> 1.0".freeze])
|
|
37
37
|
s.add_runtime_dependency(%q<ollama-ruby>.freeze, ["~> 1.23".freeze])
|
|
38
|
-
s.add_runtime_dependency(%q<documentrix>.freeze, [">= 0.
|
|
38
|
+
s.add_runtime_dependency(%q<documentrix>.freeze, [">= 0.7.0".freeze])
|
|
39
39
|
s.add_runtime_dependency(%q<unix_socks>.freeze, [">= 0.4".freeze])
|
|
40
40
|
s.add_runtime_dependency(%q<rss>.freeze, ["~> 0.3".freeze])
|
|
41
41
|
s.add_runtime_dependency(%q<term-ansicolor>.freeze, ["~> 1.11".freeze])
|
|
@@ -411,11 +411,11 @@ describe OllamaChat::Commands, protect_env: true do
|
|
|
411
411
|
end
|
|
412
412
|
|
|
413
413
|
it 'returns "success" when input is "/input embedding -p (.+)"' do
|
|
414
|
-
expect(chat).to receive(:
|
|
415
|
-
with(
|
|
416
|
-
and_return 'success'
|
|
417
|
-
expect(chat.handle_input("/input embedding -a -p #{asset('*.rb')}"))
|
|
418
|
-
to
|
|
414
|
+
expect(chat).to receive(:bulk_embed_sources).
|
|
415
|
+
with(anything).
|
|
416
|
+
and_return [ 'success' ]
|
|
417
|
+
expect(chat.handle_input("/input embedding -a -p #{asset('*.rb')}"))
|
|
418
|
+
.to eq [ 'success' ]
|
|
419
419
|
end
|
|
420
420
|
|
|
421
421
|
it 'returns :next when input is "/input embedding"' do
|
|
@@ -97,5 +97,15 @@ describe OllamaChat::InputContent do
|
|
|
97
97
|
and_return(nil)
|
|
98
98
|
expect(chat.context_spook(nil)).to be_nil
|
|
99
99
|
end
|
|
100
|
+
|
|
101
|
+
it 'returns the serialized context instead of nil' do
|
|
102
|
+
patterns = ['spec/assets/example.rb']
|
|
103
|
+
expect(STDOUT).to receive(:puts).with(/Ingesting context now/)
|
|
104
|
+
result = chat.context_spook(patterns, all: true)
|
|
105
|
+
expect(result).to be_a(String)
|
|
106
|
+
json = JSON.parse(result)
|
|
107
|
+
expected = Pathname.new('spec/assets/example.rb').expand_path.to_path
|
|
108
|
+
expect(json['files'].keys).to include(expected)
|
|
109
|
+
end
|
|
100
110
|
end
|
|
101
111
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ollama_chat
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.119
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Frank
|
|
@@ -169,14 +169,14 @@ dependencies:
|
|
|
169
169
|
requirements:
|
|
170
170
|
- - ">="
|
|
171
171
|
- !ruby/object:Gem::Version
|
|
172
|
-
version: 0.
|
|
172
|
+
version: 0.7.0
|
|
173
173
|
type: :runtime
|
|
174
174
|
prerelease: false
|
|
175
175
|
version_requirements: !ruby/object:Gem::Requirement
|
|
176
176
|
requirements:
|
|
177
177
|
- - ">="
|
|
178
178
|
- !ruby/object:Gem::Version
|
|
179
|
-
version: 0.
|
|
179
|
+
version: 0.7.0
|
|
180
180
|
- !ruby/object:Gem::Dependency
|
|
181
181
|
name: unix_socks
|
|
182
182
|
requirement: !ruby/object:Gem::Requirement
|