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 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
+ [![Gem Version](https://badge.fury.io/rb/ruby_llm.svg)](https://badge.fury.io/rb/ruby_llm)
6
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](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
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/clean"
3
+
4
+ task default: %w[build]
data/bin/console ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ require "bundler/setup"
3
+ require "ruby_llm"
4
+
5
+ require "irb"
6
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
@@ -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
@@ -0,0 +1,9 @@
1
+ module RubyLLM
2
+ class Railtie < Rails::Railtie
3
+ initializer 'ruby_llm.initialize' do
4
+ ActiveSupport.on_load(:active_record) do
5
+ extend RubyLLM::ActiveRecord::ActsAs
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module RubyLLM
2
+ VERSION = "0.1.0.pre"
3
+ 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: []