chatgpt-rb 0.1.0 → 0.1.1
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 +4 -4
- data/bin/watcher +17 -0
- data/lib/chatgpt_rb/conversation.rb +52 -22
- data/lib/chatgpt_rb/dsl/base.rb +29 -0
- data/lib/chatgpt_rb/dsl/conversation.rb +17 -0
- data/lib/chatgpt_rb/dsl/function.rb +14 -0
- data/lib/chatgpt_rb/dsl/parameter.rb +9 -0
- data/lib/chatgpt_rb/function.rb +31 -0
- data/lib/chatgpt_rb/parameter.rb +31 -0
- metadata +51 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 50e30e865ade9a6e20cad5680617972114a224bda8bf25d9969b9b57e6236763
|
|
4
|
+
data.tar.gz: e7d1714512f1696b9401018b11292a46ed220c650639521def9b4fa0290303a0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a42400a64dee74e93b7b27c8d04fc1f8c750bd0b90abc1ba37c33bdd58cbc9a494906c544b2bb0e02585807fffffbaae9ff3488d328b9bdb3051cc4fbfb59c0b
|
|
7
|
+
data.tar.gz: 4f187489399450e128b1f5f1634004be8de0a5f4b71516bff12ec234e3cf5cf3498102d6e44081e0e2bd00dc8ad14c1f75ca68770425eac0a7b1e32d284ee6e4
|
data/bin/watcher
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "listen"
|
|
4
|
+
|
|
5
|
+
directory_to_watch = Dir.pwd
|
|
6
|
+
|
|
7
|
+
listener = Listen.to(directory_to_watch) do |modified, added, removed|
|
|
8
|
+
system("rspec")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
listener.start
|
|
12
|
+
puts "Watching #{directory_to_watch} for changes..."
|
|
13
|
+
|
|
14
|
+
# Stop the listener when the process is terminated
|
|
15
|
+
Signal.trap("INT") { listener.stop }
|
|
16
|
+
Signal.trap("TERM") { listener.stop }
|
|
17
|
+
sleep
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
require "httparty"
|
|
2
|
+
require_relative "./function"
|
|
3
|
+
require_relative "./dsl/conversation"
|
|
2
4
|
|
|
3
5
|
module ChatgptRb
|
|
4
6
|
class Conversation
|
|
5
|
-
|
|
7
|
+
include HTTParty
|
|
8
|
+
|
|
9
|
+
base_uri "https://api.openai.com"
|
|
10
|
+
|
|
11
|
+
attr_accessor :api_key, :model, :functions, :temperature, :max_tokens, :top_p, :frequency_penalty, :presence_penalty, :prompt
|
|
12
|
+
attr_reader :messages
|
|
6
13
|
|
|
7
14
|
# @param api_key [String]
|
|
8
15
|
# @param model [String]
|
|
9
|
-
# @param functions [Array<Hash>]
|
|
16
|
+
# @param functions [Array<Hash>, Array<ChatgptRb::Function>]
|
|
10
17
|
# @param temperature [Float]
|
|
11
18
|
# @param max_tokens [Integer]
|
|
12
19
|
# @param top_p [Float]
|
|
@@ -14,25 +21,43 @@ module ChatgptRb
|
|
|
14
21
|
# @param presence_penalty [Float]
|
|
15
22
|
# @param messages [Array<Hash>]
|
|
16
23
|
# @param prompt [String, nil] instructions that the model can use to inform its responses, for example: "Act like a sullen teenager."
|
|
17
|
-
def initialize(api_key
|
|
24
|
+
def initialize(api_key: nil, model: "gpt-3.5-turbo", functions: [], temperature: 0.7, max_tokens: 1024, top_p: 1.0, frequency_penalty: 0.0, presence_penalty: 0.0, messages: [], prompt: nil, &configuration)
|
|
18
25
|
@api_key = api_key
|
|
19
26
|
@model = model
|
|
20
|
-
@functions = functions
|
|
27
|
+
@functions = functions.each_with_object({}) do |function, hash|
|
|
28
|
+
func = function.is_a?(ChatgptRb::Function) ? function : ChatgptRb::Function.new(**function)
|
|
29
|
+
hash[func.name] = func
|
|
30
|
+
end
|
|
21
31
|
@temperature = temperature
|
|
22
32
|
@max_tokens = max_tokens
|
|
23
33
|
@top_p = top_p
|
|
24
34
|
@frequency_penalty = frequency_penalty
|
|
25
35
|
@presence_penalty = presence_penalty
|
|
26
36
|
@messages = messages
|
|
37
|
+
@prompt = prompt
|
|
38
|
+
ChatgptRb::DSL::Conversation.configure(self, &configuration) if block_given?
|
|
27
39
|
@messages << { role: "system", content: prompt } if prompt
|
|
28
40
|
end
|
|
29
41
|
|
|
30
42
|
# @param content [String]
|
|
43
|
+
# @yieldparam [String] the response, but streamed
|
|
44
|
+
# @return [String] the response
|
|
31
45
|
def ask(content, &block)
|
|
32
46
|
@messages << { role: "user", content: }
|
|
33
47
|
get_next_response(&block)
|
|
34
48
|
end
|
|
35
49
|
|
|
50
|
+
# @param content [String]
|
|
51
|
+
# @param function [ChatgptRb::Function] temporarily enhance the next response with the provided function
|
|
52
|
+
# @yieldparam [String] the response, but streamed
|
|
53
|
+
# @return [String] the response
|
|
54
|
+
def ask_with_function(content, function, &block)
|
|
55
|
+
function_was = functions[function.name]
|
|
56
|
+
functions[function.name] = function
|
|
57
|
+
get_next_response(content, &block)
|
|
58
|
+
functions[function.name] = function_was
|
|
59
|
+
end
|
|
60
|
+
|
|
36
61
|
private
|
|
37
62
|
|
|
38
63
|
def <<(message)
|
|
@@ -46,23 +71,29 @@ module ChatgptRb
|
|
|
46
71
|
streamed_function = ""
|
|
47
72
|
error_buffer = []
|
|
48
73
|
|
|
49
|
-
|
|
50
|
-
|
|
74
|
+
body = {
|
|
75
|
+
model:,
|
|
76
|
+
messages: @messages,
|
|
77
|
+
temperature:,
|
|
78
|
+
max_tokens:,
|
|
79
|
+
top_p:,
|
|
80
|
+
frequency_penalty:,
|
|
81
|
+
presence_penalty:,
|
|
82
|
+
stream: block_given?,
|
|
83
|
+
}.tap do |hash|
|
|
84
|
+
hash[:functions] = functions.values.map(&:as_json) unless functions.empty?
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
response = self.class.post(
|
|
88
|
+
"/v1/chat/completions",
|
|
51
89
|
steam_body: block_given?,
|
|
52
90
|
headers: {
|
|
53
|
-
"Content-Type"
|
|
54
|
-
"Authorization"
|
|
91
|
+
"Content-Type" => "application/json",
|
|
92
|
+
"Authorization" => "Bearer #{api_key}",
|
|
93
|
+
"Accept" => "application/json",
|
|
94
|
+
"User-Agent" => "Ruby/chatgpt-rb",
|
|
55
95
|
},
|
|
56
|
-
body:
|
|
57
|
-
model:,
|
|
58
|
-
messages: @messages,
|
|
59
|
-
temperature:,
|
|
60
|
-
max_tokens:,
|
|
61
|
-
top_p:,
|
|
62
|
-
frequency_penalty:,
|
|
63
|
-
presence_penalty:,
|
|
64
|
-
stream: block_given?,
|
|
65
|
-
}.tap { |hash| hash[:functions] = functions.map { |hash| hash.except(:implementation) } unless functions.empty? }.to_json,
|
|
96
|
+
body: body.to_json,
|
|
66
97
|
) do |fragment|
|
|
67
98
|
if block_given?
|
|
68
99
|
fragment.each_line do |line|
|
|
@@ -113,13 +144,12 @@ module ChatgptRb
|
|
|
113
144
|
function_args = @messages.last["function_call"]
|
|
114
145
|
function_name = function_args.fetch("name")
|
|
115
146
|
arguments = JSON.parse(function_args.fetch("arguments"))
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
content = function.fetch(:implementation).call(**arguments.transform_keys(&:to_sym))
|
|
147
|
+
function = functions[function_name]
|
|
148
|
+
content = function.implementation.call(**arguments.transform_keys(&:to_sym))
|
|
119
149
|
|
|
120
150
|
@messages << { role: "function", name: function_name, content: content.to_json }
|
|
121
151
|
|
|
122
|
-
get_next_response(
|
|
152
|
+
get_next_response(&block)
|
|
123
153
|
end
|
|
124
154
|
end
|
|
125
155
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module ChatgptRb
|
|
2
|
+
module DSL
|
|
3
|
+
class Base
|
|
4
|
+
# @param object [Chatgpt::Conversation, ChatgptRb::Function, ChatgptRb::Parameter]
|
|
5
|
+
# @param configuration [Block]
|
|
6
|
+
# @return [Chatgpt::Conversation, ChatgptRb::Function, ChatgptRb::Parameter]
|
|
7
|
+
def self.configure(object, &configuration)
|
|
8
|
+
new(object).instance_eval(&configuration)
|
|
9
|
+
object
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
attr_reader :object
|
|
13
|
+
|
|
14
|
+
# @param object [Chatgpt::Conversation, ChatgptRb::Function, ChatgptRb::Parameter]
|
|
15
|
+
def initialize(object)
|
|
16
|
+
@object = object
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @param [Array<Symbol>] shorthand for allowing the DSL to set iVars
|
|
20
|
+
def self.supported_fields(fields)
|
|
21
|
+
fields.each do |method_name|
|
|
22
|
+
define_method method_name do |value|
|
|
23
|
+
object.public_send("#{method_name}=", value)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require_relative "./base"
|
|
2
|
+
require_relative "./function"
|
|
3
|
+
require_relative "../function"
|
|
4
|
+
|
|
5
|
+
module ChatgptRb
|
|
6
|
+
module DSL
|
|
7
|
+
class Conversation < Base
|
|
8
|
+
supported_fields %i[api_key model functions temperature max_tokens top_p frequency_penalty presence_penalty prompt]
|
|
9
|
+
|
|
10
|
+
# @param name [String] the name of the function
|
|
11
|
+
# @param configuration [Block]
|
|
12
|
+
def function(name, &configuration)
|
|
13
|
+
object.functions[name] = ChatgptRb::DSL::Function.configure(ChatgptRb::Function.new(name:), &configuration)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require_relative "../parameter"
|
|
2
|
+
require_relative "./parameter"
|
|
3
|
+
|
|
4
|
+
module ChatgptRb
|
|
5
|
+
module DSL
|
|
6
|
+
class Function < Base
|
|
7
|
+
supported_fields %i[description implementation parameters]
|
|
8
|
+
|
|
9
|
+
def parameter(name, &configuration)
|
|
10
|
+
object.parameters << ChatgptRb::DSL::Parameter.configure(ChatgptRb::Parameter.new(name:), &configuration)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module ChatgptRb
|
|
2
|
+
class Function
|
|
3
|
+
attr_accessor :name, :description, :parameters, :implementation
|
|
4
|
+
|
|
5
|
+
# @param name [String]
|
|
6
|
+
# @param description [String, nil]
|
|
7
|
+
# @param parameters [Array<ChatgptRb::Parameter>]
|
|
8
|
+
# @param implementation [Lambda, nil]
|
|
9
|
+
def initialize(name:, description: nil, parameters: [], implementation: nil)
|
|
10
|
+
@name = name
|
|
11
|
+
@description = description
|
|
12
|
+
@parameters = parameters
|
|
13
|
+
@implementation = implementation
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @return [Hash]
|
|
17
|
+
def as_json
|
|
18
|
+
{
|
|
19
|
+
name:,
|
|
20
|
+
description:,
|
|
21
|
+
parameters: {
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: parameters.each_with_object({}) do |parameter, hash|
|
|
24
|
+
hash[parameter.name] = parameter.as_json
|
|
25
|
+
end,
|
|
26
|
+
},
|
|
27
|
+
required: parameters.select(&:required?).map(&:name),
|
|
28
|
+
}.compact
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module ChatgptRb
|
|
2
|
+
class Parameter
|
|
3
|
+
attr_accessor :name, :enum, :type, :description, :required
|
|
4
|
+
|
|
5
|
+
# @param name [String]
|
|
6
|
+
# @param enum
|
|
7
|
+
# @param type
|
|
8
|
+
# @param description
|
|
9
|
+
# @param required [true, false] whether or not this parameter is required
|
|
10
|
+
def initialize(name:, enum: nil, type: nil, description: nil, required: false)
|
|
11
|
+
@name = name
|
|
12
|
+
@enum = enum
|
|
13
|
+
@type = type
|
|
14
|
+
@description = description
|
|
15
|
+
@required = required
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def required?
|
|
19
|
+
!!required
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @return Hash
|
|
23
|
+
def as_json
|
|
24
|
+
{
|
|
25
|
+
enum:,
|
|
26
|
+
type:,
|
|
27
|
+
description:,
|
|
28
|
+
}.compact
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: chatgpt-rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aaron Breckenridge
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-07-
|
|
11
|
+
date: 2023-07-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: httparty
|
|
@@ -66,6 +66,48 @@ dependencies:
|
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '0.3'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rspec
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: listen
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: webmock
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
69
111
|
description: Provides libraries for interacting with the ChatGPT API and a CLI program
|
|
70
112
|
`chatgpt-rb` for live conversations.
|
|
71
113
|
email:
|
|
@@ -76,8 +118,15 @@ extensions: []
|
|
|
76
118
|
extra_rdoc_files: []
|
|
77
119
|
files:
|
|
78
120
|
- bin/chatgpt-rb
|
|
121
|
+
- bin/watcher
|
|
79
122
|
- lib/chatgpt_rb.rb
|
|
80
123
|
- lib/chatgpt_rb/conversation.rb
|
|
124
|
+
- lib/chatgpt_rb/dsl/base.rb
|
|
125
|
+
- lib/chatgpt_rb/dsl/conversation.rb
|
|
126
|
+
- lib/chatgpt_rb/dsl/function.rb
|
|
127
|
+
- lib/chatgpt_rb/dsl/parameter.rb
|
|
128
|
+
- lib/chatgpt_rb/function.rb
|
|
129
|
+
- lib/chatgpt_rb/parameter.rb
|
|
81
130
|
homepage: https://github.com/breckenedge/chatgpt-rb
|
|
82
131
|
licenses:
|
|
83
132
|
- MIT
|