import * as React from 'react'; import { Alert, Box, Button, CircularProgress, Divider, FormControl, FormHelperText, FormLabel, Modal, ModalClose, ModalDialog, Option, Select, Slider, Stack, Textarea, Typography } from '@mui/joy'; import { ChatModelId, ChatModels, fastChatModelId } from '@/lib/data'; import { Section } from '@/components/dialogs/SettingsModal'; import { TokenBadge } from '@/components/util/TokenBadge'; import { countModelTokens } from '@/lib/llm/tokens'; import { summerizeToFitContextBudget } from '@/lib/llm/summerize'; function TokenUsageAlert({ usedTokens, tokenLimit }: { usedTokens: number, tokenLimit: number }) { const remainingTokens = tokenLimit - usedTokens; const message = remainingTokens >= 1 ? `${usedTokens.toLocaleString()} reduced tokens and ${remainingTokens.toLocaleString()} tokens remaining.` : `⚠️ These ${usedTokens.toLocaleString()} tokens go over budget by ${(-remainingTokens).toLocaleString()} tokens.`; return = 1 ? 'primary' : 'danger'} sx={{ mt: 1 }}>{message}; } /** * Dialog to compress a PDF */ export function ContentReducerModal(props: { initialText: string, initialTokens: number, tokenLimit: number, onClose: () => void, onReducedText: (text: string) => void, }) { // state const [reducerModelId, setReducerModelId] = React.useState(fastChatModelId); const [compressionLevel, setCompressionLevel] = React.useState(3); const [reducedText, setReducedText] = React.useState(''); const [processing, setProcessing] = React.useState(false); // derived state const reducedTokens = countModelTokens(reducedText, reducerModelId, 'content reducer reduce'); const remainingTokens = props.tokenLimit - reducedTokens; const handleChatModelChange = (event: any, value: ChatModelId | null) => value && setReducerModelId(value); const handleCompressionLevelChange = (event: Event, newValue: number | number[]) => setCompressionLevel(newValue as number); const handlePreviewClicked = async () => { setProcessing(true); const reducedText = await summerizeToFitContextBudget(props.initialText, props.tokenLimit, reducerModelId); setReducedText(reducedText); setProcessing(false); }; const handleUseReducedTextClicked = () => props.onReducedText(reducedText); // DISABLED: user shall select the model and compression level first // upon load, click the preview button // React.useEffect(() => { // // noinspection JSIgnoredPromiseFromCall // handlePreviewClicked(); // }, [handlePreviewClicked]); return ( Content Reducer (preview) {/* Settings */}
Input: {props.initialTokens.toLocaleString()} tokens · Limit: {props.tokenLimit.toLocaleString()} tokens
compression needed ≥ {props.tokenLimit ? Math.round(100 * props.initialTokens / props.tokenLimit) : 0} %
Reducer model {ChatModels[reducerModelId]?.tradeoff} {reducerModelId && } Compression {compressionLevel < 2 ? 'Low' : compressionLevel > 4 ? 'High' : 'Medium'}
{/* Outputs */}
{/* Readonly output and token counter */}