Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

typesafe models #166

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
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
6 changes: 3 additions & 3 deletions Demo/DemoChat/Sources/ChatStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public final class ChatStore: ObservableObject {
func sendMessage(
_ message: Message,
conversationId: Conversation.ID,
model: Model
model: String
) async {
guard let conversationIndex = conversations.firstIndex(where: { $0.id == conversationId }) else {
return
Expand All @@ -65,14 +65,14 @@ public final class ChatStore: ObservableObject {

await completeChat(
conversationId: conversationId,
model: model
model: ChatModel(rawValue: model) ?? ChatModel.allCases.first!
)
}

@MainActor
func completeChat(
conversationId: Conversation.ID,
model: Model
model: ChatModel
) async {
guard let conversation = conversations.first(where: { $0.id == conversationId }) else {
return
Expand Down
6 changes: 3 additions & 3 deletions Demo/DemoChat/Sources/UI/DetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ struct DetailView: View {
@State var inputText: String = ""
@FocusState private var isFocused: Bool
@State private var showsModelSelectionSheet = false
@State private var selectedChatModel: Model = .gpt4_0613
@State private var selectedChatModel: String = ChatModel.allCases.first!.rawValue

private static let availableChatModels: [Model] = [.gpt3_5Turbo, .gpt4]
private static let availableChatModels: [String] = ChatModel.allCases.map { $0.rawValue }

let conversation: Conversation
let error: Error?
let sendMessage: (String, Model) -> Void
let sendMessage: (String, String) -> Void

private var fillColor: Color {
#if os(iOS)
Expand Down
6 changes: 3 additions & 3 deletions Demo/DemoChat/Sources/UI/TextToSpeechView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ public struct TextToSpeechView: View {
@State private var speed: Double = AudioSpeechQuery.Speed.normal.rawValue
@State private var responseFormat: AudioSpeechQuery.AudioSpeechResponseFormat = .mp3
@State private var showsModelSelectionSheet = false
@State private var selectedSpeechModel: String = Model.tts_1
@State private var selectedSpeechModel: String = SpeechModel.tts_1.rawValue

private static let availableSpeechModels: [String] = [Model.tts_1, Model.tts_1_hd]
private static let availableSpeechModels: [String] = SpeechModel.allCases.map { $0.rawValue }

public init(store: SpeechStore) {
self.store = store
Expand Down Expand Up @@ -83,7 +83,7 @@ public struct TextToSpeechView: View {
Section {
HStack {
Button("Create Speech") {
let query = AudioSpeechQuery(model: selectedSpeechModel,
let query = AudioSpeechQuery(model: SpeechModel(rawValue: selectedSpeechModel) ?? SpeechModel.allCases.first!,
input: prompt,
voice: voice,
responseFormat: responseFormat,
Expand Down
3 changes: 2 additions & 1 deletion Sources/OpenAI/Public/Models/AudioSpeechQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Foundation
/// Generates audio from the input text.
/// Learn more: [OpenAI Speech – Documentation](https://platform.openai.com/docs/api-reference/audio/createSpeech)
public struct AudioSpeechQuery: Codable {
public typealias Model = SpeechModel

/// Encapsulates the voices available for audio generation.
///
Expand Down Expand Up @@ -61,7 +62,7 @@ public struct AudioSpeechQuery: Codable {
}

public init(model: Model, input: String, voice: AudioSpeechVoice, responseFormat: AudioSpeechResponseFormat = .mp3, speed: Double?) {
self.model = AudioSpeechQuery.validateSpeechModel(model)
self.model = model
self.speed = AudioSpeechQuery.normalizeSpeechSpeed(speed)
self.input = input
self.voice = voice
Expand Down
1 change: 1 addition & 0 deletions Sources/OpenAI/Public/Models/AudioTranscriptionQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Foundation

public struct AudioTranscriptionQuery: Codable {
public typealias Model = AudioTranscriptionModel

public enum ResponseFormat: String, Codable, Equatable, CaseIterable {
case json
Expand Down
1 change: 1 addition & 0 deletions Sources/OpenAI/Public/Models/AudioTranslationQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Foundation

/// Translates audio into English.
public struct AudioTranslationQuery: Codable {
public typealias Model = AudioTranslationModel
public typealias FileType = AudioTranscriptionQuery.FileType
public typealias ResponseFormat = AudioTranscriptionQuery.ResponseFormat

Expand Down
1 change: 1 addition & 0 deletions Sources/OpenAI/Public/Models/ChatQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Foundation
/// Creates a model response for the given chat conversation
/// https://platform.openai.com/docs/guides/text-generation
public struct ChatQuery: Equatable, Codable, Streamable {
public typealias Model = ChatModel

/// A list of messages comprising the conversation so far
public let messages: [Self.ChatCompletionMessageParam]
Expand Down
2 changes: 2 additions & 0 deletions Sources/OpenAI/Public/Models/CompletionsQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import Foundation

public struct CompletionsQuery: Codable, Streamable {
public typealias Model = CompletionsModel // legacy

/// ID of the model to use.
public let model: Model
/// The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays.
Expand Down
2 changes: 1 addition & 1 deletion Sources/OpenAI/Public/Models/CompletionsResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public struct CompletionsResult: Codable, Equatable {
public let id: String
public let object: String
public let created: TimeInterval
public let model: Model
public let model: String
public let choices: [Choice]
public let usage: Usage?
}
2 changes: 2 additions & 0 deletions Sources/OpenAI/Public/Models/EditsQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import Foundation

public struct EditsQuery: Codable {
public typealias Model = String // endpoint obsolete

/// ID of the model to use.
public let model: Model
/// Input text to get embeddings for.
Expand Down
1 change: 1 addition & 0 deletions Sources/OpenAI/Public/Models/EmbeddingsQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Foundation

public struct EmbeddingsQuery: Codable {
public typealias Model = EmbeddingsModel

/// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or array of token arrays. The input must not exceed the max input tokens for the model (8192 tokens for text-embedding-ada-002), cannot be an empty string, and any array must be 2048 dimensions or less.
public let input: Self.Input
Expand Down
1 change: 1 addition & 0 deletions Sources/OpenAI/Public/Models/ImageEditsQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Foundation

public struct ImageEditsQuery: Codable {
public typealias Model = ImageModel // only dall-e-2 is supported at this time
public typealias ResponseFormat = ImagesQuery.ResponseFormat
public typealias Size = ImagesQuery.Size

Expand Down
1 change: 1 addition & 0 deletions Sources/OpenAI/Public/Models/ImageVariationsQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Foundation

public struct ImageVariationsQuery: Codable {
public typealias Model = ImageModel // only dall-e-2 is supported at this time
public typealias ResponseFormat = ImagesQuery.ResponseFormat

/// The image to edit. Must be a valid PNG file, less than 4MB, and square.
Expand Down
2 changes: 1 addition & 1 deletion Sources/OpenAI/Public/Models/ImagesQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import Foundation
/// Given a prompt and/or an input image, the model will generate a new image.
/// https://platform.openai.com/docs/guides/images
public struct ImagesQuery: Codable {
public typealias Model = ImageModel

public enum ResponseFormat: String, Codable, Equatable {
case url
case b64_json
}

/// A text description of the desired image(s). The maximum length is 1000 characters for dall-e-2 and 4000 characters for dall-e-3.
public let prompt: String
/// The model to use for image generation.
Expand Down
4 changes: 2 additions & 2 deletions Sources/OpenAI/Public/Models/Models/ModelQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import Foundation
/// Retrieves a model instance, providing basic information about the model such as the owner and permissioning.
public struct ModelQuery: Codable, Equatable {
/// The ID of the model to use for this request.
public let model: Model
public let model: String

public init(model: Model) {
public init(model: String) {
self.model = model
}
}
185 changes: 66 additions & 119 deletions Sources/OpenAI/Public/Models/Models/Models.swift
Original file line number Diff line number Diff line change
@@ -1,134 +1,81 @@
//
// Models.swift
//
//
//
// Created by Sergii Kryvoblotskyi on 12/19/22.
//

/// Defines all available OpenAI models supported by the library.
public typealias Model = String

public extension Model {
// Chat Completion
// GPT-4
import Foundation

/// `gpt-4-turbo`, the latest gpt-4 model with improved instruction following, JSON mode, reproducible outputs, parallel function calling and more. Maximum of 4096 output tokens
static let gpt4_turbo_preview = "gpt-4-turbo-preview"
public enum ChatModel: String, Codable, CaseIterable {
public static var allCases: [ChatModel] = [.gpt_3_5_turbo_0125, .gpt_3_5_turbo_1106, .gpt_3_5_turbo, .gpt_4, .gpt_4_32k, .gpt_4_0613, .gpt_4_32k_0613, .gpt_4_1106_preview, .gpt_4_vision_preview]

/// `gpt-4-vision-preview`, able to understand images, in addition to all other GPT-4 Turbo capabilities.
static let gpt4_vision_preview = "gpt-4-vision-preview"

/// Snapshot of `gpt-4-turbo-preview` from January 25th 2024. This model reduces cases of “laziness” where the model doesn’t complete a task. Also fixes the bug impacting non-English UTF-8 generations. Maximum of 4096 output tokens
static let gpt4_0125_preview = "gpt-4-0125-preview"

/// Snapshot of `gpt-4-turbo-preview` from November 6th 2023. Improved instruction following, JSON mode, reproducible outputs, parallel function calling and more. Maximum of 4096 output tokens
@available(*, deprecated, message: "Please upgrade to the newer model")
static let gpt4_1106_preview = "gpt-4-1106-preview"

/// Most capable `gpt-4` model, outperforms any GPT-3.5 model, able to do more complex tasks, and optimized for chat.
static let 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.
static let gpt4_0613 = "gpt-4-0613"

/// Snapshot of `gpt-4` from March 14th 2023. Unlike gpt-4, this model will not receive updates, and will only be supported for a three month period ending on June 14th 2023.
/// The latest GPT-3.5 Turbo model with higher accuracy at responding in requested formats and a fix for a bug which caused a text encoding issue for non-English language function calls. Returns a maximum of 4,096 output tokens.
case gpt_3_5_turbo_0125 = "gpt-3.5-turbo-0125" // system
/// GPT-3.5 Turbo model with improved instruction following, JSON mode, reproducible outputs, parallel function calling, and more. Returns a maximum of 4,096 output tokens.
case gpt_3_5_turbo_1106 = "gpt-3.5-turbo-1106" // system
/// Currently points to gpt-3.5-turbo-0613. The gpt-3.5-turbo model alias will be automatically upgraded from gpt-3.5-turbo-0613 to gpt-3.5-turbo-0125 on February 16th.
case gpt_3_5_turbo = "gpt-3.5-turbo" // openai
/// Currently points to gpt-3.5-turbo-0613.
@available(*, deprecated, message: "Please upgrade to the newer model")
static let gpt4_0314 = "gpt-4-0314"

/// Same capabilities as the base `gpt-4` model but with 4x the context length. Will be updated with our latest model iteration.
static let gpt4_32k = "gpt-4-32k"

/// Snapshot of `gpt-4-32k` 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.
static let gpt4_32k_0613 = "gpt-4-32k-0613"

/// Snapshot of `gpt-4-32k` from March 14th 2023. Unlike `gpt-4-32k`, this model will not receive updates, and will only be supported for a three month period ending on June 14th 2023.
@available(*, deprecated, message: "Please upgrade to the newer model")
static let gpt4_32k_0314 = "gpt-4-32k-0314"
case gpt_3_5_turbo_16k = "gpt-3.5-turbo-16k" // openai-internal
/// Snapshot of gpt-3.5-turbo from June 13th 2023. Will be deprecated on June 13, 2024.
@available(*, deprecated, message: "Please upgrade to the newer model. Will be deprecated on June 13, 2024.")
case gpt_3_5_turbo_0613 = "gpt-3.5-turbo-0613" // openai
/// Snapshot of gpt-3.5-16k-turbo from June 13th 2023. Will be deprecated on June 13, 2024.
@available(*, deprecated, message: "Please upgrade to the newer model. Will be deprecated on June 13, 2024.")
case gpt_3_5_turbo_16k_0613 = "gpt-3.5-turbo-16k-0613" // openai

// GPT-3.5

/// Most capable `gpt-3.5-turbo` model and optimized for chat. Will be updated with our latest model iteration.
static let gpt3_5Turbo = "gpt-3.5-turbo"

/// Snapshot of `gpt-3.5-turbo` from January 25th 2024. Decreased prices by 50%. Various improvements including higher accuracy at responding in requested formats and a fix for a bug which caused a text encoding issue for non-English language function calls.
static let gpt3_5Turbo_0125 = "gpt-3.5-turbo-0125"

/// Snapshot of `gpt-3.5-turbo` from November 6th 2023. The latest `gpt-3.5-turbo` model with improved instruction following, JSON mode, reproducible outputs, parallel function calling and more.
@available(*, deprecated, message: "Please upgrade to the newer model")
static let gpt3_5Turbo_1106 = "gpt-3.5-turbo-1106"

/// Snapshot of `gpt-3.5-turbo` from June 13th 2023 with function calling data. Unlike `gpt-3.5-turbo`, this model will not receive updates, and will be deprecated 3 months after a new version is released.
@available(*, deprecated, message: "Please upgrade to the newer model")
static let gpt3_5Turbo_0613 = "gpt-3.5-turbo-0613"

/// Snapshot of `gpt-3.5-turbo` from March 1st 2023. Unlike `gpt-3.5-turbo`, this model will not receive updates, and will only be supported for a three month period ending on June 1st 2023.
@available(*, deprecated, message: "Please upgrade to the newer model")
static let gpt3_5Turbo_0301 = "gpt-3.5-turbo-0301"

/// Same capabilities as the standard `gpt-3.5-turbo` model but with 4 times the context.
static let gpt3_5Turbo_16k = "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.
static let gpt3_5Turbo_16k_0613 = "gpt-3.5-turbo-16k-0613"
/// The latest GPT-4 model with improved instruction following, JSON mode, reproducible outputs, parallel function calling, and more. Returns a maximum of 4,096 output tokens. This preview model is not yet suited for production traffic.
case gpt_4_1106_preview = "gpt-4-1106-preview" // -- "ChatGPT Plus" SUBSCRIPTION ONLY
/// Ability to understand images, in addition to all other GPT-4 Turbo capabilties. Returns a maximum of 4,096 output tokens. This is a preview model version and not suited yet for production traffic.
case gpt_4_vision_preview = "gpt-4-vision-preview" // -- "ChatGPT Plus" SUBSCRIPTION ONLY
/// Currently points to gpt-4-0613.
case gpt_4 = "gpt-4"
/// Currently points to gpt-4-32k-0613.
case gpt_4_32k = "gpt-4-32k" // -- "ChatGPT Plus" SUBSCRIPTION ONLY
/// Snapshot of gpt-4 from June 13th 2023 with improved function calling support.
case gpt_4_0613 = "gpt-4-0613" // -- "ChatGPT Plus" SUBSCRIPTION ONLY
/// Snapshot of gpt-4-32k from June 13th 2023 with improved function calling support.
case gpt_4_32k_0613 = "gpt-4-32k-0613" // -- "ChatGPT Plus" SUBSCRIPTION ONLY
}

public enum ImageModel: String, Codable, CaseIterable {
/// The previous DALL·E model released in Nov 2022. The 2nd iteration of DALL·E with more realistic, accurate, and 4x greater resolution images than the original model.
case dall_e_2 = "dall-e-2" // system
// /// The latest DALL·E model released in Nov 2023.
case dall_e_3 = "dall-e-3" // system -- "ChatGPT Plus" SUBSCRIPTION ONLY, ImageGenerateParams only
}

// Completions

/// Can do any language task with better quality, longer output, and consistent instruction-following than the curie, babbage, or ada models. Also supports inserting completions within text.
static let textDavinci_003 = "text-davinci-003"
/// Similar capabilities to text-davinci-003 but trained with supervised fine-tuning instead of reinforcement learning.
static let textDavinci_002 = "text-davinci-002"
/// Very capable, faster and lower cost than Davinci.
static let textCurie = "text-curie-001"
/// Capable of straightforward tasks, very fast, and lower cost.
static let textBabbage = "text-babbage-001"
/// Capable of very simple tasks, usually the fastest model in the GPT-3 series, and lowest cost.
static let textAda = "text-ada-001"

// Edits

static let textDavinci_001 = "text-davinci-001"
static let codeDavinciEdit_001 = "code-davinci-edit-001"

// Speech

public enum SpeechModel: String, Codable, CaseIterable {
/// The latest text to speech model, optimized for speed.
static let tts_1 = "tts-1"
case tts_1 = "tts-1" // openai-internal
/// The latest text to speech model, optimized for quality.
static let tts_1_hd = "tts-1-hd"

// Transcriptions / Translations

static let whisper_1 = "whisper-1"
case tts_1_hd = "tts-1-hd" // system
}

public enum AudioTranslationModel: String, Codable, CaseIterable {
case whisper_1 = "whisper-1" // openai-internal
}
public enum AudioTranscriptionModel: String, Codable, CaseIterable {
case whisper_1 = "whisper-1" // openai-internal
}

public enum EmbeddingsModel: String, Codable, CaseIterable {
case text_embedding_3_small = "text-embedding-3-small"
case text_embedding_3_large = "text-embedding-3-large"
case text_embedding_ada_002 = "text-embedding-ada-002" // openai-internal
// case text_embedding_ada_002_v2 = "text-embedding-ada-002-v2" // UNLISTED AT MODEL ENDPOINT; RETURNED WHEN .text_embedding_ada_002 IS SENT, BUT CANNOT BE SPECIFIED -- EXAMPLE OF WHY Result MUST RETURN String, NOT ...Model
}

public enum ModerationsModel: String, Codable, CaseIterable {
case textModerationStable = "text-moderation-stable" // UNLISTED AT MODEL ENDPOINT -- text-moderation-005 RETURNED BY ENDPOINT
case textModerationLatest = "text-moderation-latest" // UNLISTED AT MODEL ENDPOINT -- text-moderation-006 RETURNED BY ENDPOINT
}

// Image Generation
static let dall_e_2 = "dall-e-2"
static let dall_e_3 = "dall-e-3"

// Fine Tunes

/// Most capable GPT-3 model. Can do any task the other models can do, often with higher quality.
static let davinci = "davinci"
/// Very capable, but faster and lower cost than Davinci.
static let curie = "curie"
/// Capable of straightforward tasks, very fast, and lower cost.
static let babbage = "babbage"
/// Capable of very simple tasks, usually the fastest model in the GPT-3 series, and lowest cost.
static let ada = "ada"

// Embeddings

static let textEmbeddingAda = "text-embedding-ada-002"
static let textSearchAda = "text-search-ada-doc-001"
static let textSearchBabbageDoc = "text-search-babbage-doc-001"
static let textSearchBabbageQuery001 = "text-search-babbage-query-001"
static let textEmbedding3 = "text-embedding-3-small"
static let textEmbedding3Large = "text-embedding-3-large"

// Moderations

/// Almost as capable as the latest model, but slightly older.
static let textModerationStable = "text-moderation-stable"
/// Most capable moderation model. Accuracy will be slightly higher than the stable model.
static let textModerationLatest = "text-moderation-latest"
static let moderation = "text-moderation-007"
@available(*, deprecated, message: "Please upgrade to the chatCompletions endpoint")
public enum CompletionsModel: String, Codable, CaseIterable {
case gpt_3_5_turbo_instruct = "gpt-3.5-turbo-instruct"
case babbage_002 = "babbage-002"
case davinci_002 = "davinci-002"
}
2 changes: 2 additions & 0 deletions Sources/OpenAI/Public/Models/ModerationsQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import Foundation

public struct ModerationsQuery: Codable {
public typealias Model = ModerationsModel

/// The input text to classify.
public let input: String
/// ID of the model to use.
Expand Down
2 changes: 1 addition & 1 deletion Sources/OpenAI/Public/Models/ModerationsResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,6 @@ public struct ModerationsResult: Codable, Equatable {
}

public let id: String
public let model: Model
public let model: String
public let results: [CategoryResult]
}
Loading
Loading