Skip to content

Commit e1360a2

Browse files
committed
Merge branch 'feature/function-calling-fallback' into develop
2 parents bbf5dc0 + 930177e commit e1360a2

4 files changed

Lines changed: 68 additions & 26 deletions

File tree

Core/Sources/ChatService/ChatService.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Preferences
77

88
public final class ChatService: ObservableObject {
99
public let memory: ContextAwareAutoManagedChatGPTMemory
10-
public let configuration: OverridingChatGPTConfiguration<UserPreferenceChatGPTConfiguration>
10+
public let configuration: ChatGPTConfiguration
1111
public let chatGPTService: any ChatGPTServiceType
1212
public var allPluginCommands: [String] { allPlugins.map { $0.command } }
1313
@Published public internal(set) var isReceivingMessage = false
@@ -20,7 +20,7 @@ public final class ChatService: ObservableObject {
2020

2121
init<T: ChatGPTServiceType>(
2222
memory: ContextAwareAutoManagedChatGPTMemory,
23-
configuration: OverridingChatGPTConfiguration<UserPreferenceChatGPTConfiguration>,
23+
configuration: ChatGPTConfiguration,
2424
chatGPTService: T
2525
) {
2626
self.memory = memory

Tool/Sources/OpenAIService/ChatGPTService.swift

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ extension ChatGPTService {
182182
func sendMemory() async throws -> AsyncThrowingStream<StreamContent, Error> {
183183
guard let url = URL(string: configuration.endpoint)
184184
else { throw ChatGPTServiceError.endpointIncorrect }
185-
185+
186186
await memory.refresh()
187187

188188
let messages = await memory.messages.map {
@@ -282,7 +282,7 @@ extension ChatGPTService {
282282
func sendMemoryAndWait() async throws -> ChatMessage? {
283283
guard let url = URL(string: configuration.endpoint)
284284
else { throw ChatGPTServiceError.endpointIncorrect }
285-
285+
286286
await memory.refresh()
287287

288288
let messages = await memory.messages.map {
@@ -368,16 +368,7 @@ extension ChatGPTService {
368368
let messageId = messageId ?? uuidGenerator()
369369

370370
guard var function = functionProvider.function(named: call.name) else {
371-
let content = "Error: function not found"
372-
let responseMessage = ChatMessage(
373-
id: messageId,
374-
role: .function,
375-
content: content,
376-
name: call.name,
377-
summary: "Function `\(call.name)` not found."
378-
)
379-
await memory.appendMessage(responseMessage)
380-
return content
371+
return await fallbackFunctionCall(call, messageId: messageId)
381372
}
382373

383374
// Insert the chat message into memory to indicate the start of the function.
@@ -414,6 +405,56 @@ extension ChatGPTService {
414405
return content
415406
}
416407
}
408+
409+
/// Mock a function call result when the bot is calling a function that is not implemented.
410+
func fallbackFunctionCall(
411+
_ call: ChatMessage.FunctionCall,
412+
messageId: String
413+
) async -> String {
414+
let memory = ConversationChatGPTMemory(systemPrompt: {
415+
if call.name == "python" {
416+
return """
417+
Act like a Python interpreter.
418+
I will give you Python code and you will execute it.
419+
Reply with output of the code and tell me it's an answer generated by LLM.
420+
"""
421+
} else {
422+
return """
423+
You are a function simulator. Your name is \(call.name).
424+
Act like a function.
425+
I will send you the arguments.
426+
Reply with output of the function and tell me it's an answer generated by LLM.
427+
"""
428+
}
429+
}())
430+
431+
let service = ChatGPTService(
432+
memory: memory,
433+
configuration: OverridingChatGPTConfiguration(overriding: configuration, with: .init(
434+
temperature: 0
435+
)),
436+
functionProvider: NoChatGPTFunctionProvider()
437+
)
438+
439+
let content: String = await {
440+
do {
441+
return try await service.sendAndWait(content: """
442+
\(call.arguments)
443+
""") ?? "No result."
444+
} catch {
445+
return "No result."
446+
}
447+
}()
448+
let responseMessage = ChatMessage(
449+
id: messageId,
450+
role: .function,
451+
content: content,
452+
name: call.name,
453+
summary: "Finished running function."
454+
)
455+
await memory.appendMessage(responseMessage)
456+
return content
457+
}
417458
}
418459

419460
extension ChatGPTService {
@@ -430,5 +471,5 @@ func maxTokenForReply(model: String, remainingTokens: Int?) -> Int? {
430471
guard let remainingTokens else { return nil }
431472
guard let model = ChatGPTModel(rawValue: model) else { return remainingTokens }
432473
return min(model.maxToken / 2, remainingTokens)
433-
}
474+
}
434475

Tool/Sources/OpenAIService/Configuration/ChatGPTConfiguration.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ public extension ChatGPTConfiguration {
3939
}
4040

4141
func overriding(
42-
_ overrides: OverridingChatGPTConfiguration<Self>.Overriding
43-
) -> OverridingChatGPTConfiguration<Self> {
42+
_ overrides: OverridingChatGPTConfiguration.Overriding
43+
) -> OverridingChatGPTConfiguration {
4444
.init(overriding: self, with: overrides)
4545
}
4646

4747
func overriding(
48-
_ update: (inout OverridingChatGPTConfiguration<Self>.Overriding) -> Void = { _ in }
49-
) -> OverridingChatGPTConfiguration<Self> {
50-
var overrides = OverridingChatGPTConfiguration<Self>.Overriding()
48+
_ update: (inout OverridingChatGPTConfiguration.Overriding) -> Void = { _ in }
49+
) -> OverridingChatGPTConfiguration {
50+
var overrides = OverridingChatGPTConfiguration.Overriding()
5151
update(&overrides)
5252
return .init(overriding: self, with: overrides)
5353
}

Tool/Sources/OpenAIService/Configuration/UserPreferenceChatGPTConfiguration.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ public struct UserPreferenceChatGPTConfiguration: ChatGPTConfiguration {
4343
public init() {}
4444
}
4545

46-
public class OverridingChatGPTConfiguration<
47-
Configuration: ChatGPTConfiguration
48-
>: ChatGPTConfiguration {
46+
public class OverridingChatGPTConfiguration: ChatGPTConfiguration {
4947
public struct Overriding {
5048
public var featureProvider: ChatFeatureProvider?
5149
public var temperature: Double?
@@ -80,10 +78,13 @@ public class OverridingChatGPTConfiguration<
8078
}
8179
}
8280

83-
private let configuration: Configuration
81+
private let configuration: ChatGPTConfiguration
8482
public var overriding = Overriding()
8583

86-
public init(overriding configuration: Configuration, with overrides: Overriding = .init()) {
84+
public init(
85+
overriding configuration: any ChatGPTConfiguration,
86+
with overrides: Overriding = .init()
87+
) {
8788
overriding = overrides
8889
self.configuration = configuration
8990
}
@@ -123,7 +124,7 @@ public class OverridingChatGPTConfiguration<
123124
public var minimumReplyTokens: Int {
124125
overriding.minimumReplyTokens ?? configuration.minimumReplyTokens
125126
}
126-
127+
127128
public var runFunctionsAutomatically: Bool {
128129
overriding.runFunctionsAutomatically ?? configuration.runFunctionsAutomatically
129130
}

0 commit comments

Comments
 (0)