Download client/src/hooks/Chat/useChatFunctions.ts from Zhitomir/chat: direct link, hf CLI and curl.
- Browser
- Download file 7.83 kB
-
https://huggingface.co/spaces/Zhitomir/chat/resolve/main/client/src/hooks/Chat/useChatFunctions.ts
- Command line
-
hf download hf://spaces/Zhitomir/chat/client/src/hooks/Chat/useChatFunctions.ts
-
curl -L -o useChatFunctions.ts https://huggingface.co/spaces/Zhitomir/chat/resolve/main/client/src/hooks/Chat/useChatFunctions.ts
7.83 kB
| import { v4 } from 'uuid'; | |
| import { useQueryClient } from '@tanstack/react-query'; | |
| import { | |
| Constants, | |
| QueryKeys, | |
| ContentTypes, | |
| parseCompactConvo, | |
| isAssistantsEndpoint, | |
| } from 'librechat-data-provider'; | |
| import { useSetRecoilState, useResetRecoilState } from 'recoil'; | |
| import type { | |
| TMessage, | |
| TSubmission, | |
| TConversation, | |
| TEndpointOption, | |
| TEndpointsConfig, | |
| } from 'librechat-data-provider'; | |
| import type { SetterOrUpdater } from 'recoil'; | |
| import type { TAskFunction, ExtendedFile } from '~/common'; | |
| import useSetFilesToDelete from '~/hooks/Files/useSetFilesToDelete'; | |
| import useGetSender from '~/hooks/Conversations/useGetSender'; | |
| import { getEndpointField, logger } from '~/utils'; | |
| import useUserKey from '~/hooks/Input/useUserKey'; | |
| import store from '~/store'; | |
| export default function useChatFunctions({ | |
| index = 0, | |
| files, | |
| setFiles, | |
| getMessages, | |
| setMessages, | |
| isSubmitting, | |
| conversation, | |
| latestMessage, | |
| setSubmission, | |
| setLatestMessage, | |
| }: { | |
| index?: number; | |
| isSubmitting: boolean; | |
| paramId?: string | undefined; | |
| conversation: TConversation | null; | |
| latestMessage: TMessage | null; | |
| getMessages: () => TMessage[] | undefined; | |
| setMessages: (messages: TMessage[]) => void; | |
| files?: Map<string, ExtendedFile>; | |
| setFiles?: SetterOrUpdater<Map<string, ExtendedFile>>; | |
| setSubmission: SetterOrUpdater<TSubmission | null>; | |
| setLatestMessage?: SetterOrUpdater<TMessage | null>; | |
| }) { | |
| const resetLatestMultiMessage = useResetRecoilState(store.latestMessageFamily(index + 1)); | |
| const setShowStopButton = useSetRecoilState(store.showStopButtonByIndex(index)); | |
| const setFilesToDelete = useSetFilesToDelete(); | |
| const getSender = useGetSender(); | |
| const queryClient = useQueryClient(); | |
| const { getExpiry } = useUserKey(conversation?.endpoint ?? ''); | |
| const ask: TAskFunction = ( | |
| { | |
| text, | |
| overrideConvoId, | |
| overrideUserMessageId, | |
| parentMessageId = null, | |
| conversationId = null, | |
| messageId = null, | |
| }, | |
| { | |
| editedText = null, | |
| editedMessageId = null, | |
| resubmitFiles = false, | |
| isRegenerate = false, | |
| isContinued = false, | |
| isEdited = false, | |
| overrideMessages, | |
| } = {}, | |
| ) => { | |
| setShowStopButton(false); | |
| resetLatestMultiMessage(); | |
| if (!!isSubmitting || text === '') { | |
| return; | |
| } | |
| const endpoint = conversation?.endpoint; | |
| if (endpoint === null) { | |
| console.error('No endpoint available'); | |
| return; | |
| } | |
| conversationId = conversationId ?? conversation?.conversationId ?? null; | |
| if (conversationId == 'search') { | |
| console.error('cannot send any message under search view!'); | |
| return; | |
| } | |
| if (isContinued && !latestMessage) { | |
| console.error('cannot continue AI message without latestMessage!'); | |
| return; | |
| } | |
| const isEditOrContinue = isEdited || isContinued; | |
| let currentMessages: TMessage[] | null = overrideMessages ?? getMessages() ?? []; | |
| // construct the query message | |
| // this is not a real messageId, it is used as placeholder before real messageId returned | |
| text = text.trim(); | |
| const intermediateId = overrideUserMessageId ?? v4(); | |
| parentMessageId = parentMessageId || latestMessage?.messageId || Constants.NO_PARENT; | |
| if (conversationId == 'new') { | |
| parentMessageId = Constants.NO_PARENT; | |
| currentMessages = []; | |
| conversationId = null; | |
| } | |
| const parentMessage = currentMessages?.find( | |
| (msg) => msg.messageId === latestMessage?.parentMessageId, | |
| ); | |
| let thread_id = parentMessage?.thread_id ?? latestMessage?.thread_id; | |
| if (!thread_id) { | |
| thread_id = currentMessages.find((message) => message.thread_id)?.thread_id; | |
| } | |
| const endpointsConfig = queryClient.getQueryData<TEndpointsConfig>([QueryKeys.endpoints]); | |
| const endpointType = getEndpointField(endpointsConfig, endpoint, 'type'); | |
| // set the endpoint option | |
| const convo = parseCompactConvo({ | |
| endpoint, | |
| endpointType, | |
| conversation: conversation ?? {}, | |
| }); | |
| const { modelDisplayLabel } = endpointsConfig?.[endpoint ?? ''] ?? {}; | |
| const endpointOption = { | |
| ...convo, | |
| endpoint, | |
| thread_id, | |
| endpointType, | |
| overrideConvoId, | |
| key: getExpiry(), | |
| modelDisplayLabel, | |
| overrideUserMessageId, | |
| } as TEndpointOption; | |
| const responseSender = getSender({ model: conversation?.model, ...endpointOption }); | |
| const currentMsg: TMessage = { | |
| text, | |
| sender: 'User', | |
| isCreatedByUser: true, | |
| parentMessageId, | |
| conversationId, | |
| messageId: isContinued && messageId ? messageId : intermediateId, | |
| thread_id, | |
| error: false, | |
| }; | |
| const reuseFiles = (isRegenerate || resubmitFiles) && parentMessage?.files; | |
| if (setFiles && reuseFiles && parentMessage.files?.length) { | |
| currentMsg.files = parentMessage.files; | |
| setFiles(new Map()); | |
| setFilesToDelete({}); | |
| } else if (setFiles && files && files.size > 0) { | |
| currentMsg.files = Array.from(files.values()).map((file) => ({ | |
| file_id: file.file_id, | |
| filepath: file.filepath, | |
| type: file.type || '', // Ensure type is not undefined | |
| height: file.height, | |
| width: file.width, | |
| })); | |
| setFiles(new Map()); | |
| setFilesToDelete({}); | |
| } | |
| // construct the placeholder response message | |
| const generation = editedText ?? latestMessage?.text ?? ''; | |
| const responseText = isEditOrContinue ? generation : ''; | |
| const responseMessageId = editedMessageId ?? latestMessage?.messageId ?? null; | |
| const initialResponse: TMessage = { | |
| sender: responseSender, | |
| text: responseText, | |
| endpoint: endpoint ?? '', | |
| parentMessageId: isRegenerate ? messageId : intermediateId, | |
| messageId: responseMessageId ?? `${isRegenerate ? messageId : intermediateId}_`, | |
| thread_id, | |
| conversationId, | |
| unfinished: false, | |
| isCreatedByUser: false, | |
| isEdited: isEditOrContinue, | |
| iconURL: convo.iconURL, | |
| error: false, | |
| }; | |
| if (isAssistantsEndpoint(endpoint)) { | |
| initialResponse.model = conversation?.assistant_id ?? ''; | |
| initialResponse.text = ''; | |
| initialResponse.content = [ | |
| { | |
| type: ContentTypes.TEXT, | |
| [ContentTypes.TEXT]: { | |
| value: responseText, | |
| }, | |
| }, | |
| ]; | |
| } else { | |
| setShowStopButton(true); | |
| } | |
| if (isContinued) { | |
| currentMessages = currentMessages.filter((msg) => msg.messageId !== responseMessageId); | |
| } | |
| const submission: TSubmission = { | |
| conversation: { | |
| ...conversation, | |
| conversationId, | |
| }, | |
| endpointOption, | |
| userMessage: { | |
| ...currentMsg, | |
| generation, | |
| responseMessageId, | |
| overrideParentMessageId: isRegenerate ? messageId : null, | |
| }, | |
| messages: currentMessages, | |
| isEdited: isEditOrContinue, | |
| isContinued, | |
| isRegenerate, | |
| initialResponse, | |
| }; | |
| if (isRegenerate) { | |
| setMessages([...submission.messages, initialResponse]); | |
| } else { | |
| setMessages([...submission.messages, currentMsg, initialResponse]); | |
| } | |
| if (index === 0 && setLatestMessage) { | |
| setLatestMessage(initialResponse); | |
| } | |
| setSubmission(submission); | |
| logger.log('Submission:'); | |
| logger.dir(submission, { depth: null }); | |
| }; | |
| const regenerate = ({ parentMessageId }) => { | |
| const messages = getMessages(); | |
| const parentMessage = messages?.find((element) => element.messageId == parentMessageId); | |
| if (parentMessage && parentMessage.isCreatedByUser) { | |
| ask({ ...parentMessage }, { isRegenerate: true }); | |
| } else { | |
| console.error( | |
| 'Failed to regenerate the message: parentMessage not found or not created by user.', | |
| ); | |
| } | |
| }; | |
| return { | |
| ask, | |
| regenerate, | |
| }; | |
| } | |