@@ -3,10 +3,86 @@ import Foundation
33import GoogleGenerativeAI
44import Preferences
55
6+ extension ChatGPTPrompt {
7+ var googleAICompatible : ChatGPTPrompt {
8+ var history = self . history
9+ var reformattedHistory = [ ChatMessage] ( )
10+
11+ // We don't want to combine the new user message with others.
12+ let newUserMessage : ChatMessage ? = if history. last? . role == . user {
13+ history. removeLast ( )
14+ } else {
15+ nil
16+ }
17+
18+ for message in history {
19+ let lastIndex = reformattedHistory. endIndex - 1
20+ guard lastIndex >= 0 else { // first message
21+ if message. role == . system {
22+ reformattedHistory. append ( . init(
23+ role: . user,
24+ content: ModelContent . convertContent ( of: message)
25+ ) )
26+ reformattedHistory. append ( . init(
27+ role: . assistant,
28+ content: " Got it. Let's start our conversation. "
29+ ) )
30+ continue
31+ }
32+
33+ reformattedHistory. append ( message)
34+ continue
35+ }
36+
37+ let lastMessage = reformattedHistory [ lastIndex]
38+
39+ if ModelContent . convertRole ( lastMessage. role) == ModelContent
40+ . convertRole ( message. role)
41+ {
42+ let newMessage = ChatMessage (
43+ role: message. role == . assistant ? . assistant : . user,
44+ content: """
45+ \( ModelContent . convertContent ( of: lastMessage) )
46+
47+ ======
48+
49+ \( ModelContent . convertContent ( of: message) )
50+ """
51+ )
52+ reformattedHistory [ lastIndex] = newMessage
53+ } else {
54+ reformattedHistory. append ( message)
55+ }
56+ }
57+
58+ if let newUserMessage {
59+ if let last = reformattedHistory. last,
60+ ModelContent . convertRole ( last. role) == ModelContent
61+ . convertRole ( newUserMessage. role)
62+ {
63+ // Add dummy message
64+ let dummyMessage = ChatMessage (
65+ role: . assistant,
66+ content: " OK "
67+ )
68+ reformattedHistory. append ( dummyMessage)
69+ }
70+ reformattedHistory. append ( newUserMessage)
71+ }
72+
73+ return . init(
74+ history: reformattedHistory,
75+ references: references,
76+ remainingTokenCount: remainingTokenCount
77+ )
78+ }
79+ }
80+
681struct GoogleCompletionAPI : CompletionAPI {
782 let apiKey : String
883 let model : ChatModel
984 var requestBody : CompletionRequestBody
85+ let prompt : ChatGPTPrompt
1086
1187 func callAsFunction( ) async throws -> CompletionResponseBody {
1288 let aiModel = GenerativeModel (
@@ -17,22 +93,22 @@ struct GoogleCompletionAPI: CompletionAPI {
1793 topP: requestBody. top_p. map ( Float . init)
1894 ) )
1995 )
20- let history = requestBody . messages . map { message in
96+ let history = prompt . googleAICompatible . history . map { message in
2197 ModelContent (
2298 ChatMessage (
2399 role: message. role,
24100 content: message. content,
25101 name: message. name,
26- functionCall: message. function_call . map {
27- . init( name: $0. name, arguments: $0. arguments ?? " " )
102+ functionCall: message. functionCall . map {
103+ . init( name: $0. name, arguments: $0. arguments)
28104 }
29105 )
30106 )
31107 }
32108
33109 do {
34110 let response = try await aiModel. generateContent ( history)
35-
111+
36112 return . init(
37113 object: " chat.completion " ,
38114 model: model. info. modelName,
@@ -64,7 +140,7 @@ struct GoogleCompletionAPI: CompletionAPI {
64140 return " Internal Error: \( s) "
65141 }
66142 }
67-
143+
68144 switch error {
69145 case let . internalError( underlying) :
70146 throw ErrorWrapper ( error: underlying)
0 commit comments