refactor: title generation logic

- Changed the title generation endpoint from POST to GET, allowing for more efficient retrieval of titles based on conversation ID.
- Implemented exponential backoff for title fetching retries, improving responsiveness and reducing server load.
- Introduced a queuing mechanism for title generation, ensuring titles are generated only after job completion.
- Updated relevant components and hooks to utilize the new title generation logic, enhancing user experience and application performance.
This commit is contained in:
Danny Avila 2025-12-17 17:10:14 -05:00
parent 24263c9874
commit c7bc5548bc
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
9 changed files with 118 additions and 97 deletions

View file

@ -21,7 +21,6 @@ import type {
} from 'librechat-data-provider';
import type { TResData, TFinalResData, ConvoGenerator } from '~/common';
import type { InfiniteData } from '@tanstack/react-query';
import type { TGenTitleMutation } from '~/data-provider';
import type { SetterOrUpdater, Resetter } from 'recoil';
import type { ConversationCursorData } from '~/utils';
import {
@ -54,7 +53,6 @@ type TSyncData = {
export type EventHandlerParams = {
isAddedRequest?: boolean;
genTitle?: TGenTitleMutation;
setCompleted: React.Dispatch<React.SetStateAction<Set<unknown>>>;
setMessages: (messages: TMessage[]) => void;
getMessages: () => TMessage[] | undefined;
@ -167,7 +165,6 @@ export const getConvoTitle = ({
};
export default function useEventHandlers({
genTitle,
setMessages,
getMessages,
setCompleted,
@ -258,13 +255,6 @@ export default function useEventHandlers({
removeConvoFromAllQueries(queryClient, submission.conversation.conversationId as string);
}
// refresh title
if (genTitle && isNewConvo && requestMessage.parentMessageId === Constants.NO_PARENT) {
setTimeout(() => {
genTitle.mutate({ conversationId: convoUpdate.conversationId as string });
}, 2500);
}
if (setConversation && !isAddedRequest) {
setConversation((prevState) => {
const update = { ...prevState, ...convoUpdate };
@ -274,7 +264,7 @@ export default function useEventHandlers({
setIsSubmitting(false);
},
[setMessages, setConversation, genTitle, isAddedRequest, queryClient, setIsSubmitting],
[setMessages, setConversation, isAddedRequest, queryClient, setIsSubmitting],
);
const syncHandler = useCallback(
@ -443,7 +433,7 @@ export default function useEventHandlers({
messages,
conversation: submissionConvo,
isRegenerate = false,
isTemporary = false,
isTemporary: _isTemporary = false,
} = submission;
try {
@ -532,19 +522,6 @@ export default function useEventHandlers({
removeConvoFromAllQueries(queryClient, submissionConvo.conversationId);
}
/* Refresh title */
if (
genTitle &&
isNewConvo &&
!isTemporary &&
requestMessage &&
requestMessage.parentMessageId === Constants.NO_PARENT
) {
setTimeout(() => {
genTitle.mutate({ conversationId: conversation.conversationId as string });
}, 2500);
}
if (setConversation && isAddedRequest !== true) {
setConversation((prevState) => {
const update = {
@ -588,7 +565,6 @@ export default function useEventHandlers({
},
[
navigate,
genTitle,
getMessages,
setMessages,
queryClient,

View file

@ -12,8 +12,8 @@ import {
} from 'librechat-data-provider';
import type { TMessage, TPayload, TSubmission, EventSubmission } from 'librechat-data-provider';
import type { EventHandlerParams } from './useEventHandlers';
import { useGenTitleMutation, useGetStartupConfig, useGetUserBalance } from '~/data-provider';
import { activeJobsQueryKey } from '~/data-provider/SSE/queries';
import { useGetStartupConfig, useGetUserBalance } from '~/data-provider';
import { activeJobsQueryKey, queueTitleGeneration } from '~/data-provider/SSE/queries';
import { useAuthContext } from '~/hooks/AuthContext';
import useEventHandlers from './useEventHandlers';
import store from '~/store';
@ -61,7 +61,6 @@ export default function useResumableSSE(
isAddedRequest = false,
runIndex = 0,
) {
const genTitle = useGenTitleMutation();
const queryClient = useQueryClient();
const setActiveRunId = useSetRecoilState(store.activeRunFamily(runIndex));
@ -123,7 +122,6 @@ export default function useResumableSSE(
attachmentHandler,
resetContentHandler,
} = useEventHandlers({
genTitle,
setMessages,
getMessages,
setCompleted,
@ -596,6 +594,11 @@ export default function useResumableSSE(
setStreamId(newStreamId);
// Optimistically add to active jobs
addActiveJob(newStreamId);
// Queue title generation if this is a new conversation (first message)
const isNewConvo = submission.userMessage?.parentMessageId === Constants.NO_PARENT;
if (isNewConvo) {
queueTitleGeneration(newStreamId);
}
subscribeToStream(newStreamId, submission);
} else {
console.error('[ResumableSSE] Failed to get streamId from startGeneration');

View file

@ -13,7 +13,7 @@ import {
import type { TMessage, TPayload, TSubmission, EventSubmission } from 'librechat-data-provider';
import type { EventHandlerParams } from './useEventHandlers';
import type { TResData } from '~/common';
import { useGenTitleMutation, useGetStartupConfig, useGetUserBalance } from '~/data-provider';
import { useGetStartupConfig, useGetUserBalance } from '~/data-provider';
import { useAuthContext } from '~/hooks/AuthContext';
import useEventHandlers from './useEventHandlers';
import store from '~/store';
@ -44,7 +44,6 @@ export default function useSSE(
isAddedRequest = false,
runIndex = 0,
) {
const genTitle = useGenTitleMutation();
const setActiveRunId = useSetRecoilState(store.activeRunFamily(runIndex));
const { token, isAuthenticated } = useAuthContext();
@ -73,7 +72,6 @@ export default function useSSE(
attachmentHandler,
abortConversation,
} = useEventHandlers({
genTitle,
setMessages,
getMessages,
setCompleted,