Class: OllamaChat::Chat

Overview

A chat client for interacting with Ollama models through a terminal interface.

The Chat class provides a complete command-line interface for chatting with language models via the Ollama API. It handles configuration management, message history, document processing, web searching, and various interactive features including voice output, markdown rendering, and embedding capabilities.

Examples:

Initializing a chat session

chat = OllamaChat::Chat.new(argv: ['-m', 'llama3.1'])

Starting an interactive chat

chat.start

Constant Summary

Constants included from Parsing

Parsing::CONTENT_REGEXP

Instance Attribute Summary collapse

Attributes included from ToolCalling

#enabled_tools, #tool_call_results

Attributes included from ServerSocket

#server_socket_message

Attributes included from Switches

#embedding, #embedding_enabled, #embedding_paused, #location, #markdown, #runtime_info, #stream, #think_loud, #tools_support, #voice

Instance Method Summary collapse

Methods included from PersonaeManagement

#add_persona, #available_personae, #choose_persona, #default_persona_name, #delete_persona, #edit_persona, #info_persona, #list_personae, #load_persona_file, #load_personae, #persona_backup_pathname, #personae_backup_directory, #personae_directory, #personae_result, #play_persona, #play_persona_file, #play_persona_prompt, #reload_default_persona, #setup_persona_from_opts, #setup_personae_directory

Methods included from ConfigHandling

#config=, #display_config, #edit_config, #fix_config, #reload_config

Methods included from ToolCalling

#configured_tools, #default_enabled_tools, #disable_tool, #enable_tool, #handle_tool_call_results?, #list_tools, #tool_configured?, #tool_enabled?, #tool_function, #tool_paths_allowed, #tool_registered?, #tools

Methods included from LocationHandling

#location_data, #location_description, #location_description?

Methods included from MessageEditing

#change_response

Methods included from InputContent

#all_file_set, #choose_filename, #context_spook, #file_set_each, #input, #provide_file_set_content

Methods included from Conversation

#load_conversation, #save_conversation

Methods included from FileEditing

#edit_file, #edit_text, #perform_insert, #vim

Methods included from KramdownANSI

#configure_kramdown_ansi_styles, #kramdown_ansi_parse

Methods included from ServerSocket

create_socket_server, #init_server_socket, send_to_server_socket

Methods included from History

#clear_history, #init_chat_history, #save_history

Methods included from Pager

#determine_pager_command, #use_pager

Methods included from MessageFormat

#message_type, #talk_annotate, #think_annotate

Methods included from Clipboard

#copy_to_clipboard, #last_message_content, #paste_from_clipboard, #perform_copy_to_clipboard, #perform_paste_from_clipboard

Methods included from MessageOutput

#attempt_to_write_file, #output, #pipe

Methods included from Information

#client, #collection_stats, #display_chat_help, #info, #runtime_information, #runtime_information_values, #server_url, #server_version, #usage, #version

Methods included from ThinkControl

#think, #think?, #think_loud?

Methods included from Dialog

#ask?, #change_system_prompt, #change_voice, #choose_collection, #choose_file_set, #choose_prompt, #confirm?, #connect_message, #go_command, #message_list

Methods included from WebSearching

#search_engine, #search_web, #search_web_with_duckduckgo, #search_web_with_searxng

Methods included from SourceFetching

#add_image, #embed, #embed_source, #fetch_source, #fetch_source_as_filename, #import, #import_source, #links, #summarize, #summarize_source

Methods included from Parsing

#parse_atom, #parse_content, #parse_csv, #parse_rss, #parse_source, #pdf_read, #ps_read, #reverse_markdown

Methods included from Utils::AnalyzeDirectory

#generate_structure, #recurse_generate_structure, #structure_each_entry

Methods included from ModelHandling

#choose_model, #model_present?, #model_with_size, #pull_model_from_remote, #pull_model_unless_present, #use_model

Methods included from StateSelectors

#setup_state_selectors

Methods included from Switches

#setup_switches

Methods included from DocumentCache

#configure_cache, #document_cache_class

Methods included from Logging

#log, #logger

Methods included from HTTPHandling

#get_url, #http_options

Constructor Details

#initialize(argv: ARGV.dup) ⇒ Chat

Initializes a new OllamaChat::Chat instance with the given command-line arguments.

Sets up the chat environment including configuration parsing, Ollama client initialization, model selection, system prompt handling, document processing setup, and history management. This method handles all the bootstrapping necessary to create a functional chat session that can communicate with an Ollama server and process various input types including text, documents, web content, and images.

The initialization process includes parsing command-line options using Tins::GO for robust argument handling, setting up the Ollama client with configurable timeouts (connect, read, write), validating Ollama API version compatibility (requires >= 0.9.0 for features used), configuring model selection based on command-line or configuration defaults, initializing system prompts from files or inline content, setting up document processing pipeline with embedding capabilities through Documentrix::Documents, creating message history management through OllamaChat::MessageList, initializing cache systems for document embeddings, setting up voice support and image handling for multimodal interactions, enabling optional server socket functionality for remote input, and handling configuration errors with interactive recovery mechanisms.

Parameters:

  • argv (Array<String>) (defaults to: ARGV.dup)

    Command-line arguments to parse (defaults to ARGV.dup)

Raises:

  • (RuntimeError)

    If the Ollama API version is less than 0.9.0, indicating incompatibility with required API features



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/ollama_chat/chat.rb', line 92

def initialize(argv: ARGV.dup)
  @opts               = go 'f:u:m:s:p:c:C:D:MESVh', argv
  @opts[?h] and exit usage
  @opts[?V] and exit version
  @messages           = OllamaChat::MessageList.new(self)
  @ollama_chat_config = OllamaChat::OllamaChatConfig.new(@opts[?f])
  self.config         = @ollama_chat_config.config
  setup_switches(config)
  setup_state_selectors(config)
  connect_ollama
  if conversation_file = @opts[?c]
    messages.load_conversation(conversation_file)
  elsif backup_file = OC::XDG_CACHE_HOME + 'backup.json' and backup_file.exist?
    messages.load_conversation(backup_file)
    FileUtils.rm_f backup_file
  else
    @setup_system_prompt = true
  end
  embedding_enabled.set(config.embedding.enabled && !@opts[?E])
  @documents            = setup_documents
  @cache                = setup_cache
  @images               = []
  @kramdown_ansi_styles = configure_kramdown_ansi_styles
  @enabled_tools        = default_enabled_tools
  @tool_call_results    = {}
  init_chat_history
  setup_personae_directory
  @opts[?S] and init_server_socket
rescue ComplexConfig::AttributeMissing, ComplexConfig::ConfigurationSyntaxError => e
  fix_config(e)
end

Instance Attribute Details

#cacheObject (readonly)

Provides read-only access to the cache instance used by the object



164
165
166
# File 'lib/ollama_chat/chat.rb', line 164

def cache
  @cache
end

#document_policyOllamaChat::StateSelector (readonly)

The document_policy reader returns the document policy selector for the chat session.

Returns:

  • (OllamaChat::StateSelector)

    the document policy selector object that manages the policy for handling document references in user text



128
129
130
# File 'lib/ollama_chat/chat.rb', line 128

def document_policy
  @document_policy
end

#documentsDocumentrix::Documents (readonly)

Returns the documents set for this object, initializing it lazily if needed.

The documents set is memoized, meaning it will only be created once per object instance and subsequent calls will return the same Documentrix::Documents instance.

Returns:

  • (Documentrix::Documents)

    A Documentrix::Documents object containing all documents associated with this instance



149
150
151
# File 'lib/ollama_chat/chat.rb', line 149

def documents
  @documents
end

#messagesOllamaChat::MessageList (readonly)

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.

Returns:



159
160
161
# File 'lib/ollama_chat/chat.rb', line 159

def messages
  @messages
end

#ollamaOllama::Client (readonly)

The ollama reader returns the Ollama API client instance.

Returns:

  • (Ollama::Client)

    the configured Ollama API client



139
140
141
# File 'lib/ollama_chat/chat.rb', line 139

def ollama
  @ollama
end

#think_modeOllamaChat::StateSelector (readonly)

The think_mode reader returns the think mode selector for the chat session.

Returns:

  • (OllamaChat::StateSelector)

    the think mode selector object that manages the thinking mode setting for the Ollama model interactions



134
135
136
# File 'lib/ollama_chat/chat.rb', line 134

def think_mode
  @think_mode
end

Instance Method Details

#add_documents_from_argv(document_list) ⇒ Object (private)

Note:

Empty entries in the document list will trigger a collection clear operation

Note:

Documents are processed in batches of 25 to manage memory usage

Note:

Progress is reported to STDOUT during processing

Adds documents from command line arguments to the document collection

Processes a list of document paths or URLs, handling both local files and remote resources.

Examples:

Adding local files

add_documents_from_argv(['/path/to/file1.txt', '/path/to/file2.pdf'])

Adding remote URLs

add_documents_from_argv(['https://example.com/page1', 'http://example.com/page2'])

Mixed local and remote

add_documents_from_argv(['/local/file.txt', 'https://remote.com/document'])

Parameters:

  • document_list (Array<String>)

    List of document paths or URLs to process



1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
# File 'lib/ollama_chat/chat.rb', line 1201

def add_documents_from_argv(document_list)
  if document_list.any?(&:empty?)
    STDOUT.puts "Clearing collection #{bold{documents.collection}}."
    documents.clear
    document_list.reject!(&:empty?)
  end
  unless document_list.empty?
    document_list.map! do |doc|
      if doc =~ %r(\Ahttps?://)
        doc
      else
        File.expand_path(doc)
      end
    end
    STDOUT.puts "Collection #{bold{documents.collection}}: Adding #{document_list.size} documents…"
    count = 1
    document_list.each_slice(25) do |docs|
      docs.each do |doc|
        fetch_source(doc) do |doc_io|
          embed_source(doc_io, doc, count:)
        end
        count += 1
      end
    end
  end
end

#base_urlString (private)

The base_url method returns the Ollama server URL from command-line options or environment configuration.

Returns:

  • (String)

    the base URL used for connecting to the Ollama API



1100
1101
1102
# File 'lib/ollama_chat/chat.rb', line 1100

def base_url
  @opts[?u] || OC::OLLAMA::URL
end

#clean(what) ⇒ Object (private)

The clean method clears various parts of the chat session based on the specified parameter.

Parameters:

  • what (String, nil)

    the type of data to clear, defaults to ‘messages’ if nil



902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
# File 'lib/ollama_chat/chat.rb', line 902

def clean(what)
  persona_profile = nil
  case what
  when 'messages', nil
    messages.clear
    persona_profile = reload_default_persona
    STDOUT.puts "Cleared messages."
  when 'links'
    links.clear
    STDOUT.puts "Cleared links."
  when 'history'
    clear_history
    STDOUT.puts "Cleared history."
  when 'tags'
    @documents.clear
    STDOUT.puts "Cleared all tags."
  when 'all'
    if confirm?(prompt: '🔔 Are you sure to clear messages and collection? (y/n) ') =~ /y/i
      messages.clear
      @documents.clear
      links.clear
      clear_history
      persona_profile = reload_default_persona
      STDOUT.puts "Cleared messages and collection #{bold{@documents.collection}}."
    else
      STDOUT.puts 'Cancelled.'
    end
  end
  persona_profile
end

#collectionObject (private)

Collection



479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
# File 'lib/ollama_chat/chat.rb', line 479

command(
  name: :collection,
  regexp: %r(^/collection(?:\s+(clear|change))?$),
  complete: [ 'collection', %w[ clear change ] ],
  help: 'change (default) collection or clear'
) do |subcommand|
  case subcommand || 'change'
  when 'clear'
    loop do
      tags = @documents.tags.add('[EXIT]').add('[ALL]')
      tag = OllamaChat::Utils::Chooser.choose(tags, prompt: 'Clear? %s')
      case tag
      when nil, '[EXIT]'
        STDOUT.puts "Exiting chooser."
        break
      when '[ALL]'
        if confirm?(prompt: '🔔 Are you sure? (y/n) ') =~ /y/i
          @documents.clear
          STDOUT.puts "Cleared collection #{bold{@documents.collection}}."
          break
        else
          STDOUT.puts 'Cancelled.'
          sleep 3
        end
      when /./
        @documents.clear(tags: [ tag ])
        STDOUT.puts "Cleared tag #{tag} from collection #{bold{@documents.collection}}."
        sleep 3
      end
    end
  when 'change'
    choose_collection(@documents.collection)
  end
  :next
end

#composeObject (private)

Input



581
582
583
584
585
586
587
# File 'lib/ollama_chat/chat.rb', line 581

command(
  name: :compose,
  regexp: %r(^/compose$),
  help: 'compose content using an EDITOR'
) do
  compose or :next
end

#configObject (private)

Settings



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/ollama_chat/chat.rb', line 239

command(
  name: :config,
  regexp: %r(^/config(?:\s+(edit|reload))?$),
  complete: [ 'config', %w[ edit reload ] ],
  optional: true,
  help: 'output/edit/reload configuration'
) do |subcommand|
  case subcommand
  when 'edit'
    edit_config
  when 'reload'
    reload_config
  else
    display_config
  end
  :next
end

#connect_ollamaOllama::Client (private)

The connect_ollama method establishes a connection to the Ollama API server.

This method initializes a new Ollama::Client instance with configured timeouts and connection parameters, then verifies that the connected server meets the minimum required API version (0.9.0). It sets the @ollama instance variable to the configured client and stores the server version in @server_version.

Returns:

  • (Ollama::Client)

    the configured Ollama client instance

Raises:

  • (RuntimeError)

    if the connected Ollama server API version is less than 0.9.0



1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
# File 'lib/ollama_chat/chat.rb', line 1114

def connect_ollama
  @server_version = nil
  @ollama = Ollama::Client.new(
    connect_timeout: config.timeouts.connect_timeout?,
    read_timeout:    config.timeouts.read_timeout?,
    write_timeout:   config.timeouts.write_timeout?,
    base_url:        base_url,
    debug:           ,
    user_agent:
  )
  if server_version.version < '0.9.0'.version
    raise 'require ollama API version 0.9.0 or higher'
  end
  log(:info, "Connection to #{base_url} established.")
  @ollama
end

#copyObject (private)

Clipboard



219
220
221
222
223
224
225
226
# File 'lib/ollama_chat/chat.rb', line 219

command(
  name: :copy,
  regexp: %r(/copy$),
  help: 'to copy last response to clipboard'
) do
  copy_to_clipboard
  :next
end

#debugTrueClass, FalseClass

The debug method accesses the debug configuration setting.

Returns:

  • (TrueClass, FalseClass)

    the current debug mode status



186
187
188
# File 'lib/ollama_chat/chat.rb', line 186

def debug
  OC::OLLAMA::CHAT::DEBUG
end

#disable_content_parsingObject (private)

The disable_content_parsing method turns off content parsing by setting ‘@parse_content` to false.

This prevents automatic parsing of user input content during chat processing.



211
212
213
# File 'lib/ollama_chat/chat.rb', line 211

def disable_content_parsing
  @parse_content = false
end

#enable_command_completion(&block) ⇒ Object (private)

Enables tab completion for chat commands within the interactive session

Temporarily replaces the current Reline completion procedure with a custom one that provides command completion based on the chat help message.

Parameters:

  • block (Proc)

    The block to execute with enhanced tab completion enabled

Returns:

  • (Object)

    The return value of the executed block



1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
# File 'lib/ollama_chat/chat.rb', line 1253

def enable_command_completion(&block)
  old = Reline.completion_proc
  Reline.autocompletion = true
  Reline.completion_proc = -> input, pre {
    before = [ pre, input ].join
    case before
    when %r(^/)
      start = [ pre, input ].join(' ').strip.gsub(/\s+/, ' ')
      command_completions.select { _1.start_with?(start) }
    when %r((./\S*))
      OllamaChat::Utils::PathCompleter.new(pre, input).complete
    end
  }
  block.()
ensure
  Reline.completion_proc = old
end

#handle_input(content) ⇒ Symbol, ... (private)

Handles user input commands and processes chat interactions.

Parameters:

  • content (String)

    The input content to process

Returns:

  • (Symbol, String, nil)

    Returns a symbol indicating next action, the content to be processed, or nil for no action needed



785
786
787
788
789
790
791
# File 'lib/ollama_chat/chat.rb', line 785

def handle_input(content)
  commands.each do |_name, command|
    action = command.execute_if_match?(content) {}
    action and return action
  end
  content
end

#interact_with_userObject (private)

The interact_with_user method manages the interactive loop for user input and chat processing. It handles reading user input, processing commands, managing messages, and communicating with the Ollama server. The method supports command completion, prefilling prompts, socket input handling, and various chat features including embedding context and voice support. It processes user input through command handling, content parsing, and message formatting before sending requests to the Ollama server. The method also handles server socket messages, manages chat history, and ensures proper cleanup and configuration handling throughout the interaction.



945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
# File 'lib/ollama_chat/chat.rb', line 945

def interact_with_user
  loop do
    if persona_result = setup_persona_from_opts
      disable_content_parsing
      content = persona_result
    else
      @parse_content = true
      type           = :terminal_input
      input_prompt   = bold { color(172) { message_type(@images) + " user" } } + bold { "> " }
      begin
        if content = handle_tool_call_results?
          disable_content_parsing
        else
          content = enable_command_completion do
            if prefill_prompt = @prefill_prompt.full?
              Reline.pre_input_hook = -> {
                Reline.insert_text prefill_prompt.gsub(/\n*\z/, '')
                @prefill_prompt = nil
              }
            else
              Reline.pre_input_hook = nil
            end
            Reline.readline(input_prompt, true)&.chomp
          end
        end
      rescue Interrupt
        if message = server_socket_message
          type           = message.type.full?(:to_sym) || :socket_input
          content        = message.content
          @parse_content = message.parse
          STDOUT.puts color(112) { "Received a server socket message. Processing now…" }
        else
          raise
        end
      end

      if type == :terminal_input
        case next_action = handle_input(content)
        when :next
          next
        when :redo
          redo
        when :return
          return
        when String
          content = next_action
        end
      end
    end

    content = content.encode(invalid: :replace)

    content, tags = if @parse_content
                      parse_content(content, @images)
                    else
                      [ content, Documentrix::Utils::Tags.new(valid_tag: /\A#*([\w\]\[]+)/) ]
                    end

    if embedding.on? && content
      records = @documents.find_where(
        content.downcase.first(config.embedding.model.context_length),
        tags:,
        prompt:     config.embedding.model.prompt?,
        text_size:  config.embedding.found_texts_size?,
        text_count: config.embedding.found_texts_count?,
      )
      unless records.empty?
        content << ?\n << JSON(
          prompt: "Consider these snippets generated from retrieval when formulating your response!",
          ollama_chat_retrieval_snippets: records.map { |r|
            {
              text: r.text,
              tags: r.tags_set.map { |t| { name: t.to_s(link: false), source: t.source }.compact }
            }
          },
        )
      end
    end

    runtime_info.on? && content and
      content << ?\n << {
        ollama_chat_runtime_information: runtime_information
      }.to_json

    messages << Ollama::Message.new(role: 'user', content:, images: @images.dup)
    @images.clear
    handler = OllamaChat::FollowChat.new(
      chat:     self,
      messages:,
      voice:    (@voices.selected if voice.on?)
    )
    begin
      retried = false
      ollama.chat(
        model:    @model,
        messages: ,
        options:  @model_options,
        stream:   stream.on?,
        think:    ,
        tools:    ,
        &handler
      )
    rescue Ollama::Errors::BadRequestError
      if (think? || tools_support.on?) && !retried
        STDOUT.puts "#{bold('Error')}: in think mode/with tool support, switch both off and retry."
        sleep 1
        think_mode.selected  = 'disabled'
        tools_support.set false
        retried = true
        retry
      else
        raise
      end
    end
    if embedding.on? && !records.empty?
      STDOUT.puts "", records.map { |record|
        link = if record.source =~ %r(\Ahttps?://)
                 record.source
               else
                 'file://%s' % File.expand_path(record.source)
               end
        [ link, ?# + record.tags.first ]
      }.uniq.map { |l, t| hyperlink(l, t) }.join(' ')
      debug and jj messages.to_ary
    end

    case type
    when :socket_input
      server_socket_message&.disconnect
    when :socket_input_with_response
      if message = handler.messages.last
        server_socket_message.respond({ role: message.role, content: message.content })
      end
      server_socket_message&.disconnect
    end
  rescue Ollama::Errors::TimeoutError
    msg = "Currently lost connection to ollama server and cannot send command."
    log(:warn, msg, warn: true)
  rescue Interrupt
    STDOUT.puts "Type /quit to quit."
  ensure
      self.server_socket_message = nil
  end
  0
rescue ComplexConfig::AttributeMissing, ComplexConfig::ConfigurationSyntaxError => e
  log(:error, e)
  fix_config(e)
ensure
  save_history
end

#listObject (private)

Conversation



361
362
363
364
365
366
367
368
369
370
# File 'lib/ollama_chat/chat.rb', line 361

command(
  name: :list,
  regexp: %r(^/list(?:\s+(\d*))?$),
  options: '[n=1]',
  help: 'list the last n / all conversation exchanges'
) do
  n = 2 * _1.to_i if _1
  messages.list_conversation(n)
  :next
end

The manage_links method handles operations on a collection of links, such as displaying them or clearing specific entries.

It supports two main commands: ‘clear’ and nil (default). When the command is ‘clear’, it presents an interactive menu to either clear all links or individual links. When the command is nil, it displays the current list of links with hyperlinks.

Parameters:

  • command (String, nil)

    the operation to perform on the links



860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
# File 'lib/ollama_chat/chat.rb', line 860

def manage_links(command)
  case command
  when 'clear'
    loop do
      links_options = links.dup.add('[EXIT]').add('[ALL]')
      link = OllamaChat::Utils::Chooser.choose(links_options, prompt: 'Clear? %s')
      case link
      when nil, '[EXIT]'
        STDOUT.puts "Exiting chooser."
        break
      when '[ALL]'
        if confirm?(prompt: '🔔 Are you sure? (y/n) ') =~ /y/i
          links.clear
          STDOUT.puts "Cleared all links in list."
          break
        else
          STDOUT.puts 'Cancelled.'
          sleep 3
        end
      when /./
        links.delete(link)
        STDOUT.puts "Cleared link from links in list."
        sleep 3
      end
    end
  when nil
    if links.empty?
      STDOUT.puts "List is empty."
    else
      w       = Math.log10(links.size + 1).ceil
      format  = "%#{w}s. %s"
      connect = -> link { hyperlink(link) { link } }
      STDOUT.puts links.each_with_index.map { |x, i| format % [ i + 1, connect.(x) ] }
    end
  end
end

#reconnectObject (private)

Actions



719
720
721
722
723
724
725
726
727
728
# File 'lib/ollama_chat/chat.rb', line 719

command(
  name: :reconnect,
  regexp: %r(^/reconnect$),
  help: 'reconnect to current ollama server'
) do
  STDERR.print green { "Reconnecting to ollama #{base_url.to_s.inspect}" }
  connect_ollama
  STDERR.puts green { " Done." }
  :next
end

#setup_cacheOllamaChat::RedisCache? (private)

The setup_cache method initializes and returns a Redis cache instance with expiring keys if a Redis URL is configured.

Returns:



1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
# File 'lib/ollama_chat/chat.rb', line 1233

def setup_cache
  if url = config.redis.expiring.url?
    ex = config.redis.expiring.ex?.to_i
    OllamaChat::RedisCache.new(
      prefix: 'Expiring-',
      url:,
      ex:
    )
  end
end

#setup_documentsDocumentrix::Documents, NULL (private)

The setup_documents method initializes the document processing pipeline by configuring the embedding model and database connection. It then loads specified documents into the system and returns the configured document collection.

Returns:

  • (Documentrix::Documents, NULL)

    the initialized document collection if embedding is enabled, otherwise NULL



1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
# File 'lib/ollama_chat/chat.rb', line 1156

def setup_documents
  if embedding.on?
    @embedding_model         = config.embedding.model.name
    @embedding_model_options = Ollama::Options[config.embedding.model.options]
    pull_model_unless_present(@embedding_model)
    collection = @opts[?C] || config.embedding.collection
    @documents = Documentrix::Documents.new(
      ollama:,
      model:             @embedding_model,
      model_options:     config.embedding.model.options,
      embedding_length:  config.embedding.model.embedding_length,
      database_filename: config.embedding.database_filename || @ollama_chat_config.database_path,
      collection:        ,
      cache:             configure_cache,
      redis_url:         config.redis.documents.url?,
      debug:
    )

    document_list = @opts[?D].to_a
    add_documents_from_argv(document_list)
    @documents
  else
    NULL
  end
end

#setup_system_promptObject (private)

Sets up the system prompt for the chat session.

This method determines whether to use a default system prompt or a custom one specified via command-line options. If a custom system prompt is provided with a regexp selector (starting with ?), it invokes the change_system_prompt method to handle the selection. Otherwise, it retrieves the system prompt from a file or uses the default value, then sets it in the message history.



1139
1140
1141
1142
1143
1144
1145
1146
1147
# File 'lib/ollama_chat/chat.rb', line 1139

def setup_system_prompt
  default = config.system_prompts.default? || @model_metadata.system
  if @opts[?s] =~ /\A\?/
    change_system_prompt(default, system: @opts[?s])
  else
    system = OllamaChat::Utils::FileArgument.get_file_argument(@opts[?s], default:)
    system.present? and messages.set_system_prompt(system)
  end
end

#startObject

The start method initializes the chat session by displaying information, then prompts the user for input to begin interacting with the chat.



168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/ollama_chat/chat.rb', line 168

def start
  begin
    use_model(@opts[?m].full? || config.model.name)
  rescue OllamaChat::UnknownModelError => e
    abort "Failed to use to model: #{e}"
  end
  @model_options  = Ollama::Options[config.model.options]

  @setup_system_prompt and setup_system_prompt

  STDOUT.puts "\nType /help to display the chat help."

  interact_with_user
end

#strip_internal_json_markers(name, content) ⇒ String (private)

Removes lines that are JSON objects containing the given key.

Parameters:

  • name (String, Symbol)

    key to look for in each line

  • content (String)

    multiline text that may contain internal JSON markers

Returns:

  • (String)

    text with matching marker lines removed



197
198
199
200
201
202
203
204
# File 'lib/ollama_chat/chat.rb', line 197

def strip_internal_json_markers(name, content)
  name = name.to_s
  content.each_line.map do |line|
    JSON(line).fetch(name) and next
  rescue
    line
  end.compact.join
end

#web(count, query) ⇒ String, Symbol (private)

Performs a web search and processes the results based on document processing configuration.

Searches for the given query using the configured search engine and processes up to the specified number of URLs. The processing approach varies based on the current document policy and embedding status:

  • **Embedding mode**: When ‘document_policy.selected == ’embedding’‘ AND `@embedding.on?` is true, each result is embedded and the query is interpolated into the web_embed prompt.

  • **Summarizing mode**: When ‘document_policy.selected == ’summarizing’‘, each result is summarized and both query and results are interpolated into the web_summarize prompt.

  • **Importing mode**: For all other cases, each result is imported and both query and results are interpolated into the web_import prompt.

Examples:

Basic web search

web('3', 'ruby programming tutorials')

Web search with embedding policy

# With document_policy.selected == 'embedding' and @embedding.on?
# Processes results through embedding pipeline

Web search with summarizing policy

# With document_policy.selected == 'summarizing'
# Processes results through summarization pipeline

Parameters:

  • count (String)

    The maximum number of search results to process (defaults to 1)

  • query (String)

    The search query string

Returns:

  • (String, Symbol)

    The interpolated prompt content when successful, or :next if no URLs were found or processing failed



823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
# File 'lib/ollama_chat/chat.rb', line 823

def web(count, query)
  urls = search_web(query, count.to_i) or return :next
  if document_policy.selected == 'embedding' && @embedding.on?
    prompt = config.prompts.web_embed
    urls.each do |url|
      fetch_source(url) { |url_io| embed_source(url_io, url) }
    end
    prompt.named_placeholders_interpolate({query:})
  elsif document_policy.selected == 'summarizing'
    prompt = config.prompts.web_import
    results = urls.each_with_object('') do |url, content|
      summarize(url).full? do |c|
        content << c.ask_and_send_or_self(:read)
      end
    end
    prompt.named_placeholders_interpolate({query:, results:})
  else
    prompt = config.prompts.web_summarize
    results = urls.each_with_object('') do |url, content|
      import(url).full? do |c|
        content << c.ask_and_send_or_self(:read)
      end
    end
    prompt.named_placeholders_interpolate({query:, results:})
  end
end