anthropic-rb 0.2.5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e3bf7350209fe6270479e8bc20f1418975257b6cfb1beb2d67547eec8d4e168
4
- data.tar.gz: 38c41a98c7095491ade15304025a8d6febb35ec10d758a7a0b725ad23a4e19e7
3
+ metadata.gz: b5e066105f3157621c27e2f974ed43bde9f14e6e55187d1d7a4f095b79a5a1ba
4
+ data.tar.gz: f32d479f7ec06c29a0347f69084a4378a64d69233d78ed280f5a1c924e15d708
5
5
  SHA512:
6
- metadata.gz: a69135f37ef25151067595106f6955c4fea146d4a95eb4093925d4a8eb26f9be46b4dcf4920e3a0cc8e55b462690a23ee929ab93468b358d51169aea90ed9f3d
7
- data.tar.gz: 0405140a9574e4e4afa23504714f25687ed7a47acb5a02adec25e4b5e7ab6007ab3d160835e82a46795dba63f91b83801ba671db32cc8f5e47098e86278d9c06
6
+ metadata.gz: 90040c86504a3dfd28e0093d1b8525252387f4e978271908aa158d1cffe10a3dd5766aadc243bc31f45ca6dd38ecf1259d009b2da9f2f78670fcc114c76574a3
7
+ data.tar.gz: 8ca46c62fe204b3b2403cce1267b6661f43c52159c8d31877b9d2522be604427996eedcbac67ba22a1b6df703259ededd98ea2b86d49755d7aa057835458321c
data/.reek.yml CHANGED
@@ -5,3 +5,9 @@ detectors:
5
5
  TooManyStatements:
6
6
  exclude:
7
7
  - 'Anthropic::Client#self.post'
8
+ BooleanParameter:
9
+ exclude:
10
+ - 'Anthropic::Messages#initialize'
11
+ DuplicateMethodCall:
12
+ exclude:
13
+ - 'Anthropic::Messages#create'
data/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.4.0] - 2024-04-20
6
+
7
+ ### Added
8
+
9
+ - Add support for the tools beta.
10
+
11
+ ### Updated
12
+
13
+ - Remove beta header for Messages API as the API is no longer in beta.
14
+
15
+ ## [0.3.0] - 2023-12-28
16
+
17
+ ### Added
18
+
19
+ - Add support for sending headers to client.
20
+ - Add support for beta Messages API.
21
+
5
22
  ## [0.2.5] - 2023-12-27
6
23
 
7
24
  ### Fixed
@@ -40,7 +57,9 @@
40
57
 
41
58
  - Initial release
42
59
 
43
- [Unreleased]: https://github.com/dickdavis/anthropic-rb/compare/v0.2.5...HEAD
60
+ [Unreleased]: https://github.com/dickdavis/anthropic-rb/compare/v0.4.0...HEAD
61
+ [0.4.0]: https://github.com/dickdavis/anthropic-rb/compare/v0.3.0...v0.4.0
62
+ [0.3.0]: https://github.com/dickdavis/anthropic-rb/compare/v0.2.5...v0.3.0
44
63
  [0.2.5]: https://github.com/dickdavis/anthropic-rb/compare/v0.2.3...v0.2.5
45
64
  [0.2.3]: https://github.com/dickdavis/anthropic-rb/compare/v0.2.2...v0.2.3
46
65
  [0.2.2]: https://github.com/dickdavis/anthropic-rb/compare/v0.2.1...v0.2.2
data/README.md CHANGED
@@ -6,27 +6,90 @@ The goal of this project is feature parity with Anthropic's Python SDK until an
6
6
 
7
7
  ## Usage
8
8
 
9
- anthropic-rb will default to the value of the `ANTHROPIC_API_KEY` environment variable. However, you may initialize the library with your API key:
9
+ anthropic-rb will default to the value of the `ANTHROPIC_API_KEY` environment variable. However, you may initialize the library with your API key. You must set your API key before using the library.
10
10
 
11
11
  ```ruby
12
- require 'anthropic-rb'
12
+ require 'anthropic'
13
13
 
14
14
  Anthropic.setup do |config|
15
15
  config.api_key = 'YOUR_API_KEY'
16
16
  end
17
17
  ```
18
18
 
19
- You can also specify an API version to use by setting the `ANTHROPIC_API_VERSION` environment variable or during initialization:
19
+ You can also specify an API version to use by setting the `ANTHROPIC_API_VERSION` environment variable or during initialization. This is optional; if not set, the library will default to `2023-06-01`.
20
20
 
21
21
  ```ruby
22
- require 'anthropic-rb'
22
+ require 'anthropic'
23
23
 
24
24
  Anthropic.setup do |config|
25
25
  config.api_version = '2023-06-01'
26
26
  end
27
27
  ```
28
28
 
29
- The default API version is `2023-06-01`.
29
+ ### Messages API
30
+
31
+ You can send a request to the Messages API.
32
+
33
+ ```ruby
34
+ Anthropic.messages.create(model: 'claude-2.1', max_tokens: 200, messages: [{role: 'user', content: 'Yo what up?'}])
35
+
36
+ # Output =>
37
+ # {
38
+ # id: "msg_013ePdwEkb4RMC1hCE61Hbm8",
39
+ # type: "message",
40
+ # role: "assistant",
41
+ # content: [{type: "text", text: "Hello! Not much up with me, just chatting. How about you?"}],
42
+ # model: "claude-2.1",
43
+ # stop_reason: "end_turn",
44
+ # stop_sequence: nil
45
+ # }
46
+ ```
47
+
48
+ Alternatively, you can stream the response:
49
+
50
+ ```ruby
51
+ Anthropic.messages.create(model: 'claude-2.1', max_tokens: 200, messages: [{role: 'user', content: 'Yo what up?'}], stream: true) do |event|
52
+ puts event
53
+ end
54
+
55
+ # Output =>
56
+ # { type: 'message_start', message: { id: 'msg_012pkeozZynwyNvSagwL7kMw', type: 'message', role: 'assistant', content: [], model: 'claude-2.1', stop_reason: nil, stop_sequence: nil } }
57
+ # { type: 'content_block_start', index: 0, content_block: { type: 'text', text: '' } }
58
+ # { type: 'content_block_delta', index: 0, delta: { type: 'text_delta', text: 'Hello' } }
59
+ # { type: 'content_block_delta', index: 0, delta: { type: 'text_delta', text: '.' } }
60
+ # { type: 'content_block_stop', index: 0 }
61
+ # { type: 'message_delta', delta: { stop_reason: 'end_turn', stop_sequence: nil } }
62
+ # { type: 'message_stop' }
63
+ ```
64
+
65
+ You can also experiment with the new tools beta by passing the `beta` flag when calling the API. This will ensure each request includes the correct beta header.
66
+
67
+ ```ruby
68
+ tools = [
69
+ {
70
+ name: 'get_weather',
71
+ description: 'Get the current weather in a given location',
72
+ input_schema: {
73
+ type: 'object',
74
+ properties: {
75
+ location: { type: 'string' }
76
+ },
77
+ required: ['location']
78
+ }
79
+ }
80
+ ]
81
+
82
+ Anthropic.messages(beta: true).create(
83
+ model: 'claude-3-opus-20240229',
84
+ max_tokens: 200,
85
+ tools:,
86
+ messages: [{role: 'user', content: 'What is the weather like in Nashville?'}]
87
+ )
88
+ ```
89
+
90
+ Streaming is currently not supported by the tools beta. You can find out more information about tools in the [documentation](https://docs.anthropic.com/claude/docs/tool-use).
91
+
92
+ ### Completions API
30
93
 
31
94
  To make a request to the Completions API:
32
95
 
@@ -55,21 +118,21 @@ Anthropic.completions.create(model: 'claude-2', max_tokens_to_sample: 200, promp
55
118
  end
56
119
 
57
120
  # Output =>
58
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>" Hello", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
59
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>"!", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
60
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>" Not", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
61
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>" much", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
62
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>",", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
63
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>" just", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
64
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>" chatting", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
65
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>" with", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
66
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>" people", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
67
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>".", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
68
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>" How", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
69
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>" about", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
70
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>" you", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
71
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>"?", :stop_reason=>nil, :model=>"claude-2.1", :stop=>nil, :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
72
- # {:type=>"completion", :id=>"compl_01G6cEfdZtLEEJVRzwUShiDY", :completion=>"", :stop_reason=>"stop_sequence", :model=>"claude-2.1", :stop=>"\n\nHuman:", :log_id=>"compl_01G6cEfdZtLEEJVRzwUShiDY"}
121
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: ' Hello', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
122
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: '!', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
123
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: ' Not', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
124
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: ' much', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
125
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: ',', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
126
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: ' just', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
127
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: ' chatting', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
128
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: ' with', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
129
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: ' people', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
130
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: '.', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
131
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: ' How', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
132
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: ' about', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
133
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: ' you', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
134
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: '?', stop_reason: nil, model: 'claude-2.1', stop: nil, log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
135
+ # { type: 'completion', id: 'compl_01G6cEfdZtLEEJVRzwUShiDY', completion: '', stop_reason: 'stop_sequence', model: 'claude-2.1', stop: "\n\nHuman:", log_id: 'compl_01G6cEfdZtLEEJVRzwUShiDY' }
73
136
  ```
74
137
 
75
138
  ## Installation
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/anthropic/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'anthropic-rb'
7
+ spec.version = Anthropic::VERSION
8
+ spec.authors = ['Dick Davis']
9
+ spec.email = ['dick@hey.com']
10
+
11
+ spec.summary = 'Ruby bindings for the Anthropic API'
12
+ spec.homepage = 'https://github.com/dickdavis/anthropic-rb'
13
+ spec.license = 'MIT'
14
+
15
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
16
+ spec.metadata['homepage_uri'] = spec.homepage
17
+ spec.metadata['source_code_uri'] = 'https://github.com/dickdavis/anthropic-rb'
18
+ spec.metadata['changelog_uri'] = 'https://github.com/dickdavis/anthropic-rb/blob/main/CHANGELOG.md'
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(__dir__) do
23
+ `git ls-files -z`.split("\x0").reject do |f|
24
+ (File.expand_path(f) == __FILE__) ||
25
+ f.start_with?(*%w[bin/ spec/ .git .github/ Gemfile])
26
+ end
27
+ end
28
+ spec.bindir = 'exe'
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ['lib']
31
+
32
+ # Uncomment to register a new dependency of your gem
33
+ # spec.add_dependency "example-gem", "~> 1.0"
34
+
35
+ # For more information and examples about making a new gem, check out our
36
+ # guide at: https://bundler.io/guides/creating_gem.html
37
+ spec.metadata['rubygems_mfa_required'] = 'true'
38
+
39
+ spec.required_ruby_version = '>= 3.1'
40
+ spec.add_dependency 'httpx', '>= 1.1.5'
41
+ spec.add_dependency 'json-schema', '>= 4.1.1'
42
+ end
@@ -32,13 +32,13 @@ module Anthropic
32
32
  # Provides a client for sending HTTP requests.
33
33
  class Client
34
34
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
35
- def self.post(url, data)
35
+ def self.post(url, data, headers = {})
36
36
  response = HTTPX.with(
37
37
  headers: {
38
38
  'Content-Type' => 'application/json',
39
39
  'x-api-key' => Anthropic.api_key,
40
40
  'anthropic-version' => Anthropic.api_version
41
- }
41
+ }.merge(headers)
42
42
  ).post(url, json: data)
43
43
 
44
44
  response_body = JSON.parse(response.body, symbolize_names: true)
@@ -65,13 +65,13 @@ module Anthropic
65
65
  end
66
66
  end
67
67
 
68
- def self.post_as_stream(url, data)
68
+ def self.post_as_stream(url, data, headers = {})
69
69
  response = HTTPX.plugin(:stream).with(
70
70
  headers: {
71
71
  'Content-Type' => 'application/json',
72
72
  'x-api-key' => Anthropic.api_key,
73
73
  'anthropic-version' => Anthropic.api_version
74
- }
74
+ }.merge(headers)
75
75
  ).post(url, json: data, stream: true)
76
76
 
77
77
  response.each_line do |line|
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Anthropic
4
+ ##
5
+ # Provides bindings for the Anthropic messages API
6
+ class Messages
7
+ # Error for when the API version is not supported.
8
+ class UnsupportedApiVersionError < StandardError; end
9
+
10
+ # Error for when a beta feature is not used correctly
11
+ class UnsupportedBetaOptionError < StandardError; end
12
+
13
+ ENDPOINT = 'https://api.anthropic.com/v1/messages'
14
+ V1_SCHEMA = {
15
+ type: 'object',
16
+ required: %w[model messages max_tokens],
17
+ properties: {
18
+ model: { type: 'string' },
19
+ messages: { type: 'array' },
20
+ max_tokens: { type: 'integer' },
21
+ system: { type: 'string' },
22
+ stop_sequences: { type: 'array', items: { type: 'string' } },
23
+ temperature: { type: 'number' },
24
+ tools: {
25
+ type: 'array',
26
+ items: {
27
+ name: { type: 'string' },
28
+ description: { type: 'string' },
29
+ input_schema: { type: 'object' }
30
+ }
31
+ },
32
+ top_k: { type: 'integer' },
33
+ top_p: { type: 'number' },
34
+ metadata: { type: 'object' },
35
+ stream: { type: 'boolean' }
36
+ },
37
+ additionalProperties: false
38
+ }.freeze
39
+
40
+ def initialize(beta: false)
41
+ @beta = beta
42
+ end
43
+
44
+ def create(**params, &)
45
+ raise UnsupportedBetaOptionError, 'Tool use is not yet supported in streaming mode' if params[:stream] && beta
46
+
47
+ JSON::Validator.validate!(schema_for_api_version, params)
48
+
49
+ return Anthropic::Client.post(ENDPOINT, params, additional_headers) unless params[:stream]
50
+
51
+ Anthropic::Client.post_as_stream(ENDPOINT, params, additional_headers, &)
52
+ rescue JSON::Schema::ValidationError => error
53
+ raise ArgumentError, error.message
54
+ end
55
+
56
+ private
57
+
58
+ attr_reader :beta
59
+
60
+ def schema_for_api_version
61
+ api_version = Anthropic.api_version
62
+ case api_version
63
+ when '2023-06-01'
64
+ V1_SCHEMA
65
+ else
66
+ raise UnsupportedApiVersionError, "Unsupported API version: #{api_version}"
67
+ end
68
+ end
69
+
70
+ def additional_headers
71
+ return {} unless beta
72
+
73
+ { 'anthropic-beta' => 'tools-2024-04-04' }
74
+ end
75
+ end
76
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Anthropic
4
- VERSION = '0.2.5'
4
+ VERSION = '0.4.0'
5
5
  end
data/lib/anthropic.rb CHANGED
@@ -6,6 +6,7 @@ require 'json-schema'
6
6
 
7
7
  require_relative 'anthropic/client'
8
8
  require_relative 'anthropic/completions'
9
+ require_relative 'anthropic/messages'
9
10
  require_relative 'anthropic/version'
10
11
 
11
12
  ##
@@ -43,4 +44,8 @@ module Anthropic
43
44
  def self.completions
44
45
  Completions.new
45
46
  end
47
+
48
+ def self.messages(...)
49
+ Messages.new(...)
50
+ end
46
51
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anthropic-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dick Davis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-28 00:00:00.000000000 Z
11
+ date: 2024-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpx
@@ -54,9 +54,11 @@ files:
54
54
  - LICENSE.txt
55
55
  - README.md
56
56
  - Rakefile
57
+ - anthropic-rb.gemspec
57
58
  - lib/anthropic.rb
58
59
  - lib/anthropic/client.rb
59
60
  - lib/anthropic/completions.rb
61
+ - lib/anthropic/messages.rb
60
62
  - lib/anthropic/version.rb
61
63
  - sig/anthropic/rb.rbs
62
64
  homepage: https://github.com/dickdavis/anthropic-rb