-
-
Notifications
You must be signed in to change notification settings - Fork 306
Add OpenRouter as a supported provider #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
1c1bfbe to
399c9eb
Compare
|
This is an excellent PR! You've clearly understood RubyLLM's design philosophy and implemented OpenRouter support in a way that fits seamlessly with the rest of the library. I'll test it out and do a comprehensive code review soon. Your concern about models.json is valid - we need a better long-term solution. Requiring users to refresh models has its own issues (filesystem access, rate limits), so maybe we need something like a CDN that we update via GitHub Actions. For multi-provider model selection, we might want to introduce a provider: parameter to .chat and a .with_provider(:sym) method to let users explicitly choose, with defaults to the original provider. This would let us cleanly handle cases where multiple providers offer the same model. |
Models.json issueShould I propose some provider options? If that's the case should I do it in another PR or extend this one? I think Ollama PR already has some progress by creating a concept of enabled/disabled providers and fetching models on demand, but of course we can do that CDN option as well :) Python's AI ecosystem often downloads config/model files during first run (and some Ruby AI ecosystem follow this pattern, like for example Tokenizers gem), so it wouldn't be unusual to fetch models.json during initialization. We can also leverage github or huggingface for hosting that models.json. Rate limits and depending on 3rd party APIsOne thing that I've noticed about openrouter is that the models API is actually public and doesn't require any keys which simplifies the implementation a bit. However it's also somewhat undocumented, as the supported capabilities aren't mentioned in the docs, but they are used by the openrouter website. |
6a18236 to
7ccdea5
Compare
|
Rebased to resolve a conflict in README.md |
|
Two new features to consider in your provider implementation:
|
|
Added configuration requirements handling in 75f99a1 Each provider now specifies what configuration is required via a simple
Example of the new error messages: RubyLLM::ConfigurationError: anthropic provider is not configured. Add this to your initialization:
RubyLLM.configure do |config|
config.anthropic_api_key = ENV['ANTHROPIC_API_KEY']
end |
7ab894a to
c4c3ac1
Compare
|
@crmne Updated according to your specs |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #29 +/- ##
==========================================
- Coverage 92.73% 91.01% -1.73%
==========================================
Files 73 79 +6
Lines 2795 2915 +120
Branches 406 424 +18
==========================================
+ Hits 2592 2653 +61
- Misses 203 262 +59 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
I'll add some tests to raise the coverage |
534d2b6 to
fb912f2
Compare
|
Added specs, rebased on top of main branch. |
|
Side note - maybe we shouldn't sort models by name but by provider, then name. This might be better for PR diffs |
29589e3 to
443cd85
Compare
|
Rebased on top of main branch and resolved conflicts. @crmne any chance for a review? I'd like to merge this :) |
crmne
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this PR!
I have left a couple of comments about it.
In addition to those, it would be great to add haiku to the chat_content_spec.rb, chat_error_spec.rb, chat_functions_spec.rb, chat_pdf_spec.rb
Looking forward to see the changes!
| "gpt-4o": { | ||
| "openrouter": "openai/gpt-4o" | ||
| }, | ||
| "gpt-4o-mini": { | ||
| "openrouter": "openai/gpt-4o-mini" | ||
| }, | ||
| "gpt-4-turbo": { | ||
| "openrouter": "openai/gpt-4-turbo" | ||
| }, | ||
| "gemini-1.5-flash": { | ||
| "openrouter": "google/gemini-flash-1.5" | ||
| }, | ||
| "gemini-1.5-flash-8b": { | ||
| "openrouter": "google/gemini-flash-1.5-8b" | ||
| }, | ||
| "gemini-1.5-pro": { | ||
| "openrouter": "google/gemini-pro-1.5" | ||
| }, | ||
| "gemini-2.0-flash": { | ||
| "openrouter": "google/gemini-2.0-flash-001" | ||
| }, | ||
| "o1": { | ||
| "openrouter": "openai/o1" | ||
| }, | ||
| "o3-mini": { | ||
| "openrouter": "openai/o3-mini" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's add the openai version here first just to keep the style consistent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean, can you explain a bit more?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we don't need the entire capabilities module since their API returns all we need. Check out https://github.com/crmne/ruby_llm/blob/main/lib/ruby_llm/providers/openai/models.rb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure about this? If I read this correctly then OpenAI provider in RubyLLM basically just hardcodes list of capabilities here: https://github.com/crmne/ruby_llm/blob/main/lib/ruby_llm/providers/openai/capabilities.rb and does the lookup by id in the file you mentioned. This won't work for a very broad and dynamic list of models that OpenRouter provides, so it's easier to use their API to detect model capabilties.
9b5f2bb to
f9efd4b
Compare
187dfad to
a4c909c
Compare
a4c909c to
b19b3e1
Compare
|
@khasinski I'm playing around with the OpenAI API of OpenRouter and so far things are going smoothly. Is there any reason to implement their API anymore? |
|
Other than fetching the models not really. We can probably close this if you're ok with not having the model list in the API or we can trim it down to just fetching the list of models. Your choice :) |
|
Hi @khasinski I decided to go ahead and implement it myself in d698dd1. Thank you very much for your effort and contribution! |
Addresses #8
This adds support for OpenRouter.
You can use it by configuring the provider with:
Then calling models by their OpenRouter ids (it might be wise to prefix those with openrouter or something else if there is a possibility there will be more multi-model providers in the future)
OpenRouter doesn't support embedding models and image generation so those are not implemented here.
Getting model details requires multiple calls to OpenRouter API, since they don't expose function calling and structured output support in the responses. However they do allow filtering models by those capabilities. I memoized those calls for subsequent lookups, so the model fetching goes faster.
Code is based on OpenAI provider, since they share most of the API, but I've kept it separate since they might differ in future.
A small note - this adds a lot of data to models.json, it might be wise to generate that file on first use instead of bundling it with the gem or add refreshing to docs just like Ollama PR does (#10).