目录
关于项目
OpenAIKit 是一个由社区驱动的 Swift SDK,旨在为 Swift 开发人员提供一种无缝、高效且符合 Swift 风格的方式来与 OpenAI REST 端点进行交互。我们的目标是降低 Swift 开发人员的使用门槛,使他们能够在不深入了解 RESTful 服务的情况下,将 OpenAI 的强大功能集成到他们的应用程序中。
动机
随着现代应用中对 AI 功能需求的增加,开发人员需要能够简化集成过程的工具。虽然 OpenAI 提供了一套令人难以置信的功能,但显然需要一个专门的 Swift SDK,以符合该语言的惯用实践和 Swift 开发人员社区的期望。
我们的愿景
我们设想了一个工具,不仅提供对 OpenAI 功能的原始访问,还通过清晰直观的 API 增强了开发人员的体验。我们最终的目标是通过为 Swift 社区提供正确的工具,轻松地将 AI 功能集成到其应用程序中,从而促进创新。
功能
- 使用 Dall-E 2 生成新的、编辑过的和变体图像(Dall-E 3 即将推出)。
- 使用 GPT-3 和 GPT-4 生成编辑和补全。
- 列出可用于 GPT-3 和 GPT-4 的模型。
- 获取 GPT-3 和 GPT-4 提示词的嵌入向量。
- 通过流式数据获取 GPT-3 和 GPT-4 的补全。
- 使用 ChatGPT 生成聊天响应。
- 查看和上传训练文件。
- 查看提示词是否被审核端点标记。
- 全面的单元和集成测试覆盖。
- 从 iOS 13、macOS 10.15、tvOS 13、watchOS 6 和 visionOS 1.0 兼容 Swift 并发。
- 完整的 OpenAIKit 文档。
要求
平台 | 最低 Swift 版本 | 安装 | 状态 |
---|---|---|---|
iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+ / visionOS 1.0+ | 5.7 | Swift 包管理器 | 完全测试 |
安装
Swift 包管理器
Swift 包管理器 使开发人员能够轻松将包集成到其 Xcode 项目和包中;此工具也已完全集成到 swift
编译器中。
通过 Xcode 项目使用 SPM
- 文件 > Swift 包 > 添加包依赖
- 添加
https://github.com/OpenDive/OpenAIKit.git
- 选择 "到下一个主要版本" 并选择 "2.0.1"
通过 Xcode 包使用 SPM
一旦你设置好你的 Swift 包,在 Package.swift
文件的 dependencies
值中添加 Git 链接。
dependencies: [
.package(url: "https://github.com/OpenDive/OpenAIKit.git", .upToNextMajor(from: "2.0.1"))
]
使用 OpenAIKit
获取 API 密钥
要获取 API 密钥,请访问您的账户页面上的 API Keys
页面 这里。
⚠️ 🔑 重要:不要将 OpenAI API 密钥直接存储在代码中! 🔑⚠️
使用 OpenAI 的 API 时,出于安全考虑,请勿将 API 密钥直接嵌入应用程序的代码库中。直接在源代码中嵌入密钥可能会将其暴露给未经授权的用户和恶意行为者,导致潜在的滥用。
最佳做法:
- 环境变量: 将您的 API 密钥存储在环境变量中,并在代码中访问它们。这样,它们就不会被硬编码到应用程序中,可以安全地管理。
- 密钥管理: 使用安全的密钥管理工具或服务来存储和检索您的 API 密钥。诸如 AWS Secrets Manager、HashiCorp Vault、Firebase、CloudKit 或 Azure Key Vault 等工具专门设计用于存储、管理和检索敏感数据。这样,用户就无法在设备上访问密钥。
- .gitignore: 如果您将 API 密钥存储在配置文件中,请确保始终将此文件添加到
.gitignore
或类似的机制中,以防止它被意外提交到源代码控制系统中。- 定期轮换密钥: 定期轮换 API 密钥以减轻泄漏的潜在影响。
记住,安全性至关重要。始终优先考虑安全处理类似 API 密钥的敏感信息!
想了解更多信息,请查看 这篇文章 ,它详细讲述了 Swift 开发人员如何管理 API 密钥。
图像
使用 OpenAI 提供的 DALL-E 2(即将推出 DALL-E 3)开始探索下一代 AI 驱动的图像生成技术。作为其前身的延续,DALL-E 2 提供了增强的能力,可以从文本提示生成复杂的视觉效果,在语言和图像之间创造出无缝的桥梁。开发人员可以利用这一突破性技术丰富用户体验,打造动态内容,激发新的创意。通过集成 DALL-E 2 的尖端技术来革新您的应用和项目。
OpenAI 提供了三个与 DALL-E 2 交互的终端:
- createImage
是主要的终端,可以根据文本提示直接生成图像。以下是如何使用该终端的示例,以及相应的输出:
do {
let imageParam = ImageParameters(
// 希望获得图像的文本描述。
prompt: "一个鳄梨形状的扶手椅",
// 生成图像的大小。
resolution: .large,
// 返回生成图像的格式。
responseFormat: .base64Json
)
let result = try await openAi.createImage(
parameters: imageParam
)
let b64Image = result.data[0].image
let image = try openAi.decodeBase64Image(b64Image)
} catch {
// 在这里插入您自己的错误处理方法。
}
- `createImageEdit` 允许开发人员根据输入的原始图像创建编辑版本,并添加一个启用了透明的图像,透明部分表示要编辑的区域,并提供一个描述所要编辑图像的提示词。以下是如何使用该终端的示例,以及相应的输出:
do {
let imageEditParam = try ImageEditParameters(
// 要编辑的图像。
image: image,
// 一个附加图像,其完全透明部分表示应在哪些地方进行编辑。
mask: mask,
// 希望获得图像的文本描述。
prompt: "戴着贝雷帽的蒙娜丽莎,风格像列奥纳多·达·芬奇",
// 生成图像的大小。
resolution: .large,
// 返回生成图像的格式。
responseFormat: .base64Json
)
let imageResponse = try await openAI.generateImageEdits(
parameters: imageEditParam
)
let image = try openAI.decodeBase64Image(imageResponse.data[0].image)
} catch {
// 在这里插入您自己的错误处理方法。
}
原图 | 遮罩 | 编辑后 |
createImageVariation
允许开发人员创建给定输入图像的变体。以下是如何使用该端点的示例,以及相应的输出:
do {
let imageVariationParam = try ImageVariationParameters(
// 用作变体基础的图像。
image: image,
// 生成图像的尺寸。
resolution: .large,
// 生成图像返回的格式。
responseFormat: .base64Json
)
let variationResponse = try await openAI.generateImageVariations(
parameters: imageVariationParam
)
self.image = try openAI.decodeBase64Image(
variationResponse.data[0].image
)
} catch {
// 在此处插入自己的错误处理方法。
}
原图 | 变体 |
聊天
ChatGPT 基于 OpenAI 的 GPT-4 架构,是一种尖端的会话 AI 模型。它为开发人员提供了一个强大的工具,用于将先进的自然语言处理能力集成到应用程序中。使用 ChatGPT 可以增强用户互动、提高效率,并在各种使用场景中提供 AI 驱动的解决方案。将 GPT-4 的强大功能融入您的项目中,以获得实实在在的成果。
此功能有一个单一的端点,但此 SDK 将端点分成两个函数,共三个独立的功能:
generateChatCompletion
允许开发人员使用 OpenAI 提供的模型或由开发人员自行调优的模型生成聊天完成。以下是如何使用该端点的示例以及相应的输出:
do {
let chat: [ChatMessage] = [
ChatMessage(role: .system, content: "你是一个乐于助人的助手。"),
ChatMessage(role: .user, content: "2020年世界大赛冠军是谁?"),
ChatMessage(role: .assistant, content: "洛杉矶道奇队赢得了2020年世界大赛。"),
ChatMessage(role: .user, content: "比赛在哪儿举行?")
]
let chatParameters = ChatParameters(
model: .gpt4, // 使用的模型ID。
messages: chat // 至今为止对话消息列表。
)
let chatCompletion = try await openAI.generateChatCompletion(
parameters: chatParameters
)
if let message = chatCompletion.choices[0].message {
let content = message.content
}
} catch {
// 在此处插入自己的错误处理方法。
}
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("2020年世界大赛在德克萨斯州阿灵顿的Globe Life Field球场举行。"),
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: "获取指定位置的当前天气",
parameters: Parameters(
type: "object",
properties: [
"location": ParameterDetail(
type: "string",
description: "城市和州,例如:旧金山,加州"
),
"unit": ParameterDetail(
type: "string",
enumValues: ["fahrenheit", "celsius"]
)
],
required: ["location"]
)
)
]
let messages: [ChatMessage] = [
ChatMessage(role: .user, content: "波士顿的天气如何?")
]
let chatParameters = ChatParameters(
model: .gpt4, // 使用的模型ID。
messages: messages, // 至今为止对话消息列表。
functionCall: "auto", // 控制模型如何调用函数。
functions: functions // 模型可能生成 JSON 输入的一系列函数。
)
let chatCompletion = try await openAI.generateChatCompletion(
parameters: chatParameters
)
} catch {
// 在此处插入自己的错误处理方法。
}
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\": \"波士顿,马萨诸塞州\"\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: ["晴朗", "有风"])
}
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 {
// 在此处插入自己的错误处理方法。
}
}
}
generateChatCompletionStreaming
允许开发人员从端点流式传输聊天完成数据。以下是如何使用该端点的示例以及相应的输出:
do {
let chat: [ChatMessage] = [
ChatMessage(role: .system, content: "你是一个乐于助人的助手。"),
ChatMessage(role: .user, content: "2020年世界大赛冠军是谁?"),
ChatMessage(role: .assistant, content: "洛杉矶道奇队赢得了2020年世界大赛。"),
ChatMessage(role: .user, content: "比赛在哪儿举行?")
]
let chatParameters = ChatParameters(model: .chatGPTTurbo, messages: chat)
let stream = try openAI.generateChatCompletionStreaming(
parameters: chatParameters
)
} catch {
// 在此处插入自己的错误处理方法。
}
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 {
// 在此处插入自己的错误处理方法。
}
从最深沉的睡眠中醒来,我们打破了某个梦的薄丝网。然而在一秒钟之后,那个网可能是如此脆弱,我们不记得我们曾经做过梦。从昏厥中复苏的过程中有两个阶段,首先是心理或精神上的感受,其次是身体存在的感受。似乎如果在达到第二阶段时,我们能回忆起第一阶段的印象,那么这些印象会在对彼岸的记忆中变得雄辩。那个彼岸是什么?我们至少应该如何区分它的阴影与坟墓的阴影?
createTranslation
是第二个端点,允许开发人员将任何非英语音频转换为转录英语文本。以下是如何使用该端点的示例,以及相应的返回项目:
do {
let audioParameters = TranscriptionParameters(file: audio)
let transcriptionCompletion = try await openAI.createTranslation(parameters: audioParameters)
} catch {
// 在这里插入你自己的错误处理方法。
}
在夜晚,当我失去理智,并且我痛苦、麻木和疲倦,想到一个久已忘却的美好和善良的教训,我的头开始摇晃,我突然听到滴答声,吓醒
了我。在这种天气里可能是谁?我想,是有人在这种天气里敲我的房门。就是这样,不多也不少。
工具
嵌入
嵌入使用 OpenAI 的 GPT 模型生成文本的密集向量表示。这些嵌入捕捉了语义信息,使开发人员能够执行相似性搜索、聚类或对特定任务进行微调等任务。通过将 GPT 嵌入集成到应用程序中,开发人员可以增强文本分析和检索能力,从而进行更有效的数据处理和洞察。
以下是如何使用它的示例,以及端点的预期输出:
do {
let embeddingsParam = EmbeddingsParameters(model: "text-similarity-ada-002", input: input)
self.embeddingsResponse = try await openAI.createEmbeddings(parameters: embeddingsParam)
} catch {
// 在这里插入你自己的错误处理方法。
}
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
)
)
模型
模型端点允许开发人员从 OpenAI 获取当前可用的模型以及他们自己微调的模型。
有两个端点可用于此功能:
listModels
获取对开发人员可用的所有模型的列表。以下是示例用法,以及相应的输出:
do {
let modelsResponse = try await openAi.listModels()
} catch {
// 在这里插入你自己的错误处理方法。
}
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 {
// 在这里插入你自己的错误处理方法。
}
OpenAIKit.Model(
id: "text-davinci-001",
object: OpenAIKit.OpenAIObject.model,
created: 1649364042,
ownedBy: "openai"
)
完成
⚠️ 完成 API 的弃用通知 ⚠️
截至2023年7月6日,OpenAI 已宣布弃用完成 API 中的旧模型,这些模型将于2024年初退役。强烈建议过渡到 Chat Completions API,它提供了更结构化的提示界面和多轮对话功能。Chat Completions API 已证明能够处理大多数以前的用例和新的对话需求,具有更高的灵活性和特异性,显著提升开发者体验。有关更多详细信息,请参阅官方公告。
从 1.x 迁移到 2.x
从 2.x 开始,Chat Completion Models 使用枚举来标记每个可用模型,用于默认模型的主要用途。以下是如何从使用旧的 ChatParameter
初始化器迁移到 2.x 初始化器的示例:
// ❌ 1.x 实现
let chatParameters = ChatParameters(model: "gpt4", messages: chat)
// ✅ 2.x 实现
let chatParameters = ChatParameters(model: .gpt4, messages: chat)
如果您需要用于微调模型的自定义字符串,请使用 customModel
参数:
// ✅ 2.x 实现用于自定义模型 ID
let chatParameters = ChatParameters(customModel: "INSERT-MODEL-ID", message: chat)
示例项目
(待定)
开发和测试
我们欢迎任何人通过发布问题来为项目做出贡献,如果他们在使用 OpenAIKit 时遇到任何错误/故障;也欢迎通过创建拉取请求来添加任何附加功能。
许可证
OpenAIKit 根据 MIT 许可证发布,任何使用 OpenAI 的 REST 端点的行为将遵循他们制定的使用政策。
在此授予获得该软件及其相关文档文件(“软件”)副本的任何人免费处理该软件的权限,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许向其提供软件的人员这样做,但须符合以下条件:
上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。
该软件按“原样”提供,不附带任何形式的明示或暗示担保,包括但不限于适销性、适用性和非侵权性的担保。在任何情况下,对于因软件或使用或其他处理软件而引起的任何索赔、损害或其他责任,作者或版权持有人概不负责,无论是在合同诉讼、侵权诉讼或其他诉讼中。