abort when clear conversations
This commit is contained in:
		
							parent
							
								
									c3084a3290
								
							
						
					
					
						commit
						db4e0a5734
					
				@ -1,22 +1,22 @@
 | 
				
			|||||||
import React, {FC, useEffect, useRef, useState} from 'react';
 | 
					import React, { FC, useEffect, useRef, useState } from 'react';
 | 
				
			||||||
import {useTranslation} from 'react-i18next';
 | 
					import { useTranslation } from 'react-i18next';
 | 
				
			||||||
import {RunButton} from '../components/RunButton';
 | 
					import { RunButton } from '../components/RunButton';
 | 
				
			||||||
import {Avatar, Divider, PresenceBadge, Text, Textarea} from '@fluentui/react-components';
 | 
					import { Avatar, Divider, PresenceBadge, Text, Textarea } from '@fluentui/react-components';
 | 
				
			||||||
import commonStore, {ModelStatus} from '../stores/commonStore';
 | 
					import commonStore, { ModelStatus } from '../stores/commonStore';
 | 
				
			||||||
import {observer} from 'mobx-react-lite';
 | 
					import { observer } from 'mobx-react-lite';
 | 
				
			||||||
import {PresenceBadgeStatus} from '@fluentui/react-badge';
 | 
					import { PresenceBadgeStatus } from '@fluentui/react-badge';
 | 
				
			||||||
import {ConfigSelector} from '../components/ConfigSelector';
 | 
					import { ConfigSelector } from '../components/ConfigSelector';
 | 
				
			||||||
import {v4 as uuid} from 'uuid';
 | 
					import { v4 as uuid } from 'uuid';
 | 
				
			||||||
import classnames from 'classnames';
 | 
					import classnames from 'classnames';
 | 
				
			||||||
import {fetchEventSource} from '@microsoft/fetch-event-source';
 | 
					import { fetchEventSource } from '@microsoft/fetch-event-source';
 | 
				
			||||||
import {ConversationPair, getConversationPairs, Record} from '../utils/get-conversation-pairs';
 | 
					import { ConversationPair, getConversationPairs, Record } from '../utils/get-conversation-pairs';
 | 
				
			||||||
import logo from '../../../build/appicon.png';
 | 
					import logo from '../../../build/appicon.png';
 | 
				
			||||||
import MarkdownRender from '../components/MarkdownRender';
 | 
					import MarkdownRender from '../components/MarkdownRender';
 | 
				
			||||||
import {ToolTipButton} from '../components/ToolTipButton';
 | 
					import { ToolTipButton } from '../components/ToolTipButton';
 | 
				
			||||||
import {ArrowCircleUp28Regular, Delete28Regular, RecordStop28Regular} from '@fluentui/react-icons';
 | 
					import { ArrowCircleUp28Regular, Delete28Regular, RecordStop28Regular } from '@fluentui/react-icons';
 | 
				
			||||||
import {CopyButton} from '../components/CopyButton';
 | 
					import { CopyButton } from '../components/CopyButton';
 | 
				
			||||||
import {ReadButton} from '../components/ReadButton';
 | 
					import { ReadButton } from '../components/ReadButton';
 | 
				
			||||||
import {toast} from 'react-toastify';
 | 
					import { toast } from 'react-toastify';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const userName = 'M E';
 | 
					export const userName = 'M E';
 | 
				
			||||||
export const botName = 'A I';
 | 
					export const botName = 'A I';
 | 
				
			||||||
@ -46,7 +46,7 @@ export type Conversations = {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ChatPanel: FC = observer(() => {
 | 
					const ChatPanel: FC = observer(() => {
 | 
				
			||||||
  const {t} = useTranslation();
 | 
					  const { t } = useTranslation();
 | 
				
			||||||
  const [message, setMessage] = useState('');
 | 
					  const [message, setMessage] = useState('');
 | 
				
			||||||
  const bodyRef = useRef<HTMLDivElement>(null);
 | 
					  const bodyRef = useRef<HTMLDivElement>(null);
 | 
				
			||||||
  const inputRef = useRef<HTMLTextAreaElement>(null);
 | 
					  const inputRef = useRef<HTMLTextAreaElement>(null);
 | 
				
			||||||
@ -95,7 +95,7 @@ const ChatPanel: FC = observer(() => {
 | 
				
			|||||||
    if (e.type === 'click' || (e.keyCode === 13 && !e.shiftKey)) {
 | 
					    if (e.type === 'click' || (e.keyCode === 13 && !e.shiftKey)) {
 | 
				
			||||||
      e.preventDefault();
 | 
					      e.preventDefault();
 | 
				
			||||||
      if (commonStore.modelStatus === ModelStatus.Offline) {
 | 
					      if (commonStore.modelStatus === ModelStatus.Offline) {
 | 
				
			||||||
        toast(t('Please click the button in the top right corner to start the model'), {type: 'warning'});
 | 
					        toast(t('Please click the button in the top right corner to start the model'), { type: 'warning' });
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (!message) return;
 | 
					      if (!message) return;
 | 
				
			||||||
@ -127,13 +127,13 @@ const ChatPanel: FC = observer(() => {
 | 
				
			|||||||
          const questionId = commonStore.conversationsOrder[index - 1];
 | 
					          const questionId = commonStore.conversationsOrder[index - 1];
 | 
				
			||||||
          const question = commonStore.conversations[questionId];
 | 
					          const question = commonStore.conversations[questionId];
 | 
				
			||||||
          if (question.done && question.type === MessageType.Normal && question.sender === userName) {
 | 
					          if (question.done && question.type === MessageType.Normal && question.sender === userName) {
 | 
				
			||||||
            records.push({question: question.content, answer: conversation.content});
 | 
					            records.push({ question: question.content, answer: conversation.content });
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    const messages = getConversationPairs(records, false);
 | 
					    const messages = getConversationPairs(records, false);
 | 
				
			||||||
    (messages as ConversationPair[]).push({role: 'user', content: message});
 | 
					    (messages as ConversationPair[]).push({ role: 'user', content: message });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const answerId = uuid();
 | 
					    const answerId = uuid();
 | 
				
			||||||
    commonStore.conversations[answerId] = {
 | 
					    commonStore.conversations[answerId] = {
 | 
				
			||||||
@ -224,7 +224,7 @@ const ChatPanel: FC = observer(() => {
 | 
				
			|||||||
            <Avatar
 | 
					            <Avatar
 | 
				
			||||||
              color={conversation.color}
 | 
					              color={conversation.color}
 | 
				
			||||||
              name={conversation.sender}
 | 
					              name={conversation.sender}
 | 
				
			||||||
              image={conversation.avatarImg ? {src: conversation.avatarImg} : undefined}
 | 
					              image={conversation.avatarImg ? { src: conversation.avatarImg } : undefined}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <div
 | 
					            <div
 | 
				
			||||||
              className={classnames(
 | 
					              className={classnames(
 | 
				
			||||||
@ -236,15 +236,15 @@ const ChatPanel: FC = observer(() => {
 | 
				
			|||||||
              <MarkdownRender>{conversation.content}</MarkdownRender>
 | 
					              <MarkdownRender>{conversation.content}</MarkdownRender>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div className="flex flex-col gap-1 items-start">
 | 
					            <div className="flex flex-col gap-1 items-start">
 | 
				
			||||||
              <div className="grow"/>
 | 
					              <div className="grow" />
 | 
				
			||||||
              {(conversation.type === MessageType.Error || !conversation.done) &&
 | 
					              {(conversation.type === MessageType.Error || !conversation.done) &&
 | 
				
			||||||
                <PresenceBadge size="extra-small" status={
 | 
					                <PresenceBadge size="extra-small" status={
 | 
				
			||||||
                  conversation.type === MessageType.Error ? 'busy' : 'away'
 | 
					                  conversation.type === MessageType.Error ? 'busy' : 'away'
 | 
				
			||||||
                }/>
 | 
					                } />
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
              <div className="flex invisible" id={'utils-' + uuid}>
 | 
					              <div className="flex invisible" id={'utils-' + uuid}>
 | 
				
			||||||
                <ReadButton content={conversation.content}/>
 | 
					                <ReadButton content={conversation.content} />
 | 
				
			||||||
                <CopyButton content={conversation.content}/>
 | 
					                <CopyButton content={conversation.content} />
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>;
 | 
					          </div>;
 | 
				
			||||||
@ -252,12 +252,14 @@ const ChatPanel: FC = observer(() => {
 | 
				
			|||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div className="flex items-end gap-2">
 | 
					      <div className="flex items-end gap-2">
 | 
				
			||||||
        <ToolTipButton desc={t('Clear')}
 | 
					        <ToolTipButton desc={t('Clear')}
 | 
				
			||||||
                       icon={<Delete28Regular/>}
 | 
					          icon={<Delete28Regular />}
 | 
				
			||||||
                       size="large" shape="circular" appearance="subtle"
 | 
					          size="large" shape="circular" appearance="subtle"
 | 
				
			||||||
                       onClick={(e) => {
 | 
					          onClick={(e) => {
 | 
				
			||||||
                         commonStore.setConversations({});
 | 
					            if (generating)
 | 
				
			||||||
                         commonStore.setConversationsOrder([]);
 | 
					              sseControllerRef.current?.abort();
 | 
				
			||||||
                       }}
 | 
					            commonStore.setConversations({});
 | 
				
			||||||
 | 
					            commonStore.setConversationsOrder([]);
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
        <Textarea
 | 
					        <Textarea
 | 
				
			||||||
          ref={inputRef}
 | 
					          ref={inputRef}
 | 
				
			||||||
@ -269,21 +271,21 @@ const ChatPanel: FC = observer(() => {
 | 
				
			|||||||
          onKeyDown={handleKeyDownOrClick}
 | 
					          onKeyDown={handleKeyDownOrClick}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
        <ToolTipButton desc={generating ? t('Stop') : t('Send')}
 | 
					        <ToolTipButton desc={generating ? t('Stop') : t('Send')}
 | 
				
			||||||
                       icon={generating ? <RecordStop28Regular/> : <ArrowCircleUp28Regular/>}
 | 
					          icon={generating ? <RecordStop28Regular /> : <ArrowCircleUp28Regular />}
 | 
				
			||||||
                       size="large" shape="circular" appearance="subtle"
 | 
					          size="large" shape="circular" appearance="subtle"
 | 
				
			||||||
                       onClick={(e) => {
 | 
					          onClick={(e) => {
 | 
				
			||||||
                         if (generating) {
 | 
					            if (generating) {
 | 
				
			||||||
                           sseControllerRef.current?.abort();
 | 
					              sseControllerRef.current?.abort();
 | 
				
			||||||
                           if (lastMessageId) {
 | 
					              if (lastMessageId) {
 | 
				
			||||||
                             commonStore.conversations[lastMessageId].type = MessageType.Error;
 | 
					                commonStore.conversations[lastMessageId].type = MessageType.Error;
 | 
				
			||||||
                             commonStore.conversations[lastMessageId].done = true;
 | 
					                commonStore.conversations[lastMessageId].done = true;
 | 
				
			||||||
                             commonStore.setConversations(commonStore.conversations);
 | 
					                commonStore.setConversations(commonStore.conversations);
 | 
				
			||||||
                             commonStore.setConversationsOrder([...commonStore.conversationsOrder]);
 | 
					                commonStore.setConversationsOrder([...commonStore.conversationsOrder]);
 | 
				
			||||||
                           }
 | 
					              }
 | 
				
			||||||
                         } else {
 | 
					            } else {
 | 
				
			||||||
                           handleKeyDownOrClick(e);
 | 
					              handleKeyDownOrClick(e);
 | 
				
			||||||
                         }
 | 
					            }
 | 
				
			||||||
                       }}/>
 | 
					          }} />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
@ -304,26 +306,26 @@ const badgeStatus: { [modelStatus: number]: PresenceBadgeStatus } = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Chat: FC = observer(() => {
 | 
					export const Chat: FC = observer(() => {
 | 
				
			||||||
  const {t} = useTranslation();
 | 
					  const { t } = useTranslation();
 | 
				
			||||||
  const port = commonStore.getCurrentModelConfig().apiParameters.apiPort;
 | 
					  const port = commonStore.getCurrentModelConfig().apiParameters.apiPort;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className="flex flex-col gap-1 p-2 h-full overflow-hidden">
 | 
					    <div className="flex flex-col gap-1 p-2 h-full overflow-hidden">
 | 
				
			||||||
      <div className="flex justify-between items-center">
 | 
					      <div className="flex justify-between items-center">
 | 
				
			||||||
        <div className="flex items-center gap-2">
 | 
					        <div className="flex items-center gap-2">
 | 
				
			||||||
          <PresenceBadge status={badgeStatus[commonStore.modelStatus]}/>
 | 
					          <PresenceBadge status={badgeStatus[commonStore.modelStatus]} />
 | 
				
			||||||
          <Text size={100}>{t('Model Status') + ': ' + t(statusText[commonStore.modelStatus])}</Text>
 | 
					          <Text size={100}>{t('Model Status') + ': ' + t(statusText[commonStore.modelStatus])}</Text>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div className="flex items-center gap-2">
 | 
					        <div className="flex items-center gap-2">
 | 
				
			||||||
          <ConfigSelector size="small"/>
 | 
					          <ConfigSelector size="small" />
 | 
				
			||||||
          <RunButton iconMode/>
 | 
					          <RunButton iconMode />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <Text size={100}>
 | 
					      <Text size={100}>
 | 
				
			||||||
        {t('This tool’s API is compatible with OpenAI API. It can be used with any ChatGPT tool you like. Go to the settings of some ChatGPT tool, replace the \'https://api.openai.com\' part in the API address with \'') + `http://127.0.0.1:${port}` + '\'.'}
 | 
					        {t('This tool’s API is compatible with OpenAI API. It can be used with any ChatGPT tool you like. Go to the settings of some ChatGPT tool, replace the \'https://api.openai.com\' part in the API address with \'') + `http://127.0.0.1:${port}` + '\'.'}
 | 
				
			||||||
      </Text>
 | 
					      </Text>
 | 
				
			||||||
      <Divider style={{flexGrow: 0}}/>
 | 
					      <Divider style={{ flexGrow: 0 }} />
 | 
				
			||||||
      <ChatPanel/>
 | 
					      <ChatPanel />
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user