Class: OllamaAgent::Providers::Ollama

Inherits:
Base
  • Object
show all
Defined in:
lib/ollama_agent/providers/ollama.rb

Overview

Ollama provider — wraps the existing ollama-client gem.

Supports two modes:

Local Ollama (default)
  host:    "http://localhost:11434"  (or OLLAMA_HOST)
  api_key: nil

Ollama Cloud
  host:    "https://api.ollama.com"  (or OLLAMA_BASE_URL)
  api_key: "ollama_..."               (or OLLAMA_API_KEY)

When api_key is provided the key is injected into Ollama::Config so every request carries Authorization: Bearer <key>. This is how multi-key Ollama Cloud credential pools work — each Credential supplies its own key.

Constant Summary collapse

CLOUD_HOST =
"https://api.ollama.com"
LOCAL_HOST =
"http://localhost:11434"
DEFAULT_TIMEOUT =
120

Instance Attribute Summary

Attributes inherited from Base

#name

Instance Method Summary collapse

Methods inherited from Base

#estimate_cost, #to_s

Constructor Details

#initialize(host: nil, api_key: nil, timeout: nil) ⇒ Ollama

Returns a new instance of Ollama.



27
28
29
30
31
32
33
# File 'lib/ollama_agent/providers/ollama.rb', line 27

def initialize(host: nil, api_key: nil, timeout: nil, **)
  super(name: "ollama", **)
  @api_key = api_key || ENV.fetch("OLLAMA_API_KEY", nil)
  @host    = host    || ENV.fetch("OLLAMA_BASE_URL", nil) ||
             ENV.fetch("OLLAMA_HOST", LOCAL_HOST)
  @timeout = timeout || DEFAULT_TIMEOUT
end

Instance Method Details

#available?Boolean

Returns:

  • (Boolean)


58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/ollama_agent/providers/ollama.rb', line 58

def available?
  require "net/http"
  # For Ollama Cloud, check by hitting the tags endpoint with the key
  uri = URI("#{@host}/api/tags")
  req = Net::HTTP::Get.new(uri)
  req["Authorization"] = "Bearer #{@api_key}" if @api_key
  resp = Net::HTTP.start(uri.host, uri.port,
                         use_ssl: uri.scheme == "https",
                         open_timeout: 5, read_timeout: 10) { |h| h.request(req) }
  resp.is_a?(Net::HTTPSuccess)
rescue StandardError
  false
end

#chat(messages:, model:, tools: nil, stream_hooks: nil, temperature: 0.2, think: nil, **_opts) ⇒ Response

Parameters:

  • messages (Array<Hash>)
  • model (String)
  • tools (Array<Hash>) (defaults to: nil)
  • stream_hooks (Hash) (defaults to: nil)

    :on_token, :on_thinking lambdas

  • temperature (Float) (defaults to: 0.2)
  • think (String, nil) (defaults to: nil)

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/ollama_agent/providers/ollama.rb', line 42

def chat(messages:, model:, tools: nil, stream_hooks: nil, temperature: 0.2, think: nil, **_opts)
  require "ollama_client"

  client = build_client
  req    = build_request(messages: messages, model: model, tools: tools,
                         temperature: temperature, think: think)

  raw = if stream_hooks
          client.chat(**req, hooks: stream_hooks)
        else
          client.chat(**req)
        end

  build_response(raw, model)
end

#cloud?Boolean

True when this credential is configured for Ollama Cloud (has an api_key).

Returns:

  • (Boolean)


77
78
79
# File 'lib/ollama_agent/providers/ollama.rb', line 77

def cloud?
  @api_key && !@api_key.to_s.strip.empty?
end

#streaming_supported?Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/ollama_agent/providers/ollama.rb', line 72

def streaming_supported?
  true
end

#subscription_required?(model) ⇒ Boolean

Performs a pre-flight check using the /api/show endpoint.

Parameters:

  • model (String)

Returns:

  • (Boolean)

    true if the model specifically requires a subscription



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/ollama_agent/providers/ollama.rb', line 84

def subscription_required?(model)
  return false unless cloud?

  require "net/http"
  require "json"

  uri = URI("#{@host}/api/show")
  req = Net::HTTP::Post.new(uri)
  req["Authorization"] = "Bearer #{@api_key}" if @api_key
  req.body = { name: model }.to_json
  req.content_type = "application/json"

  resp = Net::HTTP.start(uri.host, uri.port,
                         use_ssl: uri.scheme == "https",
                         open_timeout: 5, read_timeout: 10) { |h| h.request(req) }

  # Ollama Cloud returns 403 with a "subscription required" message for gated models.
  resp.code == "403" && resp.body.to_s.match?(/subscription/i)
rescue StandardError
  false
end