ruby_llm 0.1.0.pre4 → 0.1.0.pre5

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.
metadata CHANGED
@@ -1,14 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_llm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre4
4
+ version: 0.1.0.pre5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carmine Paolino
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 2025-01-30 00:00:00.000000000 Z
11
+ date: 2025-02-01 00:00:00.000000000 Z
11
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: event_stream_parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.3.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.3.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.0
12
33
  - !ruby/object:Gem::Dependency
13
34
  name: faraday
14
35
  requirement: !ruby/object:Gem::Requirement
@@ -322,21 +343,22 @@ files:
322
343
  - bin/console
323
344
  - bin/setup
324
345
  - lib/ruby_llm.rb
325
- - lib/ruby_llm/active_record/acts_as.rb
326
- - lib/ruby_llm/client.rb
346
+ - lib/ruby_llm/chat.rb
347
+ - lib/ruby_llm/chunk.rb
327
348
  - lib/ruby_llm/configuration.rb
328
- - lib/ruby_llm/conversation.rb
329
349
  - lib/ruby_llm/message.rb
330
350
  - lib/ruby_llm/model_capabilities/anthropic.rb
331
- - lib/ruby_llm/model_capabilities/base.rb
332
351
  - lib/ruby_llm/model_capabilities/openai.rb
333
352
  - lib/ruby_llm/model_info.rb
353
+ - lib/ruby_llm/models.json
354
+ - lib/ruby_llm/models.rb
355
+ - lib/ruby_llm/provider.rb
334
356
  - lib/ruby_llm/providers/anthropic.rb
335
- - lib/ruby_llm/providers/base.rb
336
357
  - lib/ruby_llm/providers/openai.rb
337
358
  - lib/ruby_llm/railtie.rb
338
359
  - lib/ruby_llm/tool.rb
339
360
  - lib/ruby_llm/version.rb
361
+ - lib/tasks/models.rake
340
362
  - ruby_llm.gemspec
341
363
  homepage: https://github.com/crmne/ruby_llm
342
364
  licenses:
@@ -347,6 +369,7 @@ metadata:
347
369
  changelog_uri: https://github.com/crmne/ruby_llm/blob/main/CHANGELOG.md
348
370
  documentation_uri: https://rubydoc.info/gems/ruby_llm
349
371
  bug_tracker_uri: https://github.com/crmne/ruby_llm/issues
372
+ post_install_message:
350
373
  rdoc_options: []
351
374
  require_paths:
352
375
  - lib
@@ -361,7 +384,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
361
384
  - !ruby/object:Gem::Version
362
385
  version: '0'
363
386
  requirements: []
364
- rubygems_version: 3.6.2
387
+ rubygems_version: 3.5.22
388
+ signing_key:
365
389
  specification_version: 4
366
390
  summary: The Ruby LLM client library - unified interface for OpenAI, Anthropic, and
367
391
  other LLM providers
@@ -1,115 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyLLM
4
- module ActiveRecord
5
- # Provides ActsAs functionality for LLM-related models
6
- module ActsAs
7
- def acts_as_llm_model(_options = {})
8
- include ModelMethods
9
- end
10
-
11
- def acts_as_llm_conversation(_options = {})
12
- include ConversationMethods
13
- has_many :messages, -> { order(created_at: :asc) }
14
- end
15
-
16
- def acts_as_llm_message(_options = {})
17
- include MessageMethods
18
- belongs_to :conversation
19
- end
20
- end
21
-
22
- # Methods for LLM model functionality
23
- module ModelMethods
24
- extend ActiveSupport::Concern
25
-
26
- included do
27
- validates :name, presence: true
28
- validates :provider, presence: true
29
- end
30
-
31
- class_methods do
32
- def sync_models
33
- # Logic to sync models from providers
34
- end
35
- end
36
- end
37
-
38
- # Methods for LLM conversation handling
39
- module ConversationMethods
40
- extend ActiveSupport::Concern
41
-
42
- included do
43
- before_create :set_default_model
44
- end
45
-
46
- def send_message(content, model: nil)
47
- transaction do
48
- create_user_message(content)
49
- create_assistant_response(model)
50
- end
51
- end
52
-
53
- private
54
-
55
- def create_user_message(content)
56
- messages.create!(
57
- role: :user,
58
- content: content
59
- )
60
- end
61
-
62
- def create_assistant_response(model)
63
- response = RubyLLM.client.chat(
64
- conversation_messages,
65
- model: model || current_model
66
- )
67
-
68
- messages.create!(
69
- role: :assistant,
70
- content: response.content,
71
- token_count: response.token_count
72
- )
73
- end
74
-
75
- def conversation_messages
76
- messages.map(&:to_llm_format)
77
- end
78
-
79
- def set_default_model
80
- self.current_model ||= RubyLLM.configuration.default_model
81
- end
82
- end
83
-
84
- # Methods for LLM message handling
85
- module MessageMethods
86
- extend ActiveSupport::Concern
87
-
88
- included do
89
- validates :role, presence: true, inclusion: { in: RubyLLM::Message::VALID_ROLES.map(&:to_s) }
90
- validates :content, presence: true, unless: :tool_call?
91
-
92
- before_save :calculate_tokens
93
- end
94
-
95
- def to_llm_format
96
- RubyLLM::Message.new(
97
- role: role.to_sym,
98
- content: content,
99
- tool_calls: tool_calls,
100
- tool_results: tool_results
101
- )
102
- end
103
-
104
- private
105
-
106
- def calculate_tokens
107
- # Logic to calculate tokens
108
- end
109
-
110
- def tool_call?
111
- tool_calls.present? || tool_results.present?
112
- end
113
- end
114
- end
115
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyLLM
4
- # Client class for handling LLM provider interactions
5
- class Client
6
- def initialize
7
- @providers = {}
8
- end
9
-
10
- def chat(messages, model: nil, temperature: 0.7, stream: false, tools: nil, &block)
11
- # Convert any hash messages to Message objects
12
- formatted_messages = messages.map do |msg|
13
- msg.is_a?(Message) ? msg : Message.new(**msg)
14
- end
15
-
16
- provider = provider_for(model)
17
- response_messages = provider.chat(
18
- formatted_messages,
19
- model: model,
20
- temperature: temperature,
21
- stream: stream,
22
- tools: tools,
23
- &block
24
- )
25
-
26
- # Always return an array of messages, even for single responses
27
- response_messages.is_a?(Array) ? response_messages : [response_messages]
28
- end
29
-
30
- def list_models(provider = nil)
31
- if provider
32
- provider_for(nil, provider).list_models
33
- else
34
- all_providers.flat_map(&:list_models)
35
- end
36
- end
37
-
38
- private
39
-
40
- def all_providers
41
- [
42
- provider_for(nil, :openai),
43
- provider_for(nil, :anthropic)
44
- ]
45
- end
46
-
47
- def provider_for(model, specific_provider = nil)
48
- provider_name = specific_provider || detect_provider(model)
49
- @providers[provider_name] ||= case provider_name
50
- when :openai then Providers::OpenAI.new
51
- when :anthropic then Providers::Anthropic.new
52
- else
53
- raise Error, "Unsupported provider: #{provider_name}"
54
- end
55
- end
56
-
57
- def detect_provider(model)
58
- return RubyLLM.configuration.default_provider unless model
59
-
60
- case model
61
- when /^gpt-/, /^text-davinci/
62
- :openai
63
- when /^claude/
64
- :anthropic
65
- else
66
- RubyLLM.configuration.default_provider
67
- end
68
- end
69
- end
70
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyLLM
4
- # Represents a conversation with an LLM
5
- class Conversation
6
- attr_reader :id, :messages, :tools
7
-
8
- def initialize(tools: [])
9
- @id = SecureRandom.uuid
10
- @messages = []
11
- @tools = tools
12
- end
13
-
14
- def add_message(message)
15
- @messages << message
16
- message
17
- end
18
- end
19
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyLLM
4
- module ModelCapabilities
5
- class Base
6
- def determine_context_window(_model_id)
7
- raise NotImplementedError
8
- end
9
-
10
- def determine_max_tokens(_model_id)
11
- raise NotImplementedError
12
- end
13
-
14
- def get_input_price(_model_id)
15
- raise NotImplementedError
16
- end
17
-
18
- def get_output_price(_model_id)
19
- raise NotImplementedError
20
- end
21
-
22
- def supports_vision?(_model_id)
23
- raise NotImplementedError
24
- end
25
-
26
- def supports_functions?(_model_id)
27
- raise NotImplementedError
28
- end
29
-
30
- def supports_json_mode?(_model_id)
31
- raise NotImplementedError
32
- end
33
- end
34
- end
35
- end
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyLLM
4
- module Providers
5
- # Base provider class for LLM interactions
6
- class Base
7
- attr_reader :connection
8
-
9
- def initialize
10
- @connection = build_connection
11
- end
12
-
13
- def chat(messages, **options, &block)
14
- raise NotImplementedError
15
- end
16
-
17
- protected
18
-
19
- def check_for_api_error(response)
20
- return unless response.body.is_a?(Hash) && response.body['type'] == 'error'
21
-
22
- error_msg = response.body.dig('error', 'message') || 'Unknown API error'
23
- raise RubyLLM::Error, "API error: #{error_msg}"
24
- end
25
-
26
- def build_connection
27
- Faraday.new(url: api_base) do |f|
28
- f.options.timeout = RubyLLM.configuration.request_timeout
29
- f.request :json
30
- f.response :json
31
- f.adapter Faraday.default_adapter
32
- end
33
- end
34
-
35
- def handle_error(error)
36
- case error
37
- when Faraday::TimeoutError
38
- raise RubyLLM::Error, 'Request timed out'
39
- when Faraday::ConnectionFailed
40
- raise RubyLLM::Error, 'Connection failed'
41
- when Faraday::ClientError
42
- handle_api_error(error)
43
- else
44
- raise error
45
- end
46
- end
47
-
48
- def handle_api_error(error)
49
- raise RubyLLM::Error, "API error: #{error.response[:status]}"
50
- end
51
-
52
- def parse_error_message(response)
53
- return "HTTP #{response.status}" unless response.body
54
-
55
- if response.body.is_a?(String)
56
- begin
57
- JSON.parse(response.body).dig('error', 'message')
58
- rescue StandardError
59
- "HTTP #{response.status}"
60
- end
61
- else
62
- response.body.dig('error', 'message') || "HTTP #{response.status}"
63
- end
64
- end
65
- end
66
- end
67
- end