Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Sources/BedrockServiceError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ public enum BedrockLibraryError: Error {
case .invalidSDKResponse(let message):
return "Invalid SDK response: \(message)"
case .invalidSDKResponseBody(let value):
return "Invalid SDK response body: \(String(describing: value))"
let valueAsString = value != nil ? String(data: value!, encoding: .utf8) ?? "" : "nil"
return "Invalid SDK response body: \(valueAsString)"
case .completionNotFound(let message):
return "Completion not found: \(message)"
case .encodingError(let message):
Expand Down
54 changes: 48 additions & 6 deletions Sources/Converse/Role.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@
@preconcurrency import AWSBedrockRuntime
import Foundation

public enum Role: String, Codable, Sendable {
case user
case assistant
public struct Role: Codable, Sendable, Equatable {
private enum RoleType: Codable, Sendable, Equatable {
case user
case assistant
}

private let type: RoleType

public init(from sdkConversationRole: BedrockRuntimeClientTypes.ConversationRole) throws {
switch sdkConversationRole {
case .user: self = .user
case .assistant: self = .assistant
case .user: self.type = .user
case .assistant: self.type = .assistant
case .sdkUnknown(let unknownRole):
throw BedrockLibraryError.notImplemented(
"Role \(unknownRole) is not implemented by BedrockRuntimeClientTypes"
Expand All @@ -32,9 +36,47 @@ public enum Role: String, Codable, Sendable {
}

public func getSDKConversationRole() -> BedrockRuntimeClientTypes.ConversationRole {
switch self {
switch self.type {
case .user: return .user
case .assistant: return .assistant
}
}

// custom encoding and decoding to handle string value with a "type" field
//
// "message":{
// "content":[
// {"text":"This is the textcompletion for: This is a test"}
// ],
// "role":"assistant"
// }},
//
public init(from decoder: any Decoder) throws {
let container = try decoder.singleValueContainer()
let role = try container.decode(String.self)
switch role {
case "user": self.type = .user
case "assistant": self.type = .assistant
default:
throw BedrockLibraryError.decodingError(
"Role \(role) is not a valid role"
)
}
}
public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()
switch self.type {
case .user: try container.encode("user")
case .assistant: try container.encode("assistant")
}
}
/// Returns the type of the role as a string.
public static func == (lhs: Role, rhs: Role) -> Bool {
lhs.type == rhs.type
}
private init(_ type: RoleType) {
self.type = type
}
public static let user = Role(.user)
public static let assistant = Role(.assistant)
}
12 changes: 7 additions & 5 deletions Tests/InvokeModel/TextGenerationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ extension BedrockServiceTests {
arguments: NovaTestConstants.textCompletionModels
)
func completeTextWithValidModel(model: BedrockModel) async throws {
let completion: TextCompletion = try await bedrock.completeText(
"This is a test",
with: model
)
#expect(completion.completion == "This is the textcompletion for: This is a test")
await #expect(throws: Never.self) {
let completion: TextCompletion = try await bedrock.completeText(
"This is a test",
with: model
)
#expect(completion.completion == "This is the textcompletion for: This is a test")
}
}

@Test(
Expand Down