regenerate button (#138)
This commit is contained in:
		
							parent
							
								
									d7fdcd0dfe
								
							
						
					
					
						commit
						d27326125b
					
				|  | @ -4,7 +4,6 @@ import { ChatInput } from "./ChatInput"; | |||
| import { ChatLoader } from "./ChatLoader"; | ||||
| import { ChatMessage } from "./ChatMessage"; | ||||
| import { ModelSelect } from "./ModelSelect"; | ||||
| import { Regenerate } from "./Regenerate"; | ||||
| import { SystemPrompt } from "./SystemPrompt"; | ||||
| 
 | ||||
| interface Props { | ||||
|  | @ -17,15 +16,13 @@ interface Props { | |||
|   messageError: boolean; | ||||
|   loading: boolean; | ||||
|   lightMode: "light" | "dark"; | ||||
|   onSend: (message: Message, isResend: boolean) => void; | ||||
|   onSend: (message: Message, isResend?: boolean, deleteCount?: number) => void; | ||||
|   onUpdateConversation: (conversation: Conversation, data: KeyValuePair) => void; | ||||
|   onEditMessage: (message: Message, messageIndex: number) => void; | ||||
|   onDeleteMessage: (message: Message, messageIndex: number) => void; | ||||
|   onRegenerate: () => void; | ||||
|   stopConversationRef: MutableRefObject<boolean>; | ||||
| } | ||||
| 
 | ||||
| export const Chat: FC<Props> = ({ conversation, models, apiKey, serverSideApiKeyIsSet, messageIsStreaming, modelError, messageError, loading, lightMode, onSend, onUpdateConversation, onEditMessage, onDeleteMessage, onRegenerate, stopConversationRef }) => { | ||||
| export const Chat: FC<Props> = ({ conversation, models, apiKey, serverSideApiKeyIsSet, messageIsStreaming, modelError, messageError, loading, lightMode, onSend, onUpdateConversation, onEditMessage, stopConversationRef }) => { | ||||
|   const [currentMessage, setCurrentMessage] = useState<Message>(); | ||||
|   const [autoScrollEnabled, setAutoScrollEnabled] = useState(true); | ||||
| 
 | ||||
|  | @ -55,6 +52,7 @@ export const Chat: FC<Props> = ({ conversation, models, apiKey, serverSideApiKey | |||
|   useEffect(() => { | ||||
|     scrollToBottom(); | ||||
|     textareaRef.current?.focus(); | ||||
|     setCurrentMessage(conversation.messages[conversation.messages.length - 2]); | ||||
|   }, [conversation.messages]); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|  | @ -69,6 +67,8 @@ export const Chat: FC<Props> = ({ conversation, models, apiKey, serverSideApiKey | |||
|     } | ||||
|   }, []); | ||||
| 
 | ||||
|   console.log("currentMessage", currentMessage); | ||||
| 
 | ||||
|   return ( | ||||
|     <div className="relative flex-1 overflow-none dark:bg-[#343541] bg-white"> | ||||
|       {!(apiKey || serverSideApiKeyIsSet) ? ( | ||||
|  | @ -120,7 +120,6 @@ export const Chat: FC<Props> = ({ conversation, models, apiKey, serverSideApiKey | |||
|                     messageIndex={index} | ||||
|                     lightMode={lightMode} | ||||
|                     onEditMessage={onEditMessage} | ||||
|                     onDeleteMessage={onDeleteMessage} | ||||
|                   /> | ||||
|                 ))} | ||||
| 
 | ||||
|  | @ -134,27 +133,22 @@ export const Chat: FC<Props> = ({ conversation, models, apiKey, serverSideApiKey | |||
|             )} | ||||
|           </div> | ||||
| 
 | ||||
|           {messageError ? ( | ||||
|             <Regenerate | ||||
|               onRegenerate={() => { | ||||
|                 if (currentMessage) { | ||||
|                   onSend(currentMessage, true); | ||||
|                 } | ||||
|               }} | ||||
|             /> | ||||
|           ) : ( | ||||
|             <ChatInput | ||||
|               stopConversationRef={stopConversationRef} | ||||
|               textareaRef={textareaRef} | ||||
|               messageIsStreaming={messageIsStreaming} | ||||
|               model={conversation.model} | ||||
|               onSend={(message) => { | ||||
|                 setCurrentMessage(message); | ||||
|                 onSend(message, false); | ||||
|               }} | ||||
|               onRegenerate={onRegenerate} | ||||
|             /> | ||||
|           )} | ||||
|           <ChatInput | ||||
|             stopConversationRef={stopConversationRef} | ||||
|             textareaRef={textareaRef} | ||||
|             messageIsStreaming={messageIsStreaming} | ||||
|             messages={conversation.messages} | ||||
|             model={conversation.model} | ||||
|             onSend={(message) => { | ||||
|               setCurrentMessage(message); | ||||
|               onSend(message); | ||||
|             }} | ||||
|             onRegenerate={() => { | ||||
|               if (currentMessage) { | ||||
|                 onSend(currentMessage, true, 2); | ||||
|               } | ||||
|             }} | ||||
|           /> | ||||
|         </> | ||||
|       )} | ||||
|     </div> | ||||
|  |  | |||
|  | @ -1,17 +1,18 @@ | |||
| import { Message, OpenAIModel, OpenAIModelID } from "@/types"; | ||||
| import { IconPlayerStop, IconSend } from "@tabler/icons-react"; | ||||
| import { IconPlayerStop, IconRepeat, IconSend } from "@tabler/icons-react"; | ||||
| import { FC, KeyboardEvent, MutableRefObject, useEffect, useState } from "react"; | ||||
| 
 | ||||
| interface Props { | ||||
|   messageIsStreaming: boolean; | ||||
|   model: OpenAIModel; | ||||
|   messages: Message[]; | ||||
|   onSend: (message: Message) => void; | ||||
|   onRegenerate: () => void; | ||||
|   stopConversationRef: MutableRefObject<boolean>; | ||||
|   textareaRef: MutableRefObject<HTMLTextAreaElement | null>; | ||||
| } | ||||
| 
 | ||||
| export const ChatInput: FC<Props> = ({ onSend, messageIsStreaming, model, stopConversationRef, textareaRef }) => { | ||||
| export const ChatInput: FC<Props> = ({ messageIsStreaming, model, messages, onSend, onRegenerate, stopConversationRef, textareaRef }) => { | ||||
|   const [content, setContent] = useState<string>(); | ||||
|   const [isTyping, setIsTyping] = useState<boolean>(false); | ||||
| 
 | ||||
|  | @ -90,6 +91,20 @@ export const ChatInput: FC<Props> = ({ onSend, messageIsStreaming, model, stopCo | |||
|             Stop Generating | ||||
|           </button> | ||||
|         )} | ||||
| 
 | ||||
|         {!messageIsStreaming && messages.length > 0 && ( | ||||
|           <button | ||||
|             className="absolute -top-2 md:top-0 left-0 right-0 mx-auto dark:bg-[#343541] border w-fit border-gray-500 py-2 px-4 rounded text-black dark:text-white hover:opacity-50" | ||||
|             onClick={onRegenerate} | ||||
|           > | ||||
|             <IconRepeat | ||||
|               size={16} | ||||
|               className="inline-block mb-[2px]" | ||||
|             />{" "} | ||||
|             Regenerate response | ||||
|           </button> | ||||
|         )} | ||||
| 
 | ||||
|         <div className="flex flex-col w-full py-2 flex-grow md:py-3 md:pl-4 relative border border-black/10 bg-white dark:border-gray-900/50 dark:text-white dark:bg-[#40414F] rounded-md shadow-[0_0_10px_rgba(0,0,0,0.10)] dark:shadow-[0_0_15px_rgba(0,0,0,0.10)]"> | ||||
|           <textarea | ||||
|             ref={textareaRef} | ||||
|  |  | |||
|  | @ -10,10 +10,9 @@ interface Props { | |||
|   messageIndex: number; | ||||
|   lightMode: "light" | "dark"; | ||||
|   onEditMessage: (message: Message, messageIndex: number) => void; | ||||
|   onDeleteMessage: (message: Message, messageIndex: number) => void; | ||||
| } | ||||
| 
 | ||||
| export const ChatMessage: FC<Props> = ({ message, messageIndex, lightMode, onEditMessage, onDeleteMessage }) => { | ||||
| export const ChatMessage: FC<Props> = ({ message, messageIndex, lightMode, onEditMessage }) => { | ||||
|   const [isEditing, setIsEditing] = useState<boolean>(false); | ||||
|   const [isHovering, setIsHovering] = useState<boolean>(false); | ||||
|   const [messageContent, setMessageContent] = useState(message.content); | ||||
|  | @ -106,7 +105,7 @@ export const ChatMessage: FC<Props> = ({ message, messageIndex, lightMode, onEdi | |||
|               )} | ||||
| 
 | ||||
|               {(isHovering || window.innerWidth < 640) && !isEditing && ( | ||||
|                 <button className={`absolute ${window.innerWidth < 640 ? "right-1 bottom-1" : "right-[-20px] top-[26px]"}`}> | ||||
|                 <button className={`absolute ${window.innerWidth < 640 ? "right-3 bottom-1" : "right-[-20px] top-[26px]"}`}> | ||||
|                   <IconEdit | ||||
|                     size={20} | ||||
|                     className="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300" | ||||
|  |  | |||
|  | @ -32,13 +32,15 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => { | |||
| 
 | ||||
|   const stopConversationRef = useRef<boolean>(false); | ||||
| 
 | ||||
|   const handleSend = async (message: Message, isResend: boolean) => { | ||||
|   const handleSend = async (message: Message, isResend = false, deleteCount = 0) => { | ||||
|     if (selectedConversation) { | ||||
|       let updatedConversation: Conversation; | ||||
| 
 | ||||
|       if (isResend) { | ||||
|         const updatedMessages = [...selectedConversation.messages]; | ||||
|         updatedMessages.pop(); | ||||
|         for (let i = 0; i < deleteCount; i++) { | ||||
|           updatedMessages.pop(); | ||||
|         } | ||||
| 
 | ||||
|         updatedConversation = { | ||||
|           ...selectedConversation, | ||||
|  | @ -373,13 +375,9 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => { | |||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   const handleDeleteMessage = (message: Message, messageIndex: number) => {}; | ||||
| 
 | ||||
|   const handleRegenerate = () => {}; | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (currentMessage) { | ||||
|       handleSend(currentMessage, false); | ||||
|       handleSend(currentMessage); | ||||
|       setCurrentMessage(undefined); | ||||
|     } | ||||
|   }, [currentMessage]); | ||||
|  | @ -524,8 +522,6 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => { | |||
|               onSend={handleSend} | ||||
|               onUpdateConversation={handleUpdateConversation} | ||||
|               onEditMessage={handleEditMessage} | ||||
|               onDeleteMessage={handleDeleteMessage} | ||||
|               onRegenerate={handleRegenerate} | ||||
|               stopConversationRef={stopConversationRef} | ||||
|             /> | ||||
|           </div> | ||||
|  |  | |||
|  | @ -18,13 +18,13 @@ export const OpenAIStream = async (model: OpenAIModel, systemPrompt: string, key | |||
|         ...messages | ||||
|       ], | ||||
|       max_tokens: 1000, | ||||
|       temperature: 0.0, | ||||
|       temperature: 1, | ||||
|       stream: true | ||||
|     }) | ||||
|   }); | ||||
| 
 | ||||
|   if (res.status !== 200) { | ||||
|     const statusText = res.statusText;  | ||||
|     const statusText = res.statusText; | ||||
|     throw new Error(`OpenAI API returned an error: ${statusText}`); | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue