Class: OllamaChat::MessageList
- Inherits:
-
Object
- Object
- OllamaChat::MessageList
- Includes:
- MessageFormat, Pager, Utils::ValueFormatter, Term::ANSIColor
- Defined in:
- lib/ollama_chat/message_list.rb
Overview
A collection class for managing chat messages with support for system prompts, paged output, and conversation history.
This class provides functionality for storing, retrieving, and displaying chat messages in a structured manner. It handles system prompts separately from regular user and assistant messages, supports pagination for displaying conversations, and offers methods for manipulating message history including clearing, loading, saving, and dropping exchanges. The class integrates with Kramdown::ANSI for formatted output.
Instance Attribute Summary collapse
-
#messages ⇒ Object
readonly
The messages attribute reader returns the messages set for this object, initializing it lazily if needed.
-
#system ⇒ Object
readonly
The system attribute reader returns the system prompt for the chat session.
-
#system_name ⇒ Object
readonly
The system_name attribute reader returns the name of the current system prompt.
Instance Method Summary collapse
-
#<<(message) ⇒ OllamaChat::MessageList
The << operator appends a message to the list of messages and returns self.
-
#clean_messages(messages: @messages) ⇒ Array<OllamaChat::Message>
Returns a new list of messages with the content replaced by their stripped versions.
-
#clean_messages!(messages: @messages) ⇒ OllamaChat::MessageList
Cleans the messages in the list by replacing them with stripped versions.
-
#clear(all: false) ⇒ OllamaChat::MessageList
The clear method removes all non-system messages from the message list.
-
#clear_images ⇒ OllamaChat::MessageList
Removes all images from all messages in the current list.
-
#drop(n) ⇒ Integer
Removes the last
nconversation exchanges from the message list. -
#each_group {|Array<OllamaChat::Message>| ... } ⇒ Enumerator
Groups user/assistant messages by their group_uuid, allowing for easy manipulation of whole exchanges (User -> Runtime Info -> Assistant -> Tools).
-
#each_message(role: %w[ user assistant ],, tool: false) {|message| ... } ⇒ Enumerator?
Iterates over messages in the conversation, yielding those matching the specified roles.
-
#find_last(content: false) {|Message| ... } ⇒ OllamaChat::Message?
Find the last message that satisfies the supplied block.
-
#initialize(chat) ⇒ MessageList
constructor
The initialize method sets up the message list for an OllamaChat session.
-
#last ⇒ OllamaChat::Message
Returns the last message from the conversation.
-
#list_conversation(last = nil, think_loud: @chat.think_loud.on?) ⇒ OllamaChat::MessageList
Displays the most recent messages from the conversation history.
-
#load_conversation(filename) ⇒ OllamaChat::MessageList
The load_conversation method loads a conversation from a file and populates the message list.
-
#read_conversation_jsonl(input) ⇒ OllamaChat::MessageList
Loads conversation messages from a JSONL (JSON Lines) input stream.
-
#save_conversation(filename, messages: @messages) ⇒ OllamaChat::MessageList
The save_conversation method saves the current conversation to a file.
-
#set_system_prompt(system_name) ⇒ OllamaChat::MessageList
Sets the system prompt for the chat session.
-
#show_last(n = nil, pager: true, think_loud: @chat.think_loud.on?) ⇒ OllamaChat::MessageList?
Displays the most recent messages that were not authored by the user.
-
#show_system_prompt ⇒ self, NilClass
The show_system_prompt method displays the system prompt configured for the chat session.
-
#size ⇒ Integer
Returns the number of messages stored in the message list.
-
#to_ary ⇒ Array
The to_ary method converts the message list into an array of OllamaChat::Message objects.
-
#write_conversation_jsonl(output, messages: @messages) ⇒ OllamaChat::MessageList
Writes each message in the conversation to the output as a JSON line.
Methods included from Utils::ValueFormatter
Methods included from Pager
Methods included from MessageFormat
#chat, #display_sender, #message_type, #role_color, #role_template, #sender_name_displayed, #talk_annotate, #think_annotate
Constructor Details
#initialize(chat) ⇒ MessageList
The initialize method sets up the message list for an OllamaChat session.
40 41 42 43 |
# File 'lib/ollama_chat/message_list.rb', line 40 def initialize(chat) @chat = chat @messages = [] end |
Instance Attribute Details
#messages ⇒ Object (readonly)
The messages attribute reader returns the messages set for this object, initializing it lazily if needed.
The messages set is memoized, meaning it will only be created once per object instance and subsequent calls will return the same OllamaChat::MessageList instance.
64 65 66 |
# File 'lib/ollama_chat/message_list.rb', line 64 def @messages end |
#system ⇒ Object (readonly)
The system attribute reader returns the system prompt for the chat session.
48 49 50 |
# File 'lib/ollama_chat/message_list.rb', line 48 def system @system end |
#system_name ⇒ Object (readonly)
The system_name attribute reader returns the name of the current system prompt.
53 54 55 |
# File 'lib/ollama_chat/message_list.rb', line 53 def system_name @system_name end |
Instance Method Details
#<<(message) ⇒ OllamaChat::MessageList
The << operator appends a message to the list of messages and returns self.
90 91 92 93 |
# File 'lib/ollama_chat/message_list.rb', line 90 def <<() @messages << sync end |
#clean_messages(messages: @messages) ⇒ Array<OllamaChat::Message>
Returns a new list of messages with the content replaced by their stripped versions. This is used to create a "clean" version of the conversation for saving or displaying without mutating the original message objects.
198 199 200 201 202 203 204 205 |
# File 'lib/ollama_chat/message_list.rb', line 198 def (messages: @messages) .map do || = .dup .content = '' if .tool? .images = nil end end |
#clean_messages!(messages: @messages) ⇒ OllamaChat::MessageList
Cleans the messages in the list by replacing them with stripped versions. This is a destructive (mutating) operation.
213 214 215 216 |
# File 'lib/ollama_chat/message_list.rb', line 213 def (messages: @messages) @messages = (messages:) self end |
#clear(all: false) ⇒ OllamaChat::MessageList
The clear method removes all non-system messages from the message list.
76 77 78 79 80 81 82 83 |
# File 'lib/ollama_chat/message_list.rb', line 76 def clear(all: false) if all @messages.clear else @messages.delete_if { _1.role != 'system' } end sync end |
#clear_images ⇒ OllamaChat::MessageList
Removes all images from all messages in the current list.
475 476 477 478 479 480 |
# File 'lib/ollama_chat/message_list.rb', line 475 def clear_images @messages.each do || .images = nil end sync end |
#drop(n) ⇒ Integer
This method automatically synchronizes the message list with the session store.
Removes the last n conversation exchanges from the message list.
An exchange is typically defined as a pair of user and assistant messages. This method iterates backwards through the history and removes messages until the requested number of exchanges have been dropped. It will stop if it encounters a system message.
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/ollama_chat/message_list.rb', line 331 def drop(n) n = n.to_i.clamp(1, Float::INFINITY) i = 0 m = 0 current_group = nil @messages.reverse_each do || .role == 'system' and next if current_group.nil? current_group = .group_uuid i += 1 elsif .group_uuid == current_group i += 1 else current_group = .group_uuid m += 1 if m < n i += 1 else break end end end i > 0 && m == 0 and m = 1 i.times do @messages.last.role == 'system' and next @messages.pop end STDOUT.puts "Dropped the last #{m} exchanges." m ensure sync end |
#each_group {|Array<OllamaChat::Message>| ... } ⇒ Enumerator
Groups user/assistant messages by their group_uuid, allowing for easy manipulation of whole exchanges (User -> Runtime Info -> Assistant -> Tools).
313 314 315 316 |
# File 'lib/ollama_chat/message_list.rb', line 313 def each_group(&block) block or return enum_for(__method__) .group_by(&:group_uuid).values.each(&block) end |
#each_message(role: %w[ user assistant ],, tool: false) {|message| ... } ⇒ Enumerator?
Iterates over messages in the conversation, yielding those matching the specified roles.
148 149 150 151 152 153 154 155 156 157 |
# File 'lib/ollama_chat/message_list.rb', line 148 def (role: %w[ user assistant ], tool: false, &block) block or return enum_for(__method__, role:, tool:) @messages.each do || role.include?(.role) or next !tool && .tool? and next yield end nil end |
#find_last(content: false) {|Message| ... } ⇒ OllamaChat::Message?
The method iterates in reverse order (reverse_each) so that the
most recent matching message is returned. It also respects the
content flag to skip empty messages, which is handy when the
chat history contains empty messages e. g. when tool calling.
Find the last message that satisfies the supplied block.
129 130 131 132 133 134 |
# File 'lib/ollama_chat/message_list.rb', line 129 def find_last(content: false, &block) @messages.reverse_each.find { |m| content and !m.content.present? and next block.(m) } end |
#last ⇒ OllamaChat::Message
Returns the last message from the conversation.
99 100 101 |
# File 'lib/ollama_chat/message_list.rb', line 99 def last @messages.last end |
#list_conversation(last = nil, think_loud: @chat.think_loud.on?) ⇒ OllamaChat::MessageList
Displays the most recent messages from the conversation history.
This method prints a specified number of trailing messages to the console using the pager for better readability. Tool messages are automatically excluded from the output. If no count is provided, the entire conversation is displayed.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/ollama_chat/message_list.rb', line 231 def list_conversation(last = nil, think_loud: @chat.think_loud.on?) = @messages.reject(&:tool?) last = (last || .size).clamp(0, .size) = [-last..-1].to_ary use_pager do |output| = (messages:) = .( output: STDERR, label: 'Message', total: .size, message: @chat., ) .each do || output.puts (, think_loud:) + end end self end |
#load_conversation(filename) ⇒ OllamaChat::MessageList
The load_conversation method loads a conversation from a file and populates the message list.
165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/ollama_chat/message_list.rb', line 165 def load_conversation(filename) filename = Pathname.new(filename). unless filename.exist? STDERR.puts "File #{filename.to_s.inspect} doesn't exist. Choose another filename." return end @messages = OllamaChat::Utils::JSONJSONLIO.new(filename).read( jsonl_transform: method(:parse_message_from_json), json_transform: method(:construct_message_from_hash) ).to_a sync end |
#read_conversation_jsonl(input) ⇒ OllamaChat::MessageList
Loads conversation messages from a JSONL (JSON Lines) input stream. Each line in the input is expected to be a valid JSON representation of a message. The method parses each line and adds the resulting message to the current conversation.
464 465 466 467 468 469 470 |
# File 'lib/ollama_chat/message_list.rb', line 464 def read_conversation_jsonl(input) @messages = OllamaChat::Utils::JSONJSONLIO.new('as.jsonl').read_io( input:, jsonl_transform: method(:parse_message_from_json) ).to_a self end |
#save_conversation(filename, messages: @messages) ⇒ OllamaChat::MessageList
The save_conversation method saves the current conversation to a file.
185 186 187 188 |
# File 'lib/ollama_chat/message_list.rb', line 185 def save_conversation(filename, messages: @messages) OllamaChat::Utils::JSONJSONLIO.new(filename).write(collection: ) self end |
#set_system_prompt(system_name) ⇒ OllamaChat::MessageList
This method:
- Removes all existing system prompts from the message list
- Adds the new system prompt to the beginning of the message list if provided
- Handles edge cases such as clearing prompts when
systemisnilorfalse
Sets the system prompt for the chat session.
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
# File 'lib/ollama_chat/message_list.rb', line 378 def set_system_prompt(system_name) @system_name = system_name if system_name == 'model_default' system = @chat.model_default_system_prompt.to_s else system = @chat.prompt(system_name, context: 'system').to_s end @messages.reject! { |msg| msg.role == 'system' } templates_values = { persona: @chat.default_persona_profile, runtime_info: (@chat.static_runtime_information if @chat.runtime_info.on?), } if new_system_prompt = system.full? { _1.to_s % templates_values } @system = new_system_prompt @messages.unshift( OllamaChat::Message.new(role: 'system', content: self.system).initialize_group_uuid ) else @system = nil end sync end |
#show_last(n = nil, pager: true, think_loud: @chat.think_loud.on?) ⇒ OllamaChat::MessageList?
Displays the most recent messages that were not authored by the user.
This is particularly useful for quickly reviewing the assistant's last responses without having to scroll through the user's own input. Output is routed through the pager.
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/ollama_chat/message_list.rb', line 265 def show_last(n = nil, pager: true, think_loud: @chat.think_loud.on?) n ||= 1 = @messages.reject { || .role == 'user' } n = n.clamp(0...size) n <= 0 and return = (last.content if last&.role == 'user') outputter = -> output do = [-n..-1].to_a = .( output: STDERR, label: 'Message', total: .size, message: @chat., ) .each do || output.puts (, think_loud:) + end ensure if = Kramdown::ANSI::Width.truncate( .inspect, length: Tins::Terminal.columns * 0.9 ) msg = <<~EOT ⚠️ Last message is actually a #{bold{'user message'}}, see: #{} You might want to /drop it or /regenerate it. EOT output.puts msg end end if pager use_pager(&outputter) else outputter.(STDOUT) end self end |
#show_system_prompt ⇒ self, NilClass
The show_system_prompt method displays the system prompt configured for the chat session.
It retrieves the system prompt from the @system instance variable, parses it using Kramdown::ANSI, and removes any trailing newlines. If the resulting string is empty, the method returns immediately.
Otherwise, it prints a formatted message to the console, including the configured system prompt and its length in characters.
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 |
# File 'lib/ollama_chat/message_list.rb', line 412 def show_system_prompt current_system = system.to_s size_bytes = current_system.size es = OllamaChat::TokenEstimator.estimate(size_bytes) system_prompt = @chat.kramdown_ansi_parse(current_system). gsub(/\n+\z/, '').full? if system_prompt.blank? if current_system.present? system_prompt = current_system else return end end use_pager do |output| output.puts <<~EOT Configured system prompt is: #{system_prompt} System prompt name: #{bold{system_name}} System prompt length: 👾#{es.bytes_formatted} 🧩#{es.tokens_formatted} EOT end self end |
#size ⇒ Integer
Returns the number of messages stored in the message list.
69 70 71 |
# File 'lib/ollama_chat/message_list.rb', line 69 def size @messages.size end |
#to_ary ⇒ Array
The to_ary method converts the message list into an array of OllamaChat::Message objects.
442 443 444 |
# File 'lib/ollama_chat/message_list.rb', line 442 def to_ary @messages.dup end |
#write_conversation_jsonl(output, messages: @messages) ⇒ OllamaChat::MessageList
Writes each message in the conversation to the output as a JSON line.
452 453 454 455 |
# File 'lib/ollama_chat/message_list.rb', line 452 def write_conversation_jsonl(output, messages: @messages) OllamaChat::Utils::JSONJSONLIO.new('as.jsonl').write_io(output:, collection: ) self end |