Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ GPUSTACK_API_BASE=http://localhost:11444/v1
GPUSTACK_API_KEY=$(op read "op://RubyLLM/GPUStack/credential")
MISTRAL_API_KEY=$(op read "op://RubyLLM/Mistral/credential")
OLLAMA_API_BASE=http://localhost:11434/v1
OLLAMA_CLOUD_API_KEY=$(op read "op://RubyLLM/Ollama Cloud/credential")
OPENAI_API_KEY=$(op read "op://RubyLLM/OpenAI/credential")
OPENROUTER_API_KEY=$(op read "op://RubyLLM/OpenRouter/credential")
PERPLEXITY_API_KEY=$(op read "op://RubyLLM/Perplexity/credential")
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ response = chat.with_schema(ProductSchema).ask "Analyze this product", with: "pr
* **Async:** Fiber-based concurrency
* **Model registry:** 800+ models with capability detection and pricing
* **Extended thinking:** Control, view, and persist model deliberation
* **Providers:** OpenAI, xAI, Anthropic, Gemini, VertexAI, Bedrock, DeepSeek, Mistral, Ollama, OpenRouter, Perplexity, GPUStack, and any OpenAI-compatible API
* **Providers:** OpenAI, xAI, Anthropic, Gemini, VertexAI, Bedrock, DeepSeek, Mistral, Ollama, Ollama Cloud, OpenRouter, Perplexity, GPUStack, and any OpenAI-compatible API

## Installation

Expand Down
30 changes: 30 additions & 0 deletions docs/_getting_started/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ RubyLLM.configure do |config|
config.ollama_api_base = 'http://localhost:11434/v1'
config.ollama_api_key = ENV['OLLAMA_API_KEY'] # Available in v1.13.0+ (optional for authenticated/remote Ollama endpoints)

# Ollama Cloud
config.ollama_cloud_api_key = ENV['OLLAMA_CLOUD_API_KEY'] # Required. Keys: https://ollama.com/settings/keys
config.ollama_cloud_api_base = ENV['OLLAMA_CLOUD_API_BASE'] # Optional. Defaults to https://ollama.com/v1

# OpenAI
config.openai_api_key = ENV['OPENAI_API_KEY']
config.openai_api_base = ENV['OPENAI_API_BASE'] # Optional custom OpenAI-compatible endpoint
Expand Down Expand Up @@ -166,6 +170,28 @@ end

By default, RubyLLM uses the 'developer' role (matching OpenAI's current API). Set `openai_use_system_role` to true for compatibility with servers that still expect 'system'.

### Ollama Cloud

Ollama's hosted service exposes OpenAI-compatible endpoints at `https://ollama.com/v1` with Bearer-token auth. Keys are issued at [ollama.com/settings/keys](https://ollama.com/settings/keys).

```ruby
RubyLLM.configure do |config|
config.ollama_cloud_api_key = ENV['OLLAMA_CLOUD_API_KEY']
end

chat = RubyLLM.chat(
model: 'gpt-oss:120b',
provider: :ollama_cloud,
assume_model_exists: true
)
chat.ask('Hello from the cloud')
```

Cloud-capable models include `gpt-oss:120b`, `gpt-oss:120b-cloud`, `qwen3-coder:480b-cloud`, and `deepseek-v3.1:671b-cloud`. Models are discovered dynamically via `/v1/models`; pass `assume_model_exists: true` until you run `RubyLLM.models.refresh!`.

> Ollama Cloud is billed by subscription tier (Free / Pro $20/mo / Max $100/mo), not per-token — so `Message#input_tokens` and `Message#output_tokens` are reported but `Model::Info#pricing` will be empty. See [ollama.com/pricing](https://ollama.com/pricing) for current tiers.
{: .note }

### Gemini API Versions
{: .d-inline-block }

Expand Down Expand Up @@ -484,6 +510,10 @@ RubyLLM.configure do |config|
config.ollama_api_base = String
config.ollama_api_key = String # v1.13.0+

# Ollama Cloud
config.ollama_cloud_api_key = String
config.ollama_cloud_api_base = String

# OpenAI
config.openai_api_key = String
config.openai_api_base = String
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ response = chat.with_schema(ProductSchema).ask "Analyze this product", with: "pr
* **Async:** Fiber-based concurrency
* **Model registry:** 800+ models with capability detection and pricing
* **Extended thinking:** Control, view, and persist model deliberation
* **Providers:** OpenAI, xAI, Anthropic, Gemini, VertexAI, Bedrock, DeepSeek, Mistral, Ollama, OpenRouter, Perplexity, GPUStack, and any OpenAI-compatible API
* **Providers:** OpenAI, xAI, Anthropic, Gemini, VertexAI, Bedrock, DeepSeek, Mistral, Ollama, Ollama Cloud, OpenRouter, Perplexity, GPUStack, and any OpenAI-compatible API

## Installation

Expand Down
1 change: 1 addition & 0 deletions lib/ruby_llm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ def logger
RubyLLM::Provider.register :gpustack, RubyLLM::Providers::GPUStack
RubyLLM::Provider.register :mistral, RubyLLM::Providers::Mistral
RubyLLM::Provider.register :ollama, RubyLLM::Providers::Ollama
RubyLLM::Provider.register :ollama_cloud, RubyLLM::Providers::OllamaCloud
RubyLLM::Provider.register :openai, RubyLLM::Providers::OpenAI
RubyLLM::Provider.register :openrouter, RubyLLM::Providers::OpenRouter
RubyLLM::Provider.register :perplexity, RubyLLM::Providers::Perplexity
Expand Down
1 change: 1 addition & 0 deletions lib/ruby_llm/models.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Models
'amazon-bedrock' => 'bedrock',
'deepseek' => 'deepseek',
'mistral' => 'mistral',
'ollama-cloud' => 'ollama_cloud',
'openrouter' => 'openrouter',
'perplexity' => 'perplexity'
}.freeze
Expand Down
42 changes: 42 additions & 0 deletions lib/ruby_llm/providers/ollama_cloud.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

module RubyLLM
module Providers
# Ollama Cloud API integration.
class OllamaCloud < Ollama
def api_base
@config.ollama_cloud_api_base || 'https://ollama.com/v1'
end

def headers
{ 'Authorization' => "Bearer #{@config.ollama_cloud_api_key}" }
end

class << self
def slug
'ollama_cloud'
end

def configuration_options
%i[ollama_cloud_api_base ollama_cloud_api_key]
end

def configuration_requirements
%i[ollama_cloud_api_key]
end

def local?
false
end

def assume_models_exist?
true
end

def capabilities
Ollama::Capabilities
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/tasks/models.rake
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def configure_from_env
config.deepseek_api_key = ENV.fetch('DEEPSEEK_API_KEY', nil)
config.gemini_api_key = ENV.fetch('GEMINI_API_KEY', nil)
config.mistral_api_key = ENV.fetch('MISTRAL_API_KEY', nil)
config.ollama_cloud_api_key = ENV.fetch('OLLAMA_CLOUD_API_KEY', nil)
config.openai_api_key = ENV.fetch('OPENAI_API_KEY', nil)
config.openrouter_api_key = ENV.fetch('OPENROUTER_API_KEY', nil)
config.perplexity_api_key = ENV.fetch('PERPLEXITY_API_KEY', nil)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading