Skip to content

Commit f46795d

Browse files
committed
Add Replicate provider
Current replicate models output images Drop 'replicate' prefix from model names Force array on replicate webhook filters Run models rake tasks I hacked the models refresh logic to append the replicate models to existing ones. Without this patch, the whole file would get overwritten and models would be missing, seeing as I don’t have credentials for all supported providers. Fold image size into model params Record model list cassettes Add tests Return DeferredImage Poll in deferred image tests Imageable -> Blobbable Remove unnecessary test No need to set `@model_id` Update docs Typo
1 parent a0efaa4 commit f46795d

28 files changed

+12211
-154
lines changed

bin/console

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ RubyLLM.configure do |config|
2323
config.openai_api_key = ENV.fetch('OPENAI_API_KEY', nil)
2424
config.openrouter_api_key = ENV.fetch('OPENROUTER_API_KEY', nil)
2525
config.perplexity_api_key = ENV.fetch('PERPLEXITY_API_KEY', nil)
26+
config.replicate_api_key = ENV.fetch('REPLICATE_API_KEY', nil)
27+
config.replicate_webhook_url = ENV.fetch('REPLICATE_WEBHOOK_URL', nil)
2628
config.vertexai_location = ENV.fetch('GOOGLE_CLOUD_LOCATION', nil)
2729
config.vertexai_project_id = ENV.fetch('GOOGLE_CLOUD_PROJECT', nil)
2830
end

docs/_core_features/image-generation.md

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ After reading this guide, you will know:
2626
* How to generate images from text prompts.
2727
* How to select different image generation models.
2828
* How to specify image sizes (for supported models).
29+
* How to use model hosting platforms like Replicate.
2930
* How to access and save generated image data (URL or Base64).
3031
* How to integrate image generation with Rails Active Storage.
3132
* Tips for writing effective image prompts.
@@ -119,12 +120,32 @@ image_portrait = RubyLLM.paint(
119120
)
120121
```
121122

122-
> Not all models support size customization. If a size is specified for a model that doesn't support it (like Google Imagen), RubyLLM may log a debug message indicating the size parameter is ignored. Check the provider's documentation or the [Available Models Guide]({% link _reference/available-models.md %}) for supported sizes.
123+
> Not all models support size customization. Check the provider's documentation or the [Available Models Guide]({% link _reference/available-models.md %}) for supported sizes.
124+
{: .note }
125+
126+
## Using model hosting platforms
127+
128+
Platforms like Replicate host a large collection of models with different capabilities and parameters. Due to the variety of models available, you should be aware of the parameters supported by the model you're using. This information is available in the platform's documentation.
129+
130+
For example, Imagen 4 Ultra supports `aspect_ratio` as a parameter when used [via Replicate](https://replicate.com/google/imagen-4-ultra). Since it's optional, you can omit it. But if you'd like to specify a value, you just need to add it to your paint call.
131+
132+
```ruby
133+
image = RubyLLM.paint(
134+
"A photorealistic image of a red panda coding Ruby on a laptop",
135+
model: "google/imagen-4-ultra",
136+
provider: :replicate,
137+
aspect_ratio: "16:9"
138+
)
139+
```
140+
141+
> When switching between different models, you'll typically need to change the parameters as well, since different models support different parameter sets. Always check the model's documentation for the specific parameters it accepts.
123142
{: .note }
124143

125144
## Working with Generated Images
126145

127-
The `RubyLLM::Image` object provides access to the generated image data and metadata.
146+
When models return the image immediately, the `RubyLLM::Image` object provides access to the generated image data and metadata.
147+
148+
Some models generate images asynchronously. In this case, you will receive a `RubyLLM::DeferredImage` object instead. You can still access the image data, but you will either need to wait for the image to be generated or fetch it by other means—typically after being notified via a webhook.
128149

129150
### Accessing Image Data
130151

@@ -133,6 +154,10 @@ The `RubyLLM::Image` object provides access to the generated image data and meta
133154
* `image.mime_type`: Returns the MIME type (e.g., `"image/png"`, `"image/jpeg"`).
134155
* `image.base64?`: Returns `true` if the image data is Base64-encoded, `false` otherwise.
135156

157+
### Accessing Deferred Image Data
158+
159+
* `deferred_image.url`: Returns the URL where you can check whether the image has been generated.
160+
136161
### Saving Images Locally
137162

138163
The `save` method works regardless of whether the image was delivered via URL or Base64. It fetches the data if necessary and writes it to the specified file path.
@@ -150,9 +175,23 @@ rescue => e
150175
end
151176
```
152177

178+
For deferred images, the `save` method will write the file and return its path only if the image has been generated. Otherwise, it will return `nil`.
179+
180+
The ideal way to handle deferred images is by having the provider notify you via webhook when the image is generated, and then fetching the image outside of RubyLLM. But if you're not able to configure a webhook, another way to handle these is to call the method recursively with a delay until it succeeds or a condition is met. This is equivalent to a "polling" mechanism. Check your provider's documentation for any rate limits that may apply.
181+
182+
```ruby
183+
# Only do this if you're not able to configure a webhook
184+
def save_deferred_image(image, path, remaining_attempts = 10)
185+
return nil if remaining_attempts <= 0
186+
image.save(path) || (sleep(2) && save_deferred_image(image, path, remaining_attempts - 1))
187+
end
188+
189+
save_deferred_image(deferred_image, "deferred_image.png")
190+
```
191+
153192
### Getting Raw Image Blob
154193

155-
The `to_blob` method returns the raw binary image data (decoded from Base64 or downloaded from URL). This is useful for integration with other libraries or frameworks.
194+
The `to_blob` method returns the raw binary image data (decoded from Base64 or downloaded from URL). This is useful for integration with other libraries or frameworks. Deferred images return `nil` if the image has not finished generating.
156195

157196
```ruby
158197
image = RubyLLM.paint("Abstract geometric patterns in pastel colors")
@@ -277,4 +316,4 @@ Image generation can take several seconds (typically 5-20 seconds depending on t
277316

278317
* [Chatting with AI Models]({% link _core_features/chat.md %}): Learn about conversational AI.
279318
* [Embeddings]({% link _core_features/embeddings.md %}): Explore text vector representations.
280-
* [Error Handling]({% link _advanced/error-handling.md %}): Master handling API errors.
319+
* [Error Handling]({% link _advanced/error-handling.md %}): Master handling API errors.

docs/_getting_started/configuration.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ RubyLLM.configure do |config|
5959
config.mistral_api_key = ENV['MISTRAL_API_KEY']
6060
config.perplexity_api_key = ENV['PERPLEXITY_API_KEY']
6161
config.openrouter_api_key = ENV['OPENROUTER_API_KEY']
62+
config.replicate_api_key = ENV['REPLICATE_API_KEY']
63+
config.replicate_webhook_url = ENV['REPLICATE_WEBHOOK_URL']
6264

6365
# Local providers
6466
config.ollama_api_base = 'http://localhost:11434/v1'
@@ -363,4 +365,4 @@ Now that you've configured RubyLLM, you're ready to:
363365

364366
- [Start chatting with AI models]({% link _core_features/chat.md %})
365367
- [Work with different providers and models]({% link _advanced/models.md %})
366-
- [Set up Rails integration]({% link _advanced/rails.md %})
368+
- [Set up Rails integration]({% link _advanced/rails.md %})

0 commit comments

Comments
 (0)