senior 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: 39730d334959dd50f95ebdf665ac8731d61fc15fda52692e61c6a521d1228b4b
4
- data.tar.gz: e2d2bb32557f3d3c7c780ec7f4293f0c56f68d885e0ed792ce2e0fce69e00b2a
3
+ metadata.gz: 448f1287d6404de5d6a2168f69b2517605310f99865992d7e4db5ffee9fc538a
4
+ data.tar.gz: f7d0392887141cd1ee232438483cebc274a6b39607d81c93a5b9033312c62415
5
5
  SHA512:
6
- metadata.gz: 30cabd4898ce92778b12e1bac480d6e6de51bf57af8a0f1356ab24f29626cbe1c778c89b89f073880bcb099e871ab45b65cbb0f162555b1a85db9014239f1342
7
- data.tar.gz: 5654b395cf96a528179988edc566ca0f4eebaa2a8f521859ba64b56f9ba1ffe60ef8a457c71f7d5da3a9ed2920b96568245fe676b2a9711b2cd9ca105cb47c1f
6
+ metadata.gz: be9c24e647fe23cbb5e5e8580d775ab0822672856b2bc4f1bc0567a61ad9677e455b08e73aad7e95f51a1a3835809abd640220fcb6c8c249f6276376f5203021
7
+ data.tar.gz: 8210280b84ae3c47b5442a1a7ae8b6cdf23cd9bdc7b255701d8b6808f7864267e855bc730b424e567abd44d5de8607f7a324256ef5e1762b9a3c92599be81b2d
data/.rubocop.yml CHANGED
@@ -44,3 +44,6 @@ Metrics/MethodLength:
44
44
 
45
45
  RSpec/ExampleLength:
46
46
  Enabled: false
47
+
48
+ RSpec/NestedGroups:
49
+ Max: 4
data/CHANGELOG.md CHANGED
@@ -2,9 +2,6 @@
2
2
 
3
3
  - Ability to wrap a method invocation. For example, `Senior.suggest_fix { my_broken_method(2) }`
4
4
  - Test generation `Senior.write_tests_for {}`
5
- - Configure API keys for the OpenAI
6
- - Use different OpenAI models
7
- - Parametrize the calls to OpenAI
8
5
  - See price per call
9
6
  - Set API calling and pricing limits
10
7
  - Use different AI APIs, not just OpenAI
@@ -13,6 +10,28 @@
13
10
  - RBS Signatures
14
11
  - Domain exceptions
15
12
 
13
+ ## [0.2.0] - 2023-04-10
14
+
15
+ ### Added
16
+ - Added the ability to configure the gem with a block:
17
+ ```ruby
18
+ Senior.configure do |config|
19
+ config.open_ai.access_token = ENV.fetch('OPEN_AI_ACCESS_TOKEN')
20
+ config.open_ai.organization_id = ENV.fetch('OPEN_AI_ORGANIZATION_ID') # Optional
21
+ config.open_ai.api_version = 'v1'
22
+ config.open_ai.max_tokens = 1024
23
+ config.open_ai.model = 'text-davinci-003'
24
+ config.open_ai.n = 1
25
+ config.open_ai.request_timeout = 120
26
+ config.open_ai.temperature = 0.7
27
+ config.open_ai.uri_base = 'https://api.openai.com/'
28
+ end
29
+ ```
30
+ These configurations are used as default values for the OpenAI API calls.
31
+
16
32
  ## [0.1.0] - 2023-04-10
17
33
 
18
34
  - Initial release
35
+
36
+ [0.2.0]: https://github.com/wilsonsilva/senior/compare/v0.1.0...v0.2.0
37
+ [0.1.0]: https://github.com/wilsonsilva/senior/compare/eecec20...v0.1.0
data/README.md CHANGED
@@ -2,10 +2,24 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/senior.svg)](https://badge.fury.io/rb/senior)
4
4
  [![Tests](https://github.com/wilsonsilva/senior/actions/workflows/main.yml/badge.svg)](https://github.com/wilsonsilva/senior/actions/workflows/main.yml)
5
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/87e6e2167d3283e3b79b/test_coverage)](https://codeclimate.com/github/wilsonsilva/senior/test_coverage)
6
+ [![Maintainability](https://api.codeclimate.com/v1/badges/87e6e2167d3283e3b79b/maintainability)](https://codeclimate.com/github/wilsonsilva/senior/maintainability)
5
7
 
6
8
  Provides AI-powered debugging and automatic suggestion of code fixes. It makes use of OpenAI's language model to analyze
7
9
  and modify the source code of broken methods, allowing them to be fixed automatically.
8
10
 
11
+ ## Table of Contents
12
+
13
+ - [Installation](#installation)
14
+ - [Usage](#usage)
15
+ - [Auto-debugging a broken method](#auto-debugging-a-broken-method)
16
+ - [Suggesting a fix for a broken method](#suggesting-a-fix-for-a-broken-method)
17
+ - [Development](#development)
18
+ - [Type checking](#type-checking)
19
+ - [Contributing](#contributing)
20
+ - [License](#license)
21
+ - [Code of Conduct](#code-of-conduct)
22
+
9
23
  ## Installation
10
24
 
11
25
  Install the gem and add to the application's Gemfile by executing:
@@ -18,8 +32,23 @@ If bundler is not being used to manage dependencies, install the gem by executin
18
32
 
19
33
  ## Usage
20
34
 
21
- Before using Senior, ensure that the environment variables `OPEN_AI_ACCESS_TOKEN` and `OPEN_AI_ORGANIZATION_ID` are
22
- defined. These variables are used by the gem to authenticate and access OpenAI's language model.
35
+ - Get your API key from https://platform.openai.com/account/api-keys
36
+ - (optional) If you belong to multiple organizations, you can get your Organization ID from https://platform.openai.com/account/org-settings
37
+ - Configure the library by passing your OpenAI API credentials:
38
+
39
+ ```ruby
40
+ Senior.configure do |config|
41
+ config.open_ai.access_token = ENV.fetch('OPEN_AI_ACCESS_TOKEN')
42
+ config.open_ai.organization_id = ENV.fetch('OPEN_AI_ORGANIZATION_ID') # Optional
43
+ end
44
+ ```
45
+
46
+ Note that `OPEN_AI_ACCESS_TOKEN` and `OPEN_AI_ORGANIZATION_ID` are environment variables that should be set in your
47
+ environment. You should never hardcode your API credentials directly in your code, as this is a security risk.
48
+ Instead, store your API credentials securely, such as using environment variables or a separate configuration file that
49
+ is excluded from source control.
50
+
51
+ Once you have configured the library, you can use the Senior module to interact with the OpenAI API.
23
52
 
24
53
  ### Auto-debugging a broken method
25
54
  To debug a broken method, call Senior.auto_debug and pass in the broken method, its arguments, and optionally its
@@ -45,8 +45,8 @@ module Senior
45
45
  #
46
46
  def open_ai_client
47
47
  @open_ai_client ||= ::OpenAI::Client.new(
48
- access_token: ENV.fetch('OPEN_AI_ACCESS_TOKEN'),
49
- organization_id: ENV.fetch('OPEN_AI_ORGANIZATION_ID')
48
+ access_token: Senior.configuration.open_ai.access_token,
49
+ organization_id: Senior.configuration.open_ai.organization_id
50
50
  )
51
51
  end
52
52
 
@@ -55,19 +55,18 @@ module Senior
55
55
  # @api private
56
56
  #
57
57
  # @param prompt [String] The prompt for which to generate a completion
58
- # @param max_tokens [Integer] The maximum number of tokens to generate in the completion. Default value is 1024
59
58
  #
60
59
  # @return [String] The create completion
61
60
  #
62
- def request_completion(prompt, max_tokens = 1024)
61
+ def request_completion(prompt)
63
62
  response = open_ai_client.completions(
64
63
  parameters: {
65
- model: 'text-davinci-003',
64
+ model: defaults.model,
66
65
  prompt:,
67
- max_tokens:,
68
- n: 1,
66
+ max_tokens: defaults.max_tokens,
67
+ n: defaults.n,
69
68
  stop: nil,
70
- temperature: 0.7
69
+ temperature: defaults.temperature
71
70
  }
72
71
  )
73
72
 
@@ -75,6 +74,16 @@ module Senior
75
74
 
76
75
  response.dig('choices', 0, 'text').strip
77
76
  end
77
+
78
+ # Returns the default configuration object for the OpenAI brain
79
+ #
80
+ # @api private
81
+ #
82
+ # @return [Senior::Configuration::OpenAI] The default configuration object for the OpenAI brain.
83
+ #
84
+ def defaults
85
+ Senior.configuration.open_ai
86
+ end
78
87
  end
79
88
  end
80
89
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'senior/configuration/open_ai'
4
+
5
+ module Senior
6
+ module Configuration
7
+ # Index file for all configurations of the gem
8
+ #
9
+ # @api public
10
+ #
11
+ class Main
12
+ # The OpenAI configuration
13
+ #
14
+ # @api public
15
+ #
16
+ #
17
+ # @example
18
+ # configuration = Senior::Configuration::Main.new
19
+ # configuration.open_ai # => #<Configuration::OpenAI:0x00007fa2a61a63d8>
20
+ #
21
+ # @return [Configuration::OpenAI] The OpenAI configuration
22
+ #
23
+ attr_accessor :open_ai
24
+
25
+ # Initializes a new instance of the configuration for the Senior gem
26
+ #
27
+ # @api public
28
+ #
29
+ # @example
30
+ # configuration = Senior::Configuration::Main.new
31
+ #
32
+ def initialize
33
+ @open_ai = Configuration::OpenAI.new
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Senior
4
+ module Configuration
5
+ # Encapsulates the OpenAI configuration
6
+ #
7
+ # @api public
8
+ class OpenAI
9
+ # The OpenAI access token
10
+ #
11
+ # @return [String, nil] The OpenAI access token, or nil if not set
12
+ #
13
+ # @example
14
+ # configuration = Senior::Configuration::OpenAI.new
15
+ # configuration.access_token = 'your_openai_api_key'
16
+ attr_writer :access_token
17
+
18
+ # The OpenAI API version
19
+ #
20
+ # @return [String] The OpenAI API version
21
+ #
22
+ # @example
23
+ # configuration = Senior::Configuration::OpenAI.new
24
+ # configuration.api_version = 'v1'
25
+ attr_accessor :api_version
26
+
27
+ # The maximum number of tokens to use in the OpenAI API request
28
+ #
29
+ # @return [Integer] The maximum number of tokens to use in the OpenAI API request
30
+ #
31
+ # @example
32
+ # configuration = Senior::Configuration::OpenAI.new
33
+ # configuration.max_tokens = 1024
34
+ attr_accessor :max_tokens
35
+
36
+ # The OpenAI model to use
37
+ #
38
+ # @return [String] The OpenAI model to use
39
+ #
40
+ # @example
41
+ # configuration = Senior::Configuration::OpenAI.new
42
+ # configuration.model = 'text-davinci-003'
43
+ attr_accessor :model
44
+
45
+ # The number of responses to generate
46
+ #
47
+ # @return [Integer] The number of responses to generate
48
+ #
49
+ # @example
50
+ # configuration = Senior::Configuration::OpenAI.new
51
+ # configuration.n = 1
52
+ attr_accessor :n
53
+
54
+ # The OpenAI organization ID
55
+ #
56
+ # @return [String, nil] The OpenAI organization ID, or nil if not set
57
+ #
58
+ # @example
59
+ # configuration = Senior::Configuration::OpenAI.new
60
+ # configuration.organization_id = 'your_organization_id'
61
+ attr_accessor :organization_id
62
+
63
+ # The maximum amount of time to wait for an OpenAI API request to complete
64
+ #
65
+ # @return [Integer] The maximum amount of time to wait for an OpenAI API request to complete
66
+ #
67
+ # @example
68
+ # configuration = Senior::Configuration::OpenAI.new
69
+ # configuration.request_timeout = 120
70
+ attr_accessor :request_timeout
71
+
72
+ # The temperature to use in the OpenAI API request
73
+ #
74
+ # @return [Float] The temperature to use in the OpenAI API request
75
+ #
76
+ # @example
77
+ # configuration = Senior::Configuration::OpenAI.new
78
+ # configuration.temperature = 0.7
79
+ attr_accessor :temperature
80
+
81
+ # The OpenAI URI base
82
+ #
83
+ # @return [String] The OpenAI URI base
84
+ #
85
+ # @example
86
+ # configuration = Senior::Configuration::OpenAI.new
87
+ # configuration.uri_base = 'https://api.openai.com/'
88
+ attr_accessor :uri_base
89
+
90
+ # The default OpenAI API version
91
+ DEFAULT_API_VERSION = 'v1'
92
+
93
+ # The default maximum number of tokens to use in the OpenAI API request
94
+ DEFAULT_MAX_TOKENS = 1024
95
+
96
+ # The default OpenAI model to use
97
+ DEFAULT_MODEL = 'text-davinci-003'
98
+
99
+ # The default number of responses to generate
100
+ DEFAULT_N = 1
101
+
102
+ # The default maximum amount of time to wait for an OpenAI API request to complete
103
+ DEFAULT_REQUEST_TIMEOUT = 120
104
+
105
+ # The default temperature to use in the OpenAI API request
106
+ DEFAULT_TEMPERATURE = 0.7
107
+
108
+ # The default OpenAI URI base
109
+ DEFAULT_URI_BASE = 'https://api.openai.com/'
110
+
111
+ # Initializes a new instance of the OpenAI configuration for the Senior gem
112
+ #
113
+ # @example
114
+ # configuration = Senior::Configuration::OpenAI.new
115
+ #
116
+ def initialize
117
+ @access_token = nil
118
+ @api_version = DEFAULT_API_VERSION
119
+ @max_tokens = DEFAULT_MAX_TOKENS
120
+ @model = DEFAULT_MODEL
121
+ @n = DEFAULT_N
122
+ @organization_id = nil
123
+ @request_timeout = DEFAULT_REQUEST_TIMEOUT
124
+ @temperature = DEFAULT_TEMPERATURE
125
+ @uri_base = DEFAULT_URI_BASE
126
+ end
127
+
128
+ # Gets the OpenAI access token, raising an error if it is not set
129
+ #
130
+ # @raise [ConfigurationError] If the OpenAI access token is not set
131
+ #
132
+ # @return [String] The OpenAI access token.
133
+ #
134
+ # @example
135
+ # configuration = Senior::Configuration::OpenAI.new
136
+ # configuration.access_token # => raises ConfigurationError if access token is not set
137
+ #
138
+ def access_token
139
+ return @access_token if @access_token
140
+
141
+ error_text = 'OpenAI access token missing! See https://github.com/wilsonsilva/senior#usage'
142
+ raise ConfigurationError, error_text
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Senior
4
+ # Base class for all Senior's errors
5
+ class Error < StandardError; end
6
+
7
+ # Raised when the gem's configuration is faulty
8
+ class ConfigurationError < Error; end
9
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Senior
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/senior.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'senior/errors'
4
+ require_relative 'senior/configuration/main'
3
5
  require_relative 'senior/brains/open_ai'
4
6
  require_relative 'senior/agent'
5
7
  require_relative 'senior/version'
@@ -56,4 +58,32 @@ module Senior
56
58
  def self.agent
57
59
  @agent ||= Agent.new
58
60
  end
61
+
62
+ # Returns the configuration object for the Senior gem
63
+ #
64
+ # @api private
65
+ #
66
+ # @return [Senior::Configuration::Main] The configuration object for the Senior gem
67
+ #
68
+ def self.configuration
69
+ @configuration ||= Configuration::Main.new
70
+ end
71
+
72
+ # Provides a way to configure the Senior gem
73
+ #
74
+ # @api public
75
+ #
76
+ # @yield [configuration] A block to configure the Senior gem
77
+ # @yieldparam configuration [Senior::Configuration::Main] The configuration object for the Senior gem
78
+ #
79
+ # @example Configuring the Senior gem
80
+ # Senior.configure do |config|
81
+ # config.open_ai.access_token = 'your_openai_api_key'
82
+ # end
83
+ #
84
+ # @return [void]
85
+ #
86
+ def self.configure
87
+ yield(configuration)
88
+ end
59
89
  end
@@ -8,7 +8,8 @@ module Senior
8
8
  private
9
9
 
10
10
  def open_ai_client: -> untyped
11
- def request_completion: (String prompt, ?Integer max_tokens) -> String
11
+ def request_completion: (String prompt) -> String
12
+ def defaults: -> Senior::Configuration::OpenAI
12
13
  end
13
14
  end
14
15
  end
@@ -0,0 +1,7 @@
1
+ module Senior
2
+ module Configuration
3
+ class Main
4
+ attr_accessor open_ai: Configuration::OpenAI
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ module Senior
2
+ module Configuration
3
+ class OpenAI
4
+ DEFAULT_API_VERSION: String
5
+ DEFAULT_MAX_TOKENS: Integer
6
+ DEFAULT_MODEL: String
7
+ DEFAULT_N: Integer
8
+ DEFAULT_REQUEST_TIMEOUT: Integer
9
+ DEFAULT_TEMPERATURE: Float
10
+ DEFAULT_URI_BASE: String
11
+
12
+ attr_writer access_token: String?|nil
13
+ attr_accessor api_version: String
14
+ attr_accessor max_tokens: Integer
15
+ attr_accessor model: String
16
+ attr_accessor n: Integer
17
+ attr_accessor organization_id: String?|nil
18
+ attr_accessor request_timeout: Integer
19
+ attr_accessor temperature: Float
20
+ attr_accessor uri_base: String
21
+
22
+ def initialize: -> void
23
+ def access_token: -> String?
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,7 @@
1
+ module Senior
2
+ class Error < StandardError
3
+ end
4
+
5
+ class ConfigurationError < Error
6
+ end
7
+ end
data/sig/senior.rbs CHANGED
@@ -1,12 +1,11 @@
1
1
  module Senior
2
2
  VERSION: String
3
+ self.@configuration: Configuration::Main
3
4
  self.@agent: Agent
4
5
 
5
6
  def self.auto_debug: (Method broken_method, untyped args, String? | nil broken_method_source) -> untyped
6
-
7
7
  def self.suggest_fix: (Method broken_method, untyped args) -> String
8
-
9
- private
10
-
8
+ def self.configuration: -> Configuration::Main
9
+ def self.configure: -> untyped
11
10
  def self.agent: -> Agent
12
11
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: senior
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
  - Wilson Silva
@@ -361,7 +361,7 @@ dependencies:
361
361
  - !ruby/object:Gem::Version
362
362
  version: '0.9'
363
363
  description: |-
364
- This gem provides a simple interface to OpenAI's GPT4 API for code repair. Given a piece of broken
364
+ This gem provides a simple interface to OpenAI's GPT API for code repair. Given a piece of broken
365
365
  code, the gem generates a corrected version.
366
366
  email:
367
367
  - wilson.dsigns@gmail.com
@@ -387,6 +387,9 @@ files:
387
387
  - lib/senior.rb
388
388
  - lib/senior/agent.rb
389
389
  - lib/senior/brains/open_ai.rb
390
+ - lib/senior/configuration/main.rb
391
+ - lib/senior/configuration/open_ai.rb
392
+ - lib/senior/errors.rb
390
393
  - lib/senior/version.rb
391
394
  - sig/gems/method_source/method.rbs
392
395
  - sig/gems/ruby-openai/client.rbs
@@ -394,6 +397,9 @@ files:
394
397
  - sig/senior/agent.rbs
395
398
  - sig/senior/brains/i_brain.rbs
396
399
  - sig/senior/brains/open_ai.rbs
400
+ - sig/senior/configuration/main.rbs
401
+ - sig/senior/configuration/open_ai.rbs
402
+ - sig/senior/errors.rbs
397
403
  homepage: https://github.com/wilsonsilva/senior
398
404
  licenses:
399
405
  - MIT