anthropic 0.3.2 → 0.4.0

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: 4b7437e17231234859a48749dd8da3cdbd5a809df002cb2654a78b6d91edbff5
4
- data.tar.gz: 38b2a62cc793013345b9eeef31d152f3fcd1a704515a45640132ff8ceccfd24c
3
+ metadata.gz: e24210f58ccd16ce106ed724e30329b939b14841939ee48021116cd0d28dee22
4
+ data.tar.gz: cf6360e53934c341149731c8b8d06899e69b728f6d5cf8a2dac9ff5d7ca48096
5
5
  SHA512:
6
- metadata.gz: 53e3400a7f4a752a981e788dac7b83c286732dd18216ad0314a7a84d703f582930b5dcaeae19ebcd8c8ab3ace746dbe277e096fe5604c5b3edc9163acf1b16fd
7
- data.tar.gz: 94ea524fb3e4b6a1e7b8f3277315b7a001488bbb7d345240cf6120820af405be212f6a8e6a30f480e2c14110cc03cd71545cf022538d6ce1c8936f7631cef41e
6
+ metadata.gz: abea1b674f82f8328b3711f79b06a9a46133b69113b5c08f3532a528c8a8fdfee38519ea1805a4c815320a587bcfdaa7248a5902420d03a520e2b5bc3dc445b0
7
+ data.tar.gz: dc7a8706a64c5e84faa3eeb265d2106c4c3b9bb0d10380bae52aaca2529291fce72679d083c03f7f26512a442f3c532ad5c5eca2a6342f363af8c273b0f8dce3
data/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.0] - 2025-03-25
9
+
10
+ ### Added
11
+
12
+ - Add Batches API! Thanks to [@ignacio-chiazzo](https://github.com/ignacio-chiazzo) for previous work on this.
13
+
8
14
  ## [0.3.2] - 2024-10-09
9
15
 
10
16
  ### Fixed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- anthropic (0.3.2)
4
+ anthropic (0.4.0)
5
5
  event_stream_parser (>= 0.3.0, < 2.0.0)
6
6
  faraday (>= 1)
7
7
  faraday-multipart (>= 1)
data/README.md CHANGED
@@ -43,7 +43,10 @@ require "anthropic"
43
43
  For a quick test you can pass your token directly to a new client:
44
44
 
45
45
  ```ruby
46
- client = Anthropic::Client.new(access_token: "access_token_goes_here")
46
+ client = Anthropic::Client.new(
47
+ access_token: "access_token_goes_here",
48
+ log_errors: true # Highly recommended in development, so you can see what errors Anthropic is returning. Not recommended in production because it could leak private data to your logs.
49
+ )
47
50
  ```
48
51
 
49
52
  ### With Config
@@ -53,10 +56,11 @@ For a more robust setup, you can configure the gem with your API keys, for examp
53
56
  ```ruby
54
57
  Anthropic.configure do |config|
55
58
  # With dotenv
56
- config.access_token = ENV.fetch("ANTHROPIC_API_KEY")
59
+ config.access_token = ENV.fetch("ANTHROPIC_API_KEY"),
57
60
  # OR
58
61
  # With Rails credentials
59
- config.access_token = Rails.application.credentials.dig(:anthropic, :api_key)
62
+ config.access_token = Rails.application.credentials.dig(:anthropic, :api_key),
63
+ config.log_errors = true # Highly recommended in development, so you can see what errors Anthropic is returning. Not recommended in production because it could leak private data to your logs.
60
64
  end
61
65
  ```
62
66
 
@@ -75,6 +79,7 @@ The default timeout for any request using this library is 120 seconds. You can c
75
79
  ```ruby
76
80
  client = Anthropic::Client.new(
77
81
  access_token: "access_token_goes_here",
82
+ log_errors: true, # Optional
78
83
  anthropic_version: "2023-01-01", # Optional
79
84
  request_timeout: 240 # Optional
80
85
  )
@@ -90,6 +95,16 @@ Anthropic.configure do |config|
90
95
  end
91
96
  ```
92
97
 
98
+ #### Logging
99
+
100
+ ##### Errors
101
+ By default, the `anthropic` gem does not log any `Faraday::Error`s encountered while executing a network request to avoid leaking data (e.g. 400s, 500s, SSL errors and more - see [here](https://www.rubydoc.info/github/lostisland/faraday/Faraday/Error) for a complete list of subclasses of `Faraday::Error` and what can cause them).
102
+
103
+ If you would like to enable this functionality, you can set `log_errors` to `true` when configuring the client:
104
+ ```ruby
105
+ client = Anthropic::Client.new(log_errors: true)
106
+ ```
107
+
93
108
  ### Models
94
109
 
95
110
  Available Models:
@@ -133,6 +148,62 @@ response = client.messages(
133
148
  # => }
134
149
  ```
135
150
 
151
+ ### Batches
152
+ The Batches API can be used to process multiple Messages API requests at once. Once a Message Batch is created, it begins processing immediately. Batches can contain up to 100,000 requests and be up to 256 MB in total size.
153
+
154
+ Create a batch of message requests:
155
+ ```ruby
156
+ response = client.messages.batches.create(
157
+ parameters: {
158
+ requests: [
159
+ {
160
+ custom_id: "my-first-request",
161
+ params: {
162
+ model: "claude-3-haiku-20240307",
163
+ max_tokens: 1024,
164
+ messages: [
165
+ { role: "user", content: "Hello, world" }
166
+ ]
167
+ }
168
+ },
169
+ {
170
+ custom_id: "my-second-request",
171
+ params: {
172
+ model: "claude-3-haiku-20240307",
173
+ max_tokens: 1024,
174
+ messages: [
175
+ { role: "user", content: "Hi again, friend" }
176
+ ]
177
+ }
178
+ }
179
+ ]
180
+ }
181
+ )
182
+ batch_id = response["id"]
183
+ ```
184
+
185
+ You can retrieve information about a specific batch:
186
+ ```ruby
187
+ batch = client.messages.batches.get(id: batch_id)
188
+ ```
189
+
190
+ To cancel a batch that is in progress:
191
+ ```ruby
192
+ client.messages.batches.cancel(id: batch_id)
193
+ ```
194
+
195
+ List all batches:
196
+ ```ruby
197
+ client.messages.batches.list
198
+ ```
199
+
200
+ Once processing ends, you can fetch the results:
201
+ ```ruby
202
+ results = client.messages.batches.results(id: batch_id)
203
+ ```
204
+
205
+ Results are returned as a .jsonl file, with each line containing the result of a single request. Results may be in any order - use the custom_id field to match results to requests.
206
+
136
207
  #### Vision
137
208
 
138
209
  Claude 3 family of models comes with vision capabilities that allow Claude to understand and analyze images.
@@ -1,3 +1,6 @@
1
+ require_relative "messages/batches"
2
+ require_relative "messages/client"
3
+
1
4
  module Anthropic
2
5
  class Client
3
6
  include Anthropic::HTTP
@@ -6,10 +9,12 @@ module Anthropic
6
9
  access_token
7
10
  anthropic_version
8
11
  api_version
12
+ log_errors
9
13
  uri_base
10
14
  request_timeout
11
15
  extra_headers
12
16
  ].freeze
17
+ attr_reader(*CONFIG_KEYS)
13
18
 
14
19
  def initialize(config = {}, &faraday_middleware)
15
20
  CONFIG_KEYS.each do |key|
@@ -30,7 +35,10 @@ module Anthropic
30
35
  end
31
36
 
32
37
  # Anthropic API Parameters as of 2024-05-07:
33
- # @see https://docs.anthropic.com/claude/reference/messages_post
38
+ # @see https://docs.anthropic.com/claude/reference/messages_post
39
+ #
40
+ # When called without parameters, returns a Messages::Batches instance for batch operations.
41
+ # When called with parameters, creates a single message.
34
42
  #
35
43
  # @param [Hash] parameters
36
44
  # @option parameters [Array] :messages - Required. An array of messages to send to the API. Each
@@ -51,20 +59,44 @@ module Anthropic
51
59
  # arguments: the first will be the text accrued so far, and the second will be the delta
52
60
  # just received in the current chunk.
53
61
  #
54
- # @returns [Hash] the response from the API (after the streaming is done, if streaming)
55
- # @example:
56
- # {
57
- # "id" => "msg_013xVudG9xjSvLGwPKMeVXzG",
58
- # "type" => "message",
59
- # "role" => "assistant",
60
- # "content" => [{"type" => "text", "text" => "The sky has no distinct"}],
61
- # "model" => "claude-2.1",
62
- # "stop_reason" => "max_tokens",
63
- # "stop_sequence" => nil,
64
- # "usage" => {"input_tokens" => 15, "output_tokens" => 5}
65
- # }
66
- def messages(parameters: {})
67
- json_post(path: "/messages", parameters: parameters)
62
+ # @returns [Hash, Messages::Client] Returns a Hash response from the API when creating a message
63
+ # with parameters, or a Messages::Client instance when called without parameters
64
+ # @example Creating a message:
65
+ # {
66
+ # "id" => "msg_013xVudG9xjSvLGwPKMeVXzG",
67
+ # "type" => "message",
68
+ # "role" => "assistant",
69
+ # "content" => [{"type" => "text", "text" => "The sky has no distinct"}],
70
+ # "model" => "claude-2.1",
71
+ # "stop_reason" => "max_tokens",
72
+ # "stop_sequence" => nil,
73
+ # "usage" => {"input_tokens" => 15, "output_tokens" => 5}
74
+ # }
75
+ # @example Accessing batches:
76
+ # client.messages.batches.create(requests: [...])
77
+ # client.messages.batches.get(id: "batch_123")
78
+ def messages(**args)
79
+ return @messages ||= Messages::Client.new(self) unless args && args[:parameters]
80
+
81
+ json_post(path: "/messages", parameters: args[:parameters])
82
+ end
83
+
84
+ # Adds Anthropic beta features to API requests. Can be used in two ways:
85
+ #
86
+ # 1. Multiple betas in one call with comma-separated string:
87
+ # client.beta("feature1,feature2").messages
88
+ #
89
+ # 2. Chaining multiple beta calls:
90
+ # client.beta("feature1").beta("feature2").messages
91
+ #
92
+ # @param version [String] The beta version(s) to enable
93
+ # @return [Client] A new client instance with the beta header(s)
94
+ def beta(version)
95
+ dup.tap do |client|
96
+ existing_beta = client.extra_headers["anthropic-beta"]
97
+ combined_beta = [existing_beta, version].compact.join(",")
98
+ client.add_headers("anthropic-beta" => combined_beta)
99
+ end
68
100
  end
69
101
 
70
102
  private
@@ -5,5 +5,6 @@ module Ruby
5
5
  Error = ::Anthropic::Error
6
6
  ConfigurationError = ::Anthropic::ConfigurationError
7
7
  Configuration = ::Anthropic::Configuration
8
+ MiddlewareErrors = ::Anthropic::MiddlewareErrors
8
9
  end
9
10
  end
@@ -7,19 +7,19 @@ module Anthropic
7
7
  module HTTP
8
8
  include HTTPHeaders
9
9
 
10
- # Unused?
11
- def get(path:)
12
- to_json(conn.get(uri(path: path)) do |req|
10
+ def get(path:, parameters: nil)
11
+ response = conn.get(uri(path: path), parameters) do |req|
13
12
  req.headers = headers
14
- end&.body)
13
+ end
14
+ response&.body
15
15
  end
16
16
 
17
- # This is currently the workhorse for all API calls.
18
17
  # rubocop:disable Metrics/MethodLength
19
- def json_post(path:, parameters:)
18
+ # rubocop:disable Metrics/AbcSize
19
+ def json_post(path:, parameters: {})
20
20
  str_resp = {}
21
21
  response = conn.post(uri(path: path)) do |req|
22
- if parameters[:stream].is_a?(Proc)
22
+ if parameters.respond_to?(:key?) && parameters[:stream].is_a?(Proc)
23
23
  req.options.on_data = to_json_stream(user_proc: parameters[:stream], response: str_resp,
24
24
  preprocess: parameters[:preprocess_stream])
25
25
  parameters[:stream] = true # Necessary to tell Anthropic to stream.
@@ -33,8 +33,9 @@ module Anthropic
33
33
  str_resp.empty? ? response.body : str_resp
34
34
  end
35
35
  # rubocop:enable Metrics/MethodLength
36
+ # rubocop:enable Metrics/AbcSize
36
37
 
37
- # Unused?
38
+ # Unused - leave in until v1 since someone might be using it.
38
39
  def multipart_post(path:, parameters: nil)
39
40
  to_json(conn(multipart: true).post(uri(path: path)) do |req|
40
41
  req.headers = headers.merge({ "Content-Type" => "multipart/form-data" })
@@ -42,7 +43,7 @@ module Anthropic
42
43
  end&.body)
43
44
  end
44
45
 
45
- # Unused?
46
+ # Unused - leave in until v1 since someone might be using it.
46
47
  def delete(path:)
47
48
  to_json(conn.delete(uri(path: path)) do |req|
48
49
  req.headers = headers
@@ -51,7 +52,7 @@ module Anthropic
51
52
 
52
53
  private
53
54
 
54
- # Used only by unused methods?
55
+ # Used only in unused methods - leave in until v1 since someone might be using it.
55
56
  def to_json(string)
56
57
  return unless string
57
58
 
@@ -63,7 +64,7 @@ module Anthropic
63
64
 
64
65
  # Given a proc, returns an outer proc that can be used to iterate over a JSON stream of chunks.
65
66
  # For each chunk, the inner user_proc is called giving it the JSON object. The JSON object could
66
- # be a data object or an error object as described in the OpenAI API documentation.
67
+ # be a data object or an error object as described in the Anthropic API documentation.
67
68
  #
68
69
  # @param user_proc [Proc] The inner proc to call for each JSON object in the chunk.
69
70
  # @return [Proc] An outer proc that iterates over a raw stream, converting it to JSON.
@@ -147,7 +148,7 @@ module Anthropic
147
148
  def log(error)
148
149
  logger = Logger.new($stdout)
149
150
  logger.formatter = proc do |_severity, _datetime, _progname, msg|
150
- "\033[31mAnthropic JSON Error (spotted in ruby-anthropic #{VERSION}): #{msg}\n\033[0m"
151
+ "\033[31mAnthropic JSON Error (spotted in anthropic #{VERSION}): #{msg}\n\033[0m"
151
152
  end
152
153
  logger.error(error)
153
154
  end
@@ -11,7 +11,7 @@ module Anthropic
11
11
  # if azure?
12
12
  # azure_headers
13
13
  # else
14
- # openai_headers
14
+ # anthropic_headers
15
15
  # end.merge(extra_headers)
16
16
  anthropic_headers.merge(extra_headers)
17
17
  end
@@ -0,0 +1,112 @@
1
+ module Anthropic
2
+ module Messages
3
+ class Batches
4
+ BETA_VERSION = "message-batches-2024-09-24".freeze
5
+
6
+ def initialize(client)
7
+ @client = client.beta(BETA_VERSION)
8
+ end
9
+
10
+ # Anthropic API Parameters as of 2024-10-09:
11
+ # @see https://docs.anthropic.com/en/api/creating-message-batches
12
+ #
13
+ # @param [Array] :parameters - List of requests for prompt completion.
14
+ # Each is an individual request to create a Message.
15
+ # Parameters are an array of hashes, each with the following keys:
16
+ # - :custom_id (required): Developer-provided ID created for each request in a Message Batch.
17
+ # Useful for matching results to requests, as results may be given out of request order.
18
+ # Must be unique for each request within the Message Batch.
19
+ # - :params (required): Messages API creation parameters for the individual request.
20
+ # See the Messages API reference for full documentation on available parameters.
21
+ #
22
+ # @returns [Hash] the response from the API (after the streaming is done, if streaming)
23
+ # @example:
24
+ #
25
+ # > messages.batches.create(parameters: [message1, message2])
26
+ # {
27
+ # "id"=>"msgbatch_01668jySCZeCpMLsxFcroNnN",
28
+ # "type"=>"message_batch",
29
+ # "processing_status"=>"in_progress",
30
+ # "request_counts"=>{
31
+ # "processing"=>2,
32
+ # "succeeded"=>0,
33
+ # "errored"=>0,
34
+ # "canceled"=>0,
35
+ # "expired"=>0
36
+ # },
37
+ # "ended_at"=>nil,
38
+ # "created_at"=>"2024-10-09T20:18:11.480471+00:00",
39
+ # "expires_at"=>"2024-10-10T20:18:11.480471+00:00",
40
+ # "cancel_initiated_at"=>nil,
41
+ # "results_url"=>nil
42
+ # }
43
+ def create(parameters: {})
44
+ @client.json_post(
45
+ path: "/messages/batches",
46
+ parameters: parameters
47
+ )
48
+ end
49
+
50
+ # Anthropic API Parameters as of 2024-10-09:
51
+ # @see https://docs.anthropic.com/en/api/creating-message-batches
52
+ #
53
+ # @param [String] :id - ID of the Message Batch.
54
+ #
55
+ # @returns [Hash] the same response shape as #create method.
56
+ def get(id:)
57
+ @client.get(path: "/messages/batches/#{id}")
58
+ end
59
+
60
+ # Anthropic API Parameters as of 2024-10-09:
61
+ # @see https://docs.anthropic.com/en/api/creating-message-batches
62
+ #
63
+ # @param [String] :id - ID of the Message Batch.
64
+ #
65
+ # Returns the results of a Message Batch as a .jsonl file.
66
+ # Each line in the file is a JSON object containing the result of a
67
+ # single request in the Message Batch.
68
+ # Results are not guaranteed to be in the same order as requests.
69
+ # Use the custom_id field to match results to requests.
70
+ def results(id:)
71
+ @client.get(path: "/messages/batches/#{id}/results")
72
+ end
73
+
74
+ # Anthropic API Parameters as of 2024-10-09:
75
+ # @see https://docs.anthropic.com/en/api/listing-message-batches
76
+ #
77
+ # List all Message Batches within a Workspace. Most recently created batches returned first.
78
+ # @param [String] :before_id - ID of the object to use as a cursor for pagination.
79
+ # When provided, returns the page of results immediately before this object.
80
+ #
81
+ # @param [String] :after_id - ID of the object to use as a cursor for pagination.
82
+ # When provided, returns the page of results immediately after this object.
83
+ #
84
+ # @param [Integer] :limit - Number of items to return per page.
85
+ # Defaults to 20. Ranges from 1 to 100.
86
+ #
87
+ # @returns [Hash] the response from the API
88
+ def list(parameters: {})
89
+ @client.get(path: "/messages/batches", parameters: parameters)
90
+ end
91
+
92
+ # Anthropic API Parameters as of 2024-10-09:
93
+ # @see https://docs.anthropic.com/en/api/creating-message-batches
94
+ #
95
+ # @param [String] :id - ID of the Message Batch.
96
+ #
97
+ # @returns [Hash] the response from the API
98
+ #
99
+ # Cancel a Message Batch.
100
+ # Batches may be canceled any time before processing ends. Once cancellation is initiated,
101
+ # the batch enters a canceling state, at which time the system may complete any in-progress,
102
+ # non-interruptible requests before finalizing cancellation.
103
+ #
104
+ # The number of canceled requests is specified in request_counts.
105
+ # To determine which requests were canceled, check the individual results within the batch.
106
+ # Note that cancellation may not cancel any requests if they were non-interruptible.
107
+ def cancel(id:)
108
+ @client.json_post(path: "/messages/batches/#{id}/cancel")
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,13 @@
1
+ module Anthropic
2
+ module Messages
3
+ class Client
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def batches
9
+ @batches ||= Batches.new(@client)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module Anthropic
2
- VERSION = "0.3.2".freeze
2
+ VERSION = "0.4.0".freeze
3
3
  end
data/lib/anthropic.rb CHANGED
@@ -17,7 +17,7 @@ module Anthropic
17
17
 
18
18
  logger = Logger.new($stdout)
19
19
  logger.formatter = proc do |_severity, _datetime, _progname, msg|
20
- "\033[31mAnthropic HTTP Error (spotted in ruby-anthropic #{VERSION}): #{msg}\n\033[0m"
20
+ "\033[31mAnthropic HTTP Error (spotted in anthropic #{VERSION}): #{msg}\n\033[0m"
21
21
  end
22
22
  logger.error(e.response[:body])
23
23
 
@@ -27,11 +27,16 @@ module Anthropic
27
27
 
28
28
  class Configuration
29
29
  attr_writer :access_token
30
- attr_accessor :anthropic_version, :api_version, :extra_headers,
31
- :request_timeout, :uri_base
30
+ attr_accessor :anthropic_version,
31
+ :api_version,
32
+ :extra_headers,
33
+ :log_errors,
34
+ :request_timeout,
35
+ :uri_base
32
36
 
33
37
  DEFAULT_API_VERSION = "v1".freeze
34
38
  DEFAULT_ANTHROPIC_VERSION = "2023-06-01".freeze
39
+ DEFAULT_LOG_ERRORS = false
35
40
  DEFAULT_URI_BASE = "https://api.anthropic.com/".freeze
36
41
  DEFAULT_REQUEST_TIMEOUT = 120
37
42
 
@@ -39,6 +44,7 @@ module Anthropic
39
44
  @access_token = nil
40
45
  @api_version = DEFAULT_API_VERSION
41
46
  @anthropic_version = DEFAULT_ANTHROPIC_VERSION
47
+ @log_errors = DEFAULT_LOG_ERRORS
42
48
  @uri_base = DEFAULT_URI_BASE
43
49
  @request_timeout = DEFAULT_REQUEST_TIMEOUT
44
50
  @extra_headers = {}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anthropic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-09 00:00:00.000000000 Z
11
+ date: 2025-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: event_stream_parser
@@ -88,6 +88,8 @@ files:
88
88
  - lib/anthropic/compatibility.rb
89
89
  - lib/anthropic/http.rb
90
90
  - lib/anthropic/http_headers.rb
91
+ - lib/anthropic/messages/batches.rb
92
+ - lib/anthropic/messages/client.rb
91
93
  - lib/anthropic/version.rb
92
94
  - lib/ruby/anthropic.rb
93
95
  - pull_request_template.md