-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathAutoManagedChatMemory.swift
More file actions
97 lines (79 loc) · 2.81 KB
/
AutoManagedChatMemory.swift
File metadata and controls
97 lines (79 loc) · 2.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import Foundation
import Logger
import Preferences
import ConversationServiceProvider
@globalActor
public enum AutoManagedChatMemoryActor: GlobalActor {
public actor Actor {}
public static let shared = Actor()
}
protocol AutoManagedChatMemoryStrategy {
func countToken(_ message: ChatMessage) async -> Int
}
/// A memory that automatically manages the history according to max tokens and max message count.
public actor AutoManagedChatMemory: ChatMemory {
public struct ComposableMessages {
public var systemPromptMessage: ChatMessage
public var historyMessage: [ChatMessage]
public var retrievedContentMessage: ChatMessage
public var contextSystemPromptMessage: ChatMessage
public var newMessage: ChatMessage
}
public typealias HistoryComposer = (ComposableMessages) -> [ChatMessage]
public private(set) var history: [ChatMessage] = [] {
didSet { onHistoryChange() }
}
public private(set) var remainingTokens: Int?
public var systemPrompt: String
public var contextSystemPrompt: String
public var retrievedContent: [ConversationReference] = []
var onHistoryChange: () -> Void = {}
let composeHistory: HistoryComposer
public init(
systemPrompt: String,
composeHistory: @escaping HistoryComposer = {
/// Default Format:
/// ```
/// [System Prompt] priority: high
/// [Functions] priority: high
/// [Retrieved Content] priority: low
/// [Retrieved Content A]
/// <separator>
/// [Retrieved Content B]
/// [Message History] priority: medium
/// [Context System Prompt] priority: high
/// [Latest Message] priority: high
/// ```
[$0.systemPromptMessage] +
$0.historyMessage +
[$0.retrievedContentMessage, $0.contextSystemPromptMessage, $0.newMessage]
}
) {
self.systemPrompt = systemPrompt
contextSystemPrompt = ""
self.composeHistory = composeHistory
}
deinit {
history.removeAll()
onHistoryChange = {}
retrievedContent.removeAll()
}
public func mutateHistory(_ update: (inout [ChatMessage]) -> Void) {
update(&history)
}
public func mutateContextSystemPrompt(_ newPrompt: String) {
contextSystemPrompt = newPrompt
}
public func mutateRetrievedContent(_ newContent: [ConversationReference]) {
retrievedContent = newContent
}
public nonisolated
func observeHistoryChange(_ onChange: @escaping () -> Void) {
Task {
await setOnHistoryChangeBlock(onChange)
}
}
func setOnHistoryChangeBlock(_ onChange: @escaping () -> Void) {
onHistoryChange = onChange
}
}