Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Import the framework in your project:

[Create an OpenAI API key](https://platform.openai.com/account/api-keys) and add it to your configuration:

`let openAI = OpenAISwift(authToken: "TOKEN")`
`let openAI = OpenAISwift(config: .makeDefaultOpenAI(apiKey: "TOKEN"))`

This framework supports Swift concurrency; each example below has both an async/await and completion handler variant.

Expand Down
27 changes: 24 additions & 3 deletions Sources/OpenAISwift/Models/ChatMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public enum ChatRole: String, Codable {

/// A structure that represents a single message in a chat conversation.
public struct ChatMessage: Codable, Identifiable {
// uuid to conform to Identifiable protocol
/// UUID to conform to the Identifiable protocol
/// - Note: This property is not de- and encoded. A DTO or other logic might be required if the `ChatMessage` instance is stored locally.
public var id = UUID()
/// The role of the sender of the message.
public let role: ChatRole?
Expand All @@ -34,6 +35,26 @@ public struct ChatMessage: Codable, Identifiable {
self.role = role
self.content = content
}

enum CodingKeys: CodingKey {
case role
case content
}

public init(from decoder: Decoder) throws {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcoboerner I may be missing something, but I don't think this is needed. Specifying CodingKeys should be sufficient. I have a fork with a commit here that fixes this issue.

(Same goes for encode() method below.)

For what it's worth I'll open up a PR with the "one line" solution that only solves the reported problem (maybe that'll get merged sooner?).

That said the other changes you made are also useful...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...nevermind, I won't open a PR because I see there are several already. :)

let container: KeyedDecodingContainer<ChatMessage.CodingKeys> = try decoder.container(keyedBy: ChatMessage.CodingKeys.self)

self.role = try container.decodeIfPresent(ChatRole.self, forKey: ChatMessage.CodingKeys.role)
self.content = try container.decodeIfPresent(String.self, forKey: ChatMessage.CodingKeys.content)

}

public func encode(to encoder: Encoder) throws {
var container: KeyedEncodingContainer<ChatMessage.CodingKeys> = encoder.container(keyedBy: ChatMessage.CodingKeys.self)

try container.encodeIfPresent(self.role, forKey: ChatMessage.CodingKeys.role)
try container.encodeIfPresent(self.content, forKey: ChatMessage.CodingKeys.content)
}
}

/// A structure that represents a chat conversation.
Expand Down Expand Up @@ -70,7 +91,7 @@ public struct ChatConversation: Encodable {

/// Modify the likelihood of specified tokens appearing in the completion. Maps tokens (specified by their token ID in the OpenAI Tokenizer—not English words) to an associated bias value from -100 to 100. Values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.
let logitBias: [Int: Double]?

/// If you're generating long completions, waiting for the response can take many seconds. To get responses sooner, you can 'stream' the completion as it's being generated. This allows you to start printing or processing the beginning of the completion before the full completion is finished.
/// https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb
let stream: Bool?
Expand All @@ -96,6 +117,6 @@ public struct ChatError: Codable {
public let message, type: String
public let param, code: String?
}

public let error: Payload
}
123 changes: 123 additions & 0 deletions Sources/OpenAISwift/Models/OpenAIEndpointModelType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//
// OpenAIEndpointModelType.swift
//
//
// Created by Marco Boerner on 01.09.23.
//

import Foundation

/// Currently available and recommended models including some, but not all, legacy models
/// https://platform.openai.com/docs/models/model-endpoint-compatibility
public struct OpenAIEndpointModelType {

public enum AudioTranscriptions: String, Codable {
/// Whisper v2-large model (under the name whisper1) is a general-purpose speech recognition model. It is trained on a large dataset of diverse audio and is also a multi-task model that can perform multilingual speech recognition as well as speech translation and language identification
case whisper1 = "whisper-1"
}

public enum AudioTranslations: String, Codable {
/// Whisper v2-large model (under the name whisper1) is a general-purpose speech recognition model. It is trained on a large dataset of diverse audio and is also a multi-task model that can perform multilingual speech recognition as well as speech translation and language identification
case whisper1 = "whisper-1"
}

public enum ChatCompletions: String, Codable {
/// More capable than any GPT-3.5 model, able to do more complex tasks, and optimized for chat. Will be updated with our latest model iteration 2 weeks after it is released. - 8,192 tokens
case gpt4 = "gpt-4"

/// Snapshot of gpt-4 from June 13th 2023 with function calling data. Unlike gpt-4, this model will not receive updates, and will be deprecated 3 months after a new version is released. - 8,192 tokens
case gpt40613 = "gpt-4-0613"

/// Same capabilities as the standard gpt-4 mode but with 4x the context length. Will be updated with our latest model iteration. - 32,768 tokens
case gpt432k = "gpt-4-32k"

/// Snapshot of gpt-4-32 from June 13th 2023. Unlike gpt-4-32k, this model will not receive updates, and will be deprecated 3 months after a new version is released. - 32,768 tokens
case gpt432k0613 = "gpt-4-32k-0613"

/// A faster version of GPT-3.5 with the same capabilities. Will be updated with our latest model iteration. - 4,096 tokens
case gpt35Turbo = "gpt-3.5-turbo"

/// Snapshot of gpt-3.5-turbo from June 13th 2023. Unlike gpt-3.5-turbo, this model will not receive updates, and will be deprecated 3 months after a new version is released. - 4,096 tokens
case gpt35Turbo0613 = "gpt-3.5-turbo-0613"

/// A faster version of GPT-3.5 with the same capabilities and 4x the context length. Will be updated with our latest model iteration. - 16,384 tokens
case gpt35Turbo16k = "gpt-3.5-turbo-16k"

/// Snapshot of gpt-3.5-turbo-16k from June 13th 2023. Unlike gpt-3.5-turbo-16k, this model will not receive updates, and will be deprecated 3 months after a new version is released. - 16,384 tokens
case gpt35Turbo16k0613 = "gpt-3.5-turbo-16k-0613"
}

public enum LegacyCompletions: String, Codable {
/// Can do any language task with better quality, longer output, and consistent instruction-following than the curie, babbage, or ada models. Also supports some additional features such as inserting text. - 4,097 tokens
case textDavinci003 = "text-davinci-003"

/// Similar capabilities to text-davinci-003 but trained with supervised fine-tuning instead of reinforcement learning - 4,097 tokens
case textDavinci002 = "text-davinci-002"

/// Optimized for code-completion tasks - 8,001 tokens
case textDavinci001 = "text-davinci-001"

/// Very capable, faster and lower cost than Davinci. - 2,049 tokens
case textCurie001 = "text-curie-001"

/// Capable of straightforward tasks, very fast, and lower cost. - 2,049 tokens
case textBabbage001 = "text-babbage-001"

/// Capable of very simple tasks, usually the fastest model in the GPT-3 series, and lowest cost. - 2,049 tokens
case textAda001 = "text-ada-001"

/// Most capable GPT-3 model. Can do any task the other models can do, often with higher quality. - 2,049 tokens
case davinci = "davinci"

/// Very capable, but faster and lower cost than Davinci. - 2,049 tokens
case curie = "curie"

/// Capable of straightforward tasks, very fast, and lower cost. - 2,049 tokens
case babbage = "babbage"

/// Capable of very simple tasks, usually the fastest model in the GPT-3 series, and lowest cost. - 2,049 tokens
case ada = "ada"
}

public enum Embeddings: String, Codable {

/// The new model, text-embedding-ada-002, replaces five separate models for text search, text similarity, and code search, and outperforms previous most capable model, Davinci, at most tasks, while being priced 99.8% lower.
case textEmbeddingAda002 = "text-embedding-ada-002"
}

public enum FineTuningJobs: String, Codable {

/// Most capable GPT-3.5 model and optimized for chat at 1/10th the cost of text-davinci-003. Will be updated with our latest model iteration 2 weeks after it is released. - 4,096 tokens
case gpt35Turbo = "gpt-3.5-turbo"

/// Replacement for the GPT-3 ada and babbage base models. - 16,384 tokens
case babbage002 = "babbage-002"

/// Replacement for the GPT-3 curie and davinci base models. - 16,384 tokens
case davinci002 = "davinci-002"
}

public enum FineTunes: String, Codable {

/// Most capable GPT-3 model. Can do any task the other models can do, often with higher quality. - 2,049 tokens
case davinci = "davinci"

/// Very capable, but faster and lower cost than Davinci. - 2,049 tokens
case curie = "curie"

/// Capable of straightforward tasks, very fast, and lower cost. - 2,049 tokens
case babbage = "babbage"

/// Capable of very simple tasks, usually the fastest model in the GPT-3 series, and lowest cost. - 2,049 tokens
case ada = "ada"
}

public enum Moderations: String, Codable {

/// Most capable moderation model. Accuracy will be slightly higher than the stable model.
case textModerationStable = "text-moderation-stable"

/// Almost as capable as the latest model, but slightly older.
case textModerationLatest = "text-moderation-latest"
}
}
23 changes: 22 additions & 1 deletion Sources/OpenAISwift/Models/OpenAIModelType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,28 @@ public enum OpenAIModelType {
case .other(let modelName): return modelName
}
}


/// Custom initializer that allows to enum to be constructed from a string value.
public init(rawValue: String) {
if let gtp3 = GPT3(rawValue: rawValue) {
self = .gpt3(gtp3)
} else if let codex = Codex(rawValue: rawValue) {
self = .codex(codex)
} else if let feature = Feature(rawValue: rawValue) {
self = .feature(feature)
} else if let chat = Chat(rawValue: rawValue) {
self = .chat(chat)
} else if let gpt4 = GPT4(rawValue: rawValue) {
self = .gpt4(gpt4)
} else if let embedding = Embedding(rawValue: rawValue) {
self = .embedding(embedding)
} else if let moderation = Moderation(rawValue: rawValue) {
self = .moderation(moderation)
} else {
self = .other(rawValue)
}
}

/// A set of models that can understand and generate natural language
///
/// [GPT-3 Models OpenAI API Docs](https://beta.openai.com/docs/models/gpt-3)
Expand Down
Loading