mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-24 17:10:12 +08:00
fix(web): keep reasoning and internet options when regenerating an answer (#18226)
This commit is contained in:
@@ -57,10 +57,10 @@ import {
|
||||
UseSendSingleMessageParameter,
|
||||
} from '../../hooks/use-send-single-message';
|
||||
import { useUploadFile } from '../../hooks/use-upload-file';
|
||||
import { useMessageReferences } from '../../hooks/use-message-references';
|
||||
import { EmptyReference } from '../../utils';
|
||||
import { EmptyReference, resolveResendOptions } from '../../utils';
|
||||
import { useAddChatBox } from '../use-add-box';
|
||||
import { useShowInternet } from '../use-show-internet';
|
||||
import { useMessageReferences } from '../../hooks/use-message-references';
|
||||
|
||||
type MultipleChatBoxProps = {
|
||||
controller: AbortController;
|
||||
@@ -140,6 +140,11 @@ const ChatCard = forwardRef(function ChatCard(
|
||||
|
||||
const llmId = useWatch({ control: form.control, name: 'llm_id' });
|
||||
|
||||
// Regenerate is triggered from the transcript, which has no access to the
|
||||
// input box's thinking / internet toggles. Remember what the last send used so
|
||||
// a retry keeps the same options instead of silently dropping them.
|
||||
const lastSendOptionsRef = useRef<NextMessageInputOnPressEnterParameter>({});
|
||||
|
||||
// Regenerate within this card: reuse the card's own message state and
|
||||
// resend with the card's model settings (llm_id, temperature, ...).
|
||||
const sendCardMessage = useCallback(
|
||||
@@ -147,6 +152,7 @@ const ChatCard = forwardRef(function ChatCard(
|
||||
sendMessage({
|
||||
message,
|
||||
messages,
|
||||
...resolveResendOptions(lastSendOptionsRef.current),
|
||||
...form.getValues(),
|
||||
storeHistoryMessages: false,
|
||||
omitSessionId: true,
|
||||
@@ -203,13 +209,15 @@ const ChatCard = forwardRef(function ChatCard(
|
||||
|
||||
useImperativeHandle(
|
||||
ref,
|
||||
(): HandlePressEnterType => (params) =>
|
||||
handlePressEnter({
|
||||
(): HandlePressEnterType => (params) => {
|
||||
lastSendOptionsRef.current = params;
|
||||
return handlePressEnter({
|
||||
...params,
|
||||
...form.getValues(),
|
||||
storeHistoryMessages: false,
|
||||
omitSessionId: true,
|
||||
}),
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
useChatStreamStore,
|
||||
useIsChatStreaming,
|
||||
} from '../chat-stream/store';
|
||||
import { resolveResendOptions } from '../utils';
|
||||
import { useCreateConversationBeforeSendMessage } from './use-chat-url';
|
||||
import { useFindPrologueFromDialogList } from './use-select-conversation-list';
|
||||
import { useUploadFile } from './use-upload-file';
|
||||
@@ -88,6 +89,11 @@ export const useSendMessage = () => {
|
||||
);
|
||||
const stopStream = useChatStreamStore((state) => state.stopStream);
|
||||
|
||||
// The regenerate button lives in the transcript, which has no access to the
|
||||
// input box's thinking / internet toggles. Remember what the last send used
|
||||
// so a retry keeps the same options instead of silently dropping them.
|
||||
const lastSendOptionsRef = useRef<NextMessageInputOnPressEnterParameter>({});
|
||||
|
||||
const sendMessage = useCallback(
|
||||
async ({
|
||||
message,
|
||||
@@ -98,17 +104,21 @@ export const useSendMessage = () => {
|
||||
}: {
|
||||
message: IMessage;
|
||||
currentConversationId?: string;
|
||||
messages: IMessage[];
|
||||
messages?: IMessage[];
|
||||
} & NextMessageInputOnPressEnterParameter) => {
|
||||
const sessionId = currentConversationId ?? conversationId;
|
||||
|
||||
lastSendOptionsRef.current = { enableInternet, enableThinking };
|
||||
|
||||
const { ok, aborted } = await runChatCompletionStream({
|
||||
conversationId: sessionId,
|
||||
chatId,
|
||||
// The history is always supplied by the caller, captured *before* it
|
||||
// appended the question and its placeholder to the store — reading it
|
||||
// here would include both and send the question twice.
|
||||
messages: [...explicitMessages, message],
|
||||
// An explicitly provided list is authoritative, even when empty
|
||||
// (e.g. regenerating the first question must truncate history).
|
||||
messages: [
|
||||
...(Array.isArray(explicitMessages) ? explicitMessages : messages),
|
||||
message,
|
||||
],
|
||||
enableThinking,
|
||||
enableInternet,
|
||||
});
|
||||
@@ -122,7 +132,7 @@ export const useSendMessage = () => {
|
||||
notification.error({ message: t('message.requestError') });
|
||||
}
|
||||
},
|
||||
[conversationId, chatId, failStream, t],
|
||||
[conversationId, chatId, messages, failStream, t],
|
||||
);
|
||||
|
||||
// Hand a failed question back to the input box, but only once the box is
|
||||
@@ -154,13 +164,11 @@ export const useSendMessage = () => {
|
||||
conversationId,
|
||||
};
|
||||
|
||||
// Snapshot the history before appendQuestion writes the question and its
|
||||
// assistant placeholder into the store.
|
||||
const history =
|
||||
useChatStreamStore.getState().sessions[conversationId]?.messages ?? [];
|
||||
|
||||
appendQuestion(conversationId, questionMessage);
|
||||
sendMessage({ message: questionMessage, messages: history });
|
||||
sendMessage({
|
||||
message: questionMessage,
|
||||
...resolveResendOptions(lastSendOptionsRef.current),
|
||||
});
|
||||
},
|
||||
[conversationId, isStreaming, appendQuestion, sendMessage],
|
||||
);
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
import { NextMessageInputOnPressEnterParameter } from '@/components/message-input/next';
|
||||
import { EmptyConversationId } from '@/constants/chat';
|
||||
import { IConversation, IReference } from '@/interfaces/database/chat';
|
||||
import storage from '@/utils/authorization-util';
|
||||
|
||||
/**
|
||||
* Regenerate is triggered from the transcript, which has no access to the input
|
||||
* box's thinking / internet toggles, so callers replay the options of their last
|
||||
* send. A view that hasn't sent anything yet has no record: fall back to the
|
||||
* input box's own defaults — it re-reads the persisted thinking level and starts
|
||||
* with internet off, so both stay in sync after a remount.
|
||||
*/
|
||||
export function resolveResendOptions(
|
||||
lastSendOptions: NextMessageInputOnPressEnterParameter,
|
||||
): NextMessageInputOnPressEnterParameter {
|
||||
const {
|
||||
enableThinking = storage.getThinkingLevel(),
|
||||
enableInternet = false,
|
||||
} = lastSendOptions;
|
||||
|
||||
return { enableThinking, enableInternet };
|
||||
}
|
||||
|
||||
export const isConversationIdExist = (conversationId: string) => {
|
||||
return conversationId !== EmptyConversationId && conversationId !== '';
|
||||
|
||||
Reference in New Issue
Block a user