@@ -19,20 +19,22 @@ open class TextChatViewModel<CustomContent: View> {
1919 public var senderImage : String ?
2020 public var botImage : String ?
2121 public var useStreaming = true
22+ public var renderAsMarkdown = true
2223
2324 public let api : ChatGPTAPI
2425 public var model : ChatGPTModel
2526 public var systemText : String
2627 public var temperature : Double
2728
28- public init ( messages: [ MessageRow < CustomContent > ] = [ ] , senderImage: String ? = nil , botImage: String ? = nil , useStreaming: Bool = true , model: ChatGPTModel = . gpt_hyphen_3_period_5_hyphen_turbo, systemText: String = " You're a helpful assistant " , temperature: Double = 0.6 , apiKey: String ) {
29+ public init ( messages: [ MessageRow < CustomContent > ] = [ ] , senderImage: String ? = nil , botImage: String ? = nil , useStreaming: Bool = true , model: ChatGPTModel = . gpt_hyphen_3_period_5_hyphen_turbo, systemText: String = " You're a helpful assistant " , temperature: Double = 0.6 , renderAsMarkdown : Bool = true , apiKey: String ) {
2930 self . messages = messages
3031 self . senderImage = senderImage
3132 self . botImage = botImage
3233 self . useStreaming = useStreaming
3334 self . model = model
3435 self . api = ChatGPTAPI ( apiKey: apiKey)
3536 self . systemText = systemText
37+ self . renderAsMarkdown = renderAsMarkdown
3638 self . temperature = temperature
3739 }
3840
@@ -76,9 +78,13 @@ open class TextChatViewModel<CustomContent: View> {
7678 var streamText = " "
7779 do {
7880 let parsingTask = ResponseParsingTask ( )
79- let attributedSend = await parsingTask. parse ( text: text)
80- try Task . checkCancellation ( )
81- messageRow. send = . attributed( attributedSend)
81+ if renderAsMarkdown {
82+ let attributedSend = await parsingTask. parse ( text: text)
83+ try Task . checkCancellation ( )
84+ messageRow. send = . attributed( attributedSend)
85+ } else {
86+ messageRow. send = . rawText( text)
87+ }
8288
8389 self . messages. append ( messageRow)
8490 let parserThresholdTextCount = 64
@@ -88,42 +94,48 @@ open class TextChatViewModel<CustomContent: View> {
8894 let stream = try await api. sendMessageStream ( text: text, model: model, systemText: systemText, temperature: temperature)
8995 for try await text in stream {
9096 streamText += text
91- currentTextCount += text. count
92-
93- if currentTextCount >= parserThresholdTextCount || text. contains ( " ``` " ) {
94- currentOutput = await parsingTask. parse ( text: streamText)
95- try Task . checkCancellation ( )
96- currentTextCount = 0
97- }
97+ if renderAsMarkdown {
98+ currentTextCount += text. count
99+
100+ if currentTextCount >= parserThresholdTextCount || text. contains ( " ``` " ) {
101+ currentOutput = await parsingTask. parse ( text: streamText)
102+ try Task . checkCancellation ( )
103+ currentTextCount = 0
104+ }
98105
99- if let currentOutput = currentOutput, !currentOutput. results. isEmpty {
100- let suffixText = streamText. trimmingPrefix ( currentOutput. string)
101- var results = currentOutput. results
102- let lastResult = results [ results. count - 1 ]
103- var lastAttrString = lastResult. attributedString
104- if lastResult. isCodeBlock {
105- #if os(macOS)
106- lastAttrString. append ( AttributedString ( String ( suffixText) , attributes: . init( [ . font: NSFont . systemFont ( ofSize: 12 ) . apply ( newTraits: . monoSpace) , . foregroundColor: NSColor . white] ) ) )
107- #else
108- lastAttrString. append ( AttributedString ( String ( suffixText) , attributes: . init( [ . font: UIFont . systemFont ( ofSize: 12 ) . apply ( newTraits: . traitMonoSpace) , . foregroundColor: UIColor . white] ) ) )
109- #endif
110-
106+ if let currentOutput = currentOutput, !currentOutput. results. isEmpty {
107+ let suffixText = streamText. trimmingPrefix ( currentOutput. string)
108+ var results = currentOutput. results
109+ let lastResult = results [ results. count - 1 ]
110+ var lastAttrString = lastResult. attributedString
111+ if lastResult. isCodeBlock {
112+ #if os(macOS)
113+ lastAttrString. append ( AttributedString ( String ( suffixText) , attributes: . init( [ . font: NSFont . systemFont ( ofSize: 12 ) . apply ( newTraits: . monoSpace) , . foregroundColor: NSColor . white] ) ) )
114+ #else
115+ lastAttrString. append ( AttributedString ( String ( suffixText) , attributes: . init( [ . font: UIFont . systemFont ( ofSize: 12 ) . apply ( newTraits: . traitMonoSpace) , . foregroundColor: UIColor . white] ) ) )
116+ #endif
117+
118+ } else {
119+ lastAttrString. append ( AttributedString ( String ( suffixText) ) )
120+ }
121+ results [ results. count - 1 ] = ParserResult ( attributedString: lastAttrString, isCodeBlock: lastResult. isCodeBlock, codeBlockLanguage: lastResult. codeBlockLanguage)
122+ messageRow. response = . attributed( . init( string: streamText, results: results) )
111123 } else {
112- lastAttrString. append ( AttributedString ( String ( suffixText) ) )
124+ messageRow. response = . attributed( . init( string: streamText, results: [
125+ ParserResult ( attributedString: AttributedString ( stringLiteral: streamText) , isCodeBlock: false , codeBlockLanguage: nil )
126+ ] ) )
113127 }
114- results [ results. count - 1 ] = ParserResult ( attributedString: lastAttrString, isCodeBlock: lastResult. isCodeBlock, codeBlockLanguage: lastResult. codeBlockLanguage)
115- messageRow. response = . attributed( . init( string: streamText, results: results) )
128+
116129 } else {
117- messageRow. response = . attributed( . init( string: streamText, results: [
118- ParserResult ( attributedString: AttributedString ( stringLiteral: streamText) , isCodeBlock: false , codeBlockLanguage: nil )
119- ] ) )
130+ messageRow. response = . rawText( streamText)
120131 }
121-
122132 self . messages [ self . messages. count - 1 ] = messageRow
123- if let currentString = currentOutput? . string, currentString != streamText {
124- let output = await parsingTask. parse ( text: streamText)
125- try Task . checkCancellation ( )
126- messageRow. response = . attributed( output)
133+ if renderAsMarkdown {
134+ if let currentString = currentOutput? . string, currentString != streamText {
135+ let output = await parsingTask. parse ( text: streamText)
136+ try Task . checkCancellation ( )
137+ messageRow. response = . attributed( output)
138+ }
127139 }
128140 }
129141 } catch is CancellationError {
@@ -158,12 +170,14 @@ open class TextChatViewModel<CustomContent: View> {
158170 let responseText = try await api. sendMessage ( text: text, model: model, systemText: systemText, temperature: temperature)
159171 try Task . checkCancellation ( )
160172
161- let parsingTask = ResponseParsingTask ( )
162- let output = await parsingTask. parse ( text: responseText)
163- try Task . checkCancellation ( )
164-
165- messageRow. response = . attributed( output)
166-
173+ if renderAsMarkdown {
174+ let parsingTask = ResponseParsingTask ( )
175+ let output = await parsingTask. parse ( text: responseText)
176+ try Task . checkCancellation ( )
177+ messageRow. response = . attributed( output)
178+ } else {
179+ messageRow. response = . rawText( responseText)
180+ }
167181 } catch {
168182 messageRow. responseError = error. localizedDescription
169183 }
0 commit comments