Skip to content

Commit 69e2fc0

Browse files
committed
fix: messages structure
1 parent a9ddfa0 commit 69e2fc0

File tree

8 files changed

+126
-80
lines changed

8 files changed

+126
-80
lines changed

Sources/CompilerSwiftAI/Model Calling/ChatHistory.swift

Lines changed: 0 additions & 45 deletions
This file was deleted.

Sources/CompilerSwiftAI/Model Calling/Client/CompilerClient+ModelCalling.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import OSLog
44

55
extension CompilerClient {
66
func makeModelCallWithResponse(
7-
using metadata: ModelMetadata,
87
request: CompletionRequestDTO
98
) async throws -> ChatCompletionResponse {
109
let endpoint = "\(baseURL)/v1/apps/\(appID)/end-users/model-call"

Sources/CompilerSwiftAI/Model Calling/Client/CompilerClient+Streaming.swift

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,8 @@ extension CompilerClient {
1111

1212
// Specialized String streaming version
1313
func makeStreamingModelCall(
14-
using metadata: ModelMetadata,
1514
request: CompletionRequestDTO
1615
) -> AsyncThrowingStream<ChatCompletionChunk, Error> {
17-
guard streamingProviders.contains(metadata.provider) else {
18-
return AsyncThrowingStream {
19-
$0.finish(
20-
throwing: AuthError.serverError(
21-
"Only \(streamingProviders.map { $0.rawValue }.joined(separator: ", ")) support streaming"
22-
)
23-
)
24-
}
25-
}
26-
2716
modelLogger.debug("Starting streaming model call")
2817

2918
// Prepare request URL and headers

Sources/CompilerSwiftAI/Model Calling/Client/CompilerClient.swift

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,8 @@ public final actor CompilerClient {
6868
/// - request: The completion request configuration
6969
/// - model: The model configuration to use
7070
/// - Returns: The complete model response including tokens used, finish reason, etc.
71-
public func generateText(
72-
request: CompletionRequest,
73-
using model: StreamConfiguration
74-
) async throws -> ChatCompletionResponse {
71+
public func generateText(request: CompletionRequest) async throws -> ChatCompletionResponse {
7572
try await makeModelCallWithResponse(
76-
using: model.metadata,
7773
request: request.toDTO(stream: false)
7874
)
7975
}
@@ -83,11 +79,8 @@ public final actor CompilerClient {
8379
/// - request: The completion request configuration
8480
/// - model: The model configuration to use
8581
/// - Returns: An async stream of response chunks with metadata
86-
public func streamText(
87-
request: CompletionRequest,
88-
using model: StreamConfiguration
89-
) async -> AsyncThrowingStream<ChatCompletionChunk, Error> {
90-
makeStreamingModelCall(using: model.metadata, request: request.toDTO(stream: true))
82+
public func streamText(request: CompletionRequest) async -> AsyncThrowingStream<ChatCompletionChunk, Error> {
83+
makeStreamingModelCall( request: request.toDTO(stream: true))
9184
}
9285
}
9386

Sources/CompilerSwiftAI/Model Calling/Domain Models/CompletionRequest.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public struct CompletionRequest {
1313
/// ID of the model to use
1414
public let model: String
1515

16+
/// The provider of the model
17+
public let provider: ModelProvider
18+
1619
// MARK: - Optional Parameters
1720

1821
/// Whether to store the output for model distillation or evals.
@@ -56,6 +59,7 @@ public struct CompletionRequest {
5659
public init(
5760
messages: [Message],
5861
model: String,
62+
provider: ModelProvider,
5963
store: Bool? = nil,
6064
frequencyPenalty: Double? = nil,
6165
logitBias: [String: Int]? = nil,
@@ -71,6 +75,7 @@ public struct CompletionRequest {
7175
) {
7276
self.messages = messages
7377
self.model = model
78+
self.provider = provider
7479
self.store = store
7580
self.frequencyPenalty = frequencyPenalty
7681
self.logitBias = logitBias
@@ -91,6 +96,7 @@ public struct CompletionRequest {
9196
CompletionRequestDTO(
9297
messages: messages.map { $0.toDTO() },
9398
model: model,
99+
provider: provider.rawValue,
94100
store: store,
95101
frequencyPenalty: frequencyPenalty,
96102
logitBias: logitBias,

Sources/CompilerSwiftAI/Model Calling/Domain Models/Message.swift

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,61 @@ public struct Message: Sendable, Equatable {
99
case user
1010
case assistant
1111
}
12-
12+
13+
public enum ContentType: String, Sendable {
14+
case text
15+
case imageUrl = "image_url"
16+
}
17+
18+
public enum Content: Sendable, Equatable {
19+
case text(String)
20+
case image(String)
21+
22+
var type: ContentType {
23+
switch self {
24+
case .text: return .text
25+
case .image: return .imageUrl
26+
}
27+
}
28+
29+
var value: String {
30+
switch self {
31+
case .text(let text): return text
32+
case .image(let url): return url
33+
}
34+
}
35+
}
36+
1337
public let id: String
1438
public let role: Role
15-
public let content: String
39+
public let content: [Content]
1640

17-
public init(id: String, role: Message.Role, content: String) {
41+
public init(id: String, role: Message.Role, content: [Content]) {
1842
self.id = id
1943
self.role = role
2044
self.content = content
2145
}
2246

47+
public init(role: Message.Role, content: [Content]) {
48+
self.init(id: UUID().uuidString, role: role, content: content)
49+
}
50+
51+
// Single content convenience initializer
52+
public init(role: Message.Role, content: Content) {
53+
self.init(role: role, content: [content])
54+
}
55+
2356
init(dto: MessageDTO) {
2457
self.id = dto.id
25-
self.role = .init(rawValue: dto.role)!
26-
self.content = dto.content
58+
self.role = Role(rawValue: dto.role) ?? .user
59+
self.content = dto.content.compactMap { content in
60+
if let text = content.text {
61+
return .text(text)
62+
} else if let imageUrl = content.imageUrl {
63+
return .image(imageUrl.url)
64+
}
65+
return nil
66+
}
2767
}
2868

2969
/// Convert this Message to a MessageDTO
@@ -34,14 +74,30 @@ public struct Message: Sendable, Equatable {
3474

3575
extension Message {
3676
static func systemMessage(content: String) -> Message {
37-
.init(id: UUID().uuidString, role: .system, content: content)
77+
.init(id: UUID().uuidString, role: .system, content: [.text(content)])
3878
}
3979

4080
static func userMessage(content: String) -> Message {
41-
.init(id: UUID().uuidString, role: .user, content: content)
81+
.init(id: UUID().uuidString, role: .user, content: [.text(content)])
4282
}
4383

4484
static func assistantMessage(content: String) -> Message {
45-
.init(id: UUID().uuidString, role: .assistant, content: content)
85+
.init(id: UUID().uuidString, role: .assistant, content: [.text(content)])
86+
}
87+
88+
static func systemMessage(text: String) -> Message {
89+
.init(role: .system, content: .text(text))
90+
}
91+
92+
static func userMessage(text: String) -> Message {
93+
.init(role: .user, content: .text(text))
94+
}
95+
96+
static func userMessage(imageUrl: String) -> Message {
97+
.init(role: .user, content: .image(imageUrl))
98+
}
99+
100+
static func assistantMessage(text: String) -> Message {
101+
.init(role: .assistant, content: .text(text))
46102
}
47103
}

Sources/CompilerSwiftAI/Network Models/CompletionRequestDTO.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ struct CompletionRequestDTO: Encodable {
1919
/// ID of the model to use
2020
let model: String
2121

22+
/// The provider of the model
23+
let provider: String
24+
2225
// MARK: - Optional Parameters with Defaults
2326

2427
/// Whether to store the output for model distillation or evals.
@@ -71,7 +74,7 @@ struct CompletionRequestDTO: Encodable {
7174
// MARK: - Coding Keys
7275

7376
enum CodingKeys: String, CodingKey {
74-
case messages, model, store
77+
case messages, model, provider, store
7578
case frequencyPenalty = "frequency_penalty"
7679
case logitBias = "logit_bias"
7780
case logprobs
@@ -88,6 +91,7 @@ struct CompletionRequestDTO: Encodable {
8891
init(
8992
messages: [MessageDTO],
9093
model: String,
94+
provider: String,
9195
store: Bool? = false,
9296
frequencyPenalty: Double? = 0,
9397
logitBias: [String: Int]? = nil,
@@ -104,6 +108,7 @@ struct CompletionRequestDTO: Encodable {
104108
) {
105109
self.messages = messages
106110
self.model = model
111+
self.provider = provider
107112
self.store = store
108113
self.frequencyPenalty = frequencyPenalty
109114
self.logitBias = logitBias
@@ -122,6 +127,7 @@ struct CompletionRequestDTO: Encodable {
122127
func copy(
123128
messages: [MessageDTO]? = nil,
124129
model: String? = nil,
130+
provider: String? = nil,
125131
store: Bool? = nil,
126132
frequencyPenalty: Double? = nil,
127133
logitBias: [String: Int]? = nil,
@@ -139,6 +145,7 @@ struct CompletionRequestDTO: Encodable {
139145
CompletionRequestDTO(
140146
messages: messages ?? self.messages,
141147
model: model ?? self.model,
148+
provider: provider ?? self.provider,
142149
store: store ?? self.store,
143150
frequencyPenalty: frequencyPenalty ?? self.frequencyPenalty,
144151
logitBias: logitBias ?? self.logitBias,

Sources/CompilerSwiftAI/Network Models/MessageDTO.swift

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,62 @@
88
import Foundation
99

1010
public struct MessageDTO: Codable, Sendable {
11+
public enum ContentType: String, Codable, Sendable {
12+
case text = "text"
13+
case imageUrl = "image_url"
14+
}
15+
16+
public struct Content: Codable, Sendable {
17+
let type: ContentType
18+
let text: String?
19+
let imageUrl: ImageUrl?
20+
21+
private enum CodingKeys: String, CodingKey {
22+
case type
23+
case text
24+
case imageUrl = "image_url"
25+
}
26+
}
27+
28+
public struct ImageUrl: Codable, Sendable {
29+
let url: String
30+
}
31+
1132
public let id: String
1233
public let role: String
13-
public let content: String
34+
public let content: [Content]
1435

1536
public init(message: Message) {
1637
self.id = message.id
1738
self.role = message.role.rawValue
18-
self.content = message.content
39+
self.content = message.content.map { content in
40+
switch content {
41+
case .text(let text):
42+
return Content(type: .text, text: text, imageUrl: nil)
43+
case .image(let url):
44+
return Content(type: .imageUrl, text: nil, imageUrl: ImageUrl(url: url))
45+
}
46+
}
1947
}
2048

2149
public func toMessage() -> Message {
2250
Message(
2351
id: id,
24-
role: Message.Role(rawValue: role) ?? .user,
25-
content: content
52+
role: .init(rawValue: role) ?? .user,
53+
content: content.compactMap { content in
54+
if let text = content.text {
55+
return .text(text)
56+
} else if let imageUrl = content.imageUrl {
57+
return .image(imageUrl.url)
58+
}
59+
return nil
60+
}
2661
)
2762
}
63+
64+
public func encode(to encoder: any Encoder) throws {
65+
var container = encoder.container(keyedBy: CodingKeys.self)
66+
try container.encode(self.role, forKey: .role)
67+
try container.encode(self.content, forKey: .content)
68+
}
2869
}

0 commit comments

Comments
 (0)