ollama-ruby 0.11.0 → 0.12.0
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 +39 -1
- data/README.md +3 -2
- data/Rakefile +3 -1
- data/bin/ollama_chat +74 -29
- data/lib/ollama/client.rb +5 -5
- data/lib/ollama/documents/cache/common.rb +5 -1
- data/lib/ollama/documents/cache/memory_cache.rb +1 -1
- data/lib/ollama/documents/cache/records.rb +87 -0
- data/lib/ollama/documents/cache/redis_backed_memory_cache.rb +2 -1
- data/lib/ollama/documents/cache/redis_cache.rb +3 -10
- data/lib/ollama/documents/cache/sqlite_cache.rb +215 -0
- data/lib/ollama/documents/splitters/semantic.rb +1 -0
- data/lib/ollama/documents.rb +35 -62
- data/lib/ollama/utils/chooser.rb +15 -1
- data/lib/ollama/utils/tags.rb +2 -1
- data/lib/ollama/version.rb +1 -1
- data/ollama-ruby.gemspec +9 -7
- data/spec/ollama/documents/{memory_cache_spec.rb → cache/memory_cache_spec.rb} +37 -3
- data/spec/ollama/documents/{redis_backed_memory_cache_spec.rb → cache/redis_backed_memory_cache_spec.rb} +19 -7
- data/spec/ollama/documents/{redis_cache_spec.rb → cache/redis_cache_spec.rb} +34 -19
- data/spec/ollama/documents/cache/sqlite_cache_spec.rb +141 -0
- data/spec/ollama/utils/tags_spec.rb +7 -2
- metadata +50 -10
| @@ -0,0 +1,215 @@ | |
| 1 | 
            +
            require 'ollama/documents/cache/common'
         | 
| 2 | 
            +
            require 'sqlite3'
         | 
| 3 | 
            +
            require 'sqlite_vec'
         | 
| 4 | 
            +
            require 'digest/md5'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            class Ollama::Documents::Cache::SQLiteCache
         | 
| 7 | 
            +
              include Ollama::Documents::Cache::Common
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def initialize(prefix:, embedding_length: 1_024, filename: ':memory:', debug: false)
         | 
| 10 | 
            +
                super(prefix:)
         | 
| 11 | 
            +
                @embedding_length = embedding_length
         | 
| 12 | 
            +
                @filename         = filename
         | 
| 13 | 
            +
                @debug            = debug
         | 
| 14 | 
            +
                setup_database(filename)
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              attr_reader :filename # filename for the database, `:memory:` is in memory
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              attr_reader :embedding_length # length of the embeddings vector
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              def [](key)
         | 
| 22 | 
            +
                result = execute(
         | 
| 23 | 
            +
                  %{
         | 
| 24 | 
            +
                    SELECT records.key, records.text, records.norm, records.source,
         | 
| 25 | 
            +
                      records.tags, embeddings.embedding
         | 
| 26 | 
            +
                    FROM records
         | 
| 27 | 
            +
                    INNER JOIN embeddings ON records.embedding_id = embeddings.rowid
         | 
| 28 | 
            +
                    WHERE records.key = ?
         | 
| 29 | 
            +
                  },
         | 
| 30 | 
            +
                  pre(key)
         | 
| 31 | 
            +
                )&.first or return
         | 
| 32 | 
            +
                key, text, norm, source, tags, embedding = *result
         | 
| 33 | 
            +
                embedding = embedding.unpack("f*")
         | 
| 34 | 
            +
                tags      = Ollama::Utils::Tags.new(JSON(tags.to_s).to_a, source:)
         | 
| 35 | 
            +
                convert_value_to_record(key:, text:, norm:, source:, tags:, embedding:)
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def []=(key, value)
         | 
| 39 | 
            +
                value = convert_value_to_record(value)
         | 
| 40 | 
            +
                embedding = value.embedding.pack("f*")
         | 
| 41 | 
            +
                execute(%{BEGIN})
         | 
| 42 | 
            +
                execute(%{INSERT INTO embeddings(embedding) VALUES(?)}, [ embedding ])
         | 
| 43 | 
            +
                embedding_id, = execute(%{ SELECT last_insert_rowid() }).flatten
         | 
| 44 | 
            +
                execute(%{
         | 
| 45 | 
            +
                  INSERT INTO records(key,text,embedding_id,norm,source,tags)
         | 
| 46 | 
            +
                  VALUES(?,?,?,?,?,?)
         | 
| 47 | 
            +
                }, [ pre(key), value.text, embedding_id, value.norm, value.source, JSON(value.tags) ])
         | 
| 48 | 
            +
                execute(%{COMMIT})
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              def key?(key)
         | 
| 52 | 
            +
                execute(
         | 
| 53 | 
            +
                  %{ SELECT count(records.key) FROM records WHERE records.key = ? },
         | 
| 54 | 
            +
                  pre(key)
         | 
| 55 | 
            +
                ).flatten.first == 1
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              def delete(key)
         | 
| 59 | 
            +
                result = key?(key) ? pre(key) : nil
         | 
| 60 | 
            +
                execute(
         | 
| 61 | 
            +
                  %{ DELETE FROM records WHERE records.key = ? },
         | 
| 62 | 
            +
                  pre(key)
         | 
| 63 | 
            +
                )
         | 
| 64 | 
            +
                result
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              def tags
         | 
| 68 | 
            +
                result = Ollama::Utils::Tags.new
         | 
| 69 | 
            +
                execute(%{
         | 
| 70 | 
            +
                    SELECT DISTINCT(tags) FROM records WHERE key LIKE ?
         | 
| 71 | 
            +
                  }, [ "#@prefix%" ]
         | 
| 72 | 
            +
                ).flatten.each do
         | 
| 73 | 
            +
                  JSON(_1).each { |t| result.add(t) }
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
                result
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
              def size
         | 
| 79 | 
            +
                execute(%{SELECT COUNT(*) FROM records WHERE key LIKE ?}, [ "#@prefix%" ]).flatten.first
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
              def clear_for_tags(tags = nil)
         | 
| 83 | 
            +
                tags = Ollama::Utils::Tags.new(tags).to_a
         | 
| 84 | 
            +
                if tags.present?
         | 
| 85 | 
            +
                  records = find_records_for_tags(tags)
         | 
| 86 | 
            +
                  keys = '(%s)' % records.transpose.first.map { "'%s'" % quote(_1) }.join(?,)
         | 
| 87 | 
            +
                  execute(%{DELETE FROM records WHERE key IN #{keys}})
         | 
| 88 | 
            +
                else
         | 
| 89 | 
            +
                  clear
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
                self
         | 
| 92 | 
            +
              end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
              def clear
         | 
| 95 | 
            +
                execute(%{DELETE FROM records WHERE key LIKE ?}, [ "#@prefix%" ])
         | 
| 96 | 
            +
                self
         | 
| 97 | 
            +
              end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
              def each(prefix: "#@prefix%", &block)
         | 
| 100 | 
            +
                execute(%{
         | 
| 101 | 
            +
                  SELECT records.key, records.text, records.norm, records.source,
         | 
| 102 | 
            +
                    records.tags, embeddings.embedding
         | 
| 103 | 
            +
                  FROM records
         | 
| 104 | 
            +
                  INNER JOIN embeddings ON records.embedding_id = embeddings.rowid
         | 
| 105 | 
            +
                  WHERE records.key LIKE ?
         | 
| 106 | 
            +
                }, [ prefix ]).each do |key, text, norm, source, tags, embedding|
         | 
| 107 | 
            +
                  embedding = embedding.unpack("f*")
         | 
| 108 | 
            +
                  tags      = Ollama::Utils::Tags.new(JSON(tags.to_s).to_a, source:)
         | 
| 109 | 
            +
                  value     = convert_value_to_record(key:, text:, norm:, source:, tags:, embedding:)
         | 
| 110 | 
            +
                  block.(key, value)
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
              end
         | 
| 113 | 
            +
              include Enumerable
         | 
| 114 | 
            +
             | 
| 115 | 
            +
              def full_each(&block)
         | 
| 116 | 
            +
                each(prefix: ?%, &block)
         | 
| 117 | 
            +
              end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
              def convert_to_vector(vector)
         | 
| 120 | 
            +
                vector
         | 
| 121 | 
            +
              end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
              def find_records_for_tags(tags)
         | 
| 124 | 
            +
                if tags.present?
         | 
| 125 | 
            +
                  tags_filter = Ollama::Utils::Tags.new(tags).to_a
         | 
| 126 | 
            +
                  unless  tags_filter.empty?
         | 
| 127 | 
            +
                    tags_where  = ' AND (%s)' % tags_filter.map {
         | 
| 128 | 
            +
                      'tags LIKE "%%%s%%"' % quote(_1)
         | 
| 129 | 
            +
                    }.join(' OR ')
         | 
| 130 | 
            +
                  end
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
                records = execute(%{
         | 
| 133 | 
            +
                  SELECT key, tags, embedding_id
         | 
| 134 | 
            +
                  FROM records
         | 
| 135 | 
            +
                  WHERE key LIKE ?#{tags_where}
         | 
| 136 | 
            +
                }, [ "#@prefix%" ])
         | 
| 137 | 
            +
                if tags_filter
         | 
| 138 | 
            +
                  records = records.select { |key, tags, embedding_id|
         | 
| 139 | 
            +
                    (tags_filter & JSON(tags.to_s).to_a).size >= 1
         | 
| 140 | 
            +
                  }
         | 
| 141 | 
            +
                end
         | 
| 142 | 
            +
                records
         | 
| 143 | 
            +
              end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
              def find_records(needle, tags: nil, max_records: nil)
         | 
| 146 | 
            +
                needle.size != @embedding_length and
         | 
| 147 | 
            +
                  raise ArgumentError, "needle embedding length != %s" % @embedding_length
         | 
| 148 | 
            +
                needle_binary = needle.pack("f*")
         | 
| 149 | 
            +
                max_records   = [ max_records, size, 4_096 ].compact.min
         | 
| 150 | 
            +
                records = find_records_for_tags(tags)
         | 
| 151 | 
            +
                rowids_where = '(%s)' % records.transpose.last&.join(?,)
         | 
| 152 | 
            +
                execute(%{
         | 
| 153 | 
            +
                  SELECT records.key, records.text, records.norm, records.source,
         | 
| 154 | 
            +
                    records.tags, embeddings.embedding
         | 
| 155 | 
            +
                  FROM records
         | 
| 156 | 
            +
                  INNER JOIN embeddings ON records.embedding_id = embeddings.rowid
         | 
| 157 | 
            +
                  WHERE embeddings.rowid IN #{rowids_where}
         | 
| 158 | 
            +
                    AND embeddings.embedding MATCH ? AND embeddings.k = ?
         | 
| 159 | 
            +
                }, [ needle_binary, max_records ]).map do |key, text, norm, source, tags, embedding|
         | 
| 160 | 
            +
                  key       = unpre(key)
         | 
| 161 | 
            +
                  embedding = embedding.unpack("f*")
         | 
| 162 | 
            +
                  tags      = Ollama::Utils::Tags.new(JSON(tags.to_s).to_a, source:)
         | 
| 163 | 
            +
                  convert_value_to_record(key:, text:, norm:, source:, tags:, embedding:)
         | 
| 164 | 
            +
                end
         | 
| 165 | 
            +
              end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
              private
         | 
| 168 | 
            +
             | 
| 169 | 
            +
              def execute(*a)
         | 
| 170 | 
            +
                if @debug
         | 
| 171 | 
            +
                  e = a[0].gsub(/^\s*\n/, '')
         | 
| 172 | 
            +
                  e = e.gsub(/\A\s+/, '')
         | 
| 173 | 
            +
                  n = $&.to_s.size
         | 
| 174 | 
            +
                  e = e.gsub(/^\s{0,#{n}}/, '')
         | 
| 175 | 
            +
                  e = e.chomp
         | 
| 176 | 
            +
                  STDERR.puts("EXPLANATION:\n%s\n%s" % [
         | 
| 177 | 
            +
                    e,
         | 
| 178 | 
            +
                    @database.execute("EXPLAIN #{e}", *a[1..-1]).pretty_inspect
         | 
| 179 | 
            +
                  ])
         | 
| 180 | 
            +
                end
         | 
| 181 | 
            +
                @database.execute(*a)
         | 
| 182 | 
            +
              end
         | 
| 183 | 
            +
             | 
| 184 | 
            +
              def quote(string)
         | 
| 185 | 
            +
                SQLite3::Database.quote(string)
         | 
| 186 | 
            +
              end
         | 
| 187 | 
            +
             | 
| 188 | 
            +
              def setup_database(filename)
         | 
| 189 | 
            +
                @database = SQLite3::Database.new(filename)
         | 
| 190 | 
            +
                @database.enable_load_extension(true)
         | 
| 191 | 
            +
                SqliteVec.load(@database)
         | 
| 192 | 
            +
                @database.enable_load_extension(false)
         | 
| 193 | 
            +
                execute %{
         | 
| 194 | 
            +
                  CREATE VIRTUAL TABLE IF NOT EXISTS embeddings USING vec0(
         | 
| 195 | 
            +
                    embedding float[#@embedding_length]
         | 
| 196 | 
            +
                  )
         | 
| 197 | 
            +
                }
         | 
| 198 | 
            +
                execute %{
         | 
| 199 | 
            +
                  CREATE TABLE IF NOT EXISTS records (
         | 
| 200 | 
            +
                    key          text NOT NULL PRIMARY KEY ON CONFLICT REPLACE,
         | 
| 201 | 
            +
                    text         text NOT NULL DEFAULT '',
         | 
| 202 | 
            +
                    embedding_id integer,
         | 
| 203 | 
            +
                    norm         float NOT NULL DEFAULT 0.0,
         | 
| 204 | 
            +
                    source       text,
         | 
| 205 | 
            +
                    tags         json NOT NULL DEFAULT [],
         | 
| 206 | 
            +
                    FOREIGN KEY(embedding_id) REFERENCES embeddings(id) ON DELETE CASCADE
         | 
| 207 | 
            +
                  )
         | 
| 208 | 
            +
                }
         | 
| 209 | 
            +
              end
         | 
| 210 | 
            +
             | 
| 211 | 
            +
              def convert_value_to_record(value)
         | 
| 212 | 
            +
                value.is_a?(Ollama::Documents::Record) and return value
         | 
| 213 | 
            +
                Ollama::Documents::Record[value.to_hash]
         | 
| 214 | 
            +
              end
         | 
| 215 | 
            +
            end
         | 
    
        data/lib/ollama/documents.rb
    CHANGED
    
    | @@ -4,11 +4,13 @@ require 'kramdown/ansi' | |
| 4 4 |  | 
| 5 5 | 
             
            class Ollama::Documents
         | 
| 6 6 | 
             
            end
         | 
| 7 | 
            -
             | 
| 7 | 
            +
            module Ollama::Documents::Cache
         | 
| 8 8 | 
             
            end
         | 
| 9 | 
            +
            require 'ollama/documents/cache/records'
         | 
| 9 10 | 
             
            require 'ollama/documents/cache/memory_cache'
         | 
| 10 11 | 
             
            require 'ollama/documents/cache/redis_cache'
         | 
| 11 12 | 
             
            require 'ollama/documents/cache/redis_backed_memory_cache'
         | 
| 13 | 
            +
            require 'ollama/documents/cache/sqlite_cache'
         | 
| 12 14 | 
             
            module Ollama::Documents::Splitters
         | 
| 13 15 | 
             
            end
         | 
| 14 16 | 
             
            require 'ollama/documents/splitters/character'
         | 
| @@ -16,32 +18,16 @@ require 'ollama/documents/splitters/semantic' | |
| 16 18 |  | 
| 17 19 | 
             
            class Ollama::Documents
         | 
| 18 20 | 
             
              include Kramdown::ANSI::Width
         | 
| 21 | 
            +
              include Ollama::Documents::Cache
         | 
| 19 22 |  | 
| 20 | 
            -
               | 
| 21 | 
            -
                def to_s
         | 
| 22 | 
            -
                  my_tags = tags_set
         | 
| 23 | 
            -
                  my_tags.empty? or my_tags = " #{my_tags}"
         | 
| 24 | 
            -
                  "#<#{self.class} #{text.inspect}#{my_tags} #{similarity || 'n/a'}>"
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                def tags_set
         | 
| 28 | 
            -
                  Ollama::Utils::Tags.new(tags, source:)
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                def ==(other)
         | 
| 32 | 
            -
                  text == other.text
         | 
| 33 | 
            -
                end
         | 
| 23 | 
            +
              Record = Class.new Ollama::Documents::Cache::Records::Record
         | 
| 34 24 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
              end
         | 
| 37 | 
            -
             | 
| 38 | 
            -
              def initialize(ollama:, model:, model_options: nil, collection: nil, cache: MemoryCache, redis_url: nil, debug: false)
         | 
| 25 | 
            +
              def initialize(ollama:, model:, model_options: nil, collection: nil, embedding_length: 1_024, cache: MemoryCache, database_filename: nil, redis_url: nil, debug: false)
         | 
| 39 26 | 
             
                collection ||= default_collection
         | 
| 40 | 
            -
                @ollama, @model, @model_options, @collection =
         | 
| 41 | 
            -
                  ollama, model, model_options, collection.to_sym
         | 
| 42 | 
            -
                 | 
| 43 | 
            -
                @cache | 
| 44 | 
            -
                @debug     = debug
         | 
| 27 | 
            +
                @ollama, @model, @model_options, @collection, @debug =
         | 
| 28 | 
            +
                  ollama, model, model_options, collection.to_sym, debug
         | 
| 29 | 
            +
                database_filename ||= ':memory:'
         | 
| 30 | 
            +
                @cache = connect_cache(cache, redis_url, embedding_length, database_filename)
         | 
| 45 31 | 
             
              end
         | 
| 46 32 |  | 
| 47 33 | 
             
              def default_collection
         | 
| @@ -110,40 +96,19 @@ class Ollama::Documents | |
| 110 96 | 
             
              end
         | 
| 111 97 |  | 
| 112 98 | 
             
              def clear(tags: nil)
         | 
| 113 | 
            -
                 | 
| 114 | 
            -
                  tags = Ollama::Utils::Tags.new(Array(tags)).to_a
         | 
| 115 | 
            -
                  @cache.each do |key, record|
         | 
| 116 | 
            -
                    if (tags & record.tags).size >= 1
         | 
| 117 | 
            -
                      @cache.delete(@cache.unpre(key))
         | 
| 118 | 
            -
                    end
         | 
| 119 | 
            -
                  end
         | 
| 120 | 
            -
                else
         | 
| 121 | 
            -
                  @cache.clear
         | 
| 122 | 
            -
                end
         | 
| 99 | 
            +
                @cache.clear(tags:)
         | 
| 123 100 | 
             
                self
         | 
| 124 101 | 
             
              end
         | 
| 125 102 |  | 
| 126 | 
            -
              def find(string, tags: nil, prompt: nil)
         | 
| 127 | 
            -
                needle | 
| 128 | 
            -
                 | 
| 129 | 
            -
                records = @cache
         | 
| 130 | 
            -
                if tags
         | 
| 131 | 
            -
                  tags = Ollama::Utils::Tags.new(tags).to_a
         | 
| 132 | 
            -
                  records = records.select { |_key, record| (tags & record.tags).size >= 1 }
         | 
| 133 | 
            -
                end
         | 
| 134 | 
            -
                records = records.sort_by { |key, record|
         | 
| 135 | 
            -
                  record.key        = key
         | 
| 136 | 
            -
                  record.similarity = @cache.cosine_similarity(
         | 
| 137 | 
            -
                    a: needle,
         | 
| 138 | 
            -
                    b: record.embedding,
         | 
| 139 | 
            -
                    a_norm: needle_norm,
         | 
| 140 | 
            -
                    b_norm: record.norm,
         | 
| 141 | 
            -
                  )
         | 
| 142 | 
            -
                }
         | 
| 143 | 
            -
                records.transpose.last&.reverse.to_a
         | 
| 103 | 
            +
              def find(string, tags: nil, prompt: nil, max_records: nil)
         | 
| 104 | 
            +
                needle = convert_to_vector(string, prompt:)
         | 
| 105 | 
            +
                @cache.find_records(needle, tags:, max_records: nil)
         | 
| 144 106 | 
             
              end
         | 
| 145 107 |  | 
| 146 108 | 
             
              def find_where(string, text_size: nil, text_count: nil, **opts)
         | 
| 109 | 
            +
                if text_count
         | 
| 110 | 
            +
                  opts[:max_records] =  text_count
         | 
| 111 | 
            +
                end
         | 
| 147 112 | 
             
                records = find(string, **opts)
         | 
| 148 113 | 
             
                size, count = 0, 0
         | 
| 149 114 | 
             
                records.take_while do |record|
         | 
| @@ -162,30 +127,38 @@ class Ollama::Documents | |
| 162 127 | 
             
              end
         | 
| 163 128 |  | 
| 164 129 | 
             
              def tags
         | 
| 165 | 
            -
                @cache. | 
| 166 | 
            -
                  record.tags.each do |tag|
         | 
| 167 | 
            -
                    t.add(tag, source: record.source)
         | 
| 168 | 
            -
                  end
         | 
| 169 | 
            -
                end
         | 
| 130 | 
            +
                @cache.tags
         | 
| 170 131 | 
             
              end
         | 
| 171 132 |  | 
| 172 133 | 
             
              private
         | 
| 173 134 |  | 
| 174 | 
            -
              def connect_cache(cache_class)
         | 
| 135 | 
            +
              def connect_cache(cache_class, redis_url, embedding_length, database_filename)
         | 
| 175 136 | 
             
                cache = nil
         | 
| 176 | 
            -
                if cache_class.instance_method(:redis)
         | 
| 137 | 
            +
                if (cache_class.instance_method(:redis) rescue nil)
         | 
| 177 138 | 
             
                  begin
         | 
| 178 | 
            -
                    cache = cache_class.new(prefix:, url:  | 
| 139 | 
            +
                    cache = cache_class.new(prefix:, url: redis_url, object_class: Record)
         | 
| 179 140 | 
             
                    cache.size
         | 
| 180 141 | 
             
                  rescue Redis::CannotConnectError
         | 
| 181 142 | 
             
                    STDERR.puts(
         | 
| 182 | 
            -
                      "Cannot connect to redis URL #{ | 
| 143 | 
            +
                      "Cannot connect to redis URL #{redis_url.inspect}, "\
         | 
| 183 144 | 
             
                      "falling back to MemoryCache."
         | 
| 184 145 | 
             
                    )
         | 
| 185 146 | 
             
                  end
         | 
| 147 | 
            +
                elsif cache_class == SQLiteCache
         | 
| 148 | 
            +
                  cache = cache_class.new(
         | 
| 149 | 
            +
                    prefix:,
         | 
| 150 | 
            +
                    embedding_length:,
         | 
| 151 | 
            +
                    filename: database_filename,
         | 
| 152 | 
            +
                    debug: @debug
         | 
| 153 | 
            +
                  )
         | 
| 186 154 | 
             
                end
         | 
| 187 155 | 
             
              ensure
         | 
| 188 | 
            -
                cache ||= MemoryCache.new(prefix | 
| 156 | 
            +
                cache ||= MemoryCache.new(prefix:,)
         | 
| 157 | 
            +
                cache.respond_to?(:find_records) or cache.extend(Records::FindRecords)
         | 
| 158 | 
            +
                cache.extend(Records::Tags)
         | 
| 159 | 
            +
                if cache.respond_to?(:redis)
         | 
| 160 | 
            +
                  cache.extend(Records::RedisFullEach)
         | 
| 161 | 
            +
                end
         | 
| 189 162 | 
             
                return cache
         | 
| 190 163 | 
             
              end
         | 
| 191 164 |  | 
    
        data/lib/ollama/utils/chooser.rb
    CHANGED
    
    | @@ -8,7 +8,21 @@ module Ollama::Utils::Chooser | |
| 8 8 |  | 
| 9 9 | 
             
              module_function
         | 
| 10 10 |  | 
| 11 | 
            -
               | 
| 11 | 
            +
              # The choose method presents a list of entries and prompts the user
         | 
| 12 | 
            +
              # for input, allowing them to select one entry based on their input.
         | 
| 13 | 
            +
              #
         | 
| 14 | 
            +
              # @param entries [Array] the list of entries to present to the user
         | 
| 15 | 
            +
              # @param prompt [String] the prompt message to display when asking for input (default: 'Search? %s')
         | 
| 16 | 
            +
              # @param return_immediately [Boolean] whether to immediately return the first entry if there is only one or nil when there is none (default: false)
         | 
| 17 | 
            +
              #
         | 
| 18 | 
            +
              # @return [Object] the selected entry, or nil if no entry was chosen
         | 
| 19 | 
            +
              #
         | 
| 20 | 
            +
              # @example
         | 
| 21 | 
            +
              #   choose(['entry1', 'entry2'], prompt: 'Choose an option:')
         | 
| 22 | 
            +
              def choose(entries, prompt: 'Search? %s', return_immediately: false)
         | 
| 23 | 
            +
                if return_immediately && entries.size <= 1
         | 
| 24 | 
            +
                  return entries.first
         | 
| 25 | 
            +
                end
         | 
| 12 26 | 
             
                entry = Search.new(
         | 
| 13 27 | 
             
                  prompt:,
         | 
| 14 28 | 
             
                  match: -> answer {
         | 
    
        data/lib/ollama/utils/tags.rb
    CHANGED
    
    | @@ -3,7 +3,7 @@ class Ollama::Utils::Tags | |
| 3 3 | 
             
                include Term::ANSIColor
         | 
| 4 4 |  | 
| 5 5 | 
             
                def initialize(tag, source: nil)
         | 
| 6 | 
            -
                  super(tag.to_s)
         | 
| 6 | 
            +
                  super(tag.to_s.gsub(/\A#+/, ''))
         | 
| 7 7 | 
             
                  self.source = source
         | 
| 8 8 | 
             
                end
         | 
| 9 9 |  | 
| @@ -26,6 +26,7 @@ class Ollama::Utils::Tags | |
| 26 26 | 
             
              end
         | 
| 27 27 |  | 
| 28 28 | 
             
              def initialize(tags = [], source: nil)
         | 
| 29 | 
            +
                tags = Array(tags)
         | 
| 29 30 | 
             
                @set = []
         | 
| 30 31 | 
             
                tags.each { |tag| add(tag, source:) }
         | 
| 31 32 | 
             
              end
         | 
    
        data/lib/ollama/version.rb
    CHANGED
    
    
    
        data/ollama-ruby.gemspec
    CHANGED
    
    | @@ -1,31 +1,31 @@ | |
| 1 1 | 
             
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            -
            # stub: ollama-ruby 0. | 
| 2 | 
            +
            # stub: ollama-ruby 0.12.0 ruby lib
         | 
| 3 3 |  | 
| 4 4 | 
             
            Gem::Specification.new do |s|
         | 
| 5 5 | 
             
              s.name = "ollama-ruby".freeze
         | 
| 6 | 
            -
              s.version = "0. | 
| 6 | 
            +
              s.version = "0.12.0".freeze
         | 
| 7 7 |  | 
| 8 8 | 
             
              s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
         | 
| 9 9 | 
             
              s.require_paths = ["lib".freeze]
         | 
| 10 10 | 
             
              s.authors = ["Florian Frank".freeze]
         | 
| 11 | 
            -
              s.date = "2024-11- | 
| 11 | 
            +
              s.date = "2024-11-26"
         | 
| 12 12 | 
             
              s.description = "Library that allows interacting with the Ollama API".freeze
         | 
| 13 13 | 
             
              s.email = "flori@ping.de".freeze
         | 
| 14 14 | 
             
              s.executables = ["ollama_console".freeze, "ollama_chat".freeze, "ollama_update".freeze, "ollama_cli".freeze]
         | 
| 15 | 
            -
              s.extra_rdoc_files = ["README.md".freeze, "lib/ollama.rb".freeze, "lib/ollama/client.rb".freeze, "lib/ollama/client/command.rb".freeze, "lib/ollama/client/doc.rb".freeze, "lib/ollama/commands/chat.rb".freeze, "lib/ollama/commands/copy.rb".freeze, "lib/ollama/commands/create.rb".freeze, "lib/ollama/commands/delete.rb".freeze, "lib/ollama/commands/embed.rb".freeze, "lib/ollama/commands/embeddings.rb".freeze, "lib/ollama/commands/generate.rb".freeze, "lib/ollama/commands/ps.rb".freeze, "lib/ollama/commands/pull.rb".freeze, "lib/ollama/commands/push.rb".freeze, "lib/ollama/commands/show.rb".freeze, "lib/ollama/commands/tags.rb".freeze, "lib/ollama/documents.rb".freeze, "lib/ollama/documents/cache/common.rb".freeze, "lib/ollama/documents/cache/memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_backed_memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_cache.rb".freeze, "lib/ollama/documents/splitters/character.rb".freeze, "lib/ollama/documents/splitters/semantic.rb".freeze, "lib/ollama/dto.rb".freeze, "lib/ollama/errors.rb".freeze, "lib/ollama/handlers.rb".freeze, "lib/ollama/handlers/collector.rb".freeze, "lib/ollama/handlers/concern.rb".freeze, "lib/ollama/handlers/dump_json.rb".freeze, "lib/ollama/handlers/dump_yaml.rb".freeze, "lib/ollama/handlers/markdown.rb".freeze, "lib/ollama/handlers/nop.rb".freeze, "lib/ollama/handlers/print.rb".freeze, "lib/ollama/handlers/progress.rb".freeze, "lib/ollama/handlers/say.rb".freeze, "lib/ollama/handlers/single.rb".freeze, "lib/ollama/image.rb".freeze, "lib/ollama/message.rb".freeze, "lib/ollama/options.rb".freeze, "lib/ollama/response.rb".freeze, "lib/ollama/tool.rb".freeze, "lib/ollama/tool/function.rb".freeze, "lib/ollama/tool/function/parameters.rb".freeze, "lib/ollama/tool/function/parameters/property.rb".freeze, "lib/ollama/utils/cache_fetcher.rb".freeze, "lib/ollama/utils/chooser.rb".freeze, "lib/ollama/utils/colorize_texts.rb".freeze, "lib/ollama/utils/fetcher.rb".freeze, "lib/ollama/utils/file_argument.rb".freeze, "lib/ollama/utils/math.rb".freeze, "lib/ollama/utils/tags.rb".freeze, "lib/ollama/version.rb".freeze]
         | 
| 16 | 
            -
              s.files = [".envrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_cli".freeze, "bin/ollama_console".freeze, "bin/ollama_update".freeze, "config/redis.conf".freeze, "docker-compose.yml".freeze, "lib/ollama.rb".freeze, "lib/ollama/client.rb".freeze, "lib/ollama/client/command.rb".freeze, "lib/ollama/client/doc.rb".freeze, "lib/ollama/commands/chat.rb".freeze, "lib/ollama/commands/copy.rb".freeze, "lib/ollama/commands/create.rb".freeze, "lib/ollama/commands/delete.rb".freeze, "lib/ollama/commands/embed.rb".freeze, "lib/ollama/commands/embeddings.rb".freeze, "lib/ollama/commands/generate.rb".freeze, "lib/ollama/commands/ps.rb".freeze, "lib/ollama/commands/pull.rb".freeze, "lib/ollama/commands/push.rb".freeze, "lib/ollama/commands/show.rb".freeze, "lib/ollama/commands/tags.rb".freeze, "lib/ollama/documents.rb".freeze, "lib/ollama/documents/cache/common.rb".freeze, "lib/ollama/documents/cache/memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_backed_memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_cache.rb".freeze, "lib/ollama/documents/splitters/character.rb".freeze, "lib/ollama/documents/splitters/semantic.rb".freeze, "lib/ollama/dto.rb".freeze, "lib/ollama/errors.rb".freeze, "lib/ollama/handlers.rb".freeze, "lib/ollama/handlers/collector.rb".freeze, "lib/ollama/handlers/concern.rb".freeze, "lib/ollama/handlers/dump_json.rb".freeze, "lib/ollama/handlers/dump_yaml.rb".freeze, "lib/ollama/handlers/markdown.rb".freeze, "lib/ollama/handlers/nop.rb".freeze, "lib/ollama/handlers/print.rb".freeze, "lib/ollama/handlers/progress.rb".freeze, "lib/ollama/handlers/say.rb".freeze, "lib/ollama/handlers/single.rb".freeze, "lib/ollama/image.rb".freeze, "lib/ollama/message.rb".freeze, "lib/ollama/options.rb".freeze, "lib/ollama/response.rb".freeze, "lib/ollama/tool.rb".freeze, "lib/ollama/tool/function.rb".freeze, "lib/ollama/tool/function/parameters.rb".freeze, "lib/ollama/tool/function/parameters/property.rb".freeze, "lib/ollama/utils/cache_fetcher.rb".freeze, "lib/ollama/utils/chooser.rb".freeze, "lib/ollama/utils/colorize_texts.rb".freeze, "lib/ollama/utils/fetcher.rb".freeze, "lib/ollama/utils/file_argument.rb".freeze, "lib/ollama/utils/math.rb".freeze, "lib/ollama/utils/tags.rb".freeze, "lib/ollama/version.rb".freeze, "ollama-ruby.gemspec".freeze, "spec/assets/embeddings.json".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/prompt.txt".freeze, "spec/ollama/client/doc_spec.rb".freeze, "spec/ollama/client_spec.rb".freeze, "spec/ollama/commands/chat_spec.rb".freeze, "spec/ollama/commands/copy_spec.rb".freeze, "spec/ollama/commands/create_spec.rb".freeze, "spec/ollama/commands/delete_spec.rb".freeze, "spec/ollama/commands/embed_spec.rb".freeze, "spec/ollama/commands/embeddings_spec.rb".freeze, "spec/ollama/commands/generate_spec.rb".freeze, "spec/ollama/commands/ps_spec.rb".freeze, "spec/ollama/commands/pull_spec.rb".freeze, "spec/ollama/commands/push_spec.rb".freeze, "spec/ollama/commands/show_spec.rb".freeze, "spec/ollama/commands/tags_spec.rb".freeze, "spec/ollama/documents/memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_backed_memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_cache_spec.rb".freeze, "spec/ollama/documents/splitters/character_spec.rb".freeze, "spec/ollama/documents/splitters/semantic_spec.rb".freeze, "spec/ollama/documents_spec.rb".freeze, "spec/ollama/handlers/collector_spec.rb".freeze, "spec/ollama/handlers/dump_json_spec.rb".freeze, "spec/ollama/handlers/dump_yaml_spec.rb".freeze, "spec/ollama/handlers/markdown_spec.rb".freeze, "spec/ollama/handlers/nop_spec.rb".freeze, "spec/ollama/handlers/print_spec.rb".freeze, "spec/ollama/handlers/progress_spec.rb".freeze, "spec/ollama/handlers/say_spec.rb".freeze, "spec/ollama/handlers/single_spec.rb".freeze, "spec/ollama/image_spec.rb".freeze, "spec/ollama/message_spec.rb".freeze, "spec/ollama/options_spec.rb".freeze, "spec/ollama/tool_spec.rb".freeze, "spec/ollama/utils/cache_fetcher_spec.rb".freeze, "spec/ollama/utils/colorize_texts_spec.rb".freeze, "spec/ollama/utils/fetcher_spec.rb".freeze, "spec/ollama/utils/file_argument_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
         | 
| 15 | 
            +
              s.extra_rdoc_files = ["README.md".freeze, "lib/ollama.rb".freeze, "lib/ollama/client.rb".freeze, "lib/ollama/client/command.rb".freeze, "lib/ollama/client/doc.rb".freeze, "lib/ollama/commands/chat.rb".freeze, "lib/ollama/commands/copy.rb".freeze, "lib/ollama/commands/create.rb".freeze, "lib/ollama/commands/delete.rb".freeze, "lib/ollama/commands/embed.rb".freeze, "lib/ollama/commands/embeddings.rb".freeze, "lib/ollama/commands/generate.rb".freeze, "lib/ollama/commands/ps.rb".freeze, "lib/ollama/commands/pull.rb".freeze, "lib/ollama/commands/push.rb".freeze, "lib/ollama/commands/show.rb".freeze, "lib/ollama/commands/tags.rb".freeze, "lib/ollama/documents.rb".freeze, "lib/ollama/documents/cache/common.rb".freeze, "lib/ollama/documents/cache/memory_cache.rb".freeze, "lib/ollama/documents/cache/records.rb".freeze, "lib/ollama/documents/cache/redis_backed_memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_cache.rb".freeze, "lib/ollama/documents/cache/sqlite_cache.rb".freeze, "lib/ollama/documents/splitters/character.rb".freeze, "lib/ollama/documents/splitters/semantic.rb".freeze, "lib/ollama/dto.rb".freeze, "lib/ollama/errors.rb".freeze, "lib/ollama/handlers.rb".freeze, "lib/ollama/handlers/collector.rb".freeze, "lib/ollama/handlers/concern.rb".freeze, "lib/ollama/handlers/dump_json.rb".freeze, "lib/ollama/handlers/dump_yaml.rb".freeze, "lib/ollama/handlers/markdown.rb".freeze, "lib/ollama/handlers/nop.rb".freeze, "lib/ollama/handlers/print.rb".freeze, "lib/ollama/handlers/progress.rb".freeze, "lib/ollama/handlers/say.rb".freeze, "lib/ollama/handlers/single.rb".freeze, "lib/ollama/image.rb".freeze, "lib/ollama/message.rb".freeze, "lib/ollama/options.rb".freeze, "lib/ollama/response.rb".freeze, "lib/ollama/tool.rb".freeze, "lib/ollama/tool/function.rb".freeze, "lib/ollama/tool/function/parameters.rb".freeze, "lib/ollama/tool/function/parameters/property.rb".freeze, "lib/ollama/utils/cache_fetcher.rb".freeze, "lib/ollama/utils/chooser.rb".freeze, "lib/ollama/utils/colorize_texts.rb".freeze, "lib/ollama/utils/fetcher.rb".freeze, "lib/ollama/utils/file_argument.rb".freeze, "lib/ollama/utils/math.rb".freeze, "lib/ollama/utils/tags.rb".freeze, "lib/ollama/version.rb".freeze]
         | 
| 16 | 
            +
              s.files = [".envrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_cli".freeze, "bin/ollama_console".freeze, "bin/ollama_update".freeze, "config/redis.conf".freeze, "docker-compose.yml".freeze, "lib/ollama.rb".freeze, "lib/ollama/client.rb".freeze, "lib/ollama/client/command.rb".freeze, "lib/ollama/client/doc.rb".freeze, "lib/ollama/commands/chat.rb".freeze, "lib/ollama/commands/copy.rb".freeze, "lib/ollama/commands/create.rb".freeze, "lib/ollama/commands/delete.rb".freeze, "lib/ollama/commands/embed.rb".freeze, "lib/ollama/commands/embeddings.rb".freeze, "lib/ollama/commands/generate.rb".freeze, "lib/ollama/commands/ps.rb".freeze, "lib/ollama/commands/pull.rb".freeze, "lib/ollama/commands/push.rb".freeze, "lib/ollama/commands/show.rb".freeze, "lib/ollama/commands/tags.rb".freeze, "lib/ollama/documents.rb".freeze, "lib/ollama/documents/cache/common.rb".freeze, "lib/ollama/documents/cache/memory_cache.rb".freeze, "lib/ollama/documents/cache/records.rb".freeze, "lib/ollama/documents/cache/redis_backed_memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_cache.rb".freeze, "lib/ollama/documents/cache/sqlite_cache.rb".freeze, "lib/ollama/documents/splitters/character.rb".freeze, "lib/ollama/documents/splitters/semantic.rb".freeze, "lib/ollama/dto.rb".freeze, "lib/ollama/errors.rb".freeze, "lib/ollama/handlers.rb".freeze, "lib/ollama/handlers/collector.rb".freeze, "lib/ollama/handlers/concern.rb".freeze, "lib/ollama/handlers/dump_json.rb".freeze, "lib/ollama/handlers/dump_yaml.rb".freeze, "lib/ollama/handlers/markdown.rb".freeze, "lib/ollama/handlers/nop.rb".freeze, "lib/ollama/handlers/print.rb".freeze, "lib/ollama/handlers/progress.rb".freeze, "lib/ollama/handlers/say.rb".freeze, "lib/ollama/handlers/single.rb".freeze, "lib/ollama/image.rb".freeze, "lib/ollama/message.rb".freeze, "lib/ollama/options.rb".freeze, "lib/ollama/response.rb".freeze, "lib/ollama/tool.rb".freeze, "lib/ollama/tool/function.rb".freeze, "lib/ollama/tool/function/parameters.rb".freeze, "lib/ollama/tool/function/parameters/property.rb".freeze, "lib/ollama/utils/cache_fetcher.rb".freeze, "lib/ollama/utils/chooser.rb".freeze, "lib/ollama/utils/colorize_texts.rb".freeze, "lib/ollama/utils/fetcher.rb".freeze, "lib/ollama/utils/file_argument.rb".freeze, "lib/ollama/utils/math.rb".freeze, "lib/ollama/utils/tags.rb".freeze, "lib/ollama/version.rb".freeze, "ollama-ruby.gemspec".freeze, "spec/assets/embeddings.json".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/prompt.txt".freeze, "spec/ollama/client/doc_spec.rb".freeze, "spec/ollama/client_spec.rb".freeze, "spec/ollama/commands/chat_spec.rb".freeze, "spec/ollama/commands/copy_spec.rb".freeze, "spec/ollama/commands/create_spec.rb".freeze, "spec/ollama/commands/delete_spec.rb".freeze, "spec/ollama/commands/embed_spec.rb".freeze, "spec/ollama/commands/embeddings_spec.rb".freeze, "spec/ollama/commands/generate_spec.rb".freeze, "spec/ollama/commands/ps_spec.rb".freeze, "spec/ollama/commands/pull_spec.rb".freeze, "spec/ollama/commands/push_spec.rb".freeze, "spec/ollama/commands/show_spec.rb".freeze, "spec/ollama/commands/tags_spec.rb".freeze, "spec/ollama/documents/cache/memory_cache_spec.rb".freeze, "spec/ollama/documents/cache/redis_backed_memory_cache_spec.rb".freeze, "spec/ollama/documents/cache/redis_cache_spec.rb".freeze, "spec/ollama/documents/cache/sqlite_cache_spec.rb".freeze, "spec/ollama/documents/splitters/character_spec.rb".freeze, "spec/ollama/documents/splitters/semantic_spec.rb".freeze, "spec/ollama/documents_spec.rb".freeze, "spec/ollama/handlers/collector_spec.rb".freeze, "spec/ollama/handlers/dump_json_spec.rb".freeze, "spec/ollama/handlers/dump_yaml_spec.rb".freeze, "spec/ollama/handlers/markdown_spec.rb".freeze, "spec/ollama/handlers/nop_spec.rb".freeze, "spec/ollama/handlers/print_spec.rb".freeze, "spec/ollama/handlers/progress_spec.rb".freeze, "spec/ollama/handlers/say_spec.rb".freeze, "spec/ollama/handlers/single_spec.rb".freeze, "spec/ollama/image_spec.rb".freeze, "spec/ollama/message_spec.rb".freeze, "spec/ollama/options_spec.rb".freeze, "spec/ollama/tool_spec.rb".freeze, "spec/ollama/utils/cache_fetcher_spec.rb".freeze, "spec/ollama/utils/colorize_texts_spec.rb".freeze, "spec/ollama/utils/fetcher_spec.rb".freeze, "spec/ollama/utils/file_argument_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
         | 
| 17 17 | 
             
              s.homepage = "https://github.com/flori/ollama-ruby".freeze
         | 
| 18 18 | 
             
              s.licenses = ["MIT".freeze]
         | 
| 19 19 | 
             
              s.rdoc_options = ["--title".freeze, "Ollama-ruby - Interacting with the Ollama API".freeze, "--main".freeze, "README.md".freeze]
         | 
| 20 20 | 
             
              s.required_ruby_version = Gem::Requirement.new("~> 3.1".freeze)
         | 
| 21 21 | 
             
              s.rubygems_version = "3.5.22".freeze
         | 
| 22 22 | 
             
              s.summary = "Interacting with the Ollama API".freeze
         | 
| 23 | 
            -
              s.test_files = ["spec/ollama/client/doc_spec.rb".freeze, "spec/ollama/client_spec.rb".freeze, "spec/ollama/commands/chat_spec.rb".freeze, "spec/ollama/commands/copy_spec.rb".freeze, "spec/ollama/commands/create_spec.rb".freeze, "spec/ollama/commands/delete_spec.rb".freeze, "spec/ollama/commands/embed_spec.rb".freeze, "spec/ollama/commands/embeddings_spec.rb".freeze, "spec/ollama/commands/generate_spec.rb".freeze, "spec/ollama/commands/ps_spec.rb".freeze, "spec/ollama/commands/pull_spec.rb".freeze, "spec/ollama/commands/push_spec.rb".freeze, "spec/ollama/commands/show_spec.rb".freeze, "spec/ollama/commands/tags_spec.rb".freeze, "spec/ollama/documents/memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_backed_memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_cache_spec.rb".freeze, "spec/ollama/documents/splitters/character_spec.rb".freeze, "spec/ollama/documents/splitters/semantic_spec.rb".freeze, "spec/ollama/documents_spec.rb".freeze, "spec/ollama/handlers/collector_spec.rb".freeze, "spec/ollama/handlers/dump_json_spec.rb".freeze, "spec/ollama/handlers/dump_yaml_spec.rb".freeze, "spec/ollama/handlers/markdown_spec.rb".freeze, "spec/ollama/handlers/nop_spec.rb".freeze, "spec/ollama/handlers/print_spec.rb".freeze, "spec/ollama/handlers/progress_spec.rb".freeze, "spec/ollama/handlers/say_spec.rb".freeze, "spec/ollama/handlers/single_spec.rb".freeze, "spec/ollama/image_spec.rb".freeze, "spec/ollama/message_spec.rb".freeze, "spec/ollama/options_spec.rb".freeze, "spec/ollama/tool_spec.rb".freeze, "spec/ollama/utils/cache_fetcher_spec.rb".freeze, "spec/ollama/utils/colorize_texts_spec.rb".freeze, "spec/ollama/utils/fetcher_spec.rb".freeze, "spec/ollama/utils/file_argument_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/spec_helper.rb".freeze]
         | 
| 23 | 
            +
              s.test_files = ["spec/ollama/client/doc_spec.rb".freeze, "spec/ollama/client_spec.rb".freeze, "spec/ollama/commands/chat_spec.rb".freeze, "spec/ollama/commands/copy_spec.rb".freeze, "spec/ollama/commands/create_spec.rb".freeze, "spec/ollama/commands/delete_spec.rb".freeze, "spec/ollama/commands/embed_spec.rb".freeze, "spec/ollama/commands/embeddings_spec.rb".freeze, "spec/ollama/commands/generate_spec.rb".freeze, "spec/ollama/commands/ps_spec.rb".freeze, "spec/ollama/commands/pull_spec.rb".freeze, "spec/ollama/commands/push_spec.rb".freeze, "spec/ollama/commands/show_spec.rb".freeze, "spec/ollama/commands/tags_spec.rb".freeze, "spec/ollama/documents/cache/memory_cache_spec.rb".freeze, "spec/ollama/documents/cache/redis_backed_memory_cache_spec.rb".freeze, "spec/ollama/documents/cache/redis_cache_spec.rb".freeze, "spec/ollama/documents/cache/sqlite_cache_spec.rb".freeze, "spec/ollama/documents/splitters/character_spec.rb".freeze, "spec/ollama/documents/splitters/semantic_spec.rb".freeze, "spec/ollama/documents_spec.rb".freeze, "spec/ollama/handlers/collector_spec.rb".freeze, "spec/ollama/handlers/dump_json_spec.rb".freeze, "spec/ollama/handlers/dump_yaml_spec.rb".freeze, "spec/ollama/handlers/markdown_spec.rb".freeze, "spec/ollama/handlers/nop_spec.rb".freeze, "spec/ollama/handlers/print_spec.rb".freeze, "spec/ollama/handlers/progress_spec.rb".freeze, "spec/ollama/handlers/say_spec.rb".freeze, "spec/ollama/handlers/single_spec.rb".freeze, "spec/ollama/image_spec.rb".freeze, "spec/ollama/message_spec.rb".freeze, "spec/ollama/options_spec.rb".freeze, "spec/ollama/tool_spec.rb".freeze, "spec/ollama/utils/cache_fetcher_spec.rb".freeze, "spec/ollama/utils/colorize_texts_spec.rb".freeze, "spec/ollama/utils/fetcher_spec.rb".freeze, "spec/ollama/utils/file_argument_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/spec_helper.rb".freeze]
         | 
| 24 24 |  | 
| 25 25 | 
             
              s.specification_version = 4
         | 
| 26 26 |  | 
| 27 27 | 
             
              s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 1.19".freeze])
         | 
| 28 | 
            -
              s.add_development_dependency(%q<all_images>.freeze, ["~> 0. | 
| 28 | 
            +
              s.add_development_dependency(%q<all_images>.freeze, ["~> 0.6".freeze])
         | 
| 29 29 | 
             
              s.add_development_dependency(%q<rspec>.freeze, ["~> 3.2".freeze])
         | 
| 30 30 | 
             
              s.add_development_dependency(%q<webmock>.freeze, [">= 0".freeze])
         | 
| 31 31 | 
             
              s.add_development_dependency(%q<debug>.freeze, [">= 0".freeze])
         | 
| @@ -48,4 +48,6 @@ Gem::Specification.new do |s| | |
| 48 48 | 
             
              s.add_runtime_dependency(%q<tins>.freeze, ["~> 1.34".freeze])
         | 
| 49 49 | 
             
              s.add_runtime_dependency(%q<kramdown-ansi>.freeze, ["~> 0.0".freeze, ">= 0.0.1".freeze])
         | 
| 50 50 | 
             
              s.add_runtime_dependency(%q<ostruct>.freeze, ["~> 0.0".freeze])
         | 
| 51 | 
            +
              s.add_runtime_dependency(%q<sqlite-vec>.freeze, ["~> 0.0".freeze])
         | 
| 52 | 
            +
              s.add_runtime_dependency(%q<sqlite3>.freeze, ["~> 2.0".freeze, ">= 2.0.1".freeze])
         | 
| 51 53 | 
             
            end
         | 
| @@ -1,8 +1,12 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            RSpec.describe Ollama::Documents::MemoryCache do
         | 
| 4 | 
            +
              let :prefix do
         | 
| 5 | 
            +
                'test-'
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 4 8 | 
             
              let :cache do
         | 
| 5 | 
            -
                described_class.new prefix: | 
| 9 | 
            +
                described_class.new prefix:
         | 
| 6 10 | 
             
              end
         | 
| 7 11 |  | 
| 8 12 | 
             
              it 'can be instantiated' do
         | 
| @@ -27,16 +31,46 @@ RSpec.describe Ollama::Documents::MemoryCache do | |
| 27 31 | 
             
                }.from(false).to(true)
         | 
| 28 32 | 
             
              end
         | 
| 29 33 |  | 
| 34 | 
            +
              it 'can set key with different prefixes' do
         | 
| 35 | 
            +
                key, value = 'foo', { test: true }
         | 
| 36 | 
            +
                expect {
         | 
| 37 | 
            +
                  cache[key] = value
         | 
| 38 | 
            +
                }.to change {
         | 
| 39 | 
            +
                  cache.size
         | 
| 40 | 
            +
                }.from(0).to(1)
         | 
| 41 | 
            +
                cache2 = cache.dup
         | 
| 42 | 
            +
                cache2.prefix = 'test2-'
         | 
| 43 | 
            +
                expect {
         | 
| 44 | 
            +
                  cache2[key] = value
         | 
| 45 | 
            +
                }.to change {
         | 
| 46 | 
            +
                  cache2.size
         | 
| 47 | 
            +
                }.from(0).to(1)
         | 
| 48 | 
            +
                expect(cache.size).to eq 1
         | 
| 49 | 
            +
                s = 0
         | 
| 50 | 
            +
                cache.full_each { s += 1 }
         | 
| 51 | 
            +
                expect(s).to eq 2
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 30 54 | 
             
              it 'can delete' do
         | 
| 31 55 | 
             
                key, value = 'foo', { test: true }
         | 
| 56 | 
            +
                expect(cache.delete(key)).to be_falsy
         | 
| 32 57 | 
             
                cache[key] = value
         | 
| 33 58 | 
             
                expect {
         | 
| 34 | 
            -
                  cache.delete(key)
         | 
| 59 | 
            +
                  expect(cache.delete(key)).to be_truthy
         | 
| 35 60 | 
             
                }.to change {
         | 
| 36 61 | 
             
                  cache.key?(key)
         | 
| 37 62 | 
             
                }.from(true).to(false)
         | 
| 38 63 | 
             
              end
         | 
| 39 64 |  | 
| 65 | 
            +
              it 'can iterate over keys, values' do
         | 
| 66 | 
            +
                key, value = 'foo', { test: true }
         | 
| 67 | 
            +
                cache[key] = value
         | 
| 68 | 
            +
                cache.each do |k, v|
         | 
| 69 | 
            +
                  expect(k).to eq prefix + key
         | 
| 70 | 
            +
                  expect(v).to eq value
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
             | 
| 40 74 | 
             
              it 'returns size' do
         | 
| 41 75 | 
             
                key, value = 'foo', { test: true }
         | 
| 42 76 | 
             
                expect {
         | 
| @@ -58,6 +92,6 @@ RSpec.describe Ollama::Documents::MemoryCache do | |
| 58 92 |  | 
| 59 93 | 
             
              it 'can iterate over keys under a prefix' do
         | 
| 60 94 | 
             
                cache['foo'] = 'bar'
         | 
| 61 | 
            -
                expect(cache.to_a).to eq [ % | 
| 95 | 
            +
                expect(cache.to_a).to eq [ %W[ #{prefix}foo bar ] ]
         | 
| 62 96 | 
             
              end
         | 
| 63 97 | 
             
            end
         | 
| @@ -1,17 +1,21 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            RSpec.describe Ollama::Documents::RedisBackedMemoryCache do
         | 
| 4 | 
            +
              let :prefix do
         | 
| 5 | 
            +
                'test-'
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              let :cache do
         | 
| 9 | 
            +
                described_class.new prefix: 'test-', url: 'something'
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 4 12 | 
             
              it 'raises ArgumentError if url is missing' do
         | 
| 5 13 | 
             
                expect {
         | 
| 6 | 
            -
                  described_class.new prefix | 
| 14 | 
            +
                  described_class.new prefix:, url: nil
         | 
| 7 15 | 
             
                }.to raise_error ArgumentError
         | 
| 8 16 | 
             
              end
         | 
| 9 17 |  | 
| 10 18 | 
             
              context 'test redis interactions' do
         | 
| 11 | 
            -
                let :cache do
         | 
| 12 | 
            -
                  described_class.new prefix: 'test-', url: 'something'
         | 
| 13 | 
            -
                end
         | 
| 14 | 
            -
             | 
| 15 19 | 
             
                let :data do
         | 
| 16 20 | 
             
                  cache.instance_eval { @data }
         | 
| 17 21 | 
             
                end
         | 
| @@ -31,12 +35,10 @@ RSpec.describe Ollama::Documents::RedisBackedMemoryCache do | |
| 31 35 | 
             
                end
         | 
| 32 36 |  | 
| 33 37 | 
             
                it 'can be instantiated and initialized' do
         | 
| 34 | 
            -
                  cache = described_class.new prefix: 'test-', url: 'something'
         | 
| 35 38 | 
             
                  expect(cache).to be_a described_class
         | 
| 36 39 | 
             
                end
         | 
| 37 40 |  | 
| 38 41 | 
             
                it 'defaults to nil object_class' do
         | 
| 39 | 
            -
                  cache = described_class.new prefix: 'test-', url: 'something'
         | 
| 40 42 | 
             
                  expect(cache.object_class).to be_nil
         | 
| 41 43 | 
             
                end
         | 
| 42 44 |  | 
| @@ -77,6 +79,16 @@ RSpec.describe Ollama::Documents::RedisBackedMemoryCache do | |
| 77 79 | 
             
                  cache.delete(key)
         | 
| 78 80 | 
             
                end
         | 
| 79 81 |  | 
| 82 | 
            +
                it 'can iterate over keys, values' do
         | 
| 83 | 
            +
                  key, value = 'foo', { 'test' => true }
         | 
| 84 | 
            +
                  expect(redis).to receive(:set).with('test-' + key, JSON(value))
         | 
| 85 | 
            +
                  cache[key] = value
         | 
| 86 | 
            +
                  cache.each do |k, v|
         | 
| 87 | 
            +
                    expect(k).to eq prefix + key
         | 
| 88 | 
            +
                    expect(v).to eq value
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
             | 
| 80 92 | 
             
                it 'returns size' do
         | 
| 81 93 | 
             
                  expect(cache).to receive(:count).and_return 3
         | 
| 82 94 | 
             
                  expect(cache.size).to eq 3
         |