From dbcdda9b6249a45ad1b128b902ca72ac784be075 Mon Sep 17 00:00:00 2001
From: Antonio War <59933379+antonio-war@users.noreply.github.com>
Date: Sat, 27 Apr 2024 15:30:03 +0200
Subject: [PATCH 1/3] fix: SwiftyGPTChatResponse decoding
---
.../xcshareddata/xcschemes/SwiftyGPT.xcscheme | 12 +++++++++++
.../Models/SwiftyGPTChatResponseChoice.swift | 13 ++++++++++++
.../Managers/SwiftyGPTChatManagerTests.swift | 2 +-
.../SwiftyGPTChatMockServiceTests.swift | 2 +-
.../SwiftyGPTChatNetworkingServiceTests.swift | 20 ++++++++++++++++++-
5 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/SwiftyGPT.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/SwiftyGPT.xcscheme
index 00140a4..7b93329 100644
--- a/.swiftpm/xcode/xcshareddata/xcschemes/SwiftyGPT.xcscheme
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/SwiftyGPT.xcscheme
@@ -62,6 +62,18 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
+
+
+
+
+
+
Date: Sat, 27 Apr 2024 15:50:06 +0200
Subject: [PATCH 2/3] feat: create SwiftyGPTChatResponseError
---
.../xcode/xcshareddata/xcschemes/SwiftyGPT.xcscheme | 2 +-
.../Models/SwiftyGPTChatResponseBody.swift | 1 +
.../Models/SwiftyGPTChatResponseError.swift | 13 +++++++++++++
.../SwiftyGPTChatNetworkingServiceTests.swift | 1 +
4 files changed, 16 insertions(+), 1 deletion(-)
create mode 100644 Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseError.swift
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/SwiftyGPT.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/SwiftyGPT.xcscheme
index 7b93329..cea53fd 100644
--- a/.swiftpm/xcode/xcshareddata/xcschemes/SwiftyGPT.xcscheme
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/SwiftyGPT.xcscheme
@@ -69,7 +69,7 @@
isEnabled = "YES">
diff --git a/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseBody.swift b/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseBody.swift
index c3e72ec..edc26ba 100644
--- a/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseBody.swift
+++ b/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseBody.swift
@@ -30,4 +30,5 @@ public struct SwiftyGPTChatResponseSuccessBody: SwiftyGPTChatResponseBody, Ident
}
public struct SwiftyGPTChatResponseFailureBody: SwiftyGPTChatResponseBody, Decodable {
+ let error: SwiftyGPTChatResponseError
}
diff --git a/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseError.swift b/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseError.swift
new file mode 100644
index 0000000..611ce8e
--- /dev/null
+++ b/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseError.swift
@@ -0,0 +1,13 @@
+//
+// SwiftyGPTChatResponseError.swift
+//
+//
+// Created by Antonio Guerra on 27/04/24.
+//
+
+import Foundation
+
+struct SwiftyGPTChatResponseError: Decodable, Equatable {
+ let type: String
+ let message: String
+}
diff --git a/Tests/SwiftyGPTChatTests/Services/SwiftyGPTChatNetworkingServiceTests.swift b/Tests/SwiftyGPTChatTests/Services/SwiftyGPTChatNetworkingServiceTests.swift
index cb8473c..c5a621e 100644
--- a/Tests/SwiftyGPTChatTests/Services/SwiftyGPTChatNetworkingServiceTests.swift
+++ b/Tests/SwiftyGPTChatTests/Services/SwiftyGPTChatNetworkingServiceTests.swift
@@ -37,5 +37,6 @@ final class SwiftyGPTChatNetworkingServiceTests: XCTestCase {
let requestBody = SwiftyGPTChatRequestBody(messages: [SwiftyGPTChatUserMessage(content: "Hello world!")], model: .gpt3_5_turbo, n: 1)
let responseBody = try await service.request(body: requestBody)
let failureBody = try XCTUnwrap(responseBody as? SwiftyGPTChatResponseFailureBody)
+ XCTAssertEqual(failureBody.error.type, "invalid_request_error")
}
}
From 059c8488d95e8af4eadc4dd1e11e2fa812ade7ce Mon Sep 17 00:00:00 2001
From: Antonio War <59933379+antonio-war@users.noreply.github.com>
Date: Sat, 27 Apr 2024 17:00:52 +0200
Subject: [PATCH 3/3] feat: add SwiftyGPTChatResponseTests
---
.../Models/SwiftyGPTChatResponseChoice.swift | 6 +
.../SwiftyGPTChatResponseFinishReason.swift | 2 +-
.../SwiftyGPTChatResponseChoiceTests.swift | 146 ++++++++++++++++++
.../Models/SwiftyGPTChatResponseTests.swift | 19 +++
4 files changed, 172 insertions(+), 1 deletion(-)
create mode 100644 Tests/SwiftyGPTChatTests/Models/SwiftyGPTChatResponseChoiceTests.swift
diff --git a/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseChoice.swift b/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseChoice.swift
index 0bc5b65..1236b6e 100644
--- a/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseChoice.swift
+++ b/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseChoice.swift
@@ -25,6 +25,12 @@ public struct SwiftyGPTChatResponseChoice: Decodable, Equatable {
}
}
+ init(index: Int, codableMessage: SwiftyGPTChatCodableMessage, finishReason: SwiftyGPTChatResponseFinishReason) {
+ self.index = index
+ self.codableMessage = codableMessage
+ self.finishReason = finishReason
+ }
+
public init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.index = try container.decode(Int.self, forKey: .index)
diff --git a/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseFinishReason.swift b/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseFinishReason.swift
index a78df4c..50974f7 100644
--- a/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseFinishReason.swift
+++ b/Sources/SwiftyGPTChat/Models/SwiftyGPTChatResponseFinishReason.swift
@@ -7,7 +7,7 @@
import Foundation
-enum SwiftyGPTChatResponseFinishReason: String, Decodable {
+public enum SwiftyGPTChatResponseFinishReason: String, Decodable {
case stop
case lenght
case contentFilter = "content_filter"
diff --git a/Tests/SwiftyGPTChatTests/Models/SwiftyGPTChatResponseChoiceTests.swift b/Tests/SwiftyGPTChatTests/Models/SwiftyGPTChatResponseChoiceTests.swift
new file mode 100644
index 0000000..7f767dd
--- /dev/null
+++ b/Tests/SwiftyGPTChatTests/Models/SwiftyGPTChatResponseChoiceTests.swift
@@ -0,0 +1,146 @@
+//
+// SwiftyGPTChatResponseChoiceTests.swift
+//
+//
+// Created by Antonio Guerra on 27/04/24.
+//
+
+import XCTest
+@testable import SwiftyGPTChat
+
+final class SwiftyGPTChatResponseChoiceTests: XCTestCase {
+
+ var decoder: JSONDecoder!
+
+ override func setUpWithError() throws {
+ self.decoder = JSONDecoder()
+ }
+
+ override func tearDownWithError() throws {
+ self.decoder = nil
+ }
+
+ func testInitWhenMessageIsSystem() throws {
+ let message = SwiftyGPTChatSystemMessage(content: "test")
+ let choice = SwiftyGPTChatResponseChoice(index: 0, codableMessage: .system(message), finishReason: .stop)
+ let systemMessage = try XCTUnwrap(choice.message as? SwiftyGPTChatSystemMessage)
+ XCTAssertEqual(choice.index, 0)
+ XCTAssertEqual(choice.codableMessage, .system(message))
+ XCTAssertEqual(systemMessage, message)
+ XCTAssertEqual(choice.finishReason, .stop)
+ }
+
+ func testDecodeWhenMessageIsSystem() throws {
+ let json = """
+ {
+ "index": 0,
+ "message": {
+ "role": "system",
+ "content": "test"
+ },
+ "finish_reason": "stop"
+ }
+ """
+ let data = try XCTUnwrap(json.data(using: .utf8))
+ let choice = try decoder.decode(SwiftyGPTChatResponseChoice.self, from: data)
+ let message = SwiftyGPTChatSystemMessage(content: "test")
+ XCTAssertEqual(choice.index, 0)
+ XCTAssertEqual(choice.codableMessage, .system(message))
+ let systemMessage = try XCTUnwrap(choice.message as? SwiftyGPTChatSystemMessage)
+ XCTAssertEqual(systemMessage, message)
+ XCTAssertEqual(choice.finishReason, .stop)
+ }
+
+ func testInitWhenMessageIsAssistant() throws {
+ let message = SwiftyGPTChatAssistantMessage(content: "test")
+ let choice = SwiftyGPTChatResponseChoice(index: 0, codableMessage: .assistant(message), finishReason: .stop)
+ let assistantMessage = try XCTUnwrap(choice.message as? SwiftyGPTChatAssistantMessage)
+ XCTAssertEqual(choice.index, 0)
+ XCTAssertEqual(choice.codableMessage, .assistant(message))
+ XCTAssertEqual(assistantMessage, message)
+ XCTAssertEqual(choice.finishReason, .stop)
+ }
+
+ func testDecodeWhenMessageIsAssistant() throws {
+ let json = """
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": "test"
+ },
+ "finish_reason": "stop"
+ }
+ """
+ let data = try XCTUnwrap(json.data(using: .utf8))
+ let choice = try decoder.decode(SwiftyGPTChatResponseChoice.self, from: data)
+ let message = SwiftyGPTChatAssistantMessage(content: "test")
+ XCTAssertEqual(choice.index, 0)
+ XCTAssertEqual(choice.codableMessage, .assistant(message))
+ let assistantMessage = try XCTUnwrap(choice.message as? SwiftyGPTChatAssistantMessage)
+ XCTAssertEqual(assistantMessage, message)
+ XCTAssertEqual(choice.finishReason, .stop)
+ }
+
+ func testInitWhenMessageIsUser() throws {
+ let message = SwiftyGPTChatUserMessage(content: "test")
+ let choice = SwiftyGPTChatResponseChoice(index: 0, codableMessage: .user(message), finishReason: .stop)
+ let userMessage = try XCTUnwrap(choice.message as? SwiftyGPTChatUserMessage)
+ XCTAssertEqual(choice.index, 0)
+ XCTAssertEqual(choice.codableMessage, .user(message))
+ XCTAssertEqual(userMessage, message)
+ XCTAssertEqual(choice.finishReason, .stop)
+ }
+
+ func testDecodeWhenMessageIsUser() throws {
+ let json = """
+ {
+ "index": 0,
+ "message": {
+ "role": "user",
+ "content": "test"
+ },
+ "finish_reason": "stop"
+ }
+ """
+ let data = try XCTUnwrap(json.data(using: .utf8))
+ let choice = try decoder.decode(SwiftyGPTChatResponseChoice.self, from: data)
+ let message = SwiftyGPTChatUserMessage(content: "test")
+ XCTAssertEqual(choice.index, 0)
+ XCTAssertEqual(choice.codableMessage, .user(message))
+ let userMessage = try XCTUnwrap(choice.message as? SwiftyGPTChatUserMessage)
+ XCTAssertEqual(userMessage, message)
+ XCTAssertEqual(choice.finishReason, .stop)
+ }
+
+ func testInitWhenMessageIsTool() throws {
+ let message = SwiftyGPTChatToolMessage(content: "test")
+ let choice = SwiftyGPTChatResponseChoice(index: 0, codableMessage: .tool(message), finishReason: .stop)
+ let toolMessage = try XCTUnwrap(choice.message as? SwiftyGPTChatToolMessage)
+ XCTAssertEqual(choice.index, 0)
+ XCTAssertEqual(choice.codableMessage, .tool(message))
+ XCTAssertEqual(toolMessage, message)
+ XCTAssertEqual(choice.finishReason, .stop)
+ }
+
+ func testDecodeWhenMessageIsTool() throws {
+ let json = """
+ {
+ "index": 0,
+ "message": {
+ "role": "tool",
+ "content": "test"
+ },
+ "finish_reason": "stop"
+ }
+ """
+ let data = try XCTUnwrap(json.data(using: .utf8))
+ let choice = try decoder.decode(SwiftyGPTChatResponseChoice.self, from: data)
+ let message = SwiftyGPTChatToolMessage(content: "test")
+ XCTAssertEqual(choice.index, 0)
+ XCTAssertEqual(choice.codableMessage, .tool(message))
+ let toolMessage = try XCTUnwrap(choice.message as? SwiftyGPTChatToolMessage)
+ XCTAssertEqual(toolMessage, message)
+ XCTAssertEqual(choice.finishReason, .stop)
+ }
+}
diff --git a/Tests/SwiftyGPTChatTests/Models/SwiftyGPTChatResponseTests.swift b/Tests/SwiftyGPTChatTests/Models/SwiftyGPTChatResponseTests.swift
index 8a96071..2f21c52 100644
--- a/Tests/SwiftyGPTChatTests/Models/SwiftyGPTChatResponseTests.swift
+++ b/Tests/SwiftyGPTChatTests/Models/SwiftyGPTChatResponseTests.swift
@@ -9,5 +9,24 @@
import XCTest
final class SwiftyGPTChatResponseTests: XCTestCase {
+
+ func testInitWhenBodyIsSuccess() throws {
+ let body = SwiftyGPTChatResponseSuccessBody(id: "Test", choices: [], created: 0.0, model: .gpt3_5_turbo, fingerprint: "Test", object: .completion, usage: SwiftyGPTChatResponseTokenUsage(completion: 0, prompt: 0, total: 0))
+ let response = try SwiftyGPTChatResponse(body: body)
+ XCTAssertEqual(response, .success(body: body))
+ }
+
+ func testInitWhenBodyIsFailure() throws {
+ let body = SwiftyGPTChatResponseFailureBody(error: SwiftyGPTChatResponseError(type: "Test", message: "Test"))
+ let response = try SwiftyGPTChatResponse(body: body)
+ XCTAssertEqual(response, .failure(body: body))
+ }
+
+ func testInitWhenBodyIsUnknown() throws {
+ let body = SwiftyGPTChatResponseUnknownBody()
+ XCTAssertThrowsError(try SwiftyGPTChatResponse(body: body))
+ }
+
+ struct SwiftyGPTChatResponseUnknownBody: SwiftyGPTChatResponseBody {}
}