Module: LLM::OLlamaMethods

Included in:
OLlama
Defined in:
lib/scout/llm/backends/ollama.rb

Instance Method Summary collapse

Instance Method Details

#client(options, messages = nil) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
# File 'lib/scout/llm/backends/ollama.rb', line 17

def client(options, messages = nil)
  url, key = IndiferentHash.process_options options,
    :url, :key

  Ollama.new(
    credentials: {
      address: url,
      bearer_token: key
    }
  )
end

#embed_query(client, text, parameters = {}) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/scout/llm/backends/ollama.rb', line 42

def embed_query(client, text, parameters = {})
  parameters[:input] = text

  begin
    embeddings = client.request('api/embed', parameters)
  rescue
    Log.debug 'Input parameters: ' + "\n" + JSON.pretty_generate(parameters)
    raise $!
  end

  Array === text ? embeddings.first['embeddings'] : embeddings.first['embeddings'].first
end

#extra_options(options, messages = nil) ⇒ Object



6
7
8
9
10
11
12
13
14
15
# File 'lib/scout/llm/backends/ollama.rb', line 6

def extra_options(options, messages = nil)
  format = IndiferentHash.process_options options, :format

  case format.to_sym
  when :json, :json_object
    options[:response_format] = { type: 'json_object' }
  else
    options[:response_format] = { type: format }
  end if format
end

#format_tool_call(message) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/scout/llm/backends/ollama.rb', line 99

def format_tool_call(message)
  tool_call = JSON.parse(message[:content])
  arguments = tool_call.delete('arguments') || {}
  id = tool_call.delete('id')
  name = tool_call.delete('name')
  tool_call['type'] = 'function'
  tool_call['function'] ||= {}
  tool_call['function']['name'] ||= name
  tool_call['function']['arguments'] ||= arguments
  { role: 'assistant', tool_calls: [tool_call] }
end

#format_tool_definitions(tools) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/scout/llm/backends/ollama.rb', line 81

def format_tool_definitions(tools)
  tools.values.collect do |obj, definition|
    definition = obj if Hash === obj
    definition = IndiferentHash.setup definition

    definition = case definition[:function]
                 when Hash
                   definition
                 else
                   { type: :function, function: definition }
                 end

    definition = IndiferentHash.add_defaults definition, type: :function

    definition
  end
end

#format_tool_output(message, last_id = nil) ⇒ Object



111
112
113
114
115
116
# File 'lib/scout/llm/backends/ollama.rb', line 111

def format_tool_output(message, last_id = nil)
  info = JSON.parse(message[:content])
  id = info.delete('id') || ''
  info['role'] = 'tool'
  info
end

#parse_tool_call(info) ⇒ Object



55
56
57
58
59
# File 'lib/scout/llm/backends/ollama.rb', line 55

def parse_tool_call(info)
  arguments, name = IndiferentHash.process_options info['function'], :arguments, :name
  id = info[:id] || name + '_' + Misc.digest(arguments)
  { arguments: arguments, id: id, name: name }
end

#process_response(messages, responses, tools, options, &block) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/scout/llm/backends/ollama.rb', line 61

def process_response(messages, responses, tools, options, &block)
  output = responses.collect do |response|

    message = IndiferentHash.setup response['message']
    tool_calls = response.dig('tool_calls') ||
      response.dig('message', 'tool_calls')

    next if message[:role] == 'assistant' && message[:content].empty? && tool_calls.nil?

    if tool_calls && tool_calls.any?
      tool_calls = tool_calls.collect { |tool_call| parse_tool_call(tool_call) }
      LLM.process_calls tools, tool_calls, &block
    else
      [message]
    end
  end.flatten.compact

  output
end

#query(client, messages, tools = [], parameters = {}) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/scout/llm/backends/ollama.rb', line 29

def query(client, messages, tools = [], parameters = {})
  parameters[:stream] = false
  parameters[:tools] = format_tool_definitions(tools) if tools && tools.any?
  parameters[:messages] = messages

  begin
    client.chat(parameters)
  rescue
    Log.debug 'Input parameters: ' + "\n" + JSON.pretty_generate(parameters)
    raise $!
  end
end