Skip to content

Commit f1eeffd

Browse files
committed
Make count token async
1 parent 77dcc76 commit f1eeffd

File tree

3 files changed

+47
-39
lines changed

3 files changed

+47
-39
lines changed

Pro

Submodule Pro updated from 0fd71d1 to 26f9ee8

Tool/Sources/OpenAIService/Memory/AutoManagedChatGPTMemory.swift

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -87,27 +87,27 @@ public actor AutoManagedChatGPTMemory: ChatGPTMemory {
8787
}
8888

8989
public func generatePrompt() async -> ChatGPTPrompt {
90-
return generateSendingHistory()
90+
return await generateSendingHistory()
9191
}
9292

9393
/// https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb
9494
func generateSendingHistory(
9595
maxNumberOfMessages: Int = UserDefaults.shared.value(for: \.chatGPTMaxMessageCount),
9696
encoder: TokenEncoder = AutoManagedChatGPTMemory.encoder
97-
) -> ChatGPTPrompt {
97+
) async -> ChatGPTPrompt {
9898
let (
9999
systemPromptMessage,
100100
contextSystemPromptMessage,
101101
availableTokenCountForMessages,
102102
mandatoryUsage
103-
) = generateMandatoryMessages(encoder: encoder)
103+
) = await generateMandatoryMessages(encoder: encoder)
104104

105105
let (
106106
historyMessage,
107107
newMessage,
108108
availableTokenCountForRetrievedContent,
109109
messageUsage
110-
) = generateMessageHistory(
110+
) = await generateMessageHistory(
111111
maxNumberOfMessages: maxNumberOfMessages - 1, // for the new message
112112
maxTokenCount: availableTokenCountForMessages,
113113
encoder: encoder
@@ -118,7 +118,7 @@ public actor AutoManagedChatGPTMemory: ChatGPTMemory {
118118
_,
119119
retrievedContentUsage,
120120
retrievedContent
121-
) = generateRetrievedContentMessage(
121+
) = await generateRetrievedContentMessage(
122122
maxTokenCount: availableTokenCountForRetrievedContent,
123123
encoder: encoder
124124
)
@@ -160,29 +160,36 @@ public actor AutoManagedChatGPTMemory: ChatGPTMemory {
160160
}
161161

162162
extension AutoManagedChatGPTMemory {
163-
func generateMandatoryMessages(encoder: TokenEncoder) -> (
163+
func generateMandatoryMessages(encoder: TokenEncoder) async -> (
164164
systemPrompt: ChatMessage,
165165
contextSystemPrompt: ChatMessage,
166166
remainingTokenCount: Int,
167167
usage: (systemPrompt: Int, contextSystemPrompt: Int, functions: Int)
168168
) {
169169
var smallestSystemPromptMessage = ChatMessage(role: .system, content: systemPrompt)
170170
var contextSystemPromptMessage = ChatMessage(role: .user, content: contextSystemPrompt)
171-
let smallestSystemMessageTokenCount = encoder.countToken(&smallestSystemPromptMessage)
171+
let smallestSystemMessageTokenCount = await encoder.countToken(&smallestSystemPromptMessage)
172172
let contextSystemPromptTokenCount = !contextSystemPrompt.isEmpty
173-
? encoder.countToken(&contextSystemPromptMessage)
173+
? (await encoder.countToken(&contextSystemPromptMessage))
174174
: 0
175175

176-
let functionTokenCount = functionProvider.functions.reduce(into: 0) { partial, function in
177-
var count = encoder.countToken(text: function.name)
178-
+ encoder.countToken(text: function.description)
179-
if let data = try? JSONEncoder().encode(function.argumentSchema),
180-
let string = String(data: data, encoding: .utf8)
181-
{
182-
count += encoder.countToken(text: string)
176+
let functionTokenCount = await {
177+
var totalTokenCount = 0
178+
for function in functionProvider.functions {
179+
async let nameTokenCount = encoder.countToken(text: function.name)
180+
async let descriptionTokenCount = encoder.countToken(text: function.description)
181+
async let schemaTokenCount = {
182+
guard let data = try? JSONEncoder().encode(function.argumentSchema),
183+
let string = String(data: data, encoding: .utf8)
184+
else { return 0 }
185+
return await encoder.countToken(text: string)
186+
}()
187+
188+
await totalTokenCount += nameTokenCount + descriptionTokenCount + schemaTokenCount
183189
}
184-
partial += count
185-
}
190+
return totalTokenCount
191+
}()
192+
186193
let mandatoryContentTokensCount = smallestSystemMessageTokenCount
187194
+ contextSystemPromptTokenCount
188195
+ functionTokenCount
@@ -211,7 +218,7 @@ extension AutoManagedChatGPTMemory {
211218
maxNumberOfMessages: Int,
212219
maxTokenCount: Int,
213220
encoder: TokenEncoder
214-
) -> (
221+
) async -> (
215222
history: [ChatMessage],
216223
newMessage: ChatMessage,
217224
remainingTokenCount: Int,
@@ -224,7 +231,8 @@ extension AutoManagedChatGPTMemory {
224231
for (index, message) in history.enumerated().reversed() {
225232
if maxNumberOfMessages > 0, allMessages.count >= maxNumberOfMessages { break }
226233
if message.isEmpty { continue }
227-
let tokensCount = encoder.countToken(&history[index])
234+
let tokensCount = await encoder.countToken(message)
235+
history[index].tokensCount = tokensCount
228236
if tokensCount + messageTokenCount > maxTokenCount { break }
229237
messageTokenCount += tokensCount
230238
if index == history.endIndex - 1 {
@@ -245,7 +253,7 @@ extension AutoManagedChatGPTMemory {
245253
func generateRetrievedContentMessage(
246254
maxTokenCount: Int,
247255
encoder: TokenEncoder
248-
) -> (
256+
) async -> (
249257
retrievedContent: ChatMessage,
250258
remainingTokenCount: Int,
251259
usage: Int,
@@ -259,8 +267,8 @@ extension AutoManagedChatGPTMemory {
259267
var message = ""
260268
var references = [ChatMessage.Reference]()
261269

262-
func appendToMessage(_ text: String) -> Bool {
263-
let tokensCount = encoder.countToken(text: text)
270+
func appendToMessage(_ text: String) async -> Bool {
271+
let tokensCount = await encoder.countToken(text: text)
264272
if tokensCount + retrievedContentTokenCount > thresholdMaxTokenCount { return false }
265273
retrievedContentTokenCount += tokensCount
266274
message += text
@@ -269,17 +277,17 @@ extension AutoManagedChatGPTMemory {
269277

270278
for (index, content) in retrievedContent.filter({ !$0.content.isEmpty }).enumerated() {
271279
if index == 0 {
272-
if !appendToMessage("""
280+
if !(await appendToMessage("""
273281
Here are the information you know about the system and the project, \
274282
separated by \(separator)
275283
276284
277-
""") { break }
285+
""")) { break }
278286
} else {
279-
if !appendToMessage("\n\(separator)\n") { break }
287+
if !(await appendToMessage("\n\(separator)\n")) { break }
280288
}
281289

282-
if !appendToMessage(content.content) { break }
290+
if !(await appendToMessage(content.content)) { break }
283291
references.append(content)
284292
}
285293

@@ -294,25 +302,25 @@ extension AutoManagedChatGPTMemory {
294302

295303
public extension TokenEncoder {
296304
/// https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb
297-
func countToken(message: ChatMessage) -> Int {
305+
func countToken(_ message: ChatMessage) async -> Int {
298306
var total = 3
299307
if let content = message.content {
300-
total += encode(text: content).count
308+
total += await encode(text: content).count
301309
}
302310
if let name = message.name {
303-
total += encode(text: name).count
311+
total += await encode(text: name).count
304312
total += 1
305313
}
306314
if let functionCall = message.functionCall {
307-
total += encode(text: functionCall.name).count
308-
total += encode(text: functionCall.arguments).count
315+
total += await encode(text: functionCall.name).count
316+
total += await encode(text: functionCall.arguments).count
309317
}
310318
return total
311319
}
312320

313-
func countToken(_ message: inout ChatMessage) -> Int {
321+
func countToken(_ message: inout ChatMessage) async -> Int {
314322
if let count = message.tokensCount { return count }
315-
let count = countToken(message: message)
323+
let count = await countToken(message)
316324
message.tokensCount = count
317325
return count
318326
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import Foundation
22

33
public protocol TokenEncoder: TokenCounter {
4-
func encode(text: String) -> [Int]
4+
func encode(text: String) async -> [Int]
55
}
66

7-
extension TokenEncoder {
8-
func countToken(text: String) -> Int {
9-
encode(text: text).count
7+
public extension TokenEncoder {
8+
func countToken(text: String) async -> Int {
9+
await encode(text: text).count
1010
}
1111
}
1212

1313
public protocol TokenCounter {
14-
func countToken(text: String) -> Int
14+
func countToken(text: String) async -> Int
1515
}

0 commit comments

Comments
 (0)