Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
12 changes: 6 additions & 6 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
source 'https://rubygems.org'
source "https://rubygems.org"

ruby '>= 2.7'
ruby ">= 2.7"

gem 'faraday'
gem 'faraday-net_http_persistent'
gem 'rspec'
gem 'webmock'
gem "faraday"
gem "faraday-net_http_persistent"
gem "rspec"
gem "webmock"
48 changes: 24 additions & 24 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
bigdecimal (3.1.6)
connection_pool (2.4.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
bigdecimal (3.2.2)
connection_pool (2.5.3)
crack (1.0.0)
bigdecimal
rexml
diff-lcs (1.5.1)
faraday (2.12.0)
faraday-net_http (>= 2.0, < 3.4)
diff-lcs (1.6.2)
faraday (2.13.1)
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-net_http (3.3.0)
net-http
faraday-net_http (3.4.0)
net-http (>= 0.5.0)
faraday-net_http_persistent (2.3.0)
faraday (~> 2.5)
net-http-persistent (>= 4.0.4, < 5)
hashdiff (1.1.0)
json (2.7.2)
logger (1.6.1)
net-http (0.4.1)
hashdiff (1.2.0)
json (2.12.2)
logger (1.7.0)
net-http (0.6.0)
uri
net-http-persistent (4.0.4)
connection_pool (~> 2.2)
public_suffix (5.0.4)
rexml (3.2.6)
rspec (3.13.0)
net-http-persistent (4.0.6)
connection_pool (~> 2.2, >= 2.2.4)
public_suffix (6.0.2)
rexml (3.4.1)
rspec (3.13.1)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.0)
rspec-core (3.13.4)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.0)
rspec-expectations (3.13.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.0)
rspec-mocks (3.13.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-support (3.13.0)
uri (0.13.1)
webmock (3.22.0)
rspec-support (3.13.4)
uri (1.0.3)
webmock (3.25.1)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
Expand Down
199 changes: 162 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,102 @@
[![Gem Version](https://badge.fury.io/rb/rubyai.svg)](https://badge.fury.io/rb/rubyai)
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/alexshapalov/rubyai/blob/main/LICENSE)

## Use the [OpenAI API 🤖 ](https://openai.com/blog/openai-api/) with Ruby! ❤️
## Use the [OpenAI API 🤖](https://openai.com/blog/openai-api/) with Ruby! ❤️

Generate text with ChatGPT (Generative Pre-trained Transformer)
Generate text with ChatGPT, Claude, and Gemini!

---

# Installation
## Installation

Add this line to your application's Gemfile:
Install the latest version via Bundler:

```ruby
gem "rubyai"
```

And then execute:
bundle add rubyai

$ bundle install
Then execute:

```sh
$ bundle install
```

Or install with:
Or install manually:

$ gem install rubyai
```sh
$ gem install rubyai
```

and require with:
Then require it:

```ruby
require "rubyai"
```

# Usage
---

## Usage

- Get your API key from [https://beta.openai.com/account/api-keys](https://beta.openai.com/account/api-keys)
- Get your API key from:

- [OpenAI](https://beta.openai.com/account/api-keys)

- [Anthropic](https://console.anthropic.com)

- [Gemini](https://aistudio.google.com/apikey)

- If you belong to multiple organizations (OpenAI), get your Organization ID from:

- [Org Settings](https://beta.openai.com/account/org-settings)


- If you belong to multiple organizations, you can get your Organization ID from [https://beta.openai.com/account/org-settings](https://beta.openai.com/account/org-settings)
---

### Quickstart
## Quickstart

For a quick test you can pass your token directly to a new client:
For a quick test, you can pass your token directly to a new client:

```ruby
result = RubyAI::Client.new(access_token, messages).call
```

### ChatGPT
---

## ChatGPT

ChatGPT is a conversational-style text generation model.
You can use it to [generate a response](https://platform.openai.com/docs/api-reference/chat/create) to a sequence of [messages](https://platform.openai.com/docs/guides/chat/introduction):
ChatGPT is a conversational-style text generation model. You can use it to generate a response to a sequence of messages:

```ruby
api_key = "YOUR API KEY"
messages = "Who is the best chess player in history?"

result = RubyAI::Client.new(api_key, messages, model: "gpt-4").call
result = RubyAI::Client.new(api_key: api_key, messages: messages, model: "gpt-4").call
puts result.dig("choices", 0, "message", "content")

# => As an AI language model, I do not have personal opinions, but according to historical records, Garry Kasparov is often considered as one of the best chess players in history. Other notable players include Magnus Carlsen, Bobby Fischer, and Jose Capablanca.
```

You can also pass client variables using the configuration file.
Create configruation file like on example:
**Example output:**

> As an AI language model, I do not have personal opinions, but according to historical records, Garry Kasparov is often considered as one of the best chess players in history. Other notable players include Magnus Carlsen, Bobby Fischer, and Jose Capablanca.

---

TODO(because now you can't):
~~You can also pass client variables using a configuration file:

```ruby
configuration = RubyAI::Configuration.new("YOUR API KEY", "Who is the best chess player in history?")
configuration = RubyAI::Configuration.new(
api_key: "YOUR API KEY",
messages: "Who is the best chess player in history?"
)
client = RubyAI::Client.new(configuration)
result = client.call
puts result.dig("choices", 0, "message", "content")
```
~~

---

If you're using Rails, you can use the `configure` block:

Also (mostly) if you are using Rails you can use configure method:
```ruby
RubyAI.configure do |config|
config.api_key = "YOUR API KEY"
Expand All @@ -78,30 +107,126 @@ RubyAI.configure do |config|
end
```

## Models
---

We support all popular GPT models:
### Configuration

gpt-4-turbo: A powerful variant of GPT-4 optimized for efficiency and speed, perfect for high-demand tasks.
Our gem uses separate configurations for each provider:

gpt-4o-mini: A streamlined version of GPT-4, designed to provide a balance between performance and resource efficiency.
```ruby
# For OpenAI
RubyAI.config.openai.configure do |config|
config.api = "your-api"
config.model = "o1-mini"
config.temperature = 0.75
end

o1-mini: A compact, yet effective model that is well-suited for lightweight tasks.
# For Anthropic
RubyAI.config.anthropic.configure do |config|
config.api = "your-api"
config.model = "claude-2"
config.temperature = 0.75
config.max_tokens = 1000
end

o1-preview: A preview version of the o1 model, offering insights into upcoming advancements and features.
# For Gemini
RubyAI.config.gemini.configure do |config|
config.api = "your-api"
config.model = "gemini-1.5-pro"
config.temperature = 0.75
config.max_tokens = 1000
end
```

---

### Chat

After configuration, you can chat with models using the `Chat` class:

```ruby
claude2 = RubyAI::Chat.new("anthropic", model: "claude-2")
claude2.call("Hello world") # => Hash response

# Or

gpt = RubyAI::Chat.new("openai", "gpt-4", temperature: 1)
gpt.call("Hello world!") # => Hash response
```

---

### Supported Models

We support most popular GPT models:

```ruby
p RubyAI.config.models

"openai" => {
"gpt-3.5-turbo" => "gpt-3.5-turbo",
"gpt-4" => "gpt-4",
"gpt-4-32k" => "gpt-4-32k",
"gpt-4-turbo" => "gpt-4-turbo",
"gpt-4o-mini" => "gpt-4o-mini",
"o1-mini" => "o1-mini",
"o1-preview" => "o1-preview",
"text-davinci-003" => "text-davinci-003"
},
"anthropic" => {
"claude-2" => "claude-2",
"claude-instant-100k" => "claude-instant-100k",
"claude-1" => "claude-1",
"claude-1.3" => "claude-1.3",
"claude-1.3-sonnet" => "claude-1.3-sonnet",
"claude-1.3-sonnet-100k" => "claude-1.3-sonnet-100k"
},
"gemini" => {
"gemini-1.5-pro" => "gemini-1.5-pro",
"gemini-1.5-flash" => "gemini-1.5-flash",
"gemini-1.0-pro" => "gemini-1.0-pro"
}
```

---

## TODO

- Support Gemini configuration via `configure` block
- Implement more LLM support
- Stream responses

---

## Development

After checking out the repo, run `bin/setup` to install dependencies. You can run `bin/console` for an interactive prompt that will allow you to experiment.
After checking out the repo, run:

```sh
bin/setup
```

You can also run:

To install this gem onto your local machine, run `bundle exec rake install`.
```sh
bin/console
```

To install this gem onto your local machine:

```sh
bundle exec rake install
```

---

## Contributing

Bug reports and pull requests are welcome on GitHub at <https://github.com/alexshapalov/rubyai>. This project is intended to be a safe, welcoming space for collaboration, and contributors.
Bug reports and pull requests are welcome on GitHub at [https://github.com/alexshapalov/rubyai](https://github.com/alexshapalov/rubyai).
This project is intended to be a safe, welcoming space for collaboration.

---

## License

The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
This gem is open source under the [MIT License](https://opensource.org/licenses/MIT).
26 changes: 22 additions & 4 deletions lib/rubyai.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
require 'faraday'
require 'faraday/net_http_persistent'
require 'json'
require "faraday"
require "faraday/net_http_persistent"
require "json"

require_relative "rubyai/client"
require_relative "rubyai/providers/providers_configuration"
require_relative "rubyai/providers/openai"
require_relative "rubyai/providers/anthropic"
require_relative "rubyai/providers/gemini"
require_relative "rubyai/provider"
Copy link

Choose a reason for hiding this comment

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

Do we need this also?

Copy link
Author

Choose a reason for hiding this comment

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

Sorry, could you please specify what part you mean? I’m not sure what you're referring to.

Copy link

Choose a reason for hiding this comment

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

do we need require require_relative "rubyai/provider"
if we have required all of them directly?

require_relative "rubyai/configuration"
require_relative "rubyai/http"
require_relative "rubyai/client"
require_relative "rubyai/chat"
require_relative "rubyai/version"

module RubyAI
class Error < StandardError; end

def self.models
config.models
end

def self.configure
yield config
end

def self.config(config = {})
@config ||= Configuration.new(config)
end
end
Loading