OpenAIKit 是一个由社区驱动的 Swift SDK,旨在为 Swift 开发者提供一种无缝、高效且符合 Swift 习惯的方式来与 OpenAI REST 端点交互。我们的目标是降低 Swift 开发者的门槛,使他们能够在无需深入研究 RESTful 服务复杂性的情况下,将 OpenAI 的强大功能集成到他们的应用程序中。
随着现代应用程序中对 AI 驱动功能的需求不断增长,开发者必须能够访问简化集成过程的工具。虽然 OpenAI 提供了一套令人难以置信的功能,但显然需要一个专用的 Swift SDK,该 SDK 与该语言的惯用实践和 Swift 开发者社区的期望保持一致。
我们设想了一个工具,它不仅提供对 OpenAI 功能的原始访问权限,而且还通过清晰直观的 API 增强开发人员的体验。我们的最终目标是通过为 Swift 社区提供合适的工具,将 AI 功能轻松集成到他们的应用程序中,从而促进创新。
平台 | 最低 Swift 版本 | 安装 | 状态 |
---|---|---|---|
iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+ / visionOS 1.0+ | 5.7 | Swift 包管理器 | 完全测试 |
Swift 包管理器允许开发人员轻松地将包集成到他们的 Xcode 项目和包中;并且也完全集成到 swift
编译器中。
https://github.com/OpenDive/OpenAIKit.git
设置好 Swift 包后,将 Git 链接添加到 Package.swift
文件的 dependencies
值中。
dependencies: [
.package(url: "https://github.com/OpenDive/OpenAIKit.git", .upToNextMajor(from: "2.0.1"))
]
要获取 API 密钥,请转到您的帐户页面上的 API Keys
页面此处。
在使用 OpenAI 的 API 时,出于安全原因,至关重要的是不要将您的 API 密钥直接嵌入到应用程序的代码库中。将密钥直接嵌入到源代码中可能会将它们暴露给未经授权的用户和恶意行为者,从而导致潜在的滥用。
最佳实践
- 环境变量:将您的 API 密钥存储在环境变量中,并在您的代码中访问它们。这样,它们就不会被硬编码到您的应用程序中,并且可以安全地管理。
- 密钥管理:使用安全的密钥管理工具或服务来存储和检索您的 API 密钥。AWS Secrets Manager、HashiCorp Vault、Firebase、CloudKit 或 Azure Key Vault 等工具旨在存储、管理和检索敏感数据。 这样,用户就无法在设备上访问密钥。
- .gitignore:如果您将 API 密钥存储在配置文件中,请始终确保将此文件添加到
.gitignore
或类似的机制中,以防止它被意外提交到源代码控制系统。- 定期轮换密钥:定期轮换您的 API 密钥,以减轻泄漏的潜在影响。
请记住,安全性至关重要。始终优先考虑安全处理 API 密钥等敏感信息!
有关更多信息,请查看 这篇文章,了解 Swift 开发人员的 API 密钥管理。
使用 DALL-E 2(以及即将推出的 DALL-E 3)深入了解 AI 驱动的图像生成的下一个发展阶段,由 OpenAI 提供。DALL-E 2 在其前身的基础上构建,提供了增强的功能,可以从文本提示中实现复杂的视觉效果,从而在语言和图像之间架起无缝桥梁。开发人员可以利用这项突破性技术来丰富用户体验、创建动态内容并激发新的创造途径。通过集成 DALL-E 2 的尖端力量,彻底改变您的应用程序和项目。
OpenAI 提供了三个端点来与 DALL-E 2 交互:- createImage
是主要端点,允许直接从文本提示生成图像。这是一个关于如何使用该端点的示例,以及相关的输出
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.
}
![]() |
![]() |
![]() |
---|---|---|
原始 | 遮罩 | 编辑 |
- createImageVariation
允许开发人员创建给定输入图像的变体。这是一个关于如何使用该端点的示例,以及相关的输出
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.
}
![]() |
![]() |
---|---|
原始 | 变体 |
ChatGPT 基于 OpenAI 的 GPT-4 架构构建,是一种尖端的对话式 AI 模型。它为开发人员提供了一个强大的工具,用于将高级自然语言处理能力集成到应用程序中。使用 ChatGPT 可以增强用户交互、提高效率,并在各种用例中提供 AI 驱动的解决方案。将 GPT-4 的强大功能融入您的项目中,以获得切实的成果。
此功能只有一个端点,但是,此 SDK 将该端点分为两个函数,总共有三个单独的功能:- generateChatCompletion
允许开发人员使用 OpenAI 提供的模型生成聊天补全;或者开发人员拥有的微调模型。这是一个关于如何使用该端点的示例,以及相关的输出
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
)
)
)
开发人员还可以使用函数调用来执行各种函数(即,获取天气信息、上传文件等)。这是一个关于如何使用该参数、相应的响应以及使用本地函数的示例。
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
允许开发人员从端点流式传输聊天补全数据。这是一个关于如何使用该端点的示例,以及相关的输出
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 是 OpenAI 的语音转文本 AI 模型,专为准确转录口语内容而设计。通过将音频转换为文本,它为开发人员提供了用于转录服务、语音命令、语音语言翻译或音频索引等任务的简单工具。实施 Whisper 可以帮助简化流程、使应用程序更易于访问并高效地利用语音数据。
以下是使用 Whisper 模型的两个主要端点:- createTranscription
是主要端点,允许开发人员将口语音频转录为文本。这是一个关于如何使用该端点的示例,以及相应的返回项
do {
let audioParameters = TranscriptionParameters(file: audio)
let transcriptionCompletion = try await openAI.createTranscription(parameters: audioParameters)
} catch {
// Insert your own error handling method here.
}
Arousing from the most profound of slumbers, we break the gossamer web of some dream. Yet in a second afterward, so frail may that web have been, we remember not that we have dreamed. In the return to life
from the swoon there are two stages, first, that of the sense of mental or spiritual, secondly, that of the sense of physical existence. It seems probable that if, upon reaching the second stage, we could
recall the impressions of the first, we should find these impressions eloquent in memories of the gulf beyond. And that gulf is what? How at least shall we distinguish its shadows from those of the tomb?
- createTranslation
是第二个端点,允许开发人员将任何非英语音频翻译成转录的英语文本。这是一个关于如何使用该端点的示例,以及相应的返回项
do {
let audioParameters = TranscriptionParameters(file: audio)
let transcriptionCompletion = try await openAI.createTranslation(parameters: audioParameters)
} catch {
// Insert your own error handling method here.
}
In the night, when I was out of my mind, and I, pained, numb and tired, thought about the beauty and goodness of a long-forgotten lesson, and my head began to shake, I suddenly heard something tick that scared
me out of my sleep. Who could it be in that weather? A visitor is knocking, I thought, at my room in that weather. That's all it is, and nothing more.
嵌入利用 OpenAI 的 GPT 模型来生成文本的密集向量表示。这些嵌入捕获语义信息,使开发人员能够执行诸如相似性搜索、聚类或在特定任务上进行微调等任务。通过将 GPT 嵌入集成到应用程序中,开发人员可以增强文本分析和检索能力,从而实现更有效的数据处理和见解。
这是一个关于如何使用它以及端点的预期输出的示例
do {
let embeddingsParam = EmbeddingsParameters(model: "text-similarity-ada-002", input: input)
self.embeddingsResponse = try await openAI.createEmbeddings(parameters: embeddingsParam)
} catch {
// Insert your own error handling method here.
}
OpenAIKit.EmbeddingsResponse(
object: OpenAIKit.OpenAIObject.list,
data: [
OpenAIKit.EmbeddingsData(
object: OpenAIKit.OpenAIObject.embedding,
embedding: [
0.0028667077,
0.018867997,
-0.030135695,
// ...
-0.004177677,
-0.015615467,
-0.008131327
],
index: 0
)
],
model: "text-similarity-ada:002",
usage: OpenAIKit.EmbeddingsUsage(
promptTokens: 8,
totalTokens: 8
)
)
models 端点允许开发人员从 OpenAI 获取当前可用的模型,以及他们自己的微调模型。
有两个端点可用于此功能
listModels
获取开发人员可用的所有模型列表。这是一个示例用法,以及相应的输出do {
let modelsResponse = try await openAi.listModels()
} catch {
// Insert your own error handling method here.
}
ListModelResponse(
object: OpenAIKit.OpenAIObject.list,
data: [
OpenAIKit.Model(
id: "text-search-babbage-doc-001",
object: OpenAIKit.OpenAIObject.model,
created: 1651172509,
ownedBy: "openai-dev"
),
OpenAIKit.Model(
id: "curie-search-query",
object: OpenAIKit.OpenAIObject.model,
created: 1651172509,
ownedBy: "openai-dev"
),
OpenAIKit.Model(
id: "text-search-babbage-query-001",
object: OpenAIKit.OpenAIObject.model,
created: 1651172509,
ownedBy: "openai-dev"
),
OpenAIKit.Model(
id: "babbage",
object: OpenAIKit.OpenAIObject.model,
created: 1649358449,
ownedBy: "openai"
),
OpenAIKit.Model(
id: "gpt-3.5-turbo-instruct-0914",
object: OpenAIKit.OpenAIObject.model,
created: 1694122472,
ownedBy: "system"
)
// ...
]
)
retrieveModels
获取单个模型,给定输入模型的 ID。这是一个示例用法,以及相应的输出do {
let model = try await openAI.retrieveModel(modelId: "text-davinci-001")
} catch {
// Insert your own error handling method here.
}
OpenAIKit.Model(
id: "text-davinci-001",
object: OpenAIKit.OpenAIObject.model,
created: 1649364042,
ownedBy: "openai"
)
截至 2023 年 7 月 6 日,OpenAI 宣布弃用 Completions API 中较旧的模型,这些模型将于 2024 年初停用。强烈建议过渡到 Chat Completions API,该 API 提供了更结构化的提示界面和多轮对话功能。事实证明,Chat Completions API 可以处理绝大多数先前的用例和新的对话需求,具有更高的灵活性和针对性,从而显着增强了开发人员的体验。有关更多详细信息,请参阅官方公告。
从 2.x 开始,Chat Completion Models 使用枚举来标记每个可用的模型,以用于默认模型的主要用法。这是一个关于如何从使用旧的 ChatParameter
初始化程序迁移到 2.x 初始化程序的示例
// ❌ 1.x implementation
let chatParameters = ChatParameters(model: "gpt4", messages: chat)
// ✅ 2.x implementation
let chatParameters = ChatParameters(model: .gpt4, messages: chat)
如果您需要用于微调模型的自定义字符串,请使用 customModel
参数
// ✅ 2.x implementation for custom model IDs
let chatParameters = ChatParameters(customModel: "INSERT-MODEL-ID", message: chat)
(待定)
我们欢迎任何人通过发布问题来为该项目做出贡献,如果他们在在使用 OpenAIKit 时遇到任何错误/故障;以及通过创建拉取请求,将任何其他功能添加到 OpenAIKit。
OpenAIKit 在 MIT 许可证下发布,并且对 OpenAI REST 端点的任何使用都将受到他们设置的使用政策的约束。
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.