ollama_chat 0.0.2 → 0.0.4
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/.all_images.yml +3 -4
- data/.gitignore +1 -0
- data/CHANGES.md +35 -0
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/config/searxng/settings.yml +2583 -0
- data/docker-compose.yml +21 -0
- data/lib/ollama_chat/chat.rb +4 -2
- data/lib/ollama_chat/information.rb +7 -0
- data/lib/ollama_chat/ollama_chat_config/default_config.yml +9 -0
- data/lib/ollama_chat/source_fetching.rb +1 -29
- data/lib/ollama_chat/utils/fetcher.rb +5 -3
- data/lib/ollama_chat/version.rb +1 -1
- data/lib/ollama_chat/web_searching.rb +60 -0
- data/lib/ollama_chat.rb +1 -0
- data/ollama_chat.gemspec +7 -7
- data/spec/assets/api_version.json +3 -0
- data/spec/assets/searxng.json +111 -0
- data/spec/ollama_chat/chat_spec.rb +8 -10
- data/spec/ollama_chat/clipboard_spec.rb +1 -7
- data/spec/ollama_chat/information_spec.rb +2 -7
- data/spec/ollama_chat/model_handling_spec.rb +1 -7
- data/spec/ollama_chat/parsing_spec.rb +1 -7
- data/spec/ollama_chat/source_fetching_spec.rb +1 -16
- data/spec/ollama_chat/utils/fetcher_spec.rb +15 -0
- data/spec/ollama_chat/web_searching_spec.rb +29 -0
- data/spec/spec_helper.rb +12 -0
- metadata +11 -4
data/docker-compose.yml
CHANGED
@@ -1,10 +1,31 @@
|
|
1
1
|
services:
|
2
2
|
redis:
|
3
|
+
container_name: redis
|
3
4
|
image: valkey/valkey:7.2.8-alpine
|
4
5
|
restart: unless-stopped
|
5
6
|
ports: [ "127.0.0.1:9736:6379" ]
|
6
7
|
volumes:
|
7
8
|
- "redis-data:/data:delegated"
|
8
9
|
- "./redis/redis.conf:/etc/redis.conf"
|
10
|
+
searxng:
|
11
|
+
container_name: searxng
|
12
|
+
image: searxng/searxng:latest
|
13
|
+
ports:
|
14
|
+
- "127.0.0.1:8088:8080"
|
15
|
+
restart: unless-stopped
|
16
|
+
cap_drop:
|
17
|
+
- ALL
|
18
|
+
cap_add:
|
19
|
+
- CHOWN
|
20
|
+
- SETGID
|
21
|
+
- SETUID
|
22
|
+
- DAC_OVERRIDE
|
23
|
+
logging:
|
24
|
+
driver: "json-file"
|
25
|
+
options:
|
26
|
+
max-size: "1m"
|
27
|
+
max-file: "1"
|
28
|
+
volumes:
|
29
|
+
- "./config/searxng:/etc/searxng"
|
9
30
|
volumes:
|
10
31
|
redis-data:
|
data/lib/ollama_chat/chat.rb
CHANGED
@@ -19,6 +19,7 @@ class OllamaChat::Chat
|
|
19
19
|
include OllamaChat::ModelHandling
|
20
20
|
include OllamaChat::Parsing
|
21
21
|
include OllamaChat::SourceFetching
|
22
|
+
include OllamaChat::WebSearching
|
22
23
|
include OllamaChat::Dialog
|
23
24
|
include OllamaChat::Information
|
24
25
|
include OllamaChat::Clipboard
|
@@ -37,6 +38,7 @@ class OllamaChat::Chat
|
|
37
38
|
debug: config.debug,
|
38
39
|
user_agent:
|
39
40
|
)
|
41
|
+
server_version
|
40
42
|
@document_policy = config.document_policy
|
41
43
|
@model = choose_model(@opts[?m], config.model.name)
|
42
44
|
@model_options = Ollama::Options[config.model.options]
|
@@ -200,7 +202,7 @@ class OllamaChat::Chat
|
|
200
202
|
content = embed($1) or next
|
201
203
|
when %r(^/web\s+(?:(\d+)\s+)?(.+))
|
202
204
|
parse_content = false
|
203
|
-
urls = search_web($2, $1.to_i)
|
205
|
+
urls = search_web($2, $1.to_i) or next
|
204
206
|
urls.each do |url|
|
205
207
|
fetch_source(url) { |url_io| embed_source(url_io, url) }
|
206
208
|
end
|
@@ -391,7 +393,7 @@ class OllamaChat::Chat
|
|
391
393
|
Documentrix::Documents::RedisCache.new(
|
392
394
|
prefix: 'Expiring-',
|
393
395
|
url:,
|
394
|
-
ex: config.redis.expiring.ex,
|
396
|
+
ex: config.redis.expiring.ex?.to_i,
|
395
397
|
)
|
396
398
|
end
|
397
399
|
end
|
@@ -28,6 +28,8 @@ module OllamaChat::Information
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def info
|
31
|
+
STDOUT.puts "Running ollama_chat version: #{bold(OllamaChat::VERSION)}"
|
32
|
+
STDOUT.puts "Connected to ollama server version: #{bold(server_version)}"
|
31
33
|
STDOUT.puts "Current model is #{bold{@model}}."
|
32
34
|
if @model_options.present?
|
33
35
|
STDOUT.puts " Options: #{JSON.pretty_generate(@model_options).gsub(/(?<!\A)^/, ' ')}"
|
@@ -46,6 +48,7 @@ module OllamaChat::Information
|
|
46
48
|
stream.show
|
47
49
|
location.show
|
48
50
|
STDOUT.puts "Document policy for references in user text: #{bold{@document_policy}}"
|
51
|
+
STDOUT.puts "Currently selected search engine is #{bold(search_engine)}."
|
49
52
|
if @voice.on?
|
50
53
|
STDOUT.puts "Using voice #{bold{@current_voice}} to speak."
|
51
54
|
end
|
@@ -110,4 +113,8 @@ module OllamaChat::Information
|
|
110
113
|
STDOUT.puts "%s %s" % [ progname, OllamaChat::VERSION ]
|
111
114
|
0
|
112
115
|
end
|
116
|
+
|
117
|
+
def server_version
|
118
|
+
@server_version ||= ollama.version.version
|
119
|
+
end
|
113
120
|
end
|
@@ -56,5 +56,14 @@ redis:
|
|
56
56
|
url: <%= ENV.fetch('REDIS_EXPIRING_URL', 'null') %>
|
57
57
|
ex: 86400
|
58
58
|
debug: <%= ENV['OLLAMA_CHAT_DEBUG'].to_i == 1 ? true : false %>
|
59
|
+
request_headers:
|
60
|
+
Accept: 'text/*,application/*,image/*'
|
59
61
|
ssl_no_verify: []
|
60
62
|
copy: pbcopy
|
63
|
+
web_search:
|
64
|
+
use: duckduckgo
|
65
|
+
engines:
|
66
|
+
duckduckgo:
|
67
|
+
url: 'https://www.duckduckgo.com/html/?q=%{query}'
|
68
|
+
searxng:
|
69
|
+
url: 'http://localhost:8088/search?q=%{query}&format=json'
|
@@ -22,6 +22,7 @@ module OllamaChat::SourceFetching
|
|
22
22
|
links.add(source.to_s)
|
23
23
|
OllamaChat::Utils::Fetcher.get(
|
24
24
|
source,
|
25
|
+
headers: config.request_headers?.to_h,
|
25
26
|
cache: @cache,
|
26
27
|
debug: config.debug,
|
27
28
|
http_options: http_options(OllamaChat::Utils::Fetcher.normalize_url(source))
|
@@ -140,33 +141,4 @@ module OllamaChat::SourceFetching
|
|
140
141
|
summarize(source)
|
141
142
|
end
|
142
143
|
end
|
143
|
-
|
144
|
-
def search_web(query, n = nil)
|
145
|
-
if l = @messages.at_location.full?
|
146
|
-
query += " #{l}"
|
147
|
-
end
|
148
|
-
n = n.to_i.clamp(1..)
|
149
|
-
query = URI.encode_uri_component(query)
|
150
|
-
url = "https://www.duckduckgo.com/html/?q=#{query}"
|
151
|
-
OllamaChat::Utils::Fetcher.get(url, debug: config.debug) do |tmp|
|
152
|
-
result = []
|
153
|
-
doc = Nokogiri::HTML(tmp)
|
154
|
-
doc.css('.results_links').each do |link|
|
155
|
-
if n > 0
|
156
|
-
url = link.css('.result__a').first&.[]('href')
|
157
|
-
url.sub!(%r(\A(//duckduckgo\.com)?/l/\?uddg=), '')
|
158
|
-
url.sub!(%r(&rut=.*), '')
|
159
|
-
url = URI.decode_uri_component(url)
|
160
|
-
url = URI.parse(url)
|
161
|
-
url.host =~ /duckduckgo\.com/ and next
|
162
|
-
links.add(url.to_s)
|
163
|
-
result << url
|
164
|
-
n -= 1
|
165
|
-
else
|
166
|
-
break
|
167
|
-
end
|
168
|
-
end
|
169
|
-
result
|
170
|
-
end
|
171
|
-
end
|
172
144
|
end
|
@@ -20,14 +20,14 @@ class OllamaChat::Utils::Fetcher
|
|
20
20
|
|
21
21
|
class RetryWithoutStreaming < StandardError; end
|
22
22
|
|
23
|
-
def self.get(url, **options, &block)
|
23
|
+
def self.get(url, headers: {}, **options, &block)
|
24
24
|
cache = options.delete(:cache) and
|
25
25
|
cache = OllamaChat::Utils::CacheFetcher.new(cache)
|
26
26
|
if result = cache&.get(url, &block)
|
27
27
|
infobar.puts "Getting #{url.to_s.inspect} from cache."
|
28
28
|
return result
|
29
29
|
else
|
30
|
-
new(**options).send(:get, url) do |tmp|
|
30
|
+
new(**options).send(:get, url, headers:) do |tmp|
|
31
31
|
result = block.(tmp)
|
32
32
|
if cache && !tmp.is_a?(StringIO)
|
33
33
|
tmp.rewind
|
@@ -91,7 +91,9 @@ class OllamaChat::Utils::Fetcher
|
|
91
91
|
Excon.new(url, options.merge(@http_options))
|
92
92
|
end
|
93
93
|
|
94
|
-
def get(url, &block)
|
94
|
+
def get(url, headers: {}, &block)
|
95
|
+
headers |= self.headers
|
96
|
+
headers = headers.transform_keys(&:to_s)
|
95
97
|
response = nil
|
96
98
|
Tempfile.open do |tmp|
|
97
99
|
infobar.label = 'Getting'
|
data/lib/ollama_chat/version.rb
CHANGED
@@ -0,0 +1,60 @@
|
|
1
|
+
module OllamaChat::WebSearching
|
2
|
+
def search_web(query, n = nil)
|
3
|
+
l = @messages.at_location.full? and query += " #{l}"
|
4
|
+
n = n.to_i.clamp(1..)
|
5
|
+
query = URI.encode_uri_component(query)
|
6
|
+
search_command = :"search_web_with_#{search_engine}"
|
7
|
+
if respond_to?(search_command, true)
|
8
|
+
send(search_command, query, n)
|
9
|
+
else
|
10
|
+
STDOUT.puts "Search engine #{bold{search_engine}} not implemented!"
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def search_engine
|
18
|
+
config.web_search.use
|
19
|
+
end
|
20
|
+
|
21
|
+
def search_web_with_searxng(query, n)
|
22
|
+
url = config.web_search.engines.searxng.url % { query: }
|
23
|
+
OllamaChat::Utils::Fetcher.get(
|
24
|
+
url,
|
25
|
+
headers: config.request_headers?.to_h,
|
26
|
+
debug: config.debug
|
27
|
+
) do |tmp|
|
28
|
+
data = JSON.parse(tmp.read, object_class: JSON::GenericObject)
|
29
|
+
data.results.first(n).map(&:url)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def search_web_with_duckduckgo(query, n)
|
34
|
+
url = config.web_search.engines.duckduckgo.url % { query: }
|
35
|
+
OllamaChat::Utils::Fetcher.get(
|
36
|
+
url,
|
37
|
+
headers: config.request_headers?.to_h,
|
38
|
+
debug: config.debug
|
39
|
+
) do |tmp|
|
40
|
+
result = []
|
41
|
+
doc = Nokogiri::HTML(tmp)
|
42
|
+
doc.css('.results_links').each do |link|
|
43
|
+
if n > 0
|
44
|
+
url = link.css('.result__a').first&.[]('href')
|
45
|
+
url.sub!(%r(\A(//duckduckgo\.com)?/l/\?uddg=), '')
|
46
|
+
url.sub!(%r(&rut=.*), '')
|
47
|
+
url = URI.decode_uri_component(url)
|
48
|
+
url = URI.parse(url)
|
49
|
+
url.host =~ /duckduckgo\.com/ and next
|
50
|
+
links.add(url.to_s)
|
51
|
+
result << url
|
52
|
+
n -= 1
|
53
|
+
else
|
54
|
+
break
|
55
|
+
end
|
56
|
+
end
|
57
|
+
result
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/ollama_chat.rb
CHANGED
@@ -13,6 +13,7 @@ require 'ollama_chat/message_list'
|
|
13
13
|
require 'ollama_chat/model_handling'
|
14
14
|
require 'ollama_chat/parsing'
|
15
15
|
require 'ollama_chat/source_fetching'
|
16
|
+
require 'ollama_chat/web_searching'
|
16
17
|
require 'ollama_chat/dialog'
|
17
18
|
require 'ollama_chat/information'
|
18
19
|
require 'ollama_chat/clipboard'
|
data/ollama_chat.gemspec
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: ollama_chat 0.0.
|
2
|
+
# stub: ollama_chat 0.0.4 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "ollama_chat".freeze
|
6
|
-
s.version = "0.0.
|
6
|
+
s.version = "0.0.4".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 = "2025-02-
|
11
|
+
s.date = "2025-02-21"
|
12
12
|
s.description = "The app provides a command-line interface (CLI) to an Ollama AI model,\nallowing users to engage in text-based conversations and generate\nhuman-like responses. Users can import data from local files or web pages,\nwhich are then processed through three different modes: fully importing the\ncontent into the conversation context, summarizing the information for\nconcise reference, or storing it in an embedding vector database for later\nretrieval based on the conversation.\n".freeze
|
13
13
|
s.email = "flori@ping.de".freeze
|
14
14
|
s.executables = ["ollama_chat".freeze]
|
15
|
-
s.extra_rdoc_files = ["README.md".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/information.rb".freeze, "lib/ollama_chat/message_list.rb".freeze, "lib/ollama_chat/message_type.rb".freeze, "lib/ollama_chat/model_handling.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/source_fetching.rb".freeze, "lib/ollama_chat/switches.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/version.rb".freeze]
|
16
|
-
s.files = [".all_images.yml".freeze, ".envrc".freeze, ".gitignore".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/ollama_chat".freeze, "docker-compose.yml".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/information.rb".freeze, "lib/ollama_chat/message_list.rb".freeze, "lib/ollama_chat/message_type.rb".freeze, "lib/ollama_chat/model_handling.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/ollama_chat_config/default_config.yml".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/source_fetching.rb".freeze, "lib/ollama_chat/switches.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/version.rb".freeze, "ollama_chat.gemspec".freeze, "redis/redis.conf".freeze, "spec/assets/api_show.json".freeze, "spec/assets/api_tags.json".freeze, "spec/assets/conversation.json".freeze, "spec/assets/duckduckgo.html".freeze, "spec/assets/example.atom".freeze, "spec/assets/example.csv".freeze, "spec/assets/example.html".freeze, "spec/assets/example.pdf".freeze, "spec/assets/example.ps".freeze, "spec/assets/example.rb".freeze, "spec/assets/example.rss".freeze, "spec/assets/example.xml".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/prompt.txt".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/file_argument_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
|
15
|
+
s.extra_rdoc_files = ["README.md".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/information.rb".freeze, "lib/ollama_chat/message_list.rb".freeze, "lib/ollama_chat/message_type.rb".freeze, "lib/ollama_chat/model_handling.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/source_fetching.rb".freeze, "lib/ollama_chat/switches.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/version.rb".freeze, "lib/ollama_chat/web_searching.rb".freeze]
|
16
|
+
s.files = [".all_images.yml".freeze, ".envrc".freeze, ".gitignore".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/ollama_chat".freeze, "config/searxng/settings.yml".freeze, "docker-compose.yml".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/information.rb".freeze, "lib/ollama_chat/message_list.rb".freeze, "lib/ollama_chat/message_type.rb".freeze, "lib/ollama_chat/model_handling.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/ollama_chat_config/default_config.yml".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/source_fetching.rb".freeze, "lib/ollama_chat/switches.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/version.rb".freeze, "lib/ollama_chat/web_searching.rb".freeze, "ollama_chat.gemspec".freeze, "redis/redis.conf".freeze, "spec/assets/api_show.json".freeze, "spec/assets/api_tags.json".freeze, "spec/assets/api_version.json".freeze, "spec/assets/conversation.json".freeze, "spec/assets/duckduckgo.html".freeze, "spec/assets/example.atom".freeze, "spec/assets/example.csv".freeze, "spec/assets/example.html".freeze, "spec/assets/example.pdf".freeze, "spec/assets/example.ps".freeze, "spec/assets/example.rb".freeze, "spec/assets/example.rss".freeze, "spec/assets/example.xml".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/prompt.txt".freeze, "spec/assets/searxng.json".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/file_argument_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
|
17
17
|
s.homepage = "https://github.com/flori/ollama_chat".freeze
|
18
18
|
s.licenses = ["MIT".freeze]
|
19
19
|
s.rdoc_options = ["--title".freeze, "OllamaChat - A command-line interface (CLI) for interacting with an Ollama AI model.".freeze, "--main".freeze, "README.md".freeze]
|
20
20
|
s.required_ruby_version = Gem::Requirement.new("~> 3.1".freeze)
|
21
21
|
s.rubygems_version = "3.6.2".freeze
|
22
22
|
s.summary = "A command-line interface (CLI) for interacting with an Ollama AI model.".freeze
|
23
|
-
s.test_files = ["spec/assets/example.rb".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/file_argument_spec.rb".freeze, "spec/spec_helper.rb".freeze]
|
23
|
+
s.test_files = ["spec/assets/example.rb".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/file_argument_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze]
|
24
24
|
|
25
25
|
s.specification_version = 4
|
26
26
|
|
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
|
|
32
32
|
s.add_development_dependency(%q<debug>.freeze, [">= 0".freeze])
|
33
33
|
s.add_development_dependency(%q<simplecov>.freeze, [">= 0".freeze])
|
34
34
|
s.add_runtime_dependency(%q<excon>.freeze, ["~> 1.0".freeze])
|
35
|
-
s.add_runtime_dependency(%q<ollama-ruby>.freeze, ["~> 0.
|
35
|
+
s.add_runtime_dependency(%q<ollama-ruby>.freeze, ["~> 0.15".freeze])
|
36
36
|
s.add_runtime_dependency(%q<documentrix>.freeze, ["~> 0.0".freeze])
|
37
37
|
s.add_runtime_dependency(%q<rss>.freeze, ["~> 0.3".freeze])
|
38
38
|
s.add_runtime_dependency(%q<term-ansicolor>.freeze, ["~> 1.11".freeze])
|
@@ -0,0 +1,111 @@
|
|
1
|
+
{
|
2
|
+
"query": "foo",
|
3
|
+
"number_of_results": 0,
|
4
|
+
"results": [
|
5
|
+
{
|
6
|
+
"url": "https://en.wikipedia.org/wiki/Foo_Fighters",
|
7
|
+
"title": "Foo Fighters - Wikipedia",
|
8
|
+
"content": "The Foo Fighters are an American rock band formed in Seattle in 1994. Initially founded as a one-man project by former Nirvana drummer Dave Grohl, the band comprises vocalist/guitarist Grohl, bassist Nate Mendel, guitarist Pat Smear, guitarist Chris Shiflett, keyboardist Rami Jaffee and drummer Josh Freese.Guitarist Franz Stahl and drummers William Goldsmith and Taylor Hawkins are former ...",
|
9
|
+
"publishedDate": null,
|
10
|
+
"thumbnail": null,
|
11
|
+
"engine": "brave",
|
12
|
+
"template": "default.html",
|
13
|
+
"parsed_url": [
|
14
|
+
"https",
|
15
|
+
"en.wikipedia.org",
|
16
|
+
"/wiki/Foo_Fighters",
|
17
|
+
"",
|
18
|
+
"",
|
19
|
+
""
|
20
|
+
],
|
21
|
+
"engines": [
|
22
|
+
"startpage",
|
23
|
+
"brave",
|
24
|
+
"google",
|
25
|
+
"duckduckgo"
|
26
|
+
],
|
27
|
+
"positions": [
|
28
|
+
2,
|
29
|
+
1,
|
30
|
+
2,
|
31
|
+
1
|
32
|
+
],
|
33
|
+
"score": 12.0,
|
34
|
+
"category": "general"
|
35
|
+
},
|
36
|
+
{
|
37
|
+
"url": "https://www.foofighters.com",
|
38
|
+
"title": "Home - Foo Fighters",
|
39
|
+
"content": "Official website of Foo Fighters",
|
40
|
+
"publishedDate": "2023-04-19T00:00:00",
|
41
|
+
"thumbnail": null,
|
42
|
+
"engine": "brave",
|
43
|
+
"template": "default.html",
|
44
|
+
"parsed_url": [
|
45
|
+
"https",
|
46
|
+
"www.foofighters.com",
|
47
|
+
"",
|
48
|
+
"",
|
49
|
+
"",
|
50
|
+
""
|
51
|
+
],
|
52
|
+
"engines": [
|
53
|
+
"startpage",
|
54
|
+
"brave",
|
55
|
+
"google",
|
56
|
+
"duckduckgo"
|
57
|
+
],
|
58
|
+
"positions": [
|
59
|
+
1,
|
60
|
+
2,
|
61
|
+
7,
|
62
|
+
2
|
63
|
+
],
|
64
|
+
"score": 8.571428571428571,
|
65
|
+
"category": "general"
|
66
|
+
},
|
67
|
+
{
|
68
|
+
"url": "https://www.dictionary.com/e/tech-science/foo/",
|
69
|
+
"title": "foo | Meaning & Origin | Dictionary.com",
|
70
|
+
"content": "\"Foo was here\" was a popular piece of graffiti drawn by Australian soldiers in WWII, and possibly even WWI, that depicts a little man poking his head and large nose over the wall à la Kilroy. While the origins of this foo are unclear, it appears to be unrelated to Holman's foo.",
|
71
|
+
"publishedDate": "2022-07-04T00:00:00",
|
72
|
+
"thumbnail": "",
|
73
|
+
"engine": "brave",
|
74
|
+
"template": "default.html",
|
75
|
+
"parsed_url": [
|
76
|
+
"https",
|
77
|
+
"www.dictionary.com",
|
78
|
+
"/e/tech-science/foo/",
|
79
|
+
"",
|
80
|
+
"",
|
81
|
+
""
|
82
|
+
],
|
83
|
+
"engines": [
|
84
|
+
"brave",
|
85
|
+
"duckduckgo"
|
86
|
+
],
|
87
|
+
"positions": [
|
88
|
+
13,
|
89
|
+
1
|
90
|
+
],
|
91
|
+
"score": 2.1538461538461537,
|
92
|
+
"category": "general"
|
93
|
+
}
|
94
|
+
],
|
95
|
+
"suggestions": [
|
96
|
+
"foo fighters - everlong",
|
97
|
+
"Foo meaning",
|
98
|
+
"Foo Fighters WW2",
|
99
|
+
"Foo Fighters - Learn to Fly",
|
100
|
+
"foo fighters - the colour and the shape",
|
101
|
+
"Foo Fighters tour 2024",
|
102
|
+
"Foo programming",
|
103
|
+
"Foo word"
|
104
|
+
],
|
105
|
+
"unresponsive_engines": [
|
106
|
+
[
|
107
|
+
"qwant",
|
108
|
+
"Suspended: CAPTCHA"
|
109
|
+
]
|
110
|
+
]
|
111
|
+
}
|
@@ -2,19 +2,14 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
RSpec.describe OllamaChat::Chat do
|
4
4
|
let :argv do
|
5
|
-
[]
|
5
|
+
%w[ -C test ]
|
6
6
|
end
|
7
7
|
|
8
8
|
let :chat do
|
9
9
|
OllamaChat::Chat.new argv: argv
|
10
10
|
end
|
11
11
|
|
12
|
-
|
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
|
12
|
+
connect_to_ollama_server(instantiate: false)
|
18
13
|
|
19
14
|
it 'can be instantiated' do
|
20
15
|
expect(chat).to be_a described_class
|
@@ -43,7 +38,7 @@ RSpec.describe OllamaChat::Chat do
|
|
43
38
|
describe Documentrix::Documents do
|
44
39
|
context 'with documents' do
|
45
40
|
let :argv do
|
46
|
-
%w[ -D ] << asset('example.html')
|
41
|
+
%w[ -C test -D ] << asset('example.html')
|
47
42
|
end
|
48
43
|
|
49
44
|
it 'Adds documents passed to app via -D option' do
|
@@ -66,7 +61,7 @@ RSpec.describe OllamaChat::Chat do
|
|
66
61
|
it 'can display collection_stats' do
|
67
62
|
chat
|
68
63
|
expect(STDOUT).to receive(:puts).with(
|
69
|
-
"Current Collection\n Name: \e[
|
64
|
+
"Current Collection\n Name: \e[1mtest\e[0m\n #Embeddings: 0\n #Tags: 0\n Tags: \n"
|
70
65
|
)
|
71
66
|
expect(chat.collection_stats).to be_nil
|
72
67
|
end
|
@@ -76,6 +71,8 @@ RSpec.describe OllamaChat::Chat do
|
|
76
71
|
expect(STDOUT).to receive(:puts).
|
77
72
|
with(
|
78
73
|
/
|
74
|
+
Running\ ollama_chat\ version|
|
75
|
+
Connected\ to\ ollama\ server|
|
79
76
|
Current\ model|
|
80
77
|
Options|
|
81
78
|
Embedding|
|
@@ -84,7 +81,8 @@ RSpec.describe OllamaChat::Chat do
|
|
84
81
|
output\ content|
|
85
82
|
Streaming|
|
86
83
|
Location|
|
87
|
-
Document\ policy
|
84
|
+
Document\ policy|
|
85
|
+
Currently\ selected\ search\ engine
|
88
86
|
/x
|
89
87
|
).at_least(1)
|
90
88
|
expect(chat.info).to be_nil
|
@@ -5,13 +5,7 @@ RSpec.describe OllamaChat::Clipboard do
|
|
5
5
|
OllamaChat::Chat.new
|
6
6
|
end
|
7
7
|
|
8
|
-
|
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
|
8
|
+
connect_to_ollama_server
|
15
9
|
|
16
10
|
it 'can copy to clipboard' do
|
17
11
|
expect(STDERR).to receive(:puts).with(/No response available to copy to the system clipboard/)
|
@@ -5,13 +5,7 @@ RSpec.describe OllamaChat::Information do
|
|
5
5
|
OllamaChat::Chat.new
|
6
6
|
end
|
7
7
|
|
8
|
-
|
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
|
8
|
+
connect_to_ollama_server
|
15
9
|
|
16
10
|
describe ::OllamaChat::Information::UserAgent do
|
17
11
|
it 'has progname' do
|
@@ -29,6 +23,7 @@ RSpec.describe OllamaChat::Information do
|
|
29
23
|
end
|
30
24
|
|
31
25
|
it 'can show info' do
|
26
|
+
expect(STDOUT).to receive(:puts).with(/Connected to ollama server version/)
|
32
27
|
expect(STDOUT).to receive(:puts).with(/Current model is/)
|
33
28
|
expect(STDOUT).to receive(:puts).at_least(1)
|
34
29
|
expect(chat.info).to be_nil
|
@@ -5,13 +5,7 @@ RSpec.describe OllamaChat::ModelHandling do
|
|
5
5
|
OllamaChat::Chat.new
|
6
6
|
end
|
7
7
|
|
8
|
-
|
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
|
8
|
+
connect_to_ollama_server
|
15
9
|
|
16
10
|
it 'can check if model_present?' do
|
17
11
|
expect(chat.ollama).to receive(:show).and_raise Ollama::Errors::NotFoundError
|
@@ -6,13 +6,7 @@ RSpec.describe OllamaChat::Parsing do
|
|
6
6
|
OllamaChat::Chat.new
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
stub_request(:get, %r(/api/tags\z)).
|
11
|
-
to_return(status: 200, body: asset_json('api_tags.json'))
|
12
|
-
stub_request(:post, %r(/api/show\z)).
|
13
|
-
to_return(status: 200, body: asset_json('api_show.json'))
|
14
|
-
chat
|
15
|
-
end
|
9
|
+
connect_to_ollama_server
|
16
10
|
|
17
11
|
describe '#parse_source' do
|
18
12
|
it 'can parse HTML' do
|
@@ -5,13 +5,7 @@ RSpec.describe OllamaChat::SourceFetching do
|
|
5
5
|
OllamaChat::Chat.new
|
6
6
|
end
|
7
7
|
|
8
|
-
|
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
|
-
allow(chat).to receive(:location).and_return(double(on?: false))
|
14
|
-
end
|
8
|
+
connect_to_ollama_server
|
15
9
|
|
16
10
|
it 'can import' do
|
17
11
|
expect(chat.import('./spec/assets/example.html')).to start_with(<<~EOT)
|
@@ -42,13 +36,4 @@ RSpec.describe OllamaChat::SourceFetching do
|
|
42
36
|
'This source was now embedded: ./spec/assets/example.html'
|
43
37
|
)
|
44
38
|
end
|
45
|
-
|
46
|
-
it 'can search web' do
|
47
|
-
stub_request(:get, "https://www.duckduckgo.com/html/?q=foo").
|
48
|
-
with(headers: { 'Host'=>'www.duckduckgo.com' }).
|
49
|
-
to_return(status: 200, body: asset_content('duckduckgo.html'), headers: {})
|
50
|
-
expect(chat.search_web('foo').first.to_s).to eq(
|
51
|
-
'https://en.wikipedia.org/wiki/Foo_Fighters'
|
52
|
-
)
|
53
|
-
end
|
54
39
|
end
|
@@ -33,6 +33,21 @@ RSpec.describe OllamaChat::Utils::Fetcher do
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
it 'can #get with headers' do
|
37
|
+
stub_request(:get, url).
|
38
|
+
with(headers: { 'Accept' => 'text/html' } | fetcher.headers).
|
39
|
+
to_return(
|
40
|
+
status: 200,
|
41
|
+
body: 'world',
|
42
|
+
headers: { 'Content-Type' => 'text/plain' },
|
43
|
+
)
|
44
|
+
fetcher.get(url, headers: { 'Accept' => 'text/html' }) do |tmp|
|
45
|
+
expect(tmp).to be_a Tempfile
|
46
|
+
expect(tmp.read).to eq 'world'
|
47
|
+
expect(tmp.content_type).to eq 'text/plain'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
36
51
|
it 'can #get without ssl peer verification' do
|
37
52
|
fetcher = described_class.new(
|
38
53
|
http_options: { ssl_verify_peer: false }
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe OllamaChat::WebSearching do
|
4
|
+
let :chat do
|
5
|
+
OllamaChat::Chat.new
|
6
|
+
end
|
7
|
+
|
8
|
+
connect_to_ollama_server
|
9
|
+
|
10
|
+
it 'can search web with duckduckgo' do
|
11
|
+
expect(chat).to receive(:search_engine).and_return 'duckduckgo'
|
12
|
+
stub_request(:get, 'https://www.duckduckgo.com/html/?q=foo').
|
13
|
+
with(headers: { 'Host'=>'www.duckduckgo.com' }).
|
14
|
+
to_return(status: 200, body: asset_content('duckduckgo.html'), headers: {})
|
15
|
+
expect(chat.search_web('foo').first.to_s).to eq(
|
16
|
+
'https://en.wikipedia.org/wiki/Foo_Fighters'
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'can search web with searxng' do
|
21
|
+
expect(chat).to receive(:search_engine).and_return 'searxng'
|
22
|
+
stub_request(:get, 'http://localhost:8088/search?format=json&language=en&q=foo').
|
23
|
+
with(headers: { 'Host'=>'localhost:8088' }).
|
24
|
+
to_return(status: 200, body: asset_content('searxng.json'), headers: {})
|
25
|
+
expect(chat.search_web('foo').first.to_s).to eq(
|
26
|
+
'https://en.wikipedia.org/wiki/Foo_Fighters'
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -39,6 +39,18 @@ def asset_json(name)
|
|
39
39
|
JSON(JSON(File.read(asset(name))))
|
40
40
|
end
|
41
41
|
|
42
|
+
def connect_to_ollama_server(instantiate: true)
|
43
|
+
before do
|
44
|
+
stub_request(:get, %r(/api/tags\z)).
|
45
|
+
to_return(status: 200, body: asset_json('api_tags.json'))
|
46
|
+
stub_request(:post, %r(/api/show\z)).
|
47
|
+
to_return(status: 200, body: asset_json('api_show.json'))
|
48
|
+
stub_request(:get, %r(/api/version\z)).
|
49
|
+
to_return(status: 200, body: asset_json('api_version.json'))
|
50
|
+
instantiate and chat
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
42
54
|
RSpec.configure do |config|
|
43
55
|
config.before(:suite) do
|
44
56
|
infobar.show = nil
|