Skip to content

Commit 6c129d7

Browse files
committed
Fix that multiple function result was added to history
1 parent b3ae4ec commit 6c129d7

6 files changed

Lines changed: 219 additions & 230 deletions

File tree

Tool/Package.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,11 +299,21 @@ let package = Package(
299299
"Keychain",
300300
.product(name: "JSONRPC", package: "JSONRPC"),
301301
.product(name: "AsyncAlgorithms", package: "swift-async-algorithms"),
302+
.product(
303+
name: "ComposableArchitecture",
304+
package: "swift-composable-architecture"
305+
)
302306
]
303307
),
304308
.testTarget(
305309
name: "OpenAIServiceTests",
306-
dependencies: ["OpenAIService"]
310+
dependencies: [
311+
"OpenAIService",
312+
.product(
313+
name: "ComposableArchitecture",
314+
package: "swift-composable-architecture"
315+
)
316+
]
307317
),
308318

309319
// MARK: - UI

Tool/Sources/OpenAIService/ChatGPTService.swift

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import AsyncAlgorithms
2+
import Dependencies
23
import Foundation
34
import Preferences
45

@@ -62,7 +63,6 @@ public class ChatGPTService: ChatGPTServiceType {
6263
public var configuration: ChatGPTConfiguration
6364
public var functionProvider: ChatGPTFunctionProvider
6465

65-
var uuidGenerator: () -> String = { UUID().uuidString }
6666
var runningTask: Task<Void, Never>?
6767
var buildCompletionStreamAPI: CompletionStreamAPIBuilder = OpenAICompletionStreamAPI.init
6868
var buildCompletionAPI: CompletionAPIBuilder = OpenAICompletionAPI.init
@@ -80,6 +80,9 @@ public class ChatGPTService: ChatGPTServiceType {
8080
self.configuration = configuration
8181
self.functionProvider = functionProvider
8282
}
83+
84+
@Dependency(\.uuid) var uuid
85+
@Dependency(\.date) var date
8386

8487
/// Send a message and stream the reply.
8588
public func send(
@@ -88,7 +91,7 @@ public class ChatGPTService: ChatGPTServiceType {
8891
) async throws -> AsyncThrowingStream<String, Error> {
8992
if !content.isEmpty || summary != nil {
9093
let newMessage = ChatMessage(
91-
id: uuidGenerator(),
94+
id: uuid().uuidString,
9295
role: .user,
9396
content: content,
9497
name: nil,
@@ -132,7 +135,7 @@ public class ChatGPTService: ChatGPTServiceType {
132135
#endif
133136
case let .functionCall(call):
134137
if functionCall == nil {
135-
functionCallMessageID = uuidGenerator()
138+
functionCallMessageID = uuid().uuidString
136139
functionCall = call
137140
} else {
138141
functionCall?.name.append(call.name)
@@ -171,7 +174,7 @@ public class ChatGPTService: ChatGPTServiceType {
171174
) async throws -> String? {
172175
if !content.isEmpty || summary != nil {
173176
let newMessage = ChatMessage(
174-
id: uuidGenerator(),
177+
id: uuid().uuidString,
175178
role: .user,
176179
content: content,
177180
summary: summary
@@ -276,11 +279,12 @@ extension ChatGPTService {
276279
#if DEBUG
277280
Debugger.didSendRequestBody(body: requestBody)
278281
#endif
282+
283+
let proposedId = uuid().uuidString + String(date().timeIntervalSince1970)
279284

280285
return AsyncThrowingStream<StreamContent, Error> { continuation in
281286
let task = Task {
282287
do {
283-
let proposedId = UUID().uuidString + String(Date().timeIntervalSince1970)
284288
await memory.streamMessage(
285289
id: proposedId,
286290
references: prompt.references
@@ -335,9 +339,9 @@ extension ChatGPTService {
335339
continuation.finish(throwing: error)
336340
}
337341
}
338-
342+
339343
runningTask = task
340-
344+
341345
continuation.onTermination = { _ in
342346
task.cancel()
343347
}
@@ -346,7 +350,7 @@ extension ChatGPTService {
346350

347351
/// Send the memory as prompt to ChatGPT, with stream disabled.
348352
func sendMemoryAndWait() async throws -> ChatMessage? {
349-
let proposedId = UUID().uuidString + String(Date().timeIntervalSince1970)
353+
let proposedId = uuid().uuidString + String(date().timeIntervalSince1970)
350354
let prompt = await memory.generatePrompt()
351355

352356
guard let model = configuration.model else {
@@ -425,13 +429,7 @@ extension ChatGPTService {
425429
/// to insert a message placeholder in memory.
426430
func prepareFunctionCall(_ call: ChatMessage.FunctionCall, messageId: String) async {
427431
guard let function = functionProvider.function(named: call.name) else { return }
428-
let responseMessage = ChatMessage(
429-
id: messageId,
430-
role: .function,
431-
content: nil,
432-
name: call.name
433-
)
434-
await memory.appendMessage(responseMessage)
432+
await memory.streamMessage(id: messageId, role: .function, name: call.name)
435433
await function.prepare { [weak self] summary in
436434
await self?.memory.updateMessage(id: messageId) { message in
437435
message.summary = summary
@@ -449,21 +447,13 @@ extension ChatGPTService {
449447
Debugger.didReceiveFunction(name: call.name, arguments: call.arguments)
450448
#endif
451449

452-
let messageId = messageId ?? uuidGenerator()
450+
let messageId = messageId ?? uuid().uuidString
453451

454452
guard let function = functionProvider.function(named: call.name) else {
455453
return await fallbackFunctionCall(call, messageId: messageId)
456454
}
457455

458-
// Insert the chat message into memory to indicate the start of the function.
459-
let responseMessage = ChatMessage(
460-
id: messageId,
461-
role: .function,
462-
content: nil,
463-
name: call.name
464-
)
465-
466-
await memory.appendMessage(responseMessage)
456+
await memory.streamMessage(id: messageId, role: .function, name: call.name)
467457

468458
do {
469459
// Run the function
@@ -537,14 +527,13 @@ extension ChatGPTService {
537527
return "No result."
538528
}
539529
}()
540-
let responseMessage = ChatMessage(
530+
await memory.streamMessage(
541531
id: messageId,
542532
role: .function,
543533
content: content,
544534
name: call.name,
545535
summary: "Finished running function."
546536
)
547-
await memory.appendMessage(responseMessage)
548537
return content
549538
}
550539
}
@@ -553,10 +542,6 @@ extension ChatGPTService {
553542
func changeBuildCompletionStreamAPI(_ builder: @escaping CompletionStreamAPIBuilder) {
554543
buildCompletionStreamAPI = builder
555544
}
556-
557-
func changeUUIDGenerator(_ generator: @escaping () -> String) {
558-
uuidGenerator = generator
559-
}
560545
}
561546

562547
func maxTokenForReply(maxToken: Int, remainingTokens: Int?) -> Int? {

Tool/Sources/OpenAIService/Memory/AutoManagedChatGPTMemory.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public actor AutoManagedChatGPTMemory: ChatGPTMemory {
108108
availableTokenCountForRetrievedContent,
109109
messageUsage
110110
) = generateMessageHistory(
111-
maxNumberOfMessages: maxNumberOfMessages,
111+
maxNumberOfMessages: maxNumberOfMessages - 1, // for the new message
112112
maxTokenCount: availableTokenCountForMessages,
113113
encoder: encoder
114114
)

Tool/Sources/OpenAIService/Memory/ChatGPTMemory.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public extension ChatGPTMemory {
6363
id: String,
6464
role: ChatMessage.Role? = nil,
6565
content: String? = nil,
66+
name: String? = nil,
6667
functionCall: ChatMessage.FunctionCall? = nil,
6768
summary: String? = nil,
6869
references: [ChatMessage.Reference]? = nil
@@ -93,12 +94,15 @@ public extension ChatGPTMemory {
9394
if let references {
9495
history[index].references.append(contentsOf: references)
9596
}
97+
if let name {
98+
history[index].name = name
99+
}
96100
} else {
97101
history.append(.init(
98102
id: id,
99103
role: role ?? .system,
100104
content: content,
101-
name: nil,
105+
name: name,
102106
functionCall: functionCall,
103107
summary: summary,
104108
references: references ?? []

0 commit comments

Comments
 (0)