@@ -107,9 +107,7 @@ async function onConversation() {
107
107
scrollToBottom ()
108
108
109
109
try {
110
- const magicSplit = ' t1h1i4s5i1s4a1s9i1l9l8y1s0plit'
111
- let renderText = ' '
112
- let firstTime = true
110
+ let lastText = ' '
113
111
const fetchChatAPIOnce = async () => {
114
112
await fetchChatAPIProcess <Chat .ConversationResponse >({
115
113
prompt: message ,
@@ -119,49 +117,42 @@ async function onConversation() {
119
117
const xhr = event .target
120
118
const { responseText } = xhr
121
119
// Always process the final line
122
-
123
- const splitIndexBegin = responseText .search (magicSplit )
124
- if (splitIndexBegin !== - 1 ) {
125
- const splitIndexEnd = splitIndexBegin + magicSplit .length
126
-
127
- const firstChunk = responseText .substring (0 , splitIndexBegin )
128
- const deltaText = responseText .substring (splitIndexEnd )
129
- try {
130
- const data = JSON .parse (firstChunk )
131
- if (firstTime ) {
132
- firstTime = false
133
- renderText = data .text ?? ' '
134
- }
135
- else {
136
- renderText = deltaText ?? ' '
137
- }
138
- updateChat (
139
- + uuid ,
140
- dataSources .value .length - 1 ,
141
- {
142
- dateTime: new Date ().toLocaleString (),
143
- text: renderText ,
144
- inversion: false ,
145
- error: false ,
146
- loading: false ,
147
- conversationOptions: { conversationId: data .conversationId , parentMessageId: data .id },
148
- requestOptions: { prompt: message , ... options },
149
- },
150
- )
151
-
152
- if (openLongReply && data .detail .choices [0 ].finish_reason === ' length' ) {
153
- options .parentMessageId = data .id
154
- message = ' '
155
- return fetchChatAPIOnce ()
156
- }
157
- }
158
- catch (error ) {
159
- //
120
+ const lastIndex = responseText .lastIndexOf (' \n ' , responseText .length - 2 )
121
+ let chunk = responseText
122
+ if (lastIndex !== - 1 )
123
+ chunk = responseText .substring (lastIndex )
124
+ try {
125
+ const data = JSON .parse (chunk )
126
+ updateChat (
127
+ + uuid ,
128
+ dataSources .value .length - 1 ,
129
+ {
130
+ dateTime: new Date ().toLocaleString (),
131
+ text: lastText + data .text ?? ' ' ,
132
+ inversion: false ,
133
+ error: false ,
134
+ loading: false ,
135
+ conversationOptions: { conversationId: data .conversationId , parentMessageId: data .id },
136
+ requestOptions: { prompt: message , options: { ... options } },
137
+ },
138
+ )
139
+
140
+ if (openLongReply && data .detail .choices [0 ].finish_reason === ' length' ) {
141
+ options .parentMessageId = data .id
142
+ lastText = data .text
143
+ message = ' '
144
+ return fetchChatAPIOnce ()
160
145
}
146
+
147
+ scrollToBottomIfAtBottom ()
148
+ }
149
+ catch (error ) {
150
+ //
161
151
}
162
152
},
163
153
})
164
154
}
155
+
165
156
await fetchChatAPIOnce ()
166
157
}
167
158
catch (error : any ) {
@@ -246,9 +237,7 @@ async function onRegenerate(index: number) {
246
237
)
247
238
248
239
try {
249
- const magicSplit = ' t1h1i4s5i1s4a1s9i1l9l8y1s0plit'
250
- let renderText = ' '
251
- let firstTime = true
240
+ let lastText = ' '
252
241
const fetchChatAPIOnce = async () => {
253
242
await fetchChatAPIProcess <Chat .ConversationResponse >({
254
243
prompt: message ,
@@ -258,46 +247,36 @@ async function onRegenerate(index: number) {
258
247
const xhr = event .target
259
248
const { responseText } = xhr
260
249
// Always process the final line
261
-
262
- const splitIndexBegin = responseText .search (magicSplit )
263
- if (splitIndexBegin !== - 1 ) {
264
- const splitIndexEnd = splitIndexBegin + magicSplit .length
265
-
266
- const firstChunk = responseText .substring (0 , splitIndexBegin )
267
- const deltaText = responseText .substring (splitIndexEnd )
268
- try {
269
- const data = JSON .parse (firstChunk )
270
- if (firstTime ) {
271
- firstTime = false
272
- renderText = data .text ?? ' '
273
- }
274
- else {
275
- renderText = deltaText ?? ' '
276
- }
277
- updateChat (
278
- + uuid ,
279
- index ,
280
- {
281
- dateTime: new Date ().toLocaleString (),
282
- text: renderText ,
283
- inversion: false ,
284
- error: false ,
285
- loading: false ,
286
- conversationOptions: { conversationId: data .conversationId , parentMessageId: data .id },
287
- requestOptions: { prompt: message , ... options },
288
- },
289
- )
290
-
291
- if (openLongReply && data .detail .choices [0 ].finish_reason === ' length' ) {
292
- options .parentMessageId = data .id
293
- message = ' '
294
- return fetchChatAPIOnce ()
295
- }
296
- }
297
- catch (error ) {
298
- //
250
+ const lastIndex = responseText .lastIndexOf (' \n ' , responseText .length - 2 )
251
+ let chunk = responseText
252
+ if (lastIndex !== - 1 )
253
+ chunk = responseText .substring (lastIndex )
254
+ try {
255
+ const data = JSON .parse (chunk )
256
+ updateChat (
257
+ + uuid ,
258
+ index ,
259
+ {
260
+ dateTime: new Date ().toLocaleString (),
261
+ text: lastText + data .text ?? ' ' ,
262
+ inversion: false ,
263
+ error: false ,
264
+ loading: false ,
265
+ conversationOptions: { conversationId: data .conversationId , parentMessageId: data .id },
266
+ requestOptions: { prompt: message , ... options },
267
+ },
268
+ )
269
+
270
+ if (openLongReply && data .detail .choices [0 ].finish_reason === ' length' ) {
271
+ options .parentMessageId = data .id
272
+ lastText = data .text
273
+ message = ' '
274
+ return fetchChatAPIOnce ()
299
275
}
300
276
}
277
+ catch (error ) {
278
+ //
279
+ }
301
280
},
302
281
})
303
282
}
@@ -488,13 +467,20 @@ onUnmounted(() => {
488
467
<template >
489
468
<div class =" flex flex-col w-full h-full" >
490
469
<HeaderComponent
491
- v-if =" isMobile" :using-context =" usingContext" @export =" handleExport"
470
+ v-if =" isMobile"
471
+ :using-context =" usingContext"
472
+ @export =" handleExport"
492
473
@toggle-using-context =" toggleUsingContext"
493
474
/>
494
475
<main class =" flex-1 overflow-hidden" >
495
- <div id =" scrollRef" ref =" scrollRef" class =" h-full overflow-hidden overflow-y-auto" >
476
+ <div
477
+ id =" scrollRef"
478
+ ref =" scrollRef"
479
+ class =" h-full overflow-hidden overflow-y-auto"
480
+ >
496
481
<div
497
- id =" image-wrapper" class =" w-full max-w-screen-xl m-auto dark:bg-[#101014]"
482
+ id =" image-wrapper"
483
+ class =" w-full max-w-screen-xl m-auto dark:bg-[#101014]"
498
484
:class =" [isMobile ? 'p-2' : 'p-4']"
499
485
>
500
486
<template v-if =" ! dataSources .length " >
@@ -506,8 +492,14 @@ onUnmounted(() => {
506
492
<template v-else >
507
493
<div >
508
494
<Message
509
- v-for =" (item, index) of dataSources" :key =" index" :date-time =" item.dateTime" :text =" item.text"
510
- :inversion =" item.inversion" :error =" item.error" :loading =" item.loading" @regenerate =" onRegenerate(index)"
495
+ v-for =" (item, index) of dataSources"
496
+ :key =" index"
497
+ :date-time =" item.dateTime"
498
+ :text =" item.text"
499
+ :inversion =" item.inversion"
500
+ :error =" item.error"
501
+ :loading =" item.loading"
502
+ @regenerate =" onRegenerate(index)"
511
503
@delete =" handleDelete(index)"
512
504
/>
513
505
<div class =" sticky bottom-0 left-0 flex justify-center" >
@@ -544,9 +536,15 @@ onUnmounted(() => {
544
536
<NAutoComplete v-model:value =" prompt" :options =" searchOptions" :render-label =" renderOption" >
545
537
<template #default =" { handleInput , handleBlur , handleFocus } " >
546
538
<NInput
547
- ref =" inputRef" v-model:value =" prompt" type =" textarea" :placeholder =" placeholder"
548
- :autosize =" { minRows: 1, maxRows: isMobile ? 4 : 8 }" @input =" handleInput" @focus =" handleFocus"
549
- @blur =" handleBlur" @keypress =" handleEnter"
539
+ ref =" inputRef"
540
+ v-model:value =" prompt"
541
+ type =" textarea"
542
+ :placeholder =" placeholder"
543
+ :autosize =" { minRows: 1, maxRows: isMobile ? 4 : 8 }"
544
+ @input =" handleInput"
545
+ @focus =" handleFocus"
546
+ @blur =" handleBlur"
547
+ @keypress =" handleEnter"
550
548
/>
551
549
</template >
552
550
</NAutoComplete >
0 commit comments