ollama_chat 0.0.103 → 0.0.105
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 +69 -0
- data/README.md +2 -7
- data/lib/ollama_chat/chat.rb +3 -14
- data/lib/ollama_chat/commands.rb +62 -20
- data/lib/ollama_chat/database/migrations/007_add_collections_table.rb +12 -0
- data/lib/ollama_chat/database/models/collection.rb +81 -0
- data/lib/ollama_chat/database/models/prompt.rb +1 -1
- data/lib/ollama_chat/database/models/session.rb +6 -0
- data/lib/ollama_chat/information.rb +18 -6
- data/lib/ollama_chat/model_handling.rb +73 -13
- data/lib/ollama_chat/ollama_chat_config/default_config.yml +2 -2
- data/lib/ollama_chat/prompt_management.rb +21 -0
- data/lib/ollama_chat/rag_handling.rb +217 -39
- data/lib/ollama_chat/session_management.rb +22 -15
- data/lib/ollama_chat/tools/patch_file.rb +8 -4
- data/lib/ollama_chat/tools/{retrieve_document_snippets.rb → search_knowledge.rb} +6 -6
- data/lib/ollama_chat/tools.rb +1 -1
- data/lib/ollama_chat/version.rb +1 -1
- data/ollama_chat.gemspec +5 -5
- data/spec/ollama_chat/chat_spec.rb +3 -43
- data/spec/ollama_chat/commands_spec.rb +20 -14
- data/spec/ollama_chat/session_management_spec.rb +0 -1
- data/spec/ollama_chat/tools/{retrieve_document_snippets_spec.rb → search_knowledge_spec.rb} +9 -9
- metadata +9 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cbf0c7c0df08fa3ef8a15a9c62b7e092d035924c071302a4f37e01776dec2504
|
|
4
|
+
data.tar.gz: '0996355cc3d0324936394a174aaeeee8b67b950d5306cf320fa22a70eef9ea0d'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 879adc039769558c938911909dbfdfc9625d6b4774cd398d8b39b4ebeb7055d7f7eb1fdaa1c26caf79d7fab3330c57c95b1169927e34d6909518e5f30f1c9d74
|
|
7
|
+
data.tar.gz: 7fbe2ad8b0f887cab6d83ece7efe118fd0189e1957fdbd5a40725200729b7e4d93e9c018c1a41cc8fc933dd2cee453a3a7b9090a7e647422314175d567e5496c
|
data/CHANGES.md
CHANGED
|
@@ -1,5 +1,74 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-08-04 v0.0.105
|
|
4
|
+
|
|
5
|
+
### New Features
|
|
6
|
+
|
|
7
|
+
- **Collection Management**: Introduced the
|
|
8
|
+
`OllamaChat::Database::Models::Collection` model and a corresponding `Sequel`
|
|
9
|
+
migration for persistent storage. Added interactive CLI commands under
|
|
10
|
+
`/collection` including `new`, `edit`, `delete`, and `update all`.
|
|
11
|
+
- **Model Profile Copying**: Added an `options copy` subcommand to allow users
|
|
12
|
+
to interactively copy configuration profiles between models, including
|
|
13
|
+
implementation of `copy_model_options_profile`.
|
|
14
|
+
- **Interactive Prompt Contexts**: Implemented `choose_prompt_context` in
|
|
15
|
+
`prompt_management.rb`, allowing the `/prompt` command to dynamically query
|
|
16
|
+
and select contexts via a new `-c ?` flag.
|
|
17
|
+
|
|
18
|
+
### Enhancements
|
|
19
|
+
|
|
20
|
+
- **Model Options Matching**: Improved profile matching by replacing default
|
|
21
|
+
overwrite prompts with comprehensive checks against all saved `ModelOptions`
|
|
22
|
+
profiles using `ask_and_send(:symbolize_keys_recursive)`. Added pager display
|
|
23
|
+
for available profiles via `use_pager` and the ability to switch profiles via
|
|
24
|
+
`choose_profile_for_model`.
|
|
25
|
+
- **Collection Synchronization**: Enhanced `list_collections` with descriptions
|
|
26
|
+
and paging, and implemented a `Collection.sync` method to backfill database
|
|
27
|
+
records during startup.
|
|
28
|
+
- **Command Refactoring**: Renamed `show_session` to `info_session` within the
|
|
29
|
+
`Commands` module for increased verbosity when no subcommand is provided.
|
|
30
|
+
|
|
31
|
+
### Bug Fixes & Maintenance
|
|
32
|
+
|
|
33
|
+
- **Documentation**:
|
|
34
|
+
- Clarified that the `checksum` for the `patch_file` tool must be an 8 hex
|
|
35
|
+
digit long CRC32.
|
|
36
|
+
- Added YARD `@!attribute` documentation for `links` and `history` in the
|
|
37
|
+
`Session` model.
|
|
38
|
+
- **Code Cleanup**:
|
|
39
|
+
- Replaced `.exists?` and `.first` dataset checks with `.present?` in
|
|
40
|
+
`model_handling.rb` and `session_management.rb`.
|
|
41
|
+
- Removed deprecated CLI flags `-c`, `-C`, `-D`, `-M`, and `-E` in favor of
|
|
42
|
+
interactive management.
|
|
43
|
+
- Added an `after_destroy` hook to the `Collection` model to purge
|
|
44
|
+
corresponding `Documentrix` vector data.
|
|
45
|
+
|
|
46
|
+
## 2026-07-31 v0.0.104
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
#### Added
|
|
51
|
+
|
|
52
|
+
- Enabled interactive profile creation with duplicate validation by supporting
|
|
53
|
+
the `allow_new` keyword argument in `choose_profile_for_model`.
|
|
54
|
+
|
|
55
|
+
#### Changed
|
|
56
|
+
|
|
57
|
+
- Standardized API naming conventions by renaming the `offer_new_session`
|
|
58
|
+
parameter to `allow_new` in `session_management.rb` and `choose_session`.
|
|
59
|
+
- Updated `commands.rb` to pass `allow_new: true` to `choose_profile_for_model`
|
|
60
|
+
during `/model options` and implemented an early return on profile selection
|
|
61
|
+
cancellation.
|
|
62
|
+
- Renamed the `OllamaChat::Tools::RetrieveDocumentSnippets` class to
|
|
63
|
+
`SearchKnowledge`.
|
|
64
|
+
- Updated tool registration, default configuration, and descriptions for
|
|
65
|
+
`search_knowledge` to reference knowledge collections.
|
|
66
|
+
|
|
67
|
+
#### Fixed
|
|
68
|
+
|
|
69
|
+
- Adjusted `commands_spec.rb` test cases to reflect updated method signatures
|
|
70
|
+
and expected behavior for profile selection.
|
|
71
|
+
|
|
3
72
|
## 2026-07-30 v0.0.103
|
|
4
73
|
|
|
5
74
|
### Added
|
data/README.md
CHANGED
|
@@ -83,11 +83,6 @@ Usage: ollama_chat [OPTIONS]
|
|
|
83
83
|
-n create a new session
|
|
84
84
|
-u URL the ollama base url, OLLAMA_URL
|
|
85
85
|
-m MODEL the ollama model to chat with, OLLAMA_CHAT_MODEL, ?selector
|
|
86
|
-
-c CHAT a saved chat conversation to load
|
|
87
|
-
-C COLLECTION name of the collection used in this conversation
|
|
88
|
-
-D DOCUMENT load document and add to embeddings collection (multiple)
|
|
89
|
-
-M use (empty) MemoryCache for this chat session
|
|
90
|
-
-E disable embeddings for this chat session
|
|
91
86
|
-S open a socket to receive input from ollama_chat_send
|
|
92
87
|
-V display the current version number and quit
|
|
93
88
|
-h this help
|
|
@@ -420,10 +415,10 @@ context, manipulate files, and retrieve external information.
|
|
|
420
415
|
| **Web/External** | `search_web`, `get_url`, `browse`, `get_rfc`, `get_cve`, `get_endoflife`, `get_ghr`, `get_jira_issue` | Access the internet, fetch specific URLs, and look up technical standards. |
|
|
421
416
|
| **System/Util** | `get_time`, `get_location`, `get_current_weather`, `generate_password`, `compute_bmi`, `roll_dice` | General utility functions for time, location, and simple calculations. |
|
|
422
417
|
| **Editor/Clip** | `copy_to_clipboard`, `paste_from_clipboard`, `paste_into_editor`, `open_file_in_editor` | Bridge the gap between the chat and the system clipboard or editor. |
|
|
423
|
-
| **Knowledge** | `
|
|
418
|
+
| **Knowledge** | `search_knowledge`, `file_context` | Semantic search for specific snippets vs. broad retrieval of structured project context. |
|
|
424
419
|
| **Multimodal** | `generate_image` | Generate images via a local ComfyUI server. |
|
|
425
420
|
|
|
426
|
-
***Note on Knowledge Tools**: Use `
|
|
421
|
+
***Note on Knowledge Tools**: Use `search_knowledge` for precise,
|
|
427
422
|
low-token semantic discovery and `file_context` for a comprehensive view of
|
|
428
423
|
modules or patterns. Be cautious with broad patterns in `file_context`, as
|
|
429
424
|
importing too many files can exceed the LLM's context window.*
|
data/lib/ollama_chat/chat.rb
CHANGED
|
@@ -101,7 +101,7 @@ class OllamaChat::Chat
|
|
|
101
101
|
# @raise [RuntimeError] If the Ollama API version is less than 0.9.0, indicating
|
|
102
102
|
# incompatibility with required API features
|
|
103
103
|
def initialize(argv: ARGV.dup)
|
|
104
|
-
@opts = go 'f:u:m:
|
|
104
|
+
@opts = go 'f:u:m:l:nSVh', argv
|
|
105
105
|
@opts[?h] and exit usage
|
|
106
106
|
@opts[?V] and exit version
|
|
107
107
|
@ollama_chat_config = OllamaChat::OllamaChatConfig.new(@opts[?f])
|
|
@@ -112,14 +112,8 @@ class OllamaChat::Chat
|
|
|
112
112
|
setup_switches
|
|
113
113
|
setup_state_selectors(config)
|
|
114
114
|
connect_ollama
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
else
|
|
118
|
-
messages.read_conversation_jsonl(session.messages.to_s)
|
|
119
|
-
end
|
|
120
|
-
repair_group_uuids
|
|
121
|
-
embedding_enabled.set(config.embedding.enabled && !@opts[?E])
|
|
122
|
-
@documents = setup_documents
|
|
115
|
+
@documents = setup_documents
|
|
116
|
+
models::Collection.sync(self)
|
|
123
117
|
@cache = setup_cache
|
|
124
118
|
@images = []
|
|
125
119
|
@kramdown_ansi_styles = configure_kramdown_ansi_styles
|
|
@@ -221,7 +215,6 @@ class OllamaChat::Chat
|
|
|
221
215
|
# @return [ Symbol ] the collection name symbol
|
|
222
216
|
def initial_collection
|
|
223
217
|
(
|
|
224
|
-
@opts[?C] ||
|
|
225
218
|
session&.current_collection.full? ||
|
|
226
219
|
config.embedding.collection.full? ||
|
|
227
220
|
:default
|
|
@@ -639,10 +632,6 @@ class OllamaChat::Chat
|
|
|
639
632
|
redis_url: config.redis.documents.url?,
|
|
640
633
|
debug:
|
|
641
634
|
)
|
|
642
|
-
|
|
643
|
-
document_list = @opts[?D].to_a
|
|
644
|
-
add_documents_from_argv(document_list)
|
|
645
|
-
@documents
|
|
646
635
|
else
|
|
647
636
|
NULL
|
|
648
637
|
end
|
data/lib/ollama_chat/commands.rb
CHANGED
|
@@ -139,12 +139,13 @@ module OllamaChat::Commands
|
|
|
139
139
|
|
|
140
140
|
command(
|
|
141
141
|
name: :model,
|
|
142
|
-
regexp: %r(^/model(?:\s+(change|options
|
|
143
|
-
complete: [ 'model', %w[ change options options\ from\ session options\ to\ session ] ],
|
|
142
|
+
regexp: %r(^/model(?:\s+(change|options(?: copy)?|options from session|options to session))?((?:\s+(?:-m))*)$),
|
|
143
|
+
complete: [ 'model', %w[ change options options\ copy options\ from\ session options\ to\ session ] ],
|
|
144
144
|
help: <<~EOT
|
|
145
145
|
🤖 Manage AI models & profiles:
|
|
146
146
|
- change: Switch active model
|
|
147
147
|
- options: Edit saved profile config
|
|
148
|
+
- options copy: Copy profile from another model
|
|
148
149
|
- options from session: Save live → Saved
|
|
149
150
|
- options to session: Apply Saved → Live
|
|
150
151
|
-m interactively choose a model
|
|
@@ -163,13 +164,17 @@ module OllamaChat::Commands
|
|
|
163
164
|
end
|
|
164
165
|
opts = go_command('m', opts)
|
|
165
166
|
model = opts[?m] ? choose_model('', @model) : @model
|
|
166
|
-
profile = choose_profile_for_model(model) || 'default'
|
|
167
167
|
case subcommand
|
|
168
168
|
when 'options'
|
|
169
|
+
profile = choose_profile_for_model(model, allow_new: true) or next :next
|
|
169
170
|
edit_model_options(model, profile:)
|
|
171
|
+
when 'options copy'
|
|
172
|
+
copy_model_options_profile(model)
|
|
170
173
|
when 'options from session'
|
|
174
|
+
profile = choose_profile_for_model(model) || 'default'
|
|
171
175
|
copy_model_options_from_session(model, profile:)
|
|
172
176
|
when 'options to session'
|
|
177
|
+
profile = choose_profile_for_model(model) || 'default'
|
|
173
178
|
copy_model_options_to_session(model, profile:)
|
|
174
179
|
end
|
|
175
180
|
:next
|
|
@@ -274,7 +279,7 @@ module OllamaChat::Commands
|
|
|
274
279
|
) do |subcommand, opts, name|
|
|
275
280
|
case subcommand
|
|
276
281
|
when nil
|
|
277
|
-
|
|
282
|
+
info_session
|
|
278
283
|
when 'list'
|
|
279
284
|
list_sessions
|
|
280
285
|
when 'new'
|
|
@@ -455,7 +460,7 @@ module OllamaChat::Commands
|
|
|
455
460
|
|
|
456
461
|
command(
|
|
457
462
|
name: :prompt,
|
|
458
|
-
regexp: %r(^/prompt(?:\s+(edit|info|add|delete|list|duplicate|import|export|reset|-e))?(\s+(?:-[ef]|-c\s
|
|
463
|
+
regexp: %r(^/prompt(?:\s+(edit|info|add|delete|list|duplicate|import|export|reset|-e))?(\s+(?:-[ef]|-c\s+(?:\w+|\?)))?(?:\s+([^-].*))?$),
|
|
459
464
|
complete: [ 'prompt', %w[ edit info add delete list duplicate import export reset ] ],
|
|
460
465
|
optional: true,
|
|
461
466
|
options: '[-c CONTEXT|-e|-f]',
|
|
@@ -463,42 +468,61 @@ module OllamaChat::Commands
|
|
|
463
468
|
📝 Manage prompt templates:
|
|
464
469
|
Subcommands: edit, info, add, delete, list,
|
|
465
470
|
duplicate, import, export, reset.
|
|
466
|
-
Options: -c [context]
|
|
471
|
+
Options: -c [context]
|
|
472
|
+
(? for interactive in /prompt),
|
|
473
|
+
-e (edit next)
|
|
467
474
|
EOT
|
|
468
475
|
) do |subcommand, opts, filename|
|
|
469
476
|
opts = go_command('fc:', opts)
|
|
477
|
+
context = if subcommand.nil? || subcommand == '-e'
|
|
478
|
+
if opts[?c] == ??
|
|
479
|
+
choose_prompt_context
|
|
480
|
+
else
|
|
481
|
+
opts[?c] || 'prompt'
|
|
482
|
+
end
|
|
483
|
+
else
|
|
484
|
+
opts[?c] || choose_prompt_context
|
|
485
|
+
end
|
|
486
|
+
unless context
|
|
487
|
+
STDOUT.puts 'Cancelled.'
|
|
488
|
+
next :next
|
|
489
|
+
end
|
|
490
|
+
|
|
470
491
|
case subcommand
|
|
471
492
|
when 'add'
|
|
472
|
-
add_new_prompt(context:
|
|
493
|
+
add_new_prompt(context:)
|
|
473
494
|
when 'delete'
|
|
474
|
-
choose_and_delete_prompt(context
|
|
495
|
+
choose_and_delete_prompt(context:, force: opts[?f])
|
|
475
496
|
when 'edit'
|
|
476
|
-
choose_and_edit_prompt(context:
|
|
497
|
+
choose_and_edit_prompt(context:)
|
|
477
498
|
when 'list'
|
|
478
|
-
list_prompts(context:
|
|
499
|
+
list_prompts(context:)
|
|
479
500
|
when 'duplicate'
|
|
480
|
-
duplicate_prompt(context:
|
|
501
|
+
duplicate_prompt(context:)
|
|
481
502
|
when 'import'
|
|
482
|
-
import_prompt(filename, context:
|
|
503
|
+
import_prompt(filename, context:)
|
|
483
504
|
when 'export'
|
|
484
|
-
export_prompt(context:
|
|
505
|
+
export_prompt(context:)
|
|
485
506
|
when 'info'
|
|
486
|
-
info_prompt(context:
|
|
507
|
+
info_prompt(context:)
|
|
487
508
|
when 'reset'
|
|
488
509
|
if prompt = choose_prompt(
|
|
489
510
|
default: true,
|
|
490
|
-
context
|
|
511
|
+
context:,
|
|
491
512
|
prompt: 'Which prompt needs to be restored to its origin? %s'
|
|
492
513
|
)
|
|
493
514
|
then
|
|
494
|
-
if reset_prompt_to_default(prompt.name, context:
|
|
515
|
+
if reset_prompt_to_default(prompt.name, context:)
|
|
495
516
|
STDOUT.puts "Reset prompt #{bold{prompt.name}} to default."
|
|
496
517
|
else
|
|
497
518
|
STDOUT.puts "No default value found for prompt #{bold{prompt.name}}."
|
|
498
519
|
end
|
|
499
520
|
end
|
|
500
521
|
when nil, '-e'
|
|
501
|
-
if prompt = choose_prompt(
|
|
522
|
+
if prompt = choose_prompt(
|
|
523
|
+
prompt: 'Which template shall guide the next response? %s',
|
|
524
|
+
context:
|
|
525
|
+
).full?(&:to_s)
|
|
502
526
|
if subcommand
|
|
503
527
|
prompt = edit_text(prompt)
|
|
504
528
|
next prompt
|
|
@@ -580,13 +604,17 @@ module OllamaChat::Commands
|
|
|
580
604
|
|
|
581
605
|
command(
|
|
582
606
|
name: :collection,
|
|
583
|
-
regexp: %r(^/collection(?:\s+(change|clear|list|rename|update))?$),
|
|
584
|
-
complete: [ 'collection', %w[ change clear list rename update ] ],
|
|
607
|
+
regexp: %r(^/collection(?:\s+(change|clear|list|rename|update(?: all)?|new|edit|delete))?$),
|
|
608
|
+
complete: [ 'collection', %w[ change clear list rename update update\ all new edit delete ] ],
|
|
585
609
|
optional: true,
|
|
586
610
|
help: <<~EOT
|
|
587
611
|
📚 Manage RAG collections:
|
|
588
612
|
- change/clear/list/rename
|
|
589
613
|
- update: Re-index modified docs
|
|
614
|
+
- update all: Re-index all collections
|
|
615
|
+
- new: Interactively create a new collection
|
|
616
|
+
- edit: Interactively update an existing collection
|
|
617
|
+
- delete: Permanently remove a collection
|
|
590
618
|
- (no subcommand): Show stats
|
|
591
619
|
EOT
|
|
592
620
|
) do |subcommand|
|
|
@@ -599,11 +627,25 @@ module OllamaChat::Commands
|
|
|
599
627
|
list_collections
|
|
600
628
|
when 'rename'
|
|
601
629
|
rename_collection(collection)
|
|
630
|
+
when 'update all'
|
|
631
|
+
results = ''
|
|
632
|
+
all_collections.pluck(:name).each do |collection|
|
|
633
|
+
STDOUT.puts "📝 Updating collection #{collection.inspect}… "
|
|
634
|
+
results << update_collection(collection) << ?\n
|
|
635
|
+
STDOUT.puts "✅ Done."
|
|
636
|
+
end
|
|
637
|
+
results.full? and next results
|
|
602
638
|
when 'update'
|
|
603
|
-
if results = update_collection
|
|
639
|
+
if results = update_collection(collection)
|
|
604
640
|
disable_content_parsing
|
|
605
641
|
next results
|
|
606
642
|
end
|
|
643
|
+
when 'new'
|
|
644
|
+
create_collection
|
|
645
|
+
when 'edit'
|
|
646
|
+
edit_collection
|
|
647
|
+
when 'delete'
|
|
648
|
+
delete_collection
|
|
607
649
|
when nil
|
|
608
650
|
collection_stats
|
|
609
651
|
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Sequel.migration do
|
|
2
|
+
change do
|
|
3
|
+
create_table :collections do
|
|
4
|
+
primary_key :id
|
|
5
|
+
String :name, null: false, unique: true
|
|
6
|
+
Text :description, null: false
|
|
7
|
+
Text :patterns # JSON-encoded array of globs
|
|
8
|
+
DateTime :created_at, default: Sequel::CURRENT_TIMESTAMP, null: false
|
|
9
|
+
DateTime :updated_at, default: Sequel::CURRENT_TIMESTAMP, null: false
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Represents a document collection stored in the database, allowing for
|
|
2
|
+
# dynamic management of documentrix collections.
|
|
3
|
+
#
|
|
4
|
+
# This model stores collections with a name, description, and patterns
|
|
5
|
+
# for automatic file discovery and synchronization.
|
|
6
|
+
class OllamaChat::Database::Models::Collection < Sequel::Model(OllamaChat::DB)
|
|
7
|
+
include OllamaChat::Database::Duplicatable
|
|
8
|
+
|
|
9
|
+
plugin :timestamps, update_on_create: true
|
|
10
|
+
plugin :serialization, :json, :patterns
|
|
11
|
+
plugin :validation_helpers
|
|
12
|
+
|
|
13
|
+
# Validates the collection.
|
|
14
|
+
#
|
|
15
|
+
# Ensures that the `name` is present and unique.
|
|
16
|
+
def validate
|
|
17
|
+
super
|
|
18
|
+
validates_presence :name
|
|
19
|
+
validates_unique :name
|
|
20
|
+
validates_presence :description
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Sets the chat instance associated with this collection.
|
|
24
|
+
#
|
|
25
|
+
# This allows the collection to interact with the chat's document
|
|
26
|
+
# store during lifecycle events, such as cleanup upon destruction.
|
|
27
|
+
#
|
|
28
|
+
# @param chat [OllamaChat::Chat] the chat instance
|
|
29
|
+
attr_writer :chat
|
|
30
|
+
|
|
31
|
+
# Hook to clean up the corresponding Documentrix collection when
|
|
32
|
+
# the database record is destroyed.
|
|
33
|
+
#
|
|
34
|
+
# This ensures that we don't leave orphaned vector data in the
|
|
35
|
+
# Documentrix engine when the underlying collection record is removed.
|
|
36
|
+
def after_destroy
|
|
37
|
+
super
|
|
38
|
+
@chat or return
|
|
39
|
+
@chat.switch_collection(name) do
|
|
40
|
+
@chat.documents.clear
|
|
41
|
+
end
|
|
42
|
+
true
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Synchronizes the database records with the Documentrix collections.
|
|
46
|
+
#
|
|
47
|
+
# This method iterates through the configured collections in the chat's
|
|
48
|
+
# document store and ensures that every collection has a corresponding
|
|
49
|
+
# record in the database. If a collection exists in Documentrix but not
|
|
50
|
+
# in the database, a new record is created with a default description.
|
|
51
|
+
#
|
|
52
|
+
# @param chat [OllamaChat::Chat] the chat instance providing the configuration
|
|
53
|
+
def self.sync(chat)
|
|
54
|
+
chat.documents.collections.each do |name|
|
|
55
|
+
where(name: name.to_s).first and next
|
|
56
|
+
create(
|
|
57
|
+
name: name.to_s,
|
|
58
|
+
description: "TODO: Describe collection #{name}",
|
|
59
|
+
patterns: []
|
|
60
|
+
)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @!attribute [v] id
|
|
65
|
+
# @return [Integer] The primary key for the collection entry.
|
|
66
|
+
#
|
|
67
|
+
# @!attribute [v] name
|
|
68
|
+
# @return [String] The name of the collection (matches documentrix name).
|
|
69
|
+
#
|
|
70
|
+
# @!attribute [v] description
|
|
71
|
+
# @return [String, nil] A description of the collection.
|
|
72
|
+
#
|
|
73
|
+
# @!attribute [v] patterns
|
|
74
|
+
# @return [Array, nil] An array of glob patterns for file discovery.
|
|
75
|
+
#
|
|
76
|
+
# @!attribute [v] created_at
|
|
77
|
+
# @return [Time, nil] The timestamp when the collection was created.
|
|
78
|
+
#
|
|
79
|
+
# @!attribute [v] updated_at
|
|
80
|
+
# @return [Time, nil] The timestamp of the last update to the collection.
|
|
81
|
+
end
|
|
@@ -52,7 +52,7 @@ class OllamaChat::Database::Models::Prompt < Sequel::Model(OllamaChat::DB)
|
|
|
52
52
|
# database when the underlying prompt is removed.
|
|
53
53
|
def after_destroy
|
|
54
54
|
super
|
|
55
|
-
|
|
55
|
+
models::Favourite.where(context:, name:).destroy
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
# Seeds the prompt table from the provided chat configuration.
|
|
@@ -137,6 +137,12 @@ class OllamaChat::Database::Models::Session < Sequel::Model(OllamaChat::DB)
|
|
|
137
137
|
# @!attribute [v] messages
|
|
138
138
|
# @return [String] The full conversation history, stored in JSONL format.
|
|
139
139
|
#
|
|
140
|
+
# @!attribute [v] links
|
|
141
|
+
# @return [String] A text field storing links associated with the session.
|
|
142
|
+
#
|
|
143
|
+
# @!attribute [v] history
|
|
144
|
+
# @return [String] A text field storing the history for the session.
|
|
145
|
+
#
|
|
140
146
|
# @!attribute [v] created_at
|
|
141
147
|
# @return [Time, nil] The timestamp when the session was created.
|
|
142
148
|
#
|
|
@@ -72,6 +72,7 @@ module OllamaChat::Information
|
|
|
72
72
|
#
|
|
73
73
|
# @param output [IO] the output stream to write the message to
|
|
74
74
|
def collection_stats(output: STDOUT)
|
|
75
|
+
col = database_collection?(collection)
|
|
75
76
|
length = (Tins::Terminal.cols - 10).clamp(0..)
|
|
76
77
|
wrapped_tags = Kramdown::ANSI::Width.
|
|
77
78
|
wrap(@documents.tags.to_a.join(', '), length:).
|
|
@@ -79,6 +80,7 @@ module OllamaChat::Information
|
|
|
79
80
|
output.puts <<~EOT
|
|
80
81
|
Current Collection
|
|
81
82
|
Name: #{bold{collection}}
|
|
83
|
+
Patterns: #{italic{col&.patterns&.join(' ')}}
|
|
82
84
|
#Embeddings: #{@documents.size}
|
|
83
85
|
#Tags: #{@documents.tags.size}
|
|
84
86
|
Tags:
|
|
@@ -235,11 +237,6 @@ module OllamaChat::Information
|
|
|
235
237
|
-n create a new session
|
|
236
238
|
-u URL the ollama base url, OLLAMA_URL
|
|
237
239
|
-m MODEL the ollama chat model, OLLAMA_CHAT_MODEL, ?selector
|
|
238
|
-
-c CHAT a saved chat conversation to load
|
|
239
|
-
-C COLLECTION name of the collection used in this conversation
|
|
240
|
-
-D DOCUMENT load document and add to embeddings collection (multiple)
|
|
241
|
-
-M use (empty) MemoryCache for this chat session
|
|
242
|
-
-E disable embeddings for this chat session
|
|
243
240
|
-S open a socket to receive input from ollama_chat_send
|
|
244
241
|
-V display the current version number and quit
|
|
245
242
|
-h this help
|
|
@@ -297,6 +294,21 @@ module OllamaChat::Information
|
|
|
297
294
|
config.infobar.message.to_h
|
|
298
295
|
end
|
|
299
296
|
|
|
297
|
+
# Retrieves a hash of collection names and their descriptions from the
|
|
298
|
+
# database.
|
|
299
|
+
#
|
|
300
|
+
# This is used to provide context to the AI model about available RAG
|
|
301
|
+
# collections.
|
|
302
|
+
#
|
|
303
|
+
# @return [Hash{String => String}] a hash mapping collection names to their
|
|
304
|
+
# descriptions
|
|
305
|
+
def collection_descriptions
|
|
306
|
+
cols = models::Collection.select(:name, :description).order(:name)
|
|
307
|
+
cols.each_with_object({}) do |c, hash|
|
|
308
|
+
hash[c.name] = c.description
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
300
312
|
# Generates a hash containing static runtime information.
|
|
301
313
|
#
|
|
302
314
|
# This method collects session-level constants including the user,
|
|
@@ -307,7 +319,7 @@ module OllamaChat::Information
|
|
|
307
319
|
def static_runtime_information_values
|
|
308
320
|
{
|
|
309
321
|
client: ,
|
|
310
|
-
collections: JSON.pretty_generate(
|
|
322
|
+
collections: JSON.pretty_generate(collection_descriptions),
|
|
311
323
|
current_directory: Pathname.pwd.expand_path.to_path,
|
|
312
324
|
languages: config.languages * ', ',
|
|
313
325
|
location: location.on?.full? { location_description } || 'n/a',
|
|
@@ -172,6 +172,37 @@ module OllamaChat::ModelHandling
|
|
|
172
172
|
STDOUT.puts "Model options #{italic{profile}} of #{bold{model_name}} were copied to session model options."
|
|
173
173
|
end
|
|
174
174
|
|
|
175
|
+
# Interactively copies model options from a source model/profile to the
|
|
176
|
+
# current model/profile. Displays a side-by-side comparison if the
|
|
177
|
+
# destination profile already exists and prompts for override confirmation.
|
|
178
|
+
#
|
|
179
|
+
# @param model [String] the destination model for the copied options
|
|
180
|
+
def copy_model_options_profile(model)
|
|
181
|
+
src_model = choose_model('', model)
|
|
182
|
+
src_profile = choose_profile_for_model(src_model) || 'default'
|
|
183
|
+
dst_model = model
|
|
184
|
+
dst_profile = choose_profile_for_model(dst_model, allow_new: true) || src_profile
|
|
185
|
+
|
|
186
|
+
src_opts = get_stored_model_options(src_model, profile: src_profile).full? or return
|
|
187
|
+
|
|
188
|
+
dst_opts = get_stored_model_options(dst_model, profile: dst_profile)
|
|
189
|
+
if dst_opts.present?
|
|
190
|
+
STDOUT.puts "Profile #{italic{dst_profile}} already exists for #{bold{dst_model}}."
|
|
191
|
+
STDOUT.puts "\n📥 Source (#{src_model}/#{src_profile}):"
|
|
192
|
+
STDOUT.puts JSON.pretty_generate(src_opts)
|
|
193
|
+
STDOUT.puts "\n📤 Destination (#{dst_model}/#{dst_profile}):"
|
|
194
|
+
STDOUT.puts JSON.pretty_generate(dst_opts)
|
|
195
|
+
|
|
196
|
+
unless confirm?(prompt: "⚠️ Override existing profile? (y/n) ", yes: /\Ay/i)
|
|
197
|
+
STDOUT.puts "Cancelled."
|
|
198
|
+
return
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
store_model_options(dst_model, src_opts, profile: dst_profile)
|
|
203
|
+
STDOUT.puts "✅ Copied options from #{italic{src_model}}/#{italic{src_profile}} to #{bold{dst_model}}/#{italic{dst_profile}}."
|
|
204
|
+
end
|
|
205
|
+
|
|
175
206
|
# Presents an interactive list of stored configuration profiles for the
|
|
176
207
|
# specified model and prompts the user to select one.
|
|
177
208
|
#
|
|
@@ -181,14 +212,27 @@ module OllamaChat::ModelHandling
|
|
|
181
212
|
#
|
|
182
213
|
# @param model_name [String] the name of the model whose profiles are to be listed
|
|
183
214
|
# @return [String, nil] the selected profile name, or `nil` if none was chosen
|
|
184
|
-
def choose_profile_for_model(model_name)
|
|
215
|
+
def choose_profile_for_model(model_name, allow_new: false)
|
|
185
216
|
profiles = models::ModelOptions.where(model_name:).order(:profile).map(&:profile)
|
|
186
|
-
|
|
187
|
-
|
|
217
|
+
|
|
218
|
+
if allow_new
|
|
219
|
+
profiles = [ '[EXIT]', '[NEW]' ] + profiles
|
|
220
|
+
else
|
|
221
|
+
profiles.size < 2 and return profiles.first
|
|
222
|
+
profiles = [ '[EXIT]' ] + profiles
|
|
223
|
+
end
|
|
224
|
+
|
|
188
225
|
case chosen = choose_entry(profiles, prompt: "Choose profile for #{bold{model_name}}: %s")
|
|
189
226
|
when '[EXIT]', nil
|
|
190
227
|
STDOUT.puts "Cancelled."
|
|
191
228
|
return
|
|
229
|
+
when '[NEW]'
|
|
230
|
+
name = ask?(prompt: 'Enter new profile name: ') or return
|
|
231
|
+
if models::ModelOptions.where(model_name:, profile: name).present?
|
|
232
|
+
STDERR.puts "Profile #{name.inspect} already exists!"
|
|
233
|
+
return
|
|
234
|
+
end
|
|
235
|
+
name
|
|
192
236
|
else
|
|
193
237
|
chosen
|
|
194
238
|
end
|
|
@@ -307,16 +351,32 @@ module OllamaChat::ModelHandling
|
|
|
307
351
|
session.update(model_options: default_model_options)
|
|
308
352
|
end
|
|
309
353
|
elsif !keep_options && session_model_options != stored_model_options
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
354
|
+
all_profiles = models::ModelOptions.where(model_name: @model).
|
|
355
|
+
order(:profile).all
|
|
356
|
+
|
|
357
|
+
matching = all_profiles.any? do |mo|
|
|
358
|
+
mo.options.ask_and_send(:symbolize_keys_recursive) == session_model_options
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
unless matching
|
|
362
|
+
use_pager do |output|
|
|
363
|
+
output.puts "⚠️ Session model options differ from current profile (#{italic{profile}}) and don't match any saved profile!"
|
|
364
|
+
output.puts "\n📋 Available profiles for #{bold{@model}}:"
|
|
365
|
+
all_profiles.each do |mo|
|
|
366
|
+
output.puts "\n📄 #{italic{mo.profile}}:"
|
|
367
|
+
output.puts JSON.pretty_generate(mo.options.ask_and_send(:symbolize_keys_recursive))
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
if confirm?(prompt: "\n❓ Switch to an existing profile? (y/n) ", yes: /\Ay/i)
|
|
372
|
+
chosen = choose_profile_for_model(@model)
|
|
373
|
+
if chosen
|
|
374
|
+
new_opts = get_stored_model_options(@model, profile: chosen)
|
|
375
|
+
session.update(model_options: new_opts)
|
|
376
|
+
STDOUT.puts "Switched to profile #{italic{chosen}}."
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
end
|
|
320
380
|
end
|
|
321
381
|
end
|
|
322
382
|
|
|
@@ -57,7 +57,7 @@ prompts:
|
|
|
57
57
|
- Current directory is "%{current_directory}"
|
|
58
58
|
- Client is %{client}.
|
|
59
59
|
- These tools have access to these allowed paths: %{tool_paths_allowed}
|
|
60
|
-
- Search in these collections with `
|
|
60
|
+
- Search in these collections with `search_knowledge`: %{collections}
|
|
61
61
|
dynamic_runtime_info: |
|
|
62
62
|
There is usually no reason to mention this information to the user unless
|
|
63
63
|
asked about it.
|
|
@@ -525,7 +525,7 @@ tools:
|
|
|
525
525
|
default: true
|
|
526
526
|
allowed:
|
|
527
527
|
- './tmp'
|
|
528
|
-
|
|
528
|
+
search_knowledge:
|
|
529
529
|
result_display_timeout: 3
|
|
530
530
|
default: true
|
|
531
531
|
compute_bmi:
|
|
@@ -21,6 +21,27 @@ module OllamaChat::PromptManagement
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
# The choose_prompt_context method presents a menu of available prompt
|
|
25
|
+
# contexts for selection. It allows the user to choose between 'prompt',
|
|
26
|
+
# 'system', and 'suggest' contexts.
|
|
27
|
+
#
|
|
28
|
+
# @return [String, nil] the selected context name, or nil if the user
|
|
29
|
+
# cancels the selection.
|
|
30
|
+
def choose_prompt_context
|
|
31
|
+
contexts = models::Prompt.group(:context).order(:context).pluck(:context)
|
|
32
|
+
contexts.unshift('[EXIT]')
|
|
33
|
+
case chosen = choose_entry(
|
|
34
|
+
contexts,
|
|
35
|
+
prompt: '📝 Which prompt context shall we work in? %s'
|
|
36
|
+
)
|
|
37
|
+
when '[EXIT]', nil
|
|
38
|
+
STDOUT.puts "Exiting chooser."
|
|
39
|
+
return
|
|
40
|
+
else
|
|
41
|
+
chosen
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
24
45
|
# The choose_prompt method presents a menu of available prompts for
|
|
25
46
|
# selection. It retrieves the list of prompt names from the database, adds an
|
|
26
47
|
# '[EXIT]' option, and displays them via the Chooser utility.
|