Last active
March 1, 2023 23:28
-
-
Save 0xLeif/c826372e795de39637bd96a356228936 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import c // https://github.com/0xOpenBytes/c | |
import o // https://github.com/0xOpenBytes/o | |
import Plugin // https://github.com/0xLeif/Plugin | |
import Foundation | |
class ChatService: Pluginable { | |
enum Constants { | |
enum Model { | |
static let davinci = "text-davinci-003" | |
} | |
static let apiKey = "KEY_HERE" | |
} | |
enum ChatError: String, LocalizedError { | |
case noData = "No Data" | |
case noChoices = "No AI Choices" | |
} | |
/** | |
{ | |
"id": "cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7", | |
"object": "text_completion", | |
"created": 1589478378, | |
"model": "text-davinci-003", | |
"choices": [ | |
{ | |
"text": "\n\nThis is indeed a test", | |
"index": 0, | |
"logprobs": null, | |
"finish_reason": "length" | |
} | |
], | |
"usage": { | |
"prompt_tokens": 5, | |
"completion_tokens": 7, | |
"total_tokens": 12 | |
} | |
} | |
*/ | |
enum JSONKeys { | |
enum Root: String { | |
case id, object, created, model, choices, usage | |
} | |
enum Choices: String { | |
case text, index, logprobs, finish_reason | |
} | |
enum Usage: String { | |
case prompt_tokens, completion_tokens, total_tokens | |
} | |
} | |
typealias ChatServicePluginPayload = c.JSON<JSONKeys.Root> | |
var plugins: [any Plugin] | |
init(plugins: [any Plugin] = []) { | |
self.plugins = plugins | |
} | |
func completion(for prompt: String) async throws -> String { | |
struct Payload: Codable { | |
let model: String | |
let prompt: String | |
let max_tokens: Int | |
let temperature: Int | |
} | |
let body = try JSONEncoder().encode( | |
Payload( | |
model: Constants.Model.davinci, | |
prompt: prompt, | |
max_tokens: 2048, | |
temperature: 0 | |
) | |
) | |
/* | |
curl https://api.openai.com/v1/completions \ | |
-H 'Content-Type: application/json' \ | |
-H 'Authorization: Bearer YOUR_API_KEY' \ | |
-d '{ | |
"model": "text-davinci-003", | |
"prompt": "Say this is a test", | |
"max_tokens": 7, | |
"temperature": 0 | |
}' | |
*/ | |
let dataResponse = try await o.url.post( | |
url: URL(string: "https://api.openai.com/v1/completions")!, | |
body: body, | |
headerFields: [ | |
"Content-Type": "application/json", | |
"Authorization": "Bearer \(Constants.apiKey)" | |
] | |
) | |
guard | |
let data = dataResponse.data | |
else { | |
throw ChatError.noData | |
} | |
let json = c.JSON<JSONKeys.Root>(data: data) | |
try await handle(value: json) | |
guard | |
let choices = json.array(.choices, keyed: JSONKeys.Choices.self), | |
let firstChoice = choices.first?.get(.text, as: String.self) | |
else { | |
throw ChatError.noChoices | |
} | |
return firstChoice | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment