33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
# File 'lib/scout/llm/backends/ollama.rb', line 33
def self.ask(question, options = {}, &block)
original_options = options.dup
messages = LLM.chat(question)
options = options.merge LLM.options messages
client, url, key, model, return_messages, format, stream, previous_response_id, tools = IndiferentHash.process_options options,
:client, :url, :key, :model, :return_messages, :format, :stream, :previous_response_id, :tools,
stream: false
if client.nil?
url ||= Scout::Config.get(:url, :ollama_ask, :ask, :ollama, env: 'OLLAMA_URL', default: "http://localhost:11434")
key ||= LLM.get_url_config(:key, url, :ollama_ask, :ask, :ollama, env: 'OLLAMA_KEY')
client = self.client url, key
end
if model.nil?
url ||= Scout::Config.get(:url, :ollama_ask, :ask, :ollama, env: 'OLLAMA_URL', default: "http://localhost:11434")
model ||= LLM.get_url_config(:model, url, :ollama_ask, :ask, :ollama, env: 'OLLAMA_MODEL', default: "mistral")
end
case format.to_sym
when :json, :json_object
options[:response_format] = {type: 'json_object'}
else
options[:response_format] = {type: format}
end if format
parameters = options.merge(model: model)
case tools
when Array
tools = tools.inject({}) do |acc,definition|
IndiferentHash.setup definition
name = definition.dig('name') || definition.dig('function', 'name')
acc.merge(name => definition)
end
when nil
tools = {}
end
tools.merge!(LLM.tools messages)
tools.merge!(LLM.associations messages)
if tools.any?
parameters[:tools] = LLM.tool_definitions_to_ollama tools
end
Log.low "Calling ollama #{url}: #{Log.fingerprint(parameters.except(:tools))}}"
Log.medium "Tools: #{Log.fingerprint tools.keys}}" if tools
parameters[:messages] = LLM.tools_to_ollama messages
parameters[:stream] = stream
response = self.process_response client.chat(parameters), tools, &block
res = if response.last[:role] == 'function_call_output'
response + self.ask(response + messages, original_options.except(:tool_choice).merge(return_messages: true, tools: tools), &block)
else
response
end
if return_messages
res
else
res.last['content']
end
end
|