@@ -107,9 +107,7 @@ async function onConversation() {
107107 scrollToBottom ()
108108
109109 try {
110- const magicSplit = ' t1h1i4s5i1s4a1s9i1l9l8y1s0plit'
111- let renderText = ' '
112- let firstTime = true
110+ let lastText = ' '
113111 const fetchChatAPIOnce = async () => {
114112 await fetchChatAPIProcess <Chat .ConversationResponse >({
115113 prompt: message ,
@@ -119,49 +117,42 @@ async function onConversation() {
119117 const xhr = event .target
120118 const { responseText } = xhr
121119 // 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 ()
160145 }
146+
147+ scrollToBottomIfAtBottom ()
148+ }
149+ catch (error ) {
150+ //
161151 }
162152 },
163153 })
164154 }
155+
165156 await fetchChatAPIOnce ()
166157 }
167158 catch (error : any ) {
@@ -246,9 +237,7 @@ async function onRegenerate(index: number) {
246237 )
247238
248239 try {
249- const magicSplit = ' t1h1i4s5i1s4a1s9i1l9l8y1s0plit'
250- let renderText = ' '
251- let firstTime = true
240+ let lastText = ' '
252241 const fetchChatAPIOnce = async () => {
253242 await fetchChatAPIProcess <Chat .ConversationResponse >({
254243 prompt: message ,
@@ -258,46 +247,36 @@ async function onRegenerate(index: number) {
258247 const xhr = event .target
259248 const { responseText } = xhr
260249 // 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 ()
299275 }
300276 }
277+ catch (error ) {
278+ //
279+ }
301280 },
302281 })
303282 }
@@ -488,13 +467,20 @@ onUnmounted(() => {
488467<template >
489468 <div class =" flex flex-col w-full h-full" >
490469 <HeaderComponent
491- v-if =" isMobile" :using-context =" usingContext" @export =" handleExport"
470+ v-if =" isMobile"
471+ :using-context =" usingContext"
472+ @export =" handleExport"
492473 @toggle-using-context =" toggleUsingContext"
493474 />
494475 <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+ >
496481 <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]"
498484 :class =" [isMobile ? 'p-2' : 'p-4']"
499485 >
500486 <template v-if =" ! dataSources .length " >
@@ -506,8 +492,14 @@ onUnmounted(() => {
506492 <template v-else >
507493 <div >
508494 <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)"
511503 @delete =" handleDelete(index)"
512504 />
513505 <div class =" sticky bottom-0 left-0 flex justify-center" >
@@ -544,9 +536,15 @@ onUnmounted(() => {
544536 <NAutoComplete v-model:value =" prompt" :options =" searchOptions" :render-label =" renderOption" >
545537 <template #default =" { handleInput , handleBlur , handleFocus } " >
546538 <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"
550548 />
551549 </template >
552550 </NAutoComplete >
0 commit comments