ruby_llm 0.1.0.pre22 → 0.1.0.pre24

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd4ad1e43337ca5d8af417b3cebc3ba8ce9cb29d7136342955c7f9669bb0ff6b
4
- data.tar.gz: ea5bdad3ece2f0198fa10f36f50e91876f4b402f6f0cc2c717e3a4cfdcbc103e
3
+ metadata.gz: a8bd50f20230190ef4d162a93d782718b77809cf08a69a5c937e04b1371dcb4c
4
+ data.tar.gz: af2fd4748779981144cabb58ed8156804dbf95fc49fcaee29883e8473a3715d0
5
5
  SHA512:
6
- metadata.gz: d8674edc3b37547e00831aabf777ceb6bc757b067545a33980d4a741af81a39673edf1d26693772ae3ca38579674288c9f345a87b9d2c6c1d7f173e16e79255c
7
- data.tar.gz: 5f3217f2e87794c6c5782765c8f9aa78047ed1d1ce3e4faa4d99f8ef3b0bf03bf03ed001db38d26b76d3e4a98a7a9bff2741f0ba1f18386ff6a9455d27cbf47b
6
+ metadata.gz: c51d06260e839452c179c79ff3e993b1aadaf57d61263b925735502f19221779c5310c2b80fdf82cdeb0bbc8cc1cedf0e69a9cce20aa5c5dced9229b4c4d5814
7
+ data.tar.gz: 1d10277144d9168ced74e80e22664e95ba3df57dafc3a836588b49e58b6d31e46b46290bd64a16902ae32dd7f654911530d7e5b09f2f0963cb12130610725a14
data/lib/ruby_llm/chat.rb CHANGED
@@ -16,7 +16,7 @@ module RubyLLM
16
16
  def initialize(model: nil)
17
17
  model_id = model || RubyLLM.config.default_model
18
18
  self.model = model_id
19
- @temperature = 0.7
19
+ @temperature = @model.metadata['family'] == 'o1' ? 1 : 0.7
20
20
  @messages = []
21
21
  @tools = {}
22
22
  @on = {
@@ -33,7 +33,9 @@ module RubyLLM
33
33
  alias say ask
34
34
 
35
35
  def with_tool(tool)
36
- raise Error, "Model #{@model.id} doesn't support function calling" unless @model.supports_functions
36
+ unless @model.supports_functions
37
+ raise UnsupportedFunctionsError, "Model #{@model.id} doesn't support function calling"
38
+ end
37
39
 
38
40
  tool_instance = tool.is_a?(Class) ? tool.new : tool
39
41
  @tools[tool_instance.name.to_sym] = tool_instance
@@ -19,6 +19,9 @@ module RubyLLM
19
19
  end
20
20
  end
21
21
 
22
+ class ModelNotFoundError < StandardError; end
23
+ class InvalidRoleError < StandardError; end
24
+ class UnsupportedFunctionsError < StandardError; end
22
25
  class UnauthorizedError < Error; end
23
26
  class BadRequestError < Error; end
24
27
  class RateLimitError < Error; end
@@ -27,24 +30,30 @@ module RubyLLM
27
30
  # Faraday middleware that maps provider-specific API errors to RubyLLM errors.
28
31
  # Uses provider's parse_error method to extract meaningful error messages.
29
32
  class ErrorMiddleware < Faraday::Middleware
30
- def initialize(app, provider: nil)
33
+ def initialize(app, provider:)
31
34
  super(app)
32
35
  @provider = provider
33
36
  end
34
37
 
35
- def call(env) # rubocop:disable Metrics/MethodLength
38
+ def call(env)
36
39
  @app.call(env).on_complete do |response|
37
- message = @provider&.parse_error(response)
40
+ self.class.parse_error(provider: @provider, response: response)
41
+ end
42
+ end
43
+
44
+ class << self
45
+ def parse_error(provider:, response:) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
46
+ message = provider&.parse_error(response)
38
47
 
39
48
  case response.status
40
49
  when 400
41
- raise BadRequestError.new(response, message)
50
+ raise BadRequestError.new(response, message || 'Invalid request - please check your input')
42
51
  when 401
43
- raise UnauthorizedError.new(response, 'Invalid API key - check your credentials')
52
+ raise UnauthorizedError.new(response, message || 'Invalid API key - check your credentials')
44
53
  when 429
45
- raise RateLimitError.new(response, 'Rate limit exceeded - please wait a moment')
54
+ raise RateLimitError.new(response, message || 'Rate limit exceeded - please wait a moment')
46
55
  when 500..599
47
- raise ServerError.new(response, 'API server error - please try again')
56
+ raise ServerError.new(response, message || 'API server error - please try again')
48
57
  end
49
58
  end
50
59
  end
@@ -48,7 +48,7 @@ module RubyLLM
48
48
  private
49
49
 
50
50
  def ensure_valid_role
51
- raise Error, "Expected role to be one of: #{ROLES.join(', ')}" unless ROLES.include?(role)
51
+ raise InvalidRoleError, "Expected role to be one of: #{ROLES.join(', ')}" unless ROLES.include?(role)
52
52
  end
53
53
  end
54
54
  end
@@ -25,7 +25,7 @@ module RubyLLM
25
25
  end
26
26
 
27
27
  def find(model_id)
28
- all.find { |m| m.id == model_id } or raise Error, "Unknown model: #{model_id}"
28
+ all.find { |m| m.id == model_id } or raise ModelNotFoundError, "Unknown model: #{model_id}"
29
29
  end
30
30
 
31
31
  def chat_models
@@ -74,20 +74,43 @@ module RubyLLM
74
74
  end
75
75
  end
76
76
 
77
- def to_json_stream(&block)
77
+ def to_json_stream(&block) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
78
+ buffer = String.new
78
79
  parser = EventStreamParser::Parser.new
79
- proc do |chunk, _bytes, _|
80
- parser.feed(chunk) do |_type, data|
81
- unless data == '[DONE]'
82
- parsed_data = JSON.parse(data)
83
- RubyLLM.logger.debug "chunk: #{parsed_data}"
84
- block.call(parsed_data)
80
+
81
+ proc do |chunk, _bytes, env|
82
+ if env && env.status != 200
83
+ # Accumulate error chunks
84
+ buffer << chunk
85
+ begin
86
+ error_data = JSON.parse(buffer)
87
+ error_response = env.merge(body: error_data)
88
+ ErrorMiddleware.parse_error(provider: self, response: error_response)
89
+ rescue JSON::ParserError
90
+ # Keep accumulating if we don't have complete JSON yet
91
+ RubyLLM.logger.debug "Accumulating error chunk: #{chunk}"
92
+ end
93
+ else
94
+ parser.feed(chunk) do |_type, data|
95
+ unless data == '[DONE]'
96
+ parsed_data = JSON.parse(data)
97
+ RubyLLM.logger.debug "chunk: #{parsed_data}"
98
+ block.call(parsed_data)
99
+ end
85
100
  end
86
101
  end
87
102
  end
88
103
  end
89
104
  end
90
105
 
106
+ def try_parse_json(maybe_json)
107
+ return maybe_json if maybe_json.is_a?(Hash)
108
+
109
+ JSON.parse(maybe_json)
110
+ rescue JSON::ParserError
111
+ maybe_json
112
+ end
113
+
91
114
  class << self
92
115
  def register(name, provider_class)
93
116
  providers[name.to_sym] = provider_class
@@ -95,8 +118,7 @@ module RubyLLM
95
118
 
96
119
  def for(model)
97
120
  model_info = Models.find(model)
98
- provider_class = providers[model_info.provider.to_sym] or
99
- raise Error, "No provider registered for #{model_info.provider}"
121
+ provider_class = providers[model_info.provider.to_sym]
100
122
 
101
123
  provider_class.new
102
124
  end
@@ -10,7 +10,8 @@ module RubyLLM
10
10
  def parse_error(response)
11
11
  return if response.body.empty?
12
12
 
13
- JSON.parse(response.body).dig('error', 'message')
13
+ body = try_parse_json(response.body)
14
+ body.is_a?(Hash) ? body.dig('error', 'message') : body
14
15
  end
15
16
 
16
17
  private
@@ -11,7 +11,8 @@ module RubyLLM
11
11
  def parse_error(response)
12
12
  return if response.body.empty?
13
13
 
14
- JSON.parse(response.body).dig('error', 'message')
14
+ body = try_parse_json(response.body)
15
+ body.is_a?(Hash) ? body.dig('error', 'message') : body
15
16
  end
16
17
 
17
18
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyLLM
4
- VERSION = '0.1.0.pre22'
4
+ VERSION = '0.1.0.pre24'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_llm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre22
4
+ version: 0.1.0.pre24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carmine Paolino
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-02-12 00:00:00.000000000 Z
11
+ date: 2025-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: event_stream_parser