Skip to content

Commit e58942c

Browse files
committed
Initial Commit
0 parents  commit e58942c

10 files changed

+464
-0
lines changed

.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj
5+
xcuserdata/
6+
DerivedData/
7+
.swiftpm/config/registries.json
8+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
9+
.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
10+
.netrc

Package.swift

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// swift-tools-version: 5.7
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "OpenAIAPI",
8+
products: [
9+
// Products define the executables and libraries a package produces, and make them visible to other packages.
10+
.library(
11+
name: "OpenAIAPI",
12+
targets: ["OpenAIAPI"]),
13+
],
14+
dependencies: [
15+
// Dependencies declare other packages that this package depends on.
16+
// .package(url: /* package url */, from: "1.0.0"),
17+
],
18+
targets: [
19+
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
20+
// Targets can depend on other targets in this package, and on products in packages this package depends on.
21+
.target(
22+
name: "OpenAIAPI",
23+
dependencies: []),
24+
.testTarget(
25+
name: "OpenAIAPITests",
26+
dependencies: ["OpenAIAPI"]),
27+
]
28+
)

README.md

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# OpenAIAPI
2+
3+
#### A light wrapper around [**OpenAI**](https://openai.com/api/) API, written in Swift.
4+
The full OpenAI platform docs are here: https://platform.openai.com/docs/
5+
6+
## Installation
7+
### Swift Package Manager
8+
9+
1. Select `File`/`Add Packages` from xcode menu.
10+
1. Paste `https://github.com/tranq72/OpenAIAPI.git`.
11+
12+
To update, select `Packages`/`Update to Latest Package Versions`
13+
14+
## Usage
15+
16+
```swift
17+
import OpenAIAPI
18+
let openAI = OpenAIAPI(OpenAIAPIConfig(secret: "..."))
19+
```
20+
21+
```
22+
let config = OpenAIAPIEditParms(n: 2)
23+
openAI.createEdit(instruction:"Fix spelling and grammar", input:"The pens is an the taible", config: config) { result in
24+
switch result {
25+
case .success(let success):
26+
dump(success)
27+
case .failure(let failure):
28+
print("\(failure.localizedDescription)")
29+
}
30+
}
31+
```
32+
33+
```
34+
let queryParms = OpenAIAPICompletionParms(max_tokens: 500, temperature:0.9)
35+
openAI.createCompletion(prompt: "Write a poem in the style of Dante about Steve Jobs", config: queryParms) { result in
36+
switch result {
37+
case .success(let success):
38+
dump(success)
39+
case .failure(let failure):
40+
print("\(failure.localizedDescription)")
41+
}
42+
}
43+
```
44+
45+
### Query parameters
46+
47+
Default values for most parameters can be overridden for each query using the corresponding configuration objects: `OpenAIAPICompletionParms`, `OpenAIAPIEditParms`
48+
49+
For the full list of the supported parameters and their default values see [OpenAIAPIQueryParms.swift](https://github.com/tranq72/OpenAIAPI/blob/main/Sources/OpenAIAPI/OpenAIAPIQueryParms.swift).
50+
<BR>
51+
For the supported models see [OpenAIAPIModel.swift](https://github.com/tranq72/OpenAIAPI/blob/main/Sources/OpenAIAPI/OpenAIAPIModel.swift).
52+
53+
### API secret
54+
55+
Keep your API secrets secure and away from client apps.
56+
Instead of directly calling a third party API (like OpenAI, which is a paid service) you better deploy a reverse-proxy in your backend and set the `endpoint` and `secret` parameters accordingly.

Sources/OpenAIAPI/OpenAIAPI.swift

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//
2+
// OpenAIAPI.swift
3+
//
4+
// Created by Nico Tranquilli on 05/02/23.
5+
//
6+
7+
import Foundation
8+
9+
public class OpenAIAPI : WebService { // OpenAI Service
10+
let config : OpenAIAPIConfig
11+
12+
init(_ config: OpenAIAPIConfig) {
13+
self.config = config
14+
super.init(baseURL: config.baseURL, secret: config.secret)
15+
}
16+
}
17+
18+
extension OpenAIAPI {
19+
/// Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position.
20+
public func createCompletion(prompt: String, config: OpenAIAPICompletionParms, completion: @escaping (Result<OpenAIAPICompletionResponse, WebServiceError>) -> Void) {
21+
var parms = config
22+
parms.prompt = prompt
23+
24+
// any Error
25+
postAPIRequest("/v1/completions", configParms: parms) { (result:(Result<OpenAIAPICompletionResponse, WebServiceError>) ) in
26+
completion(result)
27+
}
28+
}
29+
30+
public func createEdit(instruction: String, input: String, config: OpenAIAPIEditParms, completion: @escaping (Result<OpenAIAPIEditResponse, WebServiceError>) -> Void) {
31+
32+
var parms = config
33+
parms.instruction = instruction
34+
parms.input = input
35+
36+
postAPIRequest("/v1/edits", configParms: parms) { (result:(Result<OpenAIAPIEditResponse, WebServiceError>) ) in
37+
completion(result)
38+
}
39+
}
40+
41+
/*
42+
public func createImage() {
43+
44+
}
45+
46+
public func createEmbeddings() {
47+
48+
}
49+
50+
public func createModerations() {
51+
52+
}
53+
*/
54+
}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// OpenAIConfiguration.swift
3+
//
4+
// Created by Nico Tranquilli on 05/02/23.
5+
//
6+
7+
import Foundation
8+
9+
public struct OpenAIAPIConfig {
10+
fileprivate(set) var secret: String?
11+
var baseURL: URL
12+
13+
/// ideally, credentials should NOT be exposed in your code, hardcoded or not it doesn't matter
14+
/// set <endpoint> to your backend/reverse-proxy and don't use your real OpenAI API secret in your client app
15+
/// openai endpoint fallback is just for development and testing
16+
init (secret: String?=nil, endpoint: String?=nil) {
17+
self.secret = secret
18+
self.baseURL = URL(string: endpoint ?? "https://api.openai.com")!
19+
}
20+
}
21+
+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//
2+
// OpenAIModel.swift
3+
//
4+
// Created by Nico Tranquilli on 05/02/23.
5+
//
6+
7+
import Foundation
8+
9+
public enum OpenAIAPIModel {
10+
case text_davinci_003
11+
case text_davinci_002
12+
case text_davinci_001
13+
14+
case text_curie_001
15+
case text_babbage_001
16+
case text_ada_001
17+
18+
case text_davinci_edit_001
19+
case text_davinci_insert_002
20+
case text_davinci_insert_001
21+
22+
case code_davinci_002
23+
case code_cushman_001
24+
25+
case code_davinci_edit_001
26+
27+
case text_search_babbage_doc_001
28+
case text_search_curie_doc_001
29+
case text_search_curie_query_001
30+
case text_search_davinci_doc_001
31+
case text_search_babbage_query_001
32+
case text_search_ada_query_001
33+
case text_search_ada_doc_001
34+
case text_search_davinci_query_001
35+
36+
case text_similarity_davinci_001
37+
case text_similarity_curie_001
38+
case text_similarity_ada_001
39+
case text_similarity_babbage_001
40+
41+
case text_embedding_ada_002
42+
43+
case babbage
44+
case ada
45+
case davinci
46+
case curie
47+
48+
case davinci_similarity
49+
case babbage_similarity
50+
case ada_similarity
51+
case curie_similarity
52+
53+
case babbage_code_search_text
54+
case ada_code_search_text
55+
56+
case babbage_code_search_code
57+
case ada_code_search_code
58+
59+
case curie_search_query
60+
case babbage_search_query
61+
case davinci_search_query
62+
case ada_search_query
63+
64+
case code_search_babbage_text_001
65+
case code_search_ada_text_001
66+
67+
case code_search_babbage_code_001
68+
case code_search_ada_code_001
69+
70+
case davinci_search_document
71+
case curie_search_document
72+
case babbage_search_document
73+
case ada_search_document
74+
75+
case davinci_instruct_beta
76+
case curie_instruct_beta
77+
78+
public var name: String {
79+
return String(describing: self).replacingOccurrences(of: "_", with: "-")
80+
}
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//
2+
// CompletionParms.swift
3+
//
4+
// Created by Nico Tranquilli on 05/02/23.
5+
//
6+
7+
import Foundation
8+
9+
/*
10+
public enum OpenAIAPIQueryConfigs {
11+
case completion(OpenAIAPICompletionConfig)
12+
case edit(OpenAIAPIEditConfig)
13+
}
14+
*/
15+
public struct OpenAIAPICompletionParms : Codable {
16+
var model: String = OpenAIAPIModel.text_davinci_003.name
17+
var prompt: String = "<|endoftext|>"
18+
//var instruction: String = "do nothing"
19+
//var input: String = ""
20+
21+
var suffix: String?
22+
var max_tokens: Int = 16
23+
24+
var temperature: Float = 1
25+
var top_p: Float = 1
26+
var n: Int = 1
27+
28+
var echo: Bool = false
29+
var stop: String?
30+
var presence_penalty: Float = 0
31+
var frequency_penalty: Float = 0
32+
33+
var user: String?
34+
}
35+
public struct OpenAIAPIEditParms : Codable {
36+
var model: String = OpenAIAPIModel.text_davinci_edit_001.name
37+
38+
var input: String = ""
39+
var instruction: String = "do nothing"
40+
41+
var n: Int = 1
42+
var temperature: Float = 1
43+
var top_p: Float = 1
44+
45+
var user: String?
46+
}
47+
48+
/*
49+
extension OpenAIQueryConfig {
50+
init(defaults: String) {
51+
let data = defaults.data(using: .utf8)!
52+
self = try! JSONDecoder().decode(Self.self, from: data)
53+
}
54+
}
55+
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// OpenAIQueryResponse.swift
3+
//
4+
// Created by Nico Tranquilli on 05/02/23.
5+
//
6+
7+
import Foundation
8+
9+
public struct OpenAIAPICompletionResponse: Codable {
10+
public let id: String
11+
public let object: String
12+
public let created: TimeInterval
13+
public let model: String
14+
public let choices: [Choice]
15+
public let usage: Usage
16+
}
17+
public struct OpenAIAPIEditResponse: Codable {
18+
public let object: String
19+
public let created: TimeInterval
20+
public let choices: [Choice]
21+
public let usage: Usage
22+
}
23+
24+
public struct Choice: Codable {
25+
public let text: String
26+
public let index: Int
27+
//public let logprobs: ..
28+
public let finish_reason: String? // completions
29+
}
30+
public struct Usage: Codable {
31+
let prompt_tokens: Int
32+
let completion_tokens: Int
33+
let total_tokens: Int
34+
}

0 commit comments

Comments
 (0)