anthropic-rb 0.1.0 → 0.2.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: a8ddefe11f23c3a4da77b1307a68000db35da9ba1607407eff8cccdf21cc1d3a
4
- data.tar.gz: 936ecaf281b8f9662c689ea64c98f317f9de29a8f87f4888cf227f412efed688
3
+ metadata.gz: a00be2a4defb2218b159f10759e861f3f4d314909fb9205bb11cb79dd4460eec
4
+ data.tar.gz: 6cb65d16c68d5fc58094210ebd271908c58e1927366887d64ef59100aced49cf
5
5
  SHA512:
6
- metadata.gz: 8ba132ede7fdf85de9c9641e32601b4c544101e421a950f9fd5f25edf43397b25a3f7c7f4a27996bcd71832acf6211fb24baf1d3f58d7a927d26e1c098f67bdd
7
- data.tar.gz: 74646ab569768708d8505c9843352a418cfcc0a88e8528834647d8ee30fe6b2f3840d1ab75d3bd0fbd21d6afe25e2e82c2cb922b089979260cd5c13a5eeeda49
6
+ metadata.gz: f6c0aadeacd66bddd7ab58393cb86a3b50d1e99eb8df9d0e6fe076376c71ef0f2430f864666420af180f5da828d770ced1128dbeb59f77cf8d2f28df28b699c8
7
+ data.tar.gz: 4df1ea4f97c164bee7cbe1a2a7f92c57a1a507220a2ec62c4d9442978674b1d5b5197092ecba83f77a1ef302919b35357adcda22a4c41e9e90098ccd459e7497
data/.reek.yml ADDED
@@ -0,0 +1,7 @@
1
+ detectors:
2
+ ControlParameter:
3
+ exclude:
4
+ - Anthropic#self.api_key=
5
+ TooManyStatements:
6
+ exclude:
7
+ - 'Anthropic::Client#self.post'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
+ # Changelog
2
+
1
3
  ## [Unreleased]
2
4
 
3
5
  ## [0.1.0] - 2023-11-30
4
6
 
7
+ ### Added
8
+
5
9
  - Initial release
10
+
11
+ [Unreleased]: https://github.com/d3d1rty/event_logger_rails/compare/0.1.0...HEAD
12
+ [0.1.0]: https://github.com/d3d1rty/event_logger_rails/releases/tag/0.1.0
data/README.md CHANGED
@@ -2,9 +2,75 @@
2
2
 
3
3
  Ruby bindings for the Anthropic API. This library is unofficial and is not affiliated with Anthropic PBC.
4
4
 
5
+ The goal of this project is feature parity with Anthropic's Python SDK until an official Ruby SDK is available.
6
+
5
7
  ## Usage
6
8
 
7
- TODO: Write some code to use
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:
10
+
11
+ ```ruby
12
+ require 'anthropic-rb'
13
+
14
+ Anthropic.setup do |config|
15
+ config.api_key = 'YOUR_API_KEY'
16
+ end
17
+ ```
18
+
19
+ You can also specify an API version to use by setting the `ANTHROPIC_API_VERSION` environment variable or during initialization:
20
+
21
+ ```ruby
22
+ require 'anthropic-rb'
23
+
24
+ Anthropic.setup do |config|
25
+ config.api_version = '2023-06-01'
26
+ end
27
+ ```
28
+
29
+ The default API version is `2023-06-01`.
30
+
31
+ To make a request to the Completions API:
32
+
33
+ ```ruby
34
+ Anthropic.completions.create(
35
+ model: 'claude-2',
36
+ max_tokens_to_sample: 200,
37
+ prompt: 'Human: Yo what up?\n\nAssistant:'
38
+ )
39
+
40
+ # Output =>
41
+ # {
42
+ # completion: "Hello! Not much going on with me, just chatting. How about you?",
43
+ # stop_reason: "stop_sequence",
44
+ # model: "claude-2.1",
45
+ # stop: "\n\nHuman:",
46
+ # log_id: "2496914137c520ec2b4ae8315864bcf3a4c6ce9f2e3c96e13be4c004587313ca"
47
+ # }
48
+ ```
49
+
50
+ Alternatively, you can stream the response:
51
+
52
+ ```ruby
53
+ Anthropic.completions.create(model: 'claude-2', max_tokens_to_sample: 200, prompt: 'Human: Yo what up?\n\nAssistant:') do |event|
54
+ puts event
55
+ end
56
+
57
+ # 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"}
73
+ ```
8
74
 
9
75
  ## Installation
10
76
 
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httpx'
4
+
5
+ module Anthropic
6
+ ##
7
+ # Error when the request is malformed.
8
+ class BadRequestError < StandardError; end
9
+ ##
10
+ # Error when the API key is invalid.
11
+ class AuthenticationError < StandardError; end
12
+ ##
13
+ # Error when the account does not have permission for the operation.
14
+ class PermissionDeniedError < StandardError; end
15
+ ##
16
+ # Error when the resource is not found.
17
+ class NotFoundError < StandardError; end
18
+ ##
19
+ # Error when the resource already exists.
20
+ class ConflictError < StandardError; end
21
+ ##
22
+ # Error when the resource cannot be processed.
23
+ class UnprocessableEntityError < StandardError; end
24
+ ##
25
+ # Error when the request exceeds the rate limit.
26
+ class RateLimitError < StandardError; end
27
+ ##
28
+ # Error when the server experienced an internal error.
29
+ class InternalServerError < StandardError; end
30
+
31
+ ##
32
+ # Provides a client for sending HTTP requests.
33
+ class Client
34
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
35
+ def self.post(url, data)
36
+ response = HTTPX.with(
37
+ headers: {
38
+ 'Content-Type' => 'application/json',
39
+ 'x-api-key' => Anthropic.api_key,
40
+ 'anthropic-version' => Anthropic.api_version
41
+ }
42
+ ).post(url, json: data)
43
+
44
+ response_body = JSON.parse(response.body, symbolize_names: true)
45
+
46
+ case response.status
47
+ when 200
48
+ response_body
49
+ when 400
50
+ raise Anthropic::BadRequestError, response_body
51
+ when 401
52
+ raise Anthropic::AuthenticationError, response_body
53
+ when 403
54
+ raise Anthropic::PermissionDeniedError, response_body
55
+ when 404
56
+ raise Anthropic::NotFoundError, response_body
57
+ when 409
58
+ raise Anthropic::ConflictError, response_body
59
+ when 422
60
+ raise Anthropic::UnprocessableEntityError, response_body
61
+ when 429
62
+ raise Anthropic::RateLimitError, response_body
63
+ when 500
64
+ raise Anthropic::InternalServerError, response_body
65
+ end
66
+ end
67
+
68
+ def self.post_as_stream(url, data)
69
+ response = HTTPX.plugin(:stream).with(
70
+ headers: {
71
+ 'Content-Type' => 'application/json',
72
+ 'x-api-key' => Anthropic.api_key,
73
+ 'anthropic-version' => Anthropic.api_version
74
+ }
75
+ ).post(url, json: data, stream: true)
76
+
77
+ response.each_line do |line|
78
+ event, data = line.split(/(\w+\b:\s)/)[1..2]
79
+ next unless event && data
80
+
81
+ if event.start_with?('data')
82
+ formatted_data = JSON.parse(data, symbolize_names: true)
83
+ yield formatted_data unless %w[ping error].include?(formatted_data[:type])
84
+ end
85
+ end
86
+ rescue HTTPX::HTTPError => error
87
+ case error.response.status
88
+ when 400
89
+ raise Anthropic::BadRequestError
90
+ when 401
91
+ raise Anthropic::AuthenticationError
92
+ when 403
93
+ raise Anthropic::PermissionDeniedError
94
+ when 404
95
+ raise Anthropic::NotFoundError
96
+ when 409
97
+ raise Anthropic::ConflictError
98
+ when 422
99
+ raise Anthropic::UnprocessableEntityError
100
+ when 429
101
+ raise Anthropic::RateLimitError
102
+ when 500
103
+ raise Anthropic::InternalServerError
104
+ end
105
+ end
106
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
107
+ end
108
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Anthropic
4
+ ##
5
+ # Provides bindings for the Anthropic completions API
6
+ class Completions
7
+ # Error for when the API version is not supported.
8
+ class UnsupportedApiVersionError < StandardError; end
9
+
10
+ V1_SCHEMA = {
11
+ type: 'object',
12
+ required: %w[model prompt max_tokens_to_sample],
13
+ properties: {
14
+ model: { type: 'string' },
15
+ prompt: { type: 'string' },
16
+ max_tokens_to_sample: { type: 'integer' },
17
+ stop_sequences: { type: 'array', items: { type: 'string' } },
18
+ temperature: { type: 'number' },
19
+ top_k: { type: 'integer' },
20
+ top_p: { type: 'number' },
21
+ metadata: { type: 'object' },
22
+ stream: { type: 'boolean' }
23
+ },
24
+ additionalProperties: false
25
+ }.freeze
26
+
27
+ def initialize
28
+ @endpoint = 'https://api.anthropic.com/v1/complete'
29
+ end
30
+
31
+ def create(**params, &)
32
+ JSON::Validator.validate!(schema_for_api_version, params)
33
+ return Anthropic::Client.post(endpoint, params) unless params[:stream]
34
+
35
+ Anthropic::Client.post_as_stream(endpoint, params, &)
36
+ rescue JSON::Schema::ValidationError => error
37
+ raise ArgumentError, error.message
38
+ end
39
+
40
+ private
41
+
42
+ attr_reader :endpoint
43
+
44
+ def schema_for_api_version
45
+ api_version = Anthropic.api_version
46
+ case api_version
47
+ when '2023-06-01'
48
+ V1_SCHEMA
49
+ else
50
+ raise UnsupportedApiVersionError, "Unsupported API version: #{api_version}"
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Anthropic
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/anthropic.rb CHANGED
@@ -1,9 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'httpx'
4
+ require 'json'
5
+ require 'json-schema'
6
+
7
+ require_relative 'anthropic/client'
8
+ require_relative 'anthropic/completions'
3
9
  require_relative 'anthropic/version'
4
10
 
11
+ ##
12
+ # Namespace for anthropic-rb gem
5
13
  module Anthropic
6
14
  ##
7
15
  # Default error class
8
16
  class Error < StandardError; end
17
+
18
+ def self.setup
19
+ yield self
20
+ end
21
+
22
+ def self.reset
23
+ @api_key = nil
24
+ @api_version = nil
25
+ end
26
+
27
+ def self.api_key
28
+ @api_key || ENV.fetch('ANTHROPIC_API_KEY', nil)
29
+ end
30
+
31
+ def self.api_key=(api_key = nil)
32
+ @api_key = api_key
33
+ end
34
+
35
+ def self.api_version
36
+ @api_version || ENV.fetch('ANTHROPIC_API_VERSION', '2023-06-01')
37
+ end
38
+
39
+ def self.api_version=(api_version = nil)
40
+ @api_version = api_version
41
+ end
42
+
43
+ def self.completions
44
+ Completions.new
45
+ end
9
46
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anthropic-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.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-01 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2023-12-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httpx
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.1.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.1.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: json-schema
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 4.1.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 4.1.1
13
41
  description:
14
42
  email:
15
43
  - dick@hey.com
@@ -18,6 +46,7 @@ extensions: []
18
46
  extra_rdoc_files: []
19
47
  files:
20
48
  - ".overcommit.yml"
49
+ - ".reek.yml"
21
50
  - ".rspec"
22
51
  - ".rubocop.yml"
23
52
  - ".tool-versions"
@@ -26,6 +55,8 @@ files:
26
55
  - README.md
27
56
  - Rakefile
28
57
  - lib/anthropic.rb
58
+ - lib/anthropic/client.rb
59
+ - lib/anthropic/completions.rb
29
60
  - lib/anthropic/version.rb
30
61
  - sig/anthropic/rb.rbs
31
62
  homepage: https://github.com/dickdavis/anthropic-rb