ruby_llm 0.1.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/gem-push.yml +45 -0
- data/README.md +187 -0
- data/Rakefile +4 -0
- data/bin/console +6 -0
- data/bin/setup +6 -0
- data/lib/ruby_llm/active_record/acts_as.rb +102 -0
- data/lib/ruby_llm/client.rb +51 -0
- data/lib/ruby_llm/configuration.rb +24 -0
- data/lib/ruby_llm/conversation.rb +16 -0
- data/lib/ruby_llm/message.rb +32 -0
- data/lib/ruby_llm/providers/base.rb +41 -0
- data/lib/ruby_llm/railtie.rb +9 -0
- data/lib/ruby_llm/version.rb +3 -0
- data/lib/ruby_llm.rb +36 -0
- data/ruby_llm.gemspec +48 -0
- metadata +243 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 04c616dc84f656d17df731cee4f7ee6a0eb20793d9c1b32df549ba21fbc8c913
|
4
|
+
data.tar.gz: 2bc73cc3304cc21c1e27b97c3702cec24cdca443ca81d613fe3850fefa7224da
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: '0080ab8908d42eb938d0a357910c95d9b344a30e95319c53803944d7b6d6876cce30df9926a30e9387b870cb713224665d6edc57e8e07def08fd1d995f4ab056'
|
7
|
+
data.tar.gz: ee65b82281d0207027ed345e751b0e19d3de9e7ff3bfa6d2b8e05831906c4cd6323da3790d82d3c961658fb6904ba879e806bb2cf39336866494c2894bf96f6f
|
@@ -0,0 +1,45 @@
|
|
1
|
+
name: Ruby Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ "main" ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ "main" ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
build:
|
11
|
+
name: Build + Publish
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
permissions:
|
14
|
+
contents: read
|
15
|
+
packages: write
|
16
|
+
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v4
|
19
|
+
- name: Set up Ruby 3.3
|
20
|
+
uses: ruby/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: 3.3.x
|
23
|
+
|
24
|
+
- name: Publish to GPR
|
25
|
+
run: |
|
26
|
+
mkdir -p $HOME/.gem
|
27
|
+
touch $HOME/.gem/credentials
|
28
|
+
chmod 0600 $HOME/.gem/credentials
|
29
|
+
printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
30
|
+
gem build *.gemspec
|
31
|
+
gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
|
32
|
+
env:
|
33
|
+
GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
|
34
|
+
OWNER: ${{ github.repository_owner }}
|
35
|
+
|
36
|
+
- name: Publish to RubyGems
|
37
|
+
run: |
|
38
|
+
mkdir -p $HOME/.gem
|
39
|
+
touch $HOME/.gem/credentials
|
40
|
+
chmod 0600 $HOME/.gem/credentials
|
41
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
42
|
+
gem build *.gemspec
|
43
|
+
gem push *.gem
|
44
|
+
env:
|
45
|
+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
data/README.md
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
# RubyLLM
|
2
|
+
|
3
|
+
The Ruby library for working with Large Language Models (LLMs).
|
4
|
+
|
5
|
+
[](https://badge.fury.io/rb/ruby_llm)
|
6
|
+
[](https://github.com/testdouble/standard)
|
7
|
+
|
8
|
+
RubyLLM provides a unified interface for interacting with various LLM providers including OpenAI, Anthropic, and more. It offers both standalone usage and seamless Rails integration.
|
9
|
+
|
10
|
+
## Features
|
11
|
+
|
12
|
+
- 🤝 Unified interface for multiple LLM providers (OpenAI, Anthropic, etc.)
|
13
|
+
- 🛠️ Tool/Function calling support
|
14
|
+
- 📊 Automatic token counting and tracking
|
15
|
+
- 🔄 Streaming support
|
16
|
+
- 🚂 Seamless Rails integration
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
Add this line to your application's Gemfile:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
gem 'ruby_llm'
|
24
|
+
```
|
25
|
+
|
26
|
+
And then execute:
|
27
|
+
```bash
|
28
|
+
$ bundle install
|
29
|
+
```
|
30
|
+
|
31
|
+
Or install it directly:
|
32
|
+
|
33
|
+
```bash
|
34
|
+
$ gem install ruby_llm
|
35
|
+
```
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
### Basic Setup
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
require 'ruby_llm'
|
43
|
+
|
44
|
+
RubyLLM.configure do |config|
|
45
|
+
config.openai_api_key = ENV['OPENAI_API_KEY']
|
46
|
+
config.anthropic_api_key = ENV['ANTHROPIC_API_KEY']
|
47
|
+
config.default_model = 'gpt-4'
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
### Simple Chat
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
client = RubyLLM.client
|
55
|
+
|
56
|
+
response = client.chat([
|
57
|
+
{ role: :user, content: "Hello!" }
|
58
|
+
])
|
59
|
+
|
60
|
+
puts response.content
|
61
|
+
```
|
62
|
+
|
63
|
+
### Streaming
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
client.chat([
|
67
|
+
{ role: :user, content: "Count to 10 slowly" }
|
68
|
+
], stream: true) do |chunk|
|
69
|
+
print chunk.content
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
### Tool Usage
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
calculator = RubyLLM::Tool.new(
|
77
|
+
name: "calculator",
|
78
|
+
description: "Perform mathematical calculations",
|
79
|
+
parameters: {
|
80
|
+
expression: {
|
81
|
+
type: "string",
|
82
|
+
description: "The mathematical expression to evaluate",
|
83
|
+
required: true
|
84
|
+
}
|
85
|
+
}
|
86
|
+
) do |args|
|
87
|
+
eval(args[:expression]).to_s
|
88
|
+
end
|
89
|
+
|
90
|
+
response = client.chat([
|
91
|
+
{ role: :user, content: "What is 123 * 456?" }
|
92
|
+
], tools: [calculator])
|
93
|
+
```
|
94
|
+
|
95
|
+
## Rails Integration
|
96
|
+
|
97
|
+
RubyLLM provides seamless Rails integration with Active Record models.
|
98
|
+
|
99
|
+
### Configuration
|
100
|
+
|
101
|
+
Create an initializer `config/initializers/ruby_llm.rb`:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
RubyLLM.configure do |config|
|
105
|
+
config.openai_api_key = Rails.application.credentials.openai[:api_key]
|
106
|
+
config.anthropic_api_key = Rails.application.credentials.anthropic[:api_key]
|
107
|
+
config.default_model = Rails.env.production? ? 'gpt-4' : 'gpt-3.5-turbo'
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
### Models
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
# app/models/llm_model.rb
|
115
|
+
class LLMModel < ApplicationRecord
|
116
|
+
acts_as_llm_model
|
117
|
+
|
118
|
+
# Schema:
|
119
|
+
# t.string :provider
|
120
|
+
# t.string :name
|
121
|
+
# t.jsonb :capabilities
|
122
|
+
# t.integer :context_length
|
123
|
+
# t.timestamps
|
124
|
+
end
|
125
|
+
|
126
|
+
# app/models/conversation.rb
|
127
|
+
class Conversation < ApplicationRecord
|
128
|
+
acts_as_llm_conversation
|
129
|
+
belongs_to :user
|
130
|
+
|
131
|
+
# Schema:
|
132
|
+
# t.references :user
|
133
|
+
# t.string :title
|
134
|
+
# t.string :current_model
|
135
|
+
# t.timestamps
|
136
|
+
end
|
137
|
+
|
138
|
+
# app/models/message.rb
|
139
|
+
class Message < ApplicationRecord
|
140
|
+
acts_as_llm_message
|
141
|
+
|
142
|
+
# Schema:
|
143
|
+
# t.references :conversation
|
144
|
+
# t.string :role
|
145
|
+
# t.text :content
|
146
|
+
# t.jsonb :tool_calls
|
147
|
+
# t.jsonb :tool_results
|
148
|
+
# t.integer :token_count
|
149
|
+
# t.timestamps
|
150
|
+
end
|
151
|
+
```
|
152
|
+
|
153
|
+
### Controller Usage
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
class ConversationsController < ApplicationController
|
157
|
+
def create
|
158
|
+
@conversation = current_user.conversations.create!
|
159
|
+
redirect_to @conversation
|
160
|
+
end
|
161
|
+
|
162
|
+
def send_message
|
163
|
+
@conversation = current_user.conversations.find(params[:id])
|
164
|
+
|
165
|
+
message = @conversation.send_message(
|
166
|
+
params[:content],
|
167
|
+
model: params[:model]
|
168
|
+
)
|
169
|
+
|
170
|
+
render json: message
|
171
|
+
end
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
## Development
|
176
|
+
|
177
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
178
|
+
|
179
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
180
|
+
|
181
|
+
## Contributing
|
182
|
+
|
183
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/crmne/ruby_llm.
|
184
|
+
|
185
|
+
## License
|
186
|
+
|
187
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
module RubyLLM
|
2
|
+
module ActiveRecord
|
3
|
+
module ActsAs
|
4
|
+
def acts_as_llm_model(options = {})
|
5
|
+
include ModelMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
def acts_as_llm_conversation(options = {})
|
9
|
+
include ConversationMethods
|
10
|
+
has_many :messages, -> { order(created_at: :asc) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def acts_as_llm_message(options = {})
|
14
|
+
include MessageMethods
|
15
|
+
belongs_to :conversation
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ModelMethods
|
20
|
+
extend ActiveSupport::Concern
|
21
|
+
|
22
|
+
included do
|
23
|
+
validates :name, presence: true
|
24
|
+
validates :provider, presence: true
|
25
|
+
end
|
26
|
+
|
27
|
+
class_methods do
|
28
|
+
def sync_models
|
29
|
+
# Logic to sync models from providers
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module ConversationMethods
|
35
|
+
extend ActiveSupport::Concern
|
36
|
+
|
37
|
+
included do
|
38
|
+
before_create :set_default_model
|
39
|
+
end
|
40
|
+
|
41
|
+
def send_message(content, model: nil)
|
42
|
+
transaction do
|
43
|
+
message = messages.create!(
|
44
|
+
role: :user,
|
45
|
+
content: content
|
46
|
+
)
|
47
|
+
|
48
|
+
response = RubyLLM.client.chat(
|
49
|
+
conversation_messages,
|
50
|
+
model: model || current_model
|
51
|
+
)
|
52
|
+
|
53
|
+
messages.create!(
|
54
|
+
role: :assistant,
|
55
|
+
content: response.content,
|
56
|
+
token_count: response.token_count
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def conversation_messages
|
64
|
+
messages.map(&:to_llm_format)
|
65
|
+
end
|
66
|
+
|
67
|
+
def set_default_model
|
68
|
+
self.current_model ||= RubyLLM.configuration.default_model
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
module MessageMethods
|
73
|
+
extend ActiveSupport::Concern
|
74
|
+
|
75
|
+
included do
|
76
|
+
validates :role, presence: true, inclusion: { in: RubyLLM::Message::VALID_ROLES.map(&:to_s) }
|
77
|
+
validates :content, presence: true, unless: :tool_call?
|
78
|
+
|
79
|
+
before_save :calculate_tokens
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_llm_format
|
83
|
+
RubyLLM::Message.new(
|
84
|
+
role: role.to_sym,
|
85
|
+
content: content,
|
86
|
+
tool_calls: tool_calls,
|
87
|
+
tool_results: tool_results
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def calculate_tokens
|
94
|
+
# Logic to calculate tokens
|
95
|
+
end
|
96
|
+
|
97
|
+
def tool_call?
|
98
|
+
tool_calls.present? || tool_results.present?
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module RubyLLM
|
2
|
+
class Client
|
3
|
+
def initialize
|
4
|
+
@providers = {}
|
5
|
+
@conversations = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def chat(messages, model: nil, temperature: 1.0, stream: false, &block)
|
9
|
+
provider = provider_for(model)
|
10
|
+
response = provider.chat(
|
11
|
+
messages,
|
12
|
+
model: model,
|
13
|
+
temperature: temperature,
|
14
|
+
stream: stream,
|
15
|
+
&block
|
16
|
+
)
|
17
|
+
response
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_conversation(tools: [])
|
21
|
+
conversation = Conversation.new(tools: tools)
|
22
|
+
@conversations[conversation.id] = conversation
|
23
|
+
conversation
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def provider_for(model)
|
29
|
+
provider_name = detect_provider(model)
|
30
|
+
@providers[provider_name] ||= case provider_name
|
31
|
+
when :openai then Providers::OpenAI.new
|
32
|
+
when :anthropic then Providers::Anthropic.new
|
33
|
+
else
|
34
|
+
raise Error, "Unsupported provider: #{provider_name}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def detect_provider(model)
|
39
|
+
return RubyLLM.configuration.default_provider unless model
|
40
|
+
|
41
|
+
case model
|
42
|
+
when /^gpt-/, /^text-davinci/
|
43
|
+
:openai
|
44
|
+
when /^claude/
|
45
|
+
:anthropic
|
46
|
+
else
|
47
|
+
RubyLLM.configuration.default_provider
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module RubyLLM
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :openai_api_key, :anthropic_api_key
|
4
|
+
attr_accessor :default_provider, :default_model
|
5
|
+
attr_accessor :request_timeout
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@request_timeout = 30
|
9
|
+
@default_provider = :openai
|
10
|
+
@default_model = 'gpt-3.5-turbo'
|
11
|
+
end
|
12
|
+
|
13
|
+
def provider_settings
|
14
|
+
@provider_settings ||= {
|
15
|
+
openai: ProviderSettings.new,
|
16
|
+
anthropic: ProviderSettings.new
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class ProviderSettings
|
22
|
+
attr_accessor :api_key, :api_version, :default_model, :base_url
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module RubyLLM
|
2
|
+
class Conversation
|
3
|
+
attr_reader :id, :messages, :tools
|
4
|
+
|
5
|
+
def initialize(tools: [])
|
6
|
+
@id = SecureRandom.uuid
|
7
|
+
@messages = []
|
8
|
+
@tools = tools
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_message(message)
|
12
|
+
@messages << message
|
13
|
+
message
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module RubyLLM
|
2
|
+
class Message
|
3
|
+
VALID_ROLES = %i[system user assistant tool].freeze
|
4
|
+
|
5
|
+
attr_reader :role, :content, :tool_calls, :tool_results
|
6
|
+
|
7
|
+
def initialize(role:, content: nil, tool_calls: nil, tool_results: nil)
|
8
|
+
@role = role.to_sym
|
9
|
+
@content = content
|
10
|
+
@tool_calls = tool_calls
|
11
|
+
@tool_results = tool_results
|
12
|
+
validate!
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_h
|
16
|
+
{
|
17
|
+
role: role,
|
18
|
+
content: content,
|
19
|
+
tool_calls: tool_calls,
|
20
|
+
tool_results: tool_results
|
21
|
+
}.compact
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def validate!
|
27
|
+
unless VALID_ROLES.include?(role)
|
28
|
+
raise ArgumentError, "Invalid role: #{role}. Must be one of: #{VALID_ROLES.join(', ')}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module RubyLLM
|
2
|
+
module Providers
|
3
|
+
class Base
|
4
|
+
def initialize
|
5
|
+
@connection = build_connection
|
6
|
+
end
|
7
|
+
|
8
|
+
def chat(messages, **options, &block)
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def build_connection
|
15
|
+
Faraday.new(url: api_base) do |f|
|
16
|
+
f.options.timeout = RubyLLM.configuration.request_timeout
|
17
|
+
f.request :json
|
18
|
+
f.response :json
|
19
|
+
f.adapter Faraday.default_adapter
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle_error(error)
|
24
|
+
case error
|
25
|
+
when Faraday::TimeoutError
|
26
|
+
raise RubyLLM::Error, "Request timed out"
|
27
|
+
when Faraday::ConnectionFailed
|
28
|
+
raise RubyLLM::Error, "Connection failed"
|
29
|
+
when Faraday::ClientError
|
30
|
+
handle_api_error(error)
|
31
|
+
else
|
32
|
+
raise error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def handle_api_error(error)
|
37
|
+
raise RubyLLM::Error, "API error: #{error.response[:status]}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/ruby_llm.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'zeitwerk'
|
2
|
+
require 'faraday'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module RubyLLM
|
6
|
+
class Error < StandardError; end
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :configuration
|
10
|
+
|
11
|
+
def configure
|
12
|
+
self.configuration ||= Configuration.new
|
13
|
+
yield(configuration) if block_given?
|
14
|
+
end
|
15
|
+
|
16
|
+
def client
|
17
|
+
@client ||= Client.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def loader
|
21
|
+
@loader ||= begin
|
22
|
+
loader = Zeitwerk::Loader.for_gem
|
23
|
+
loader.inflector.inflect(
|
24
|
+
'llm' => 'LLM',
|
25
|
+
'openai' => 'OpenAI',
|
26
|
+
'api' => 'API'
|
27
|
+
)
|
28
|
+
loader.setup
|
29
|
+
loader
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Register inflections
|
36
|
+
RubyLLM.loader
|
data/ruby_llm.gemspec
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative 'lib/ruby_llm/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "ruby_llm"
|
5
|
+
spec.version = RubyLLM::VERSION
|
6
|
+
spec.authors = ["Carmine Paolino"]
|
7
|
+
spec.email = ["carmine@paolino.me"]
|
8
|
+
|
9
|
+
spec.summary = %q{The Ruby LLM client library - unified interface for OpenAI, Anthropic, and other LLM providers}
|
10
|
+
spec.description = %q{Complete Ruby library for working with Large Language Models (LLMs). Supports OpenAI, Anthropic,
|
11
|
+
and others with a consistent interface. Features include tool usage, token tracking, and seamless Rails integration.}
|
12
|
+
spec.homepage = "https://github.com/crmne/ruby_llm"
|
13
|
+
spec.license = "MIT"
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
|
15
|
+
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
18
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
19
|
+
spec.metadata["documentation_uri"] = "https://rubydoc.info/gems/ruby_llm"
|
20
|
+
spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
end
|
27
|
+
spec.bindir = "exe"
|
28
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
|
+
spec.require_paths = ["lib"]
|
30
|
+
|
31
|
+
# Runtime dependencies
|
32
|
+
spec.add_dependency "faraday", ">= 2.0"
|
33
|
+
spec.add_dependency "faraday-multipart", ">= 1.0"
|
34
|
+
spec.add_dependency "zeitwerk", ">= 2.6"
|
35
|
+
|
36
|
+
# Rails integration dependencies
|
37
|
+
spec.add_development_dependency "activesupport", ">= 6.0", "< 9.0"
|
38
|
+
spec.add_development_dependency "activerecord", ">= 6.0", "< 9.0"
|
39
|
+
|
40
|
+
# Development dependencies
|
41
|
+
spec.add_development_dependency "bundler", ">= 2.0"
|
42
|
+
spec.add_development_dependency "rake", ">= 13.0"
|
43
|
+
spec.add_development_dependency "rubocop", ">= 1.0"
|
44
|
+
spec.add_development_dependency "yard", ">= 0.9"
|
45
|
+
spec.add_development_dependency "simplecov", ">= 0.21"
|
46
|
+
spec.add_development_dependency "pry", ">= 0.14"
|
47
|
+
spec.add_development_dependency "overcommit", ">= 0.66"
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,243 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby_llm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.pre
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Carmine Paolino
|
8
|
+
bindir: exe
|
9
|
+
cert_chain: []
|
10
|
+
date: 2025-01-30 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: faraday
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - ">="
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '2.0'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '2.0'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: faraday-multipart
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: zeitwerk
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '2.6'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.6'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: activesupport
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '6.0'
|
61
|
+
- - "<"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '9.0'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '6.0'
|
71
|
+
- - "<"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '9.0'
|
74
|
+
- !ruby/object:Gem::Dependency
|
75
|
+
name: activerecord
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '6.0'
|
81
|
+
- - "<"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '9.0'
|
84
|
+
type: :development
|
85
|
+
prerelease: false
|
86
|
+
version_requirements: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '6.0'
|
91
|
+
- - "<"
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '9.0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: bundler
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '2.0'
|
101
|
+
type: :development
|
102
|
+
prerelease: false
|
103
|
+
version_requirements: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '2.0'
|
108
|
+
- !ruby/object:Gem::Dependency
|
109
|
+
name: rake
|
110
|
+
requirement: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '13.0'
|
115
|
+
type: :development
|
116
|
+
prerelease: false
|
117
|
+
version_requirements: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '13.0'
|
122
|
+
- !ruby/object:Gem::Dependency
|
123
|
+
name: rubocop
|
124
|
+
requirement: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '1.0'
|
129
|
+
type: :development
|
130
|
+
prerelease: false
|
131
|
+
version_requirements: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '1.0'
|
136
|
+
- !ruby/object:Gem::Dependency
|
137
|
+
name: yard
|
138
|
+
requirement: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0.9'
|
143
|
+
type: :development
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0.9'
|
150
|
+
- !ruby/object:Gem::Dependency
|
151
|
+
name: simplecov
|
152
|
+
requirement: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0.21'
|
157
|
+
type: :development
|
158
|
+
prerelease: false
|
159
|
+
version_requirements: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0.21'
|
164
|
+
- !ruby/object:Gem::Dependency
|
165
|
+
name: pry
|
166
|
+
requirement: !ruby/object:Gem::Requirement
|
167
|
+
requirements:
|
168
|
+
- - ">="
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '0.14'
|
171
|
+
type: :development
|
172
|
+
prerelease: false
|
173
|
+
version_requirements: !ruby/object:Gem::Requirement
|
174
|
+
requirements:
|
175
|
+
- - ">="
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
version: '0.14'
|
178
|
+
- !ruby/object:Gem::Dependency
|
179
|
+
name: overcommit
|
180
|
+
requirement: !ruby/object:Gem::Requirement
|
181
|
+
requirements:
|
182
|
+
- - ">="
|
183
|
+
- !ruby/object:Gem::Version
|
184
|
+
version: '0.66'
|
185
|
+
type: :development
|
186
|
+
prerelease: false
|
187
|
+
version_requirements: !ruby/object:Gem::Requirement
|
188
|
+
requirements:
|
189
|
+
- - ">="
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: '0.66'
|
192
|
+
description: |-
|
193
|
+
Complete Ruby library for working with Large Language Models (LLMs). Supports OpenAI, Anthropic,
|
194
|
+
and others with a consistent interface. Features include tool usage, token tracking, and seamless Rails integration.
|
195
|
+
email:
|
196
|
+
- carmine@paolino.me
|
197
|
+
executables: []
|
198
|
+
extensions: []
|
199
|
+
extra_rdoc_files: []
|
200
|
+
files:
|
201
|
+
- ".github/workflows/gem-push.yml"
|
202
|
+
- README.md
|
203
|
+
- Rakefile
|
204
|
+
- bin/console
|
205
|
+
- bin/setup
|
206
|
+
- lib/ruby_llm.rb
|
207
|
+
- lib/ruby_llm/active_record/acts_as.rb
|
208
|
+
- lib/ruby_llm/client.rb
|
209
|
+
- lib/ruby_llm/configuration.rb
|
210
|
+
- lib/ruby_llm/conversation.rb
|
211
|
+
- lib/ruby_llm/message.rb
|
212
|
+
- lib/ruby_llm/providers/base.rb
|
213
|
+
- lib/ruby_llm/railtie.rb
|
214
|
+
- lib/ruby_llm/version.rb
|
215
|
+
- ruby_llm.gemspec
|
216
|
+
homepage: https://github.com/crmne/ruby_llm
|
217
|
+
licenses:
|
218
|
+
- MIT
|
219
|
+
metadata:
|
220
|
+
homepage_uri: https://github.com/crmne/ruby_llm
|
221
|
+
source_code_uri: https://github.com/crmne/ruby_llm
|
222
|
+
changelog_uri: https://github.com/crmne/ruby_llm/blob/main/CHANGELOG.md
|
223
|
+
documentation_uri: https://rubydoc.info/gems/ruby_llm
|
224
|
+
bug_tracker_uri: https://github.com/crmne/ruby_llm/issues
|
225
|
+
rdoc_options: []
|
226
|
+
require_paths:
|
227
|
+
- lib
|
228
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
229
|
+
requirements:
|
230
|
+
- - ">="
|
231
|
+
- !ruby/object:Gem::Version
|
232
|
+
version: 2.7.0
|
233
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
234
|
+
requirements:
|
235
|
+
- - ">="
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: '0'
|
238
|
+
requirements: []
|
239
|
+
rubygems_version: 3.6.2
|
240
|
+
specification_version: 4
|
241
|
+
summary: The Ruby LLM client library - unified interface for OpenAI, Anthropic, and
|
242
|
+
other LLM providers
|
243
|
+
test_files: []
|