anthropic-rb 0.1.0 → 0.2.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: 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