openai 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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +6 -0
- data/LICENSE.txt +1 -1
- data/README.md +18 -9
- data/Rakefile +5 -1
- data/lib/openai.rb +6 -28
- data/lib/openai/choice.rb +3 -0
- data/lib/openai/client.rb +139 -0
- data/lib/openai/completion.rb +7 -0
- data/lib/openai/engine.rb +3 -0
- data/lib/openai/logprobs.rb +3 -0
- data/lib/openai/search_result.rb +3 -0
- data/lib/openai/version.rb +2 -2
- data/openai.gemspec +12 -12
- metadata +44 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72e52493a36fa127172247c0db2f53153cdbb9ff1f3025d007fe9638e9298a77
|
4
|
+
data.tar.gz: 011f3c8fd9b2704f57a65bd406d7ea62efcfe17637c90a95ce3db97c02cfc3a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a3dcb467a183d8d7c73b0a3cdc1026e26e07f84957044c4dd7d2ba586fefb68af85aacf092f460005f99191e2ec609b545bf987cec3511538423e4fdcbad768
|
7
|
+
data.tar.gz: b71e17545c81c4399bcb485e750f6222d8ca43c1744452e7477aadb988f8eec4dfbfb9aa4b28308d930153f336a77dd4b916add2c4c454c4c78da399cd658848
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2020
|
3
|
+
Copyright (c) 2020 Nilesh Trivedi, Erik Berlin
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# OpenAI API client library to access GPT-3 in Ruby
|
2
2
|
|
3
3
|
This is a wrapper for calling OpenAI and GPT-3's HTTP APIs. API docs are available here: https://beta.openai.com/api-docs
|
4
4
|
|
@@ -20,19 +20,28 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
```
|
24
|
-
require
|
25
|
-
client = Openai::Client.new(pk: "your_public_key", sk: "your_secret_key")
|
26
|
-
completions = client.completions(prompt: "Have you wondered why", max_tokens: 10)
|
27
|
-
```
|
23
|
+
```ruby
|
24
|
+
require "openai"
|
28
25
|
|
29
|
-
|
26
|
+
openai_client = OpenAI::Client.new(api_key: ENV.fetch("OPENAI_API_KEY"), default_engine: "ada")
|
30
27
|
|
31
|
-
|
32
|
-
|
28
|
+
# List Engines
|
29
|
+
openai_client.engines
|
33
30
|
|
31
|
+
# Retrieve Engine
|
32
|
+
openai_client.engine("babbage")
|
33
|
+
|
34
|
+
# Search
|
35
|
+
openai_client.search(documents: ["White House", "hospital", "school"], query: "the president")
|
36
|
+
|
37
|
+
# Create Completion
|
38
|
+
openai_client.completions(prompt: "Once upon a time", max_tokens: 5)
|
34
39
|
```
|
35
40
|
|
41
|
+
## TODO
|
42
|
+
|
43
|
+
* Stream Completion
|
44
|
+
|
36
45
|
## Development
|
37
46
|
|
38
47
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/Rakefile
CHANGED
data/lib/openai.rb
CHANGED
@@ -1,29 +1,7 @@
|
|
1
|
+
require "openai/choice"
|
2
|
+
require "openai/client"
|
3
|
+
require "openai/completion"
|
4
|
+
require "openai/engine"
|
5
|
+
require "openai/logprobs"
|
6
|
+
require "openai/search_result"
|
1
7
|
require "openai/version"
|
2
|
-
require "httparty"
|
3
|
-
|
4
|
-
module Openai
|
5
|
-
class Client
|
6
|
-
BASE_URL = "https://api.openai.com/v1/engines/davinci"
|
7
|
-
|
8
|
-
attr_accessor :pk, :sk
|
9
|
-
|
10
|
-
def initialize(pk:, sk:)
|
11
|
-
@pk, @sk = pk, sk
|
12
|
-
end
|
13
|
-
|
14
|
-
def completions(prompt:, max_tokens: 5)
|
15
|
-
response = HTTParty.post(BASE_URL + "/completions", headers: self.headers, body: {
|
16
|
-
prompt: prompt,
|
17
|
-
max_tokens: max_tokens
|
18
|
-
}.to_json)
|
19
|
-
return JSON.parse(response.body)
|
20
|
-
end
|
21
|
-
|
22
|
-
def headers
|
23
|
-
{
|
24
|
-
"Content-Type" => "application/json",
|
25
|
-
"Authorization" => "Bearer #{@sk}"
|
26
|
-
}
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require "json"
|
2
|
+
require "net/http"
|
3
|
+
require "time"
|
4
|
+
require "uri"
|
5
|
+
|
6
|
+
module OpenAI
|
7
|
+
class Client
|
8
|
+
class Error < RuntimeError
|
9
|
+
end
|
10
|
+
|
11
|
+
LastResponse = Struct.new(:date, :organization, :processing_ms, :request_id, :status_code, :status_message, keyword_init: true)
|
12
|
+
|
13
|
+
attr_reader :last_response
|
14
|
+
attr_writer :api_key
|
15
|
+
attr_accessor :default_engine
|
16
|
+
|
17
|
+
def initialize(api_key:, default_engine: "davinci")
|
18
|
+
@api_key = api_key
|
19
|
+
@default_engine = default_engine
|
20
|
+
end
|
21
|
+
|
22
|
+
def engine(id = default_engine)
|
23
|
+
engine = get("/v1/engines/#{id}")
|
24
|
+
Engine.new(**engine)
|
25
|
+
end
|
26
|
+
|
27
|
+
def engines
|
28
|
+
engines = get("/v1/engines")
|
29
|
+
engines[:data].map do |engine|
|
30
|
+
Engine.new(**engine)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def completions(prompt: nil, max_tokens: nil, temperature: nil, top_p: nil, n: nil, logprobs: nil, echo: nil, stop: nil, presence_penalty: nil, frequency_penalty: nil, engine: default_engine)
|
35
|
+
body = {
|
36
|
+
"prompt" => prompt,
|
37
|
+
"max_tokens" => max_tokens,
|
38
|
+
"temperature" => temperature,
|
39
|
+
"top_p" => top_p,
|
40
|
+
"n" => n,
|
41
|
+
"logprobs" => logprobs,
|
42
|
+
"echo" => echo,
|
43
|
+
"stop" => stop,
|
44
|
+
"presence_penalty" => presence_penalty,
|
45
|
+
"frequency_penalty" => frequency_penalty,
|
46
|
+
}.compact
|
47
|
+
|
48
|
+
completion = post("/v1/engines/#{engine}/completions", body: body)
|
49
|
+
|
50
|
+
choices = completion[:choices]&.map do |choice|
|
51
|
+
Choice.new(
|
52
|
+
finish_reason: choice[:finish_reason],
|
53
|
+
index: choice[:index],
|
54
|
+
text: choice[:text],
|
55
|
+
logprobs: choice[:logprobs]&.tap do |logprob|
|
56
|
+
Logprobs.new(
|
57
|
+
text_offset: logprob[:text_offset],
|
58
|
+
token_logprobs: logprob[:token_logprobs],
|
59
|
+
tokens: logprob[:tokens],
|
60
|
+
top_logprobs: logprob[:top_logprobs]
|
61
|
+
)
|
62
|
+
end
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
Completion.new(
|
67
|
+
choices: choices,
|
68
|
+
created: completion[:created],
|
69
|
+
id: completion[:id],
|
70
|
+
model: completion[:model],
|
71
|
+
object: completion[:object]
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
def search(documents:, query:, engine: default_engine)
|
76
|
+
body = {
|
77
|
+
"documents" => documents,
|
78
|
+
"query" => query,
|
79
|
+
}.compact
|
80
|
+
|
81
|
+
search_results = post("/v1/engines/#{engine}/search", body: body)
|
82
|
+
search_results[:data].map.with_index do |datum, index|
|
83
|
+
SearchResult.new(**datum).tap do |result|
|
84
|
+
result.text = documents[index]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
private def get(path)
|
90
|
+
uri = URI.parse("https://api.openai.com#{path}")
|
91
|
+
req = Net::HTTP::Get.new(uri)
|
92
|
+
headers.each do |name, value|
|
93
|
+
req[name] = value
|
94
|
+
end
|
95
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
|
96
|
+
http.request(req)
|
97
|
+
end
|
98
|
+
handle_response(response)
|
99
|
+
end
|
100
|
+
|
101
|
+
private def post(path, body: nil)
|
102
|
+
uri = URI.parse("https://api.openai.com#{path}")
|
103
|
+
req = Net::HTTP::Post.new(uri)
|
104
|
+
req.body = body.to_json
|
105
|
+
headers.each do |name, value|
|
106
|
+
req[name] = value
|
107
|
+
end
|
108
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
|
109
|
+
http.request(req)
|
110
|
+
end
|
111
|
+
handle_response(response)
|
112
|
+
end
|
113
|
+
|
114
|
+
private def handle_response(response)
|
115
|
+
date = Time.httpdate(response["date"]) if response["date"]
|
116
|
+
organization = response["openai-organization"]
|
117
|
+
processing_ms = response["openai-processing-ms"]&.to_i
|
118
|
+
request_id = response["x-request-id"]
|
119
|
+
status_code = response.code&.to_i
|
120
|
+
status_message = response.message
|
121
|
+
@last_response = LastResponse.new(date: date, organization: organization, processing_ms: processing_ms, request_id: request_id, status_code: status_code, status_message: status_message)
|
122
|
+
|
123
|
+
response_body = JSON.parse(response.body, symbolize_names: true)
|
124
|
+
case response
|
125
|
+
when Net::HTTPSuccess
|
126
|
+
response_body
|
127
|
+
else
|
128
|
+
raise Error, response_body[:error][:message].to_s
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
private def headers
|
133
|
+
@headers ||= {
|
134
|
+
"Authorization" => "Bearer #{@api_key}",
|
135
|
+
"Content-Type" => "application/json",
|
136
|
+
}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/lib/openai/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module
|
2
|
-
VERSION = "0.
|
1
|
+
module OpenAI
|
2
|
+
VERSION = "0.2.0".freeze
|
3
3
|
end
|
data/openai.gemspec
CHANGED
@@ -1,17 +1,16 @@
|
|
1
|
-
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require "openai/version"
|
1
|
+
require_relative "lib/openai/version"
|
4
2
|
|
5
3
|
Gem::Specification.new do |spec|
|
6
4
|
spec.name = "openai"
|
7
|
-
spec.version =
|
8
|
-
spec.authors = ["Nilesh Trivedi"]
|
9
|
-
spec.email = ["git@nileshtrivedi.com"]
|
5
|
+
spec.version = OpenAI::VERSION
|
6
|
+
spec.authors = ["Nilesh Trivedi", "Erik Berlin"]
|
7
|
+
spec.email = ["git@nileshtrivedi.com", "sferik@gmail.com"]
|
10
8
|
|
11
|
-
spec.summary =
|
12
|
-
spec.description
|
9
|
+
spec.summary = "OpenAI API client library to access GPT-3 in Ruby"
|
10
|
+
spec.description = "OpenAI API client library to access GPT-3 in Ruby"
|
13
11
|
spec.homepage = "https://github.com/nileshtrivedi/openai"
|
14
12
|
spec.license = "MIT"
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
15
14
|
|
16
15
|
spec.metadata["homepage_uri"] = spec.homepage
|
17
16
|
spec.metadata["source_code_uri"] = "https://github.com/nileshtrivedi/openai"
|
@@ -19,14 +18,15 @@ Gem::Specification.new do |spec|
|
|
19
18
|
|
20
19
|
# Specify which files should be added to the gem when it is released.
|
21
20
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
-
spec.files = Dir.chdir(File.expand_path(
|
21
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
23
22
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
23
|
end
|
25
24
|
spec.bindir = "exe"
|
26
25
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
26
|
spec.require_paths = ["lib"]
|
28
27
|
|
29
|
-
spec.add_development_dependency "bundler", "
|
30
|
-
spec.add_development_dependency "rake", "
|
31
|
-
spec.
|
28
|
+
spec.add_development_dependency "bundler", ">= 2"
|
29
|
+
spec.add_development_dependency "rake", ">= 10"
|
30
|
+
spec.add_development_dependency "rspec", ">= 3.9"
|
31
|
+
spec.add_development_dependency "webmock", ">= 3.8"
|
32
32
|
end
|
metadata
CHANGED
@@ -1,65 +1,82 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openai
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nilesh Trivedi
|
8
|
-
|
8
|
+
- Erik Berlin
|
9
|
+
autorequire:
|
9
10
|
bindir: exe
|
10
11
|
cert_chain: []
|
11
|
-
date: 2020-
|
12
|
+
date: 2020-09-17 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
|
-
- - "
|
18
|
+
- - ">="
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version: '2
|
20
|
+
version: '2'
|
20
21
|
type: :development
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
|
-
- - "
|
25
|
+
- - ">="
|
25
26
|
- !ruby/object:Gem::Version
|
26
|
-
version: '2
|
27
|
+
version: '2'
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
29
|
name: rake
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
30
31
|
requirements:
|
31
|
-
- - "
|
32
|
+
- - ">="
|
32
33
|
- !ruby/object:Gem::Version
|
33
|
-
version: '10
|
34
|
+
version: '10'
|
34
35
|
type: :development
|
35
36
|
prerelease: false
|
36
37
|
version_requirements: !ruby/object:Gem::Requirement
|
37
38
|
requirements:
|
38
|
-
- - "
|
39
|
+
- - ">="
|
39
40
|
- !ruby/object:Gem::Version
|
40
|
-
version: '10
|
41
|
+
version: '10'
|
41
42
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
43
|
+
name: rspec
|
43
44
|
requirement: !ruby/object:Gem::Requirement
|
44
45
|
requirements:
|
45
46
|
- - ">="
|
46
47
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
48
|
-
type: :
|
48
|
+
version: '3.9'
|
49
|
+
type: :development
|
49
50
|
prerelease: false
|
50
51
|
version_requirements: !ruby/object:Gem::Requirement
|
51
52
|
requirements:
|
52
53
|
- - ">="
|
53
54
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
55
|
-
|
55
|
+
version: '3.9'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: webmock
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '3.8'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '3.8'
|
70
|
+
description: OpenAI API client library to access GPT-3 in Ruby
|
56
71
|
email:
|
57
72
|
- git@nileshtrivedi.com
|
73
|
+
- sferik@gmail.com
|
58
74
|
executables: []
|
59
75
|
extensions: []
|
60
76
|
extra_rdoc_files: []
|
61
77
|
files:
|
62
78
|
- ".gitignore"
|
79
|
+
- ".travis.yml"
|
63
80
|
- Gemfile
|
64
81
|
- LICENSE.txt
|
65
82
|
- README.md
|
@@ -67,6 +84,12 @@ files:
|
|
67
84
|
- bin/console
|
68
85
|
- bin/setup
|
69
86
|
- lib/openai.rb
|
87
|
+
- lib/openai/choice.rb
|
88
|
+
- lib/openai/client.rb
|
89
|
+
- lib/openai/completion.rb
|
90
|
+
- lib/openai/engine.rb
|
91
|
+
- lib/openai/logprobs.rb
|
92
|
+
- lib/openai/search_result.rb
|
70
93
|
- lib/openai/version.rb
|
71
94
|
- openai.gemspec
|
72
95
|
homepage: https://github.com/nileshtrivedi/openai
|
@@ -76,7 +99,7 @@ metadata:
|
|
76
99
|
homepage_uri: https://github.com/nileshtrivedi/openai
|
77
100
|
source_code_uri: https://github.com/nileshtrivedi/openai
|
78
101
|
changelog_uri: https://github.com/nileshtrivedi/openai/blob/master/changelog.md
|
79
|
-
post_install_message:
|
102
|
+
post_install_message:
|
80
103
|
rdoc_options: []
|
81
104
|
require_paths:
|
82
105
|
- lib
|
@@ -84,15 +107,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
84
107
|
requirements:
|
85
108
|
- - ">="
|
86
109
|
- !ruby/object:Gem::Version
|
87
|
-
version:
|
110
|
+
version: 2.3.0
|
88
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
112
|
requirements:
|
90
113
|
- - ">="
|
91
114
|
- !ruby/object:Gem::Version
|
92
115
|
version: '0'
|
93
116
|
requirements: []
|
94
|
-
rubygems_version: 3.
|
95
|
-
signing_key:
|
117
|
+
rubygems_version: 3.1.2
|
118
|
+
signing_key:
|
96
119
|
specification_version: 4
|
97
|
-
summary:
|
120
|
+
summary: OpenAI API client library to access GPT-3 in Ruby
|
98
121
|
test_files: []
|