generated from StanfordBDHG/SwiftPackageTemplate
-
-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Update to Spezi 0.8.0 ## ⚙️ Release Notes - Small maintenance PR to update the Package to Spezi 0.8.0 ## 📝 Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md): - [x] I agree to follow the [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md).
- Loading branch information
1 parent
769ad38
commit b71b4a3
Showing
12 changed files
with
205 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// | ||
// This source file is part of the Stanford Spezi open source project | ||
// | ||
// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
import OpenAI | ||
@_exported import struct OpenAI.Model | ||
@_exported import struct OpenAI.ChatStreamResult | ||
import Foundation | ||
import Observation | ||
import SpeziSecureStorage | ||
|
||
|
||
/// View model responsible for to coordinate the interactions with the OpenAI GPT API. | ||
@Observable | ||
public class OpenAIModel { | ||
private enum Defaults { | ||
static let defaultModel: Model = .gpt3_5Turbo | ||
} | ||
|
||
|
||
private let secureStorage: SecureStorage | ||
|
||
|
||
/// The OpenAI GPT Model type that is used to interact with the OpenAI API | ||
public var openAIModel: String { | ||
get { | ||
access(keyPath: \.openAIModel) | ||
return UserDefaults.standard.value(forKey: OpenAIConstants.modelStorageKey) as? Model ?? Defaults.defaultModel | ||
} | ||
set { | ||
withMutation(keyPath: \.openAIModel) { | ||
UserDefaults.standard.set(newValue, forKey: OpenAIConstants.modelStorageKey) | ||
} | ||
} | ||
} | ||
|
||
/// The API token used to interact with the OpenAI API | ||
public var apiToken: String? { | ||
get { | ||
access(keyPath: \.apiToken) | ||
return try? secureStorage.retrieveCredentials(OpenAIConstants.credentialsUsername, server: OpenAIConstants.credentialsServer)?.password | ||
} | ||
set { | ||
withMutation(keyPath: \.apiToken) { | ||
if let newValue { | ||
try? secureStorage.store( | ||
credentials: Credentials(username: OpenAIConstants.credentialsUsername, password: newValue), | ||
server: OpenAIConstants.credentialsServer | ||
) | ||
} else { | ||
try? secureStorage.deleteCredentials(OpenAIConstants.credentialsUsername, server: OpenAIConstants.credentialsServer) | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
init(secureStorage: SecureStorage, apiToken defaultToken: String? = nil, openAIModel model: Model? = nil) { | ||
self.secureStorage = secureStorage | ||
|
||
if UserDefaults.standard.object(forKey: OpenAIConstants.modelStorageKey) == nil { | ||
self.openAIModel = model ?? Defaults.defaultModel | ||
} | ||
|
||
if let apiTokenFromStorage = try? secureStorage.retrieveCredentials( | ||
OpenAIConstants.credentialsUsername, | ||
server: OpenAIConstants.credentialsServer | ||
)?.password { | ||
self.apiToken = apiTokenFromStorage | ||
} else { | ||
self.apiToken = defaultToken | ||
} | ||
} | ||
|
||
|
||
/// Queries the OpenAI API using the provided messages. | ||
/// | ||
/// - Parameters: | ||
/// - chat: A collection of chat messages used in the conversation. | ||
/// - chatFunctionDeclaration: OpenAI functions that should be injected in the OpenAI query. | ||
/// | ||
/// - Returns: The content of the response from the API. | ||
public func queryAPI( | ||
withChat chat: [Chat], | ||
withFunction chatFunctionDeclaration: [ChatFunctionDeclaration] = [] | ||
) async throws -> AsyncThrowingStream<ChatStreamResult, Error> { | ||
guard let apiToken, !apiToken.isEmpty else { | ||
throw OpenAIError.noAPIToken | ||
} | ||
|
||
let functions = chatFunctionDeclaration.isEmpty ? nil : chatFunctionDeclaration | ||
|
||
let openAIClient = OpenAI(apiToken: apiToken) | ||
let query = ChatQuery(model: openAIModel, messages: chat, functions: functions) | ||
return openAIClient.chatsStream(query: query) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// | ||
// This source file is part of the Stanford Spezi open source project | ||
// | ||
// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
|
||
import OpenAI | ||
import Spezi | ||
import SpeziSecureStorage | ||
|
||
|
||
/// `OpenAIModule` is a module responsible for to coordinate the interactions with the OpenAI GPT API. | ||
public class OpenAIModule: Module, DefaultInitializable { | ||
@Module.Model private var model: OpenAIModel | ||
@Dependency private var secureStorage: SecureStorage | ||
|
||
|
||
private var defaultAPIToken: String? | ||
private var defaultOpenAIModel: Model? | ||
|
||
|
||
/// Initializes a new instance of `OpenAIGPT` with the specified API token and OpenAI model. | ||
/// | ||
/// - Parameters: | ||
/// - apiToken: The API token for the OpenAI API. | ||
/// - openAIModel: The OpenAI model to use for querying. | ||
public init(apiToken: String? = nil, openAIModel: Model? = nil) { | ||
defaultAPIToken = apiToken | ||
defaultOpenAIModel = openAIModel | ||
} | ||
|
||
public required convenience init() { | ||
self.init(apiToken: nil, openAIModel: nil) | ||
} | ||
|
||
|
||
public func configure() { | ||
self.model = OpenAIModel(secureStorage: secureStorage, apiToken: defaultAPIToken, openAIModel: defaultOpenAIModel) | ||
} | ||
} |
Oops, something went wrong.