ollama_chat 0.0.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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.all_images.yml +17 -0
  3. data/.gitignore +9 -0
  4. data/Gemfile +5 -0
  5. data/README.md +159 -0
  6. data/Rakefile +58 -0
  7. data/VERSION +1 -0
  8. data/bin/ollama_chat +5 -0
  9. data/lib/ollama_chat/chat.rb +398 -0
  10. data/lib/ollama_chat/clipboard.rb +23 -0
  11. data/lib/ollama_chat/dialog.rb +94 -0
  12. data/lib/ollama_chat/document_cache.rb +16 -0
  13. data/lib/ollama_chat/follow_chat.rb +60 -0
  14. data/lib/ollama_chat/information.rb +113 -0
  15. data/lib/ollama_chat/message_list.rb +216 -0
  16. data/lib/ollama_chat/message_type.rb +5 -0
  17. data/lib/ollama_chat/model_handling.rb +29 -0
  18. data/lib/ollama_chat/ollama_chat_config.rb +103 -0
  19. data/lib/ollama_chat/parsing.rb +159 -0
  20. data/lib/ollama_chat/source_fetching.rb +173 -0
  21. data/lib/ollama_chat/switches.rb +119 -0
  22. data/lib/ollama_chat/utils/cache_fetcher.rb +38 -0
  23. data/lib/ollama_chat/utils/chooser.rb +53 -0
  24. data/lib/ollama_chat/utils/fetcher.rb +175 -0
  25. data/lib/ollama_chat/utils/file_argument.rb +34 -0
  26. data/lib/ollama_chat/utils.rb +7 -0
  27. data/lib/ollama_chat/version.rb +8 -0
  28. data/lib/ollama_chat.rb +20 -0
  29. data/ollama_chat.gemspec +50 -0
  30. data/spec/assets/api_show.json +63 -0
  31. data/spec/assets/api_tags.json +21 -0
  32. data/spec/assets/conversation.json +14 -0
  33. data/spec/assets/duckduckgo.html +757 -0
  34. data/spec/assets/example.atom +26 -0
  35. data/spec/assets/example.csv +5 -0
  36. data/spec/assets/example.html +10 -0
  37. data/spec/assets/example.pdf +139 -0
  38. data/spec/assets/example.ps +4 -0
  39. data/spec/assets/example.rb +1 -0
  40. data/spec/assets/example.rss +25 -0
  41. data/spec/assets/example.xml +7 -0
  42. data/spec/assets/kitten.jpg +0 -0
  43. data/spec/assets/prompt.txt +1 -0
  44. data/spec/ollama_chat/chat_spec.rb +105 -0
  45. data/spec/ollama_chat/clipboard_spec.rb +29 -0
  46. data/spec/ollama_chat/follow_chat_spec.rb +46 -0
  47. data/spec/ollama_chat/information_spec.rb +50 -0
  48. data/spec/ollama_chat/message_list_spec.rb +132 -0
  49. data/spec/ollama_chat/model_handling_spec.rb +35 -0
  50. data/spec/ollama_chat/parsing_spec.rb +240 -0
  51. data/spec/ollama_chat/source_fetching_spec.rb +54 -0
  52. data/spec/ollama_chat/switches_spec.rb +167 -0
  53. data/spec/ollama_chat/utils/cache_fetcher_spec.rb +43 -0
  54. data/spec/ollama_chat/utils/fetcher_spec.rb +137 -0
  55. data/spec/ollama_chat/utils/file_argument_spec.rb +17 -0
  56. data/spec/spec_helper.rb +46 -0
  57. data/tmp/.keep +0 -0
  58. metadata +476 -0
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <feed xmlns="http://www.w3.org/2005/Atom">
3
+ <title>Example Feed</title>
4
+ <link rel="self" type="application/atom+xml" href="https://example.com/feed.atom"/>
5
+ <id>urn:uuid:12345678-1234-1234-1234-123456789012</id>
6
+ <updated>2024-01-01T12:00:00Z</updated>
7
+
8
+ <!-- Entry 1 -->
9
+ <entry>
10
+ <title>New Study Shows Benefits of Meditation</title>
11
+ <link rel="alternate" type="text/html" href="https://example.com/article/meditation-benefits"/>
12
+ <id>urn:uuid:23456789-2345-2345-2345-234567890123</id>
13
+ <updated>2024-01-01T12:00:00Z</updated>
14
+ <summary>A new study has found that regular meditation can have numerous physical and mental health benefits.</summary>
15
+ </entry>
16
+
17
+ <!-- Entry 2 -->
18
+ <entry>
19
+ <title>Local Business Opens New Location</title>
20
+ <link rel="alternate" type="text/html" href="https://example.com/article/local-business-new-location"/>
21
+ <id>urn:uuid:34567890-3456-3456-3456-345678901234</id>
22
+ <updated>2024-01-02T10:00:00Z</updated>
23
+ <summary>A local business has opened a new location in the area.</summary>
24
+ </entry>
25
+
26
+ </feed>
@@ -0,0 +1,5 @@
1
+ Name,Age,Occupation
2
+ John Doe,32,Software Engineer
3
+ Jane Smith,28,Marketing Manager
4
+ Bob Johnson,45,Retired
5
+ Alice Brown,25,Student
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <body>
4
+
5
+ <h1>My First Heading</h1>
6
+
7
+ <p>My first paragraph.</p>
8
+
9
+ </body>
10
+ </html>
@@ -0,0 +1,139 @@
1
+ %PDF-1.3
2
+ %����
3
+ 2 0 obj
4
+ <<
5
+ /Length 75
6
+ >>
7
+ stream
8
+ BT
9
+ /TT2 1 Tf
10
+ 36 0 0 36 72 684 Tm
11
+ 0 g
12
+ /GS1 gs
13
+ 0 Tc
14
+ 0 Tw
15
+ (Hello World!)Tj
16
+ ET
17
+ endstream
18
+ endobj
19
+ 3 0 obj
20
+ <<
21
+ /ProcSet [/PDF /Text ]
22
+ /Font <<
23
+ /TT2 4 0 R
24
+ >>
25
+ /ExtGState <<
26
+ /GS1 5 0 R
27
+ >>
28
+ >>
29
+ endobj
30
+ 5 0 obj
31
+ <<
32
+ /Type /ExtGState
33
+ /SA false
34
+ /SM 0.02
35
+ /OP false
36
+ /op false
37
+ /OPM 1
38
+ /BG2 /Default
39
+ /UCR2 /Default
40
+ /HT /Default
41
+ /TR2 /Default
42
+ >>
43
+ endobj
44
+ 7 0 obj
45
+ <<
46
+ /Type /FontDescriptor
47
+ /Ascent 750
48
+ /CapHeight 676
49
+ /Descent -250
50
+ /Flags 262178
51
+ /FontBBox [-168 -218 1000 935]
52
+ /FontName /Times-Bold
53
+ /ItalicAngle 0
54
+ /StemV 133
55
+ /XHeight 461
56
+ /StemH 139
57
+ >>
58
+ endobj
59
+ 4 0 obj
60
+ <<
61
+ /Type /Font
62
+ /Subtype /TrueType
63
+ /FirstChar 32
64
+ /LastChar 114
65
+ /Widths [250 333 0 0 0 0 0 0 0 0 0 0 0 0 0 0
66
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
67
+ 0 0 0 0 0 0 0 0 778 0 0 0 0 0 0 0
68
+ 0 0 0 0 0 0 0 1000 0 0 0 0 0 0 0 0
69
+ 0 0 0 0 556 444 0 0 0 0 0 0 278 0 0 500
70
+ 0 0 444 ]
71
+ /Encoding /WinAnsiEncoding
72
+ /BaseFont /Times-Bold
73
+ /FontDescriptor 7 0 R
74
+ >>
75
+ endobj
76
+ 1 0 obj
77
+ <<
78
+ /Type /Page
79
+ /Parent 6 0 R
80
+ /Resources 3 0 R
81
+ /Contents 2 0 R
82
+ >>
83
+ endobj
84
+ 8 0 obj
85
+ <<
86
+ /S /D
87
+ >>
88
+ endobj
89
+ 9 0 obj
90
+ <<
91
+ /Nums [0 8 0 R ]
92
+ >>
93
+ endobj
94
+ 6 0 obj
95
+ <<
96
+ /Type /Pages
97
+ /Kids [1 0 R]
98
+ /Count 1
99
+ /MediaBox [0 0 612 792]
100
+ >>
101
+ endobj
102
+ 10 0 obj
103
+ <<
104
+ /CreationDate (D:20250120235539+01'00')
105
+ /ModDate (D:20250120235539+01'00')
106
+ /Producer (Apple pstopdf)
107
+ >>
108
+ endobj
109
+ 11 0 obj
110
+ <<
111
+ /Type /Catalog
112
+ /Pages 6 0 R
113
+ /PageLabels 9 0 R
114
+ >>
115
+ endobj
116
+ xref
117
+ 0 12
118
+ 0000000000 65535 f
119
+ 0000000929 00000 n
120
+ 0000000016 00000 n
121
+ 0000000141 00000 n
122
+ 0000000577 00000 n
123
+ 0000000236 00000 n
124
+ 0000001074 00000 n
125
+ 0000000376 00000 n
126
+ 0000001009 00000 n
127
+ 0000001036 00000 n
128
+ 0000001155 00000 n
129
+ 0000001278 00000 n
130
+ trailer
131
+ <<
132
+ /Size 12
133
+ /Root 11 0 R
134
+ /Info 10 0 R
135
+ /ID [<d30f9b19200969dad7c3656d50e43d11><d30f9b19200969dad7c3656d50e43d11>]
136
+ >>
137
+ startxref
138
+ 1346
139
+ %%EOF
@@ -0,0 +1,4 @@
1
+ %!PS
2
+ /Times-Bold findfont 36 scalefont setfont
3
+ 72 684 moveto (Hello World!) show
4
+ showpage
@@ -0,0 +1 @@
1
+ puts "Hello World!"
@@ -0,0 +1,25 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <rss version="2.0">
3
+ <channel>
4
+ <title>Example News Feed</title>
5
+ <link>https://example.com</link>
6
+ <description>A sample news feed.</description>
7
+
8
+ <!-- Item 1 -->
9
+ <item>
10
+ <title>New Study Shows Benefits of Meditation</title>
11
+ <link>https://example.com/article/meditation-benefits</link>
12
+ <pubDate>Mon, 01 Jan 2024 12:00:00 GMT</pubDate>
13
+ <description>A new study has found that regular meditation can have numerous physical and mental health benefits.</description>
14
+ </item>
15
+
16
+ <!-- Item 2 -->
17
+ <item>
18
+ <title>Local Business Opens New Location</title>
19
+ <link>https://example.com/article/local-business-new-location</link>
20
+ <pubDate>Tue, 02 Jan 2024 10:00:00 GMT</pubDate>
21
+ <description>A local business has opened a new location in the area.</description>
22
+ </item>
23
+
24
+ </channel>
25
+ </rss>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <note>
3
+ <to>Tove</to>
4
+ <from>Jani</from>
5
+ <heading>Reminder</heading>
6
+ <body>Don't forget me this weekend!</body>
7
+ </note>
Binary file
@@ -0,0 +1 @@
1
+ You are a test prompt just used for testing.
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OllamaChat::Chat do
4
+ let :argv do
5
+ []
6
+ end
7
+
8
+ let :chat do
9
+ OllamaChat::Chat.new argv: argv
10
+ end
11
+
12
+ before do
13
+ stub_request(:get, %r(/api/tags\z)).
14
+ to_return(status: 200, body: asset_json('api_tags.json'))
15
+ stub_request(:post, %r(/api/show\z)).
16
+ to_return(status: 200, body: asset_json('api_show.json'))
17
+ end
18
+
19
+ it 'can be instantiated' do
20
+ expect(chat).to be_a described_class
21
+ end
22
+
23
+ describe OllamaChat::DocumentCache do
24
+ context 'with MemoryCache' do
25
+ let :argv do
26
+ %w[ -M ]
27
+ end
28
+
29
+ it 'can use MemoryCache' do
30
+ expect(chat.documents.cache).to be_a Documentrix::Documents::MemoryCache
31
+ end
32
+ end
33
+
34
+ context 'falls back to MemoryCache' do
35
+ it 'falls back to MemoryCache' do
36
+ expect_any_instance_of(OllamaChat::Chat).to\
37
+ receive(:document_cache_class).and_raise(NameError)
38
+ expect(chat.documents.cache).to be_a Documentrix::Documents::MemoryCache
39
+ end
40
+ end
41
+ end
42
+
43
+ describe Documentrix::Documents do
44
+ context 'with documents' do
45
+ let :argv do
46
+ %w[ -D ] << asset('example.html')
47
+ end
48
+
49
+ it 'Adds documents passed to app via -D option' do
50
+ expect_any_instance_of(OllamaChat::Chat).to receive(:add_documents_from_argv).
51
+ with(kind_of(Documentrix::Documents), [ asset('example.html') ])
52
+ chat
53
+ end
54
+ end
55
+ end
56
+
57
+ describe OllamaChat::Information do
58
+ it 'has progname' do
59
+ expect(chat.progname).to eq 'ollama_chat'
60
+ end
61
+
62
+ it 'has user_agent' do
63
+ expect(chat.user_agent).to match %r(\Aollama_chat/\d+\.\d+\.\d+\z)
64
+ end
65
+
66
+ it 'can display collection_stats' do
67
+ chat
68
+ expect(STDOUT).to receive(:puts).with(
69
+ "Current Collection\n Name: \e[1mdefault\e[0m\n #Embeddings: 0\n #Tags: 0\n Tags: \n"
70
+ )
71
+ expect(chat.collection_stats).to be_nil
72
+ end
73
+
74
+ it 'can display info' do
75
+ chat
76
+ expect(STDOUT).to receive(:puts).
77
+ with(
78
+ /
79
+ Current\ model|
80
+ Options|
81
+ Embedding|
82
+ Text\ splitter|
83
+ Documents\ database\ cache|
84
+ output\ content|
85
+ Streaming|
86
+ Location|
87
+ Document\ policy
88
+ /x
89
+ ).at_least(1)
90
+ expect(chat.info).to be_nil
91
+ end
92
+
93
+ it 'can display usage' do
94
+ chat
95
+ expect(STDOUT).to receive(:puts).with(/\AUsage: ollama_chat/)
96
+ expect(chat.usage).to eq 0
97
+ end
98
+
99
+ it 'can display version' do
100
+ chat
101
+ expect(STDOUT).to receive(:puts).with(/\Aollama_chat \d+\.\d+\.\d+\z/)
102
+ expect(chat.version).to eq 0
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OllamaChat::Clipboard do
4
+ let :chat do
5
+ OllamaChat::Chat.new
6
+ end
7
+
8
+ before do
9
+ stub_request(:get, %r(/api/tags\z)).
10
+ to_return(status: 200, body: asset_json('api_tags.json'))
11
+ stub_request(:post, %r(/api/show\z)).
12
+ to_return(status: 200, body: asset_json('api_show.json'))
13
+ chat
14
+ end
15
+
16
+ it 'can copy to clipboard' do
17
+ expect(STDERR).to receive(:puts).with(/No response available to copy to the system clipboard/)
18
+ expect(chat.copy_to_clipboard).to be_nil
19
+ chat.instance_variable_get(:@messages).load_conversation(asset('conversation.json'))
20
+ expect(STDOUT).to receive(:puts).with(/The last response has been copied to the system clipboard/)
21
+ expect(chat.copy_to_clipboard).to be_nil
22
+ end
23
+
24
+ it 'can paste from input' do
25
+ expect(STDOUT).to receive(:puts).with(/Paste your content/)
26
+ expect(STDIN).to receive(:read).and_return 'test input'
27
+ expect(chat.paste_from_input).to eq 'test input'
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OllamaChat::FollowChat do
4
+ let :messages do
5
+ [
6
+ Ollama::Message.new(role: 'user', content: 'hello', images: []),
7
+ ]
8
+ end
9
+
10
+ let :follow_chat do
11
+ described_class.new(messages:, output:)
12
+ end
13
+
14
+ let :output do
15
+ double('output', :sync= => true)
16
+ end
17
+
18
+ before do
19
+ allow(OllamaChat::Chat).to receive(:config).and_return(double(debug: false))
20
+ end
21
+
22
+ it 'has .call' do
23
+ expect(follow_chat).to receive(:call).with(:foo)
24
+ follow_chat.call(:foo)
25
+ end
26
+
27
+ it 'can follow without markdown' do
28
+ message = Ollama::Message.new(role: 'assistant', content: 'world')
29
+ response = double(message:, done: false)
30
+ expect(output).to receive(:puts).with(/assistant/)
31
+ expect(output).to receive(:print).with(/world/)
32
+ follow_chat.call(response)
33
+ response = double(
34
+ message: nil,
35
+ done: true,
36
+ total_duration: 777.77,
37
+ eval_duration: 666.66,
38
+ eval_count: 23,
39
+ prompt_eval_duration: 42.0,
40
+ prompt_eval_count: 7,
41
+ load_duration: 33.45,
42
+ )
43
+ expect(output).to receive(:puts).with("", /eval_duration/)
44
+ follow_chat.call(response)
45
+ end
46
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OllamaChat::Information do
4
+ let :chat do
5
+ OllamaChat::Chat.new
6
+ end
7
+
8
+ before do
9
+ stub_request(:get, %r(/api/tags\z)).
10
+ to_return(status: 200, body: asset_json('api_tags.json'))
11
+ stub_request(:post, %r(/api/show\z)).
12
+ to_return(status: 200, body: asset_json('api_show.json'))
13
+ chat
14
+ end
15
+
16
+ describe ::OllamaChat::Information::UserAgent do
17
+ it 'has progname' do
18
+ expect(chat.progname).to eq 'ollama_chat'
19
+ end
20
+
21
+ it 'has user_agent' do
22
+ expect(chat.user_agent).to match %r(\Aollama_chat/\d+\.\d+\.\d+\z)
23
+ end
24
+ end
25
+
26
+ it 'can show collection_stats' do
27
+ expect(STDOUT).to receive(:puts).with(/Current Collection/)
28
+ expect(chat.collection_stats).to be_nil
29
+ end
30
+
31
+ it 'can show info' do
32
+ expect(STDOUT).to receive(:puts).with(/Current model is/)
33
+ expect(STDOUT).to receive(:puts).at_least(1)
34
+ expect(chat.info).to be_nil
35
+ end
36
+
37
+ it 'can show display_chat_help' do
38
+ expect(STDOUT).to receive(:puts).with(%r(/info.*show information))
39
+ expect(chat.display_chat_help).to be_nil
40
+ end
41
+
42
+ it 'can show usage' do
43
+ expect(STDOUT).to receive(:puts).with(/Usage: ollama_chat/)
44
+ expect(chat.usage).to eq 0
45
+ end
46
+
47
+ it 'can show version' do
48
+ expect(chat.version).to eq 0
49
+ end
50
+ end
@@ -0,0 +1,132 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OllamaChat::MessageList do
4
+ let :config do
5
+ double(
6
+ location: double(
7
+ enabled: false,
8
+ name: 'Berlin',
9
+ decimal_degrees: [ 52.514127, 13.475211 ],
10
+ units: 'SI (International System of Units)'
11
+ ),
12
+ prompts: double(
13
+ location: 'You are at %{location_name} (%{location_decimal_degrees}), on %{localtime}, preferring %{units}'
14
+ )
15
+ )
16
+ end
17
+
18
+ let :chat do
19
+ double('Chat', config:)
20
+ end
21
+
22
+ let :list do
23
+ described_class.new(chat).tap do |list|
24
+ list << Ollama::Message.new(role: 'system', content: 'hello')
25
+ end
26
+ end
27
+
28
+ it 'can clear non system messages' do
29
+ expect(list.size).to eq 1
30
+ list.clear
31
+ expect(list.size).to eq 1
32
+ list << Ollama::Message.new(role: 'user', content: 'world')
33
+ expect(list.size).to eq 2
34
+ list.clear
35
+ expect(list.size).to eq 1
36
+ end
37
+
38
+ it 'can be added to' do
39
+ expect(list.size).to eq 1
40
+ list << Ollama::Message.new(role: 'user', content: 'world')
41
+ expect(list.size).to eq 2
42
+ end
43
+
44
+ it 'has a last message' do
45
+ expect(list.last).to be_a Ollama::Message
46
+ end
47
+
48
+ it 'can load conversations if existing' do
49
+ expect(list.messages.first.role).to eq 'system'
50
+ expect(list.load_conversation(asset('conversation-nixda.json'))).to be_nil
51
+ expect {
52
+ list.load_conversation(asset('conversation.json'))
53
+ }.to change { list.messages.size }.from(1).to(3)
54
+ expect(list.messages.map(&:role)).to eq %w[ system user assistant ]
55
+ end
56
+
57
+ it 'can save conversations' do
58
+ expect(list.save_conversation('tmp/test-conversation.json')).to eq list
59
+ expect(list.save_conversation('tmp/test-conversation.json')).to be_nil
60
+ ensure
61
+ FileUtils.rm_f 'tmp/test-conversation.json'
62
+ end
63
+
64
+ it 'can list conversations' do
65
+ expect(chat).to receive(:markdown).
66
+ and_return(double(on?: true)).at_least(:once)
67
+ list << Ollama::Message.new(role: 'user', content: 'world')
68
+ expect(STDOUT).to receive(:puts).
69
+ with("📨 \e[1m\e[38;5;213msystem\e[0m\e[0m:\nhello\n")
70
+ expect(STDOUT).to receive(:puts).
71
+ with("📨 \e[1m\e[38;5;172muser\e[0m\e[0m:\nworld\n")
72
+ list.list_conversation
73
+ end
74
+
75
+ it 'can show_system_prompt' do
76
+ expect(list).to receive(:system).and_return 'test **prompt**'
77
+ expect(Kramdown::ANSI).to receive(:parse).with('test **prompt**').
78
+ and_call_original
79
+ expect(list.show_system_prompt).to eq list
80
+ end
81
+
82
+ it 'can set_system_prompt' do
83
+ expect {
84
+ expect(list.set_system_prompt('test prompt')).to eq list
85
+ }.to change { list.system }.from(nil).to('test prompt')
86
+ end
87
+
88
+ it 'can drop n conversations exhanges' do
89
+ expect(list.size).to eq 1
90
+ expect(list.drop(1)).to eq 0
91
+ expect(list.size).to eq 1
92
+ list << Ollama::Message.new(role: 'user', content: 'world')
93
+ expect(list.size).to eq 2
94
+ expect(list.drop(1)).to eq 0
95
+ list << Ollama::Message.new(role: 'assistant', content: 'hi')
96
+ expect(list.size).to eq 3
97
+ expect(list.drop(1)).to eq 1
98
+ expect(list.size).to eq 1
99
+ end
100
+
101
+ it 'can determine location for system prompt' do
102
+ expect(chat).to receive(:location).and_return(double(on?: true))
103
+ expect(list.send(:at_location)).to match(
104
+ %r(You are at Berlin \(52.514127, 13.475211\), on))
105
+ end
106
+
107
+ it 'can be converted int an Ollama::Message array' do
108
+ expect(chat).to receive(:location).and_return(double(on?: false))
109
+ list << Ollama::Message.new(role: 'user', content: 'world')
110
+ expect(list.to_ary.map(&:as_json)).to eq [
111
+ Ollama::Message.new(role: 'system', content: 'hello').as_json,
112
+ Ollama::Message.new(role: 'user', content: 'world').as_json,
113
+ ]
114
+ end
115
+
116
+ it 'can be converted int an Ollama::Message array with location' do
117
+ expect(chat).to receive(:location).and_return(double(on?: true))
118
+ list << Ollama::Message.new(role: 'user', content: 'world')
119
+ first = list.to_ary.first
120
+ expect(first.role).to eq 'system'
121
+ expect(first.content).to match(
122
+ %r(You are at Berlin \(52.514127, 13.475211\), on))
123
+ end
124
+
125
+ it 'can display messages with images' do
126
+ expect(list.message_type([])).to eq ?📨
127
+ end
128
+
129
+ it 'can display messages without images' do
130
+ expect(list.message_type(%w[ image ])).to eq ?📸
131
+ end
132
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OllamaChat::ModelHandling do
4
+ let :chat do
5
+ OllamaChat::Chat.new
6
+ end
7
+
8
+ before do
9
+ stub_request(:get, %r(/api/tags\z)).
10
+ to_return(status: 200, body: asset_json('api_tags.json'))
11
+ stub_request(:post, %r(/api/show\z)).
12
+ to_return(status: 200, body: asset_json('api_show.json'))
13
+ chat
14
+ end
15
+
16
+ it 'can check if model_present?' do
17
+ expect(chat.ollama).to receive(:show).and_raise Ollama::Errors::NotFoundError
18
+ expect(chat.model_present?('nixda')).to eq false
19
+ expect(chat.ollama).to receive(:show).and_return 'llama3.1'
20
+ expect(chat.model_present?('llama3.1')).to be_truthy
21
+ end
22
+
23
+ it 'can pull_model_from_remote' do
24
+ stub_request(:post, %r(/api/pull\z)).
25
+ to_return(status: 200, body: asset_json('api_show.json'))
26
+ expect(chat.pull_model_from_remote('llama3.1'))
27
+ end
28
+
29
+ it 'can pull_model_unless_present' do
30
+ expect(chat).to receive(:model_present?).with('llama3.1').and_return false
31
+ expect(chat).to receive(:model_present?).with('llama3.1').and_return true
32
+ expect(chat).to receive(:pull_model_from_remote).with('llama3.1')
33
+ expect(chat.pull_model_unless_present('llama3.1', {}))
34
+ end
35
+ end