diff --git a/Sources/OpenAI/OpenAI.swift b/Sources/OpenAI/OpenAI.swift index 49715c8e..199e3eb3 100644 --- a/Sources/OpenAI/OpenAI.swift +++ b/Sources/OpenAI/OpenAI.swift @@ -100,6 +100,7 @@ final public class OpenAI: OpenAIProtocol { performRequest(request: JSONRequest(url: buildURL(path: .models), method: "GET"), completion: completion) } + @available(iOS 13.0, *) public func moderations(query: ModerationsQuery, completion: @escaping (Result) -> Void) { performRequest(request: JSONRequest(body: query, url: buildURL(path: .moderations)), completion: completion) } diff --git a/Sources/OpenAI/Public/Models/ModerationsResult.swift b/Sources/OpenAI/Public/Models/ModerationsResult.swift index 6413b043..a7c25aef 100644 --- a/Sources/OpenAI/Public/Models/ModerationsResult.swift +++ b/Sources/OpenAI/Public/Models/ModerationsResult.swift @@ -7,6 +7,7 @@ import Foundation +@available(iOS 13.0, *) public struct ModerationsResult: Codable, Equatable { public struct Moderation: Codable, Equatable { @@ -52,11 +53,6 @@ public struct ModerationsResult: Codable, Equatable { public func makeIterator() -> IndexingIterator<[(String, Bool)]> { return Mirror(reflecting: self).children.enumerated().map { (index, element) in -#if DEBUG - if #available(iOS 16.0, *) { - assert(element.label!.lowercased() == CodingKeys.allCases[index].stringValue.replacing(try! Regex("[/-]"), with: { _ in "" })) - } -#endif return (CodingKeys.allCases[index].stringValue, element.value) as! (String, Bool) }.makeIterator() } @@ -103,11 +99,6 @@ public struct ModerationsResult: Codable, Equatable { public func makeIterator() -> IndexingIterator<[(String, Bool)]> { return Mirror(reflecting: self).children.enumerated().map { (index, element) in -#if DEBUG - if #available(iOS 16.0, *) { - assert(element.label!.lowercased() == CodingKeys.allCases[index].stringValue.replacing(try! Regex("[/-]"), with: { _ in "" })) - } -#endif return (CodingKeys.allCases[index].stringValue, element.value) as! (String, Bool) }.makeIterator() } @@ -132,4 +123,5 @@ public struct ModerationsResult: Codable, Equatable { public let results: [Self.Moderation] } +@available(iOS 13.0, *) extension ModerationsResult: Identifiable {} diff --git a/Sources/OpenAI/Public/Protocols/OpenAIProtocol.swift b/Sources/OpenAI/Public/Protocols/OpenAIProtocol.swift index 8c65b190..e7cb1aa0 100644 --- a/Sources/OpenAI/Public/Protocols/OpenAIProtocol.swift +++ b/Sources/OpenAI/Public/Protocols/OpenAIProtocol.swift @@ -211,6 +211,7 @@ public protocol OpenAIProtocol { - query: A `ModerationsQuery` object containing the input parameters for the API request. This includes the input text and optionally the model to be used. - completion: A closure which receives the result when the API request finishes. The closure's parameter, `Result`, will contain either the `ModerationsResult` object with the list of category results, or an error if the request failed. **/ + @available(iOS 13.0, *) func moderations(query: ModerationsQuery, completion: @escaping (Result) -> Void) /** diff --git a/Tests/OpenAITests/OpenAITests.swift b/Tests/OpenAITests/OpenAITests.swift index 25ed4f6e..b98c3caa 100644 --- a/Tests/OpenAITests/OpenAITests.swift +++ b/Tests/OpenAITests/OpenAITests.swift @@ -254,7 +254,21 @@ class OpenAITests: XCTestCase { let result = try await openAI.moderations(query: query) XCTAssertEqual(result, moderationsResult) } - + + func testModerationsIterable() { + let categories = ModerationsResult.Moderation.Categories(harassment: false, harassmentThreatening: false, hate: false, hateThreatening: false, selfHarm: false, selfHarmIntent: false, selfHarmInstructions: false, sexual: false, sexualMinors: false, violence: false, violenceGraphic: false) + Mirror(reflecting: categories).children.enumerated().forEach { index, element in + let label = ModerationsResult.Moderation.Categories.CodingKeys.allCases[index].stringValue.replacing(try! Regex("[/-]"), with: { _ in "" }) + XCTAssertEqual(label, element.label!.lowercased()) + } + + let categoryScores = ModerationsResult.Moderation.CategoryScores(harassment: 0.1, harassmentThreatening: 0.1, hate: 0.1, hateThreatening: 0.1, selfHarm: 0.1, selfHarmIntent: 0.1, selfHarmInstructions: 0.1, sexual: 0.1, sexualMinors: 0.1, violence: 0.1, violenceGraphic: 0.1) + Mirror(reflecting: categoryScores).children.enumerated().forEach { index, element in + let label = ModerationsResult.Moderation.CategoryScores.CodingKeys.allCases[index].stringValue.replacing(try! Regex("[/-]"), with: { _ in "" }) + XCTAssertEqual(label, element.label!.lowercased()) + } + } + func testModerationsError() async throws { let query = ModerationsQuery(input: "Hello, world!") let inError = APIError(message: "foo", type: "bar", param: "baz", code: "100")