Skip to content

Conversation

josefarias
Copy link

@josefarias josefarias commented Sep 28, 2025

What this does

This PR adds Replicate as a provider. It is WIP as I’m still getting familiar with RubyLLM and Replicate’s API, which has quite a few idiosyncrasies. Tests are notably pending.

Replicate may stand out from other providers in several areas:

  • They don’t expose pricing via API (that I can tell). I’ve opted for not including pricing for now.
  • Different users/companies will name their Replicate models using different schemes. So it’s hard to come up with a general pattern to identify models of the same family. I’ve opted not to include model families for now.
  • Replicate mostly wants to you send them an HTTP request and let them ping you back via webhook when the result is ready, which is different from the existing duck type called via RubyLLM.paint.
    • This HTTP request returns a URL for the prediction, which is notably not the actual image, which isn’t ready yet.
    • Returning Image.new(url: prediction_url) seems ill-fitting (because the prediction’s url is not the image url). I’ve opted to return the full response JSON instead.
  • Replicate models have drastically different input signatures. I’ve opted to wrap these in a generic model_params hash which we forward to {ProviderInstance}#paint. I folded the existing size kwarg into the same model_params concept to keep uniformity across providers.
  • Replicate’s API is quite flexible, offering a sync mode (vs the default async mode with webhooks), a streaming option, and a number of models with drastically different capabilities. In order to keep things revieweable and completable with reasonable effort, I’ve opted to limit this PR to the default async mode, and to text-to-image models, which is selfishly my immediate need.
    • Including other kinds of models should be fairly manageable as follow-up PRs.

I patched the models refresh logic to append the replicate models to existing ones (patch not committed). 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. The result is probably suboptimal—specially as it didn’t seem to work for regenerating docs. Let me know if you’d like me to try something else!

Please do let me know if any of the assumptions above don’t hold up or you’d like to do things differently.

Thanks for reading!

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Performance improvement

Scope check

  • I read the Contributing Guide
  • This aligns with RubyLLM's focus on LLM communication
  • This isn't application-specific logic that belongs in user code
  • This benefits most users, not just my specific use case

Quality check

  • I ran overcommit --install and all hooks pass
  • I tested my changes thoroughly
    • For provider changes: Re-recorded VCR cassettes with bundle exec rake vcr:record[provider_name]
    • All tests pass: bundle exec rspec
  • I updated documentation if needed
  • I didn't modify auto-generated files manually (models.json, aliases.json)

API changes

  • Breaking change
  • New public methods/classes
  • Changed method signatures
  • No API changes

Related issues

#410

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.
config.around do |example|
cassette_name = example.full_description.parameterize(separator: '_').delete_prefix('rubyllm_')
VCR.use_cassette(cassette_name) do
VCR.use_cassette(cassette_name, record: :new_episodes) do
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is so existing stubs are kept and only new HTTP interactions are recorded onto the existing cassette. We can remove if we’re not feeling it.

)
```

> 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.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve removed the log because we’d now support passing arbitrary params. It’d be up to the user to make sure the model supports what they’re passing in.

It’s a bit of a sharp knife, but given Replicate opens the door to tons of models with tons of input signatures, allowing arbitrary params is the only way I can think of to implement. Open to other ideas though.

I’m wrapping up for today but will add this to the docs later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant