@@ -19,35 +19,21 @@ import Foundation
1919@available ( iOS 15 . 0 , macOS 12 . 0 , macCatalyst 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
2020public final class Chat : Sendable {
2121 private let model : GenerativeModel
22+ private let _history : History
2223
23- /// Initializes a new chat representing a 1:1 conversation between model and user.
2424 init ( model: GenerativeModel , history: [ ModelContent ] ) {
2525 self . model = model
26- self . history = history
26+ _history = History ( history: history )
2727 }
2828
29- private let historyLock = NSLock ( )
30- private nonisolated ( unsafe) var _history : [ ModelContent ] = [ ]
3129 /// The previous content from the chat that has been successfully sent and received from the
3230 /// model. This will be provided to the model for each message sent as context for the discussion.
3331 public var history : [ ModelContent ] {
3432 get {
35- historyLock . withLock { _history }
33+ return _history. history
3634 }
3735 set {
38- historyLock. withLock { _history = newValue }
39- }
40- }
41-
42- private func appendHistory( contentsOf: [ ModelContent ] ) {
43- historyLock. withLock {
44- _history. append ( contentsOf: contentsOf)
45- }
46- }
47-
48- private func appendHistory( _ newElement: ModelContent ) {
49- historyLock. withLock {
50- _history. append ( newElement)
36+ _history. history = newValue
5137 }
5238 }
5339
@@ -87,8 +73,8 @@ public final class Chat: Sendable {
8773 let toAdd = ModelContent ( role: " model " , parts: reply. parts)
8874
8975 // Append the request and successful result to history, then return the value.
90- appendHistory ( contentsOf: newContent)
91- appendHistory ( toAdd)
76+ _history . append ( contentsOf: newContent)
77+ _history . append ( toAdd)
9278 return result
9379 }
9480
@@ -136,63 +122,16 @@ public final class Chat: Sendable {
136122 }
137123
138124 // Save the request.
139- appendHistory ( contentsOf: newContent)
125+ _history . append ( contentsOf: newContent)
140126
141127 // Aggregate the content to add it to the history before we finish.
142- let aggregated = self . aggregatedChunks ( aggregatedContent)
143- self . appendHistory ( aggregated)
128+ let aggregated = self . _history . aggregatedChunks ( aggregatedContent)
129+ self . _history . append ( aggregated)
144130 continuation. finish ( )
145131 }
146132 }
147133 }
148134
149- private func aggregatedChunks( _ chunks: [ ModelContent ] ) -> ModelContent {
150- var parts : [ InternalPart ] = [ ]
151- var combinedText = " "
152- var combinedThoughts = " "
153-
154- func flush( ) {
155- if !combinedThoughts. isEmpty {
156- parts. append ( InternalPart ( . text( combinedThoughts) , isThought: true , thoughtSignature: nil ) )
157- combinedThoughts = " "
158- }
159- if !combinedText. isEmpty {
160- parts. append ( InternalPart ( . text( combinedText) , isThought: nil , thoughtSignature: nil ) )
161- combinedText = " "
162- }
163- }
164-
165- // Loop through all the parts, aggregating the text.
166- for part in chunks. flatMap ( { $0. internalParts } ) {
167- // Only text parts may be combined.
168- if case let . text( text) = part. data, part. thoughtSignature == nil {
169- // Thought summaries must not be combined with regular text.
170- if part. isThought ?? false {
171- // If we were combining regular text, flush it before handling "thoughts".
172- if !combinedText. isEmpty {
173- flush ( )
174- }
175- combinedThoughts += text
176- } else {
177- // If we were combining "thoughts", flush it before handling regular text.
178- if !combinedThoughts. isEmpty {
179- flush ( )
180- }
181- combinedText += text
182- }
183- } else {
184- // This is a non-combinable part (not text), flush any pending text.
185- flush ( )
186- parts. append ( part)
187- }
188- }
189-
190- // Flush any remaining text.
191- flush ( )
192-
193- return ModelContent ( role: " model " , parts: parts)
194- }
195-
196135 /// Populates the `role` field with `user` if it doesn't exist. Required in chat sessions.
197136 private func populateContentRole( _ content: ModelContent ) -> ModelContent {
198137 if content. role != nil {
0 commit comments