- About the Project
- Features
- Requirements
- Installation
- Using OpenAIKit
- Example Projects
- Development and Testing
- License
OpenAIKit is a community-driven Swift SDK designed to provide Swift developers with a seamless, efficient, and Swifty way to interact with the OpenAI REST endpoint. Our aim is to lower the barrier for Swift developers, enabling them to integrate the power of OpenAI into their apps without delving deep into the intricacies of RESTful services.
With the increasing demand for AI-powered features in modern applications, it's crucial for developers to have access to tools that simplify the integration process. While OpenAI offers an incredible suite of capabilities, there was a clear need for a dedicated Swift SDK that aligns with the idiomatic practices of the language and the expectations of the Swift developer community.
We envisioned a tool that not only provides raw access to OpenAI functionalities but also enhances the developer experience with a clear and intuitive API. Our ultimate goal is to foster innovation by providing the Swift community with the right tools to integrate AI capabilities into their applications effortlessly.
- Generate new, edited, and variations of images using Dall-E 2 (with Dall-E 3 coming soon).
- Generate edits and completions using GPT-3 and GPT-4.
- List avaiable models for use with GPT-3 and GPT-4.
- Retrieve embeddings for GPT-3 and GPT-4 prompts.
- Stream data for GPT-3 and GPT-4 completions.
- Generate Chat responses using ChatGPT.
- View and Upload training files.
- View whether a prompt is flagged by the Moderations endpoint or not.
- Comprehensive Unit and Integration Test coverage.
- Swift Concurrency compatibility back to iOS 13, macOS 10.15, tvOS 13, watchOS 6, and visionOS 1.0.
- Complete documentation of OpenAIKit.
Platform | Minimum Swift Version | Installation | Status |
---|---|---|---|
iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+ / visionOS 1.0+ | 5.7 | Swift Package Manager | Fully Tested |
The Swift Package Manager allows for developers to easily integrate packages into their Xcode projects and packages; and is also fully integrated into the swift
compiler.
- File > Swift Packages > Add Package Dependency
- Add
https://github.com/OpenDive/OpenAIKit.git
- Select "Up to next Major" with "2.0.1"
Once you have your Swift package set up, add the Git link within the dependencies
value of your Package.swift
file.
dependencies: [
.package(url: "https://github.com/OpenDive/OpenAIKit.git", .upToNextMajor(from: "2.0.1"))
]
To obtain an API Key, go to your API Keys
page on your account page here.
When working with OpenAI's API, it's essential for security reasons not to embed your API keys directly within the codebase of your application. Embedding keys directly in your source code can expose them to unauthorized users and malicious actors, leading to potential misuse.
Best Practices:
- Environment Variables: Store your API keys in environment variables and access them in your code. This way, they aren't hard-coded into your application and can be managed securely.
- Secrets Management: Use a secure secrets management tool or service to store and retrieve your API keys. Tools like AWS Secrets Manager, HashiCorp Vault, Firebase, CloudKit, or Azure Key Vault are designed to store, manage, and retrieve sensitive data. This way, the user does not have on-device access to the keys.
- .gitignore: If you store your API keys in a configuration file, always ensure that this file is added to
.gitignore
or a similar mechanism to prevent it from being accidentally committed to a source control system.- Regularly Rotate Keys: Rotate your API keys periodically to mitigate the potential impact of a leak.
Remember, security is of utmost importance. Always prioritize the safe handling of sensitive information like API keys!
For more information, check out this article all about API key management for Swift developers.
Dive into the next evolution of AI-powered image generation with DALL-E 2 (and coming soon, DALL-E 3), brought to you by OpenAI. Building upon the legacy of its predecessor, DALL-E 2 offers enhanced capabilities to materialize intricate visuals from textual prompts, creating a seamless bridge between language and imagery. Developers can harness this groundbreaking technology to enrich user experiences, craft dynamic content, and inspire new avenues of creativity. Revolutionize your applications and projects by integrating the cutting-edge power of DALL-E 2.
There are three endpoints provided by OpenAI to interact with DALL-E 2:
- createImage
is the main endpoint that allows direct image generation from a text prompt. Here's an example on how to use the endpoint, along with the correlating output:
do {
let imageParam = ImageParameters(
// A text description of the desired image(s).
prompt: "An armchair in the shape of an avocado",
// The size of the generated images.
resolution: .large,
// The format in which the generated images are returned.
responseFormat: .base64Json
)
let result = try await openAi.createImage(
parameters: imageParam
)
let b64Image = result.data[0].image
let image = try openAi.decodeBase64Image(b64Image)
} catch {
// Insert your own error handling method here.
}
do {
let imageEditParam = try ImageEditParameters(
// The image to edit.
image: image,
// An additional image whose fully transparent areas indicate where image should be edited.
mask: mask,
// A text description of the desired image(s).
prompt: "The Mona Lisa wearing a beret, in the style of Leonardo DaVinci",
// The size of the generated images.
resolution: .large,
// The format in which the generated images are returned.
responseFormat: .base64Json
)
let imageResponse = try await openAI.generateImageEdits(
parameters: imageEditParam
)
let image = try openAI.decodeBase64Image(imageResponse.data[0].image)
} catch {
// Insert your own error handling method here.
}
Original | Mask | Edit |
- createImageVariation
allows the developer to create variations of a given input image. Here's an example on how to use the endpoint, along with the correlating output:
do {
let imageVariationParam = try ImageVariationParameters(
// The image to use as the basis for the variation(s).
image: image,
// The size of the generated images.
resolution: .large,
// The format in which the generated images are returned.
responseFormat: .base64Json
)
let variationResponse = try await openAI.generateImageVariations(
parameters: imageVariationParam
)
self.image = try openAI.decodeBase64Image(
variationResponse.data[0].image
)
} catch {
// Insert your own error handling method here.
}
Original | Variation |
ChatGPT, built on OpenAI's GPT-4 architecture, is a cutting-edge conversational AI model. It provides developers with a robust tool for integrating advanced natural language processing capabilities into applications. Using ChatGPT can enhance user interactions, improve efficiency, and offer AI-driven solutions in various use cases. Incorporate GPT-4's strength into your projects for tangible results.
There is a single endpoint for this feature, however, this SDK splits the endpoint into two functions with three separate features in total:
- generateChatCompletion
allows the developer to generate chat completions using the provided models from OpenAI; or the developer's owned fine tuned models. Here's an example on how to use the endpoint, along with the correlating output:
do {
let chat: [ChatMessage] = [
ChatMessage(role: .system, content: "You are a helpful assistant."),
ChatMessage(role: .user, content: "Who won the world series in 2020?"),
ChatMessage(role: .assistant, content: "The Los Angeles Dodgers won the World Series in 2020."),
ChatMessage(role: .user, content: "Where was it played?")
]
let chatParameters = ChatParameters(
model: .gpt4, // ID of the model to use.
messages: chat // A list of messages comprising the conversation so far.
)
let chatCompletion = try await openAI.generateChatCompletion(
parameters: chatParameters
)
if let message = chatCompletion.choices[0].message {
let content = message.content
}
} catch {
// Insert your own error handling method here.
}
ChatResponse(
id: "chatcmpl-88eG5VruffcNHPNVGBKGVAV5HGk4j",
object: OpenAIKit.OpenAIObject.chatCompletion,
created: 1697072069,
choices: [
OpenAIKit.ChatChoice(
message: Optional(
OpenAIKit.ChatMessage(
id: "250FDA2D-2F38-4E6F-B97E-DAD74FED1FB6",
role: OpenAIKit.ChatRole.assistant,
content: Optional(
"The 2020 World Series was played at Globe Life Field in Arlington, Texas."
),
functionCall: nil
)
),
delta: nil,
index: 0,
logprobs: nil,
finishReason: Optional("stop")
)
],
usage: Optional(
OpenAIKit.Usage(
promptTokens: 53,
completionTokens: 17,
totalTokens: 70
)
)
)
The developer is also able to use function calls to execute various functions (i.e., fetching weather info, uploading files, etc). Here's an example on how to use the parameter, the corresponding response, and example usage with a local function.
do {
let functions: [Function] = [
Function(
name: "getCurrentWeather",
description: "Get the current weather in a given location",
parameters: Parameters(
type: "object",
properties: [
"location": ParameterDetail(
type: "string",
description: "The city and state, e.g. San Francisco, CA"
),
"unit": ParameterDetail(
type: "string", enumValues: ["fahrenheit", "celsius"]
)
],
required: ["location"]
)
)
]
let messages: [ChatMessage] = [
ChatMessage(role: .user, content: "What's the weather like in Boston?")
]
let chatParameters = ChatParameters(
model: .gpt4, // ID of the model to use.
messages: messages, // A list of messages comprising the conversation so far.
functionCall: "auto", // Controls how the model calls functions.
functions: functions // A list of functions the model may generate JSON inputs for.
)
let chatCompletion = try await openAI.generateChatCompletion(
parameters: chatParameters
)
} catch {
// Insert your own error handling method here.
}
ChatResponse(
id: "chatcmpl-88eVjsHEPtDDiSEuCexsqO8iuhnfG",
object: OpenAIKit.OpenAIObject.chatCompletion,
created: 1697073039,
choices: [
OpenAIKit.ChatChoice(
message: Optional(
OpenAIKit.ChatMessage(
id: "DCE5EECB-9521-481D-9E75-C7FF9390E4CF",
role: OpenAIKit.ChatRole.assistant,
content: nil,
functionCall: Optional(
OpenAIKit.FunctionCall(
arguments: "{\n\"location\": \"Boston, MA\"\n}",
name: "getCurrentWeather"
)
)
)
),
delta: nil,
index: 0,
logprobs: nil,
finishReason: Optional("function_call")
)
],
usage: Optional(OpenAIKit.Usage(promptTokens: 81, completionTokens: 16, totalTokens: 97))
)
func getCurrentWeather(location: String, unit: TemperatureUnit = .fahrenheit) -> WeatherInfo {
return WeatherInfo(location: location, temperature: "72", unit: unit, forecast: ["sunny", "windy"])
}
if let message = chatCompletion.choices[0].message, let functionCall = message.functionCall {
let jsonString = functionCall.arguments
if let data = jsonString.data(using: .utf8) {
do {
if
let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
let location = json["location"] as? String
{
self.weatherInfo = self.getCurrentWeather(location: location)
}
} catch {
// Insert your own error handling method here.
}
}
}
- generateChatCompletionStreaming
allows the developr to stream chat completion data from the endpoint. Here's an example on how to use the endpoint, along with the correlating output:
do {
let chat: [ChatMessage] = [
ChatMessage(role: .system, content: "You are a helpful assistant."),
ChatMessage(role: .user, content: "Who won the world series in 2020?"),
ChatMessage(role: .assistant, content: "The Los Angeles Dodgers won the World Series in 2020."),
ChatMessage(role: .user, content: "Where was it played?")
]
let chatParameters = ChatParameters(model: .chatGPTTurbo, messages: chat)
let stream = try openAI.generateChatCompletionStreaming(
parameters: chatParameters
)
} catch {
// Insert your own error handling method here.
}
ChatResponse(
id: "chatcmpl-88enklY0vmc4fNkM1mJQCkzW6hcST",
object: OpenAIKit.OpenAIObject.chatCompletionChunk,
created: 1697074156,
choices: [
OpenAIKit.ChatChoice(
message: nil,
delta: Optional(
OpenAIKit.ChatDelta(
role: Optional(OpenAIKit.ChatRole.assistant),
content: Optional("")
)
),
index: 0,
logprobs: nil,
finishReason: nil
)
],
usage: nil
)
ChatResponse(
id: "chatcmpl-88enklY0vmc4fNkM1mJQCkzW6hcST",
object: OpenAIKit.OpenAIObject.chatCompletionChunk,
created: 1697074156,
choices: [
OpenAIKit.ChatChoice(
message: nil,
delta: Optional(
OpenAIKit.ChatDelta(
role: nil,
content: Optional("The")
)
),
index: 0,
logprobs: nil,
finishReason: nil
)
],
usage: nil
)
// ...
ChatResponse(
id: "chatcmpl-88enklY0vmc4fNkM1mJQCkzW6hcST",
object: OpenAIKit.OpenAIObject.chatCompletionChunk,
created: 1697074156,
choices: [
OpenAIKit.ChatChoice(
message: nil,
delta: Optional(
OpenAIKit.ChatDelta(
role: nil,
content: Optional(".")
)
),
index: 0,
logprobs: nil,
finishReason: nil
)
],
usage: nil
)
ChatResponse(
id: "chatcmpl-88enklY0vmc4fNkM1mJQCkzW6hcST",
object: OpenAIKit.OpenAIObject.chatCompletionChunk,
created: 1697074156,
choices: [
OpenAIKit.ChatChoice(
message: nil,
delta: Optional(
OpenAIKit.ChatDelta(
role: nil,
content: nil
)
),
index: 0,
logprobs: nil,
finishReason: Optional("stop")
)
],
usage: nil
)
Whisper is OpenAI's speech-to-text AI model, designed for accurate transcription of spoken content. By converting audio into text, it offers developers a straightforward tool for tasks like transcription services, voice commands, vocal language translations, or audio indexing. Implementing Whisper can help streamline processes, make applications more accessible, and leverage voice data efficiently.
There are the two main endpoints that use the Whisper model:
- createTranscription
is the main endpoint that allows developers to transcribe spoken audio into text. Here's an example on how to use the endpoint, and the corresponding returned item:
do {
let audioParameters = TranscriptionParameters(file: audio)
let transcriptionCompletion = try await openAI.createTranscription(parameters: audioParameters)
} catch {
// Insert your own error handling method here.
}