Skip to content

Commit

Permalink
Composer: debounce token counting
Browse files Browse the repository at this point in the history
  • Loading branch information
enricoros committed Nov 9, 2023
1 parent e1f8230 commit 8fa7354
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 11 deletions.
13 changes: 7 additions & 6 deletions src/apps/chat/components/composer/Composer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { ChatModeId, useComposerStartupText } from './store-composer';
import { ChatModeMenu } from './ChatModeMenu';
import { TokenBadge } from './TokenBadge';
import { TokenProgressbar } from './TokenProgressbar';
import { useDebouncer } from '~/common/components/useDebouncer';


/// Text template helpers
Expand Down Expand Up @@ -143,7 +144,7 @@ export function Composer(props: {
sx?: SxProps;
}) {
// state
const [composeText, setComposeText] = React.useState('');
const [composeText, debouncedText, setComposeText] = useDebouncer('', 300, 1200, true);
const [speechInterimResult, setSpeechInterimResult] = React.useState<SpeechResult | null>(null);
const [isDragging, setIsDragging] = React.useState(false);
const [reducerText, setReducerText] = React.useState('');
Expand Down Expand Up @@ -173,13 +174,13 @@ export function Composer(props: {
setStartupText(null);
setComposeText(startupText);
}
}, [startupText, setStartupText]);
}, [setComposeText, setStartupText, startupText]);

// derived state
const tokenLimit = chatLLM?.contextTokens || 0;
const directTokens = React.useMemo(() => {
return (!composeText || !chatLLMId) ? 4 : 4 + countModelTokens(composeText, chatLLMId, 'composer text');
}, [chatLLMId, composeText]);
return (!debouncedText || !chatLLMId) ? 4 : 4 + countModelTokens(debouncedText, chatLLMId, 'composer text');
}, [chatLLMId, debouncedText]);
const historyTokens = conversationTokenCount;
const responseTokens = (chatLLM?.options as LLMOptionsOpenAI /* FIXME: BIG ASSUMPTION */)?.llmResponseTokens || 0;
const remainingTokens = tokenLimit - directTokens - historyTokens - responseTokens;
Expand Down Expand Up @@ -239,7 +240,7 @@ export function Composer(props: {
return prevText ? prevText + ' ' + transcript : transcript;
});
}
}, []);
}, [setComposeText]);

const { isSpeechEnabled, isSpeechError, isRecordingAudio, isRecordingSpeech, toggleRecording } = useSpeechRecognition(onSpeechResultCallback, 2000, 'm');

Expand Down Expand Up @@ -341,7 +342,7 @@ export function Composer(props: {
// no text/html or text/plain item found
console.log('Clipboard item has no text/html or text/plain item.', clipboardItem.types, clipboardItem);
}
}, []);
}, [setComposeText]);

useGlobalShortcut('v', true, true, handlePasteButtonClicked);

Expand Down
16 changes: 11 additions & 5 deletions src/common/components/useDebouncer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ export function useDebouncer<TValue = string | number>(
initialValue: TValue,
delayMs: number,
deadlineMs?: number,
): [TValue, (newValue: TValue | ((prevState: TValue) => TValue)) => void, () => TValue] {
const [debouncedValue, setDebouncedValue] = React.useState(initialValue);
immediate?: boolean,
): [TValue, TValue, (newValue: TValue | ((prevState: TValue) => TValue)) => void, () => TValue] {
const [immediateValue, setImmediateValue] = React.useState<TValue>(initialValue);
const [debouncedValue, setDebouncedValue] = React.useState<TValue>(initialValue);
const valueRef = React.useRef(initialValue);
const debounceTimeoutRef = React.useRef<number>();
const deadlineTimeoutRef = React.useRef<number>();
Expand All @@ -27,7 +29,11 @@ export function useDebouncer<TValue = string | number>(
const setValue = React.useCallback((_newValue: TValue | ((prevState: TValue) => TValue)) => {
clearDebounceTimeout();
// @ts-ignore
valueRef.current = typeof _newValue === 'function' ? _newValue(valueRef.current) : _newValue;
const newValue: TValue = typeof _newValue === 'function' ? _newValue(valueRef.current) : _newValue;
valueRef.current = newValue;
// trigger an immediate update
if (immediate)
setImmediateValue(newValue);

const handler = () => {
setDebouncedValue(valueRef.current);
Expand All @@ -41,7 +47,7 @@ export function useDebouncer<TValue = string | number>(
if (typeof deadlineMs === 'number' && deadlineMs > delayMs && deadlineTimeoutRef.current === undefined)
deadlineTimeoutRef.current = window.setTimeout(handler, deadlineMs);

}, [clearDebounceTimeout, clearDeadlineTimeout, delayMs, deadlineMs]);
}, [clearDebounceTimeout, immediate, delayMs, deadlineMs, clearDeadlineTimeout]);

const getValue = React.useCallback(() => valueRef.current, []);

Expand All @@ -52,7 +58,7 @@ export function useDebouncer<TValue = string | number>(
};
}, [clearDebounceTimeout, clearDeadlineTimeout]);

return [debouncedValue, setValue, getValue];
return [immediateValue, debouncedValue, setValue, getValue];
}


Expand Down

1 comment on commit 8fa7354

@vercel
Copy link

@vercel vercel bot commented on 8fa7354 Nov 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

big-agi – ./

big-agi-enricoros.vercel.app
big-agi-git-main-enricoros.vercel.app
get.big-agi.com

Please sign in to comment.