Class: Spectre::Ollama::Completions

Inherits:
Object
  • Object
show all
Defined in:
lib/spectre/ollama/completions.rb

Constant Summary collapse

API_PATH =
'api/chat'
DEFAULT_MODEL =
'llama3.1:8b'
DEFAULT_TIMEOUT =
60

Class Method Summary collapse

Class Method Details

.create(messages:, model: DEFAULT_MODEL, json_schema: nil, tools: nil, **args) ⇒ Hash

Class method to generate a completion based on user messages and optional tools

Parameters:

  • messages (Array<Hash>)

    The conversation messages, each with a role and content

  • model (String) (defaults to: DEFAULT_MODEL)

    The model to be used for generating completions, defaults to DEFAULT_MODEL

  • json_schema (Hash, nil) (defaults to: nil)

    An optional JSON schema to enforce structured output

  • tools (Array<Hash>, nil) (defaults to: nil)

    An optional array of tool definitions for function calling

  • args (Hash, nil)

    optional arguments like read_timeout and open_timeout. You can pass in the ollama hash to specify the path and options.

  • args.ollama.path (String, nil)

    The path to the Ollama API endpoint, defaults to API_PATH

  • args.ollama.options (Hash, nil)

    Additional model parameters listed in the documentation for the github.com/ollama/ollama/blob/main/docs/modelfile.md#valid-parameters-and-values such as temperature

Returns:

  • (Hash)

    The parsed response including any function calls or content

Raises:



27
28
29
30
31
32
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
# File 'lib/spectre/ollama/completions.rb', line 27

def self.create(messages:, model: DEFAULT_MODEL, json_schema: nil, tools: nil, **args)
  api_host = Spectre.ollama_configuration.host
  api_key = Spectre.ollama_configuration.api_key
  raise HostNotConfiguredError, "Host is not configured" unless api_host
  raise APIKeyNotConfiguredError, "API key is not configured" unless api_key

  validate_messages!(messages)

  path = args.dig(:ollama, :path) || API_PATH
  uri = URI.join(api_host, path)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true if uri.scheme == 'https'
  http.read_timeout = args.fetch(:read_timeout, DEFAULT_TIMEOUT)
  http.open_timeout = args.fetch(:open_timeout, DEFAULT_TIMEOUT)

  request = Net::HTTP::Post.new(uri.path, {
    'Content-Type' => 'application/json',
    'Authorization' => "Bearer #{api_key}"
  })

  options = args.dig(:ollama, :options)
  request.body = generate_body(messages, model, json_schema, tools, options).to_json
  response = http.request(request)

  unless response.is_a?(Net::HTTPSuccess)
    raise "Ollama API Error: #{response.code} - #{response.message}: #{response.body}"
  end

  parsed_response = JSON.parse(response.body)

  handle_response(parsed_response)
rescue JSON::ParserError => e
  raise "JSON Parse Error: #{e.message}"
end