Skip to content

Commit

Permalink
Chat AI: keep last Thinking block only (default)
Browse files Browse the repository at this point in the history
  • Loading branch information
enricoros committed Feb 25, 2025
1 parent 91929a3 commit 98eb1a6
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/apps/chat/editors/chat-persona.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export async function runPersonaOnConversationHead(
const parallelViewCount = getUXLabsHighPerformance() ? 0 : getInstantAppChatPanesCount();

// ai follow-up operations (fire/forget)
const { autoSpeak, autoSuggestDiagrams, autoSuggestHTMLUI, autoSuggestQuestions, autoTitleChat } = getChatAutoAI();
const { autoSpeak, autoSuggestDiagrams, autoSuggestHTMLUI, autoSuggestQuestions, autoTitleChat, chatKeepLastThinkingOnly } = getChatAutoAI();

// AutoSpeak
const autoSpeaker: PersonaProcessorInterface | null = autoSpeak !== 'off' ? new PersonaChatMessageSpeak(autoSpeak) : null;
Expand Down Expand Up @@ -129,6 +129,9 @@ export async function runPersonaOnConversationHead(
if (!hasBeenAborted && (autoSuggestDiagrams || autoSuggestHTMLUI || autoSuggestQuestions))
void autoChatFollowUps(conversationId, assistantMessageId, autoSuggestDiagrams, autoSuggestHTMLUI, autoSuggestQuestions);

if (chatKeepLastThinkingOnly)
cHandler.historyKeepLastThinkingOnly();

// return true if this succeeded
return messageStatus.outcome === 'success';
}
9 changes: 9 additions & 0 deletions src/apps/chat/store-app-chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ interface AppChatStore {
autoVndAntBreakpoints: boolean;
setAutoVndAntBreakpoints: (autoVndAntBreakpoints: boolean) => void;

chatKeepLastThinkingOnly: boolean,
setChatKeepLastThinkingOnly: (chatKeepLastThinkingOnly: boolean) => void;

// chat UI

clearFilters: () => void;
Expand Down Expand Up @@ -98,6 +101,9 @@ const useAppChatStore = create<AppChatStore>()(persist(
autoVndAntBreakpoints: true, // 2024-08-24: on as it saves user's money
setAutoVndAntBreakpoints: (autoVndAntBreakpoints: boolean) => _set({ autoVndAntBreakpoints }),

chatKeepLastThinkingOnly: true,
setChatKeepLastThinkingOnly: (chatKeepLastThinkingOnly: boolean) => _set({ chatKeepLastThinkingOnly }),

// Chat UI

clearFilters: () => _set({ filterHasDocFragments: false, filterHasImageAssets: false, filterHasStars: false }),
Expand Down Expand Up @@ -168,13 +174,15 @@ export const useChatAutoAI = () => useAppChatStore(useShallow(state => ({
autoSuggestQuestions: state.autoSuggestQuestions,
autoTitleChat: state.autoTitleChat,
autoVndAntBreakpoints: state.autoVndAntBreakpoints,
chatKeepLastThinkingOnly: state.chatKeepLastThinkingOnly,
setAutoSpeak: state.setAutoSpeak,
setAutoSuggestAttachmentPrompts: state.setAutoSuggestAttachmentPrompts,
setAutoSuggestDiagrams: state.setAutoSuggestDiagrams,
setAutoSuggestHTMLUI: state.setAutoSuggestHTMLUI,
setAutoSuggestQuestions: state.setAutoSuggestQuestions,
setAutoTitleChat: state.setAutoTitleChat,
setAutoVndAntBreakpoints: state.setAutoVndAntBreakpoints,
setChatKeepLastThinkingOnly: state.setChatKeepLastThinkingOnly,
})));

export const getChatAutoAI = (): {
Expand All @@ -185,6 +193,7 @@ export const getChatAutoAI = (): {
autoSuggestQuestions: boolean,
autoTitleChat: boolean,
autoVndAntBreakpoints: boolean,
chatKeepLastThinkingOnly: boolean,
} => useAppChatStore.getState();

export const useChatAutoSuggestHTMLUI = (): boolean =>
Expand Down
24 changes: 24 additions & 0 deletions src/apps/settings-modal/AppChatSettingsAI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,28 @@ import WarningRoundedIcon from '@mui/icons-material/WarningRounded';

import type { DModelDomainId } from '~/common/stores/llms/model.domains.types';
import { FormLabelStart } from '~/common/components/forms/FormLabelStart';
import { FormSelectControl, FormSelectOption } from '~/common/components/forms/FormSelectControl';
import { useLLMSelect } from '~/common/components/forms/useLLMSelect';
import { useLabsDevMode } from '~/common/state/store-ux-labs';
import { useModelDomain } from '~/common/stores/llms/hooks/useModelDomain';

import { useChatAutoAI } from '../chat/store-app-chat';


const _keepThinkingBlocksOptions: FormSelectOption<'all' | 'last-only'>[] = [
{
value: 'all',
label: 'All Messages',
description: 'Keep all blocks',
},
{
value: 'last-only',
label: 'Last Message Only',
description: 'Only keep last',
},
] as const;


function FormControlDomainModel(props: {
domainId: DModelDomainId,
title: React.ReactNode,
Expand Down Expand Up @@ -47,6 +62,7 @@ export function AppChatSettingsAI() {
autoSuggestHTMLUI, setAutoSuggestHTMLUI,
// autoSuggestQuestions, setAutoSuggestQuestions,
autoTitleChat, setAutoTitleChat,
chatKeepLastThinkingOnly, setChatKeepLastThinkingOnly,
} = useChatAutoAI();

const labsDevMode = useLabsDevMode();
Expand Down Expand Up @@ -107,6 +123,14 @@ export function AppChatSettingsAI() {
/>
)}

<FormSelectControl
title='Reasoning blocks'
tooltip='Controls how AI thinking/reasoning blocks are kept in your chat history. Keeping only in the last message (default) reduces clutter.'
options={_keepThinkingBlocksOptions}
value={chatKeepLastThinkingOnly ? 'last-only' : 'all'}
onChange={(value) => setChatKeepLastThinkingOnly(value === 'last-only')}
selectSx={{ minWidth: 140 }}
/>

<ListDivider inset='gutter'>Automatic AI Functions</ListDivider>

Expand Down
4 changes: 4 additions & 0 deletions src/common/chat-overlay/ConversationHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ export class ConversationHandler {
return _chatStoreActions.historyView(this.conversationId)?.find(m => m.id === messageId);
}

historyKeepLastThinkingOnly(): void {
return _chatStoreActions.historyKeepLastThinkingOnly(this.conversationId);
}

title(): string | undefined {
return _chatStoreActions.title(this.conversationId);
}
Expand Down
4 changes: 4 additions & 0 deletions src/common/stores/chat/chat.fragments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ export function isVoidFragment(fragment: DMessageFragment) {
return fragment.ft === 'void';
}

export function isVoidThinkingFragment(fragment: DMessageFragment): fragment is DMessageVoidFragment & { part: DVoidModelAuxPart } {
return fragment.ft === 'void' && fragment.part.pt === 'ma' && fragment.part.aType === 'reasoning';
}


export function isDocPart(part: DMessageContentFragment['part'] | DMessageAttachmentFragment['part']) {
return part.pt === 'doc';
Expand Down
44 changes: 43 additions & 1 deletion src/common/stores/chat/store-chats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { workspaceActions } from '~/common/stores/workspace/store-client-workspa
import { workspaceForConversationIdentity } from '~/common/stores/workspace/workspace.types';

import { DMessage, DMessageId, DMessageMetadata, MESSAGE_FLAG_AIX_SKIP, messageHasUserFlag } from './chat.message';
import type { DMessageFragment, DMessageFragmentId } from './chat.fragments';
import { DMessageFragment, DMessageFragmentId, isVoidThinkingFragment } from './chat.fragments';
import { V3StoreDataToHead, V4ToHeadConverters } from './chats.converters';
import { conversationTitle, createDConversation, DConversation, DConversationId, duplicateDConversation } from './chat.conversation';
import { estimateTokensForFragments } from './chat.tokens';
Expand All @@ -41,6 +41,7 @@ export interface ChatActions {
abortConversationTemp: (cId: DConversationId) => void;
historyReplace: (cId: DConversationId, messages: DMessage[]) => void;
historyTruncateToIncluded: (cId: DConversationId, mId: DMessageId, offset: number) => void;
historyKeepLastThinkingOnly: (cId: DConversationId) => void;
historyView: (cId: DConversationId) => Readonly<DMessage[]> | undefined;
appendMessage: (cId: DConversationId, message: DMessage) => void;
deleteMessage: (cId: DConversationId, mId: DMessageId) => void;
Expand Down Expand Up @@ -245,6 +246,47 @@ export const useChatStore = create<ConversationsStore>()(/*devtools(*/
};
}),

historyKeepLastThinkingOnly: (conversationId: DConversationId) =>
_get()._editConversation(conversationId, ({ messages: _currentMessages }) => {
let madeChanges = false;
const updatedMessages = [..._currentMessages];
let foundLastAssistant = false;

// reverse iterate
for (let i = updatedMessages.length - 1; i >= 0; i--) {
const message = updatedMessages[i];

// skip non-assistant messages
if (message.role !== 'assistant') continue;

// skip the last assistant message
if (!foundLastAssistant) {
foundLastAssistant = true;
continue;
}

// skip if doesn't have thinking blocks
const hasThinkingBlocks = message.fragments.some(isVoidThinkingFragment);
if (!hasThinkingBlocks) continue;

// Filter out thinking blocks
updatedMessages[i] = {
...message,
fragments: message.fragments.filter(fragment => !isVoidThinkingFragment(fragment)),
};
madeChanges = true;
}

if (!madeChanges) return {};

return {
messages: updatedMessages,
// No need to update the following as void fragments don't contribute
// tokenCount: updateMessagesTokenCounts(updatedMessages, true, 'historyKeepLastThinkingOnly'),
// updated: Date.now(),
};
}),

historyView: (conversationId: DConversationId): Readonly<DMessage[]> | undefined =>
_get().conversations.find(_c => _c.id === conversationId)?.messages ?? undefined,

Expand Down

0 comments on commit 98eb1a6

Please sign in to comment.