fix: number of context incorrect (#2653)

* fix: number of context incorrect

* feat: 优化上下文数显示样式

* fix: 上下文数显示不正确

修复无限上下文情况下,当前上下文数显示不正确的问题

* fix: slider display incorrect

* fix: Update infinity display style
This commit is contained in:
George·Dong 2025-03-08 20:49:24 +08:00 committed by kangfenmao
parent 3312befe11
commit 85bf4498c0
11 changed files with 60 additions and 19 deletions

View File

@ -86,7 +86,7 @@
"input.clear.content": "Do you want to clear all messages of the current topic?", "input.clear.content": "Do you want to clear all messages of the current topic?",
"input.clear.title": "Clear all messages?", "input.clear.title": "Clear all messages?",
"input.collapse": "Collapse", "input.collapse": "Collapse",
"input.context_count.tip": "Context Count", "input.context_count.tip": "Context / Max Context",
"input.estimated_tokens.tip": "Estimated tokens", "input.estimated_tokens.tip": "Estimated tokens",
"input.expand": "Expand", "input.expand": "Expand",
"input.file_not_supported": "Model does not support this file type", "input.file_not_supported": "Model does not support this file type",

View File

@ -86,7 +86,7 @@
"input.clear.content": "現在のトピックのすべてのメッセージをクリアしますか?", "input.clear.content": "現在のトピックのすべてのメッセージをクリアしますか?",
"input.clear.title": "すべてのメッセージをクリアしますか?", "input.clear.title": "すべてのメッセージをクリアしますか?",
"input.collapse": "折りたたむ", "input.collapse": "折りたたむ",
"input.context_count.tip": "コンテキスト数", "input.context_count.tip": "コンテキスト数 / 最大コンテキスト数",
"input.estimated_tokens.tip": "推定トークン数", "input.estimated_tokens.tip": "推定トークン数",
"input.expand": "展開", "input.expand": "展開",
"input.file_not_supported": "モデルはこのファイルタイプをサポートしません", "input.file_not_supported": "モデルはこのファイルタイプをサポートしません",

View File

@ -86,7 +86,7 @@
"input.clear.content": "Хотите очистить все сообщения текущего топика?", "input.clear.content": "Хотите очистить все сообщения текущего топика?",
"input.clear.title": "Очистить все сообщения?", "input.clear.title": "Очистить все сообщения?",
"input.collapse": "Свернуть", "input.collapse": "Свернуть",
"input.context_count.tip": "Количество контекстов", "input.context_count.tip": "Контекст / Макс. контекст",
"input.estimated_tokens.tip": "Затраты токенов", "input.estimated_tokens.tip": "Затраты токенов",
"input.expand": "Развернуть", "input.expand": "Развернуть",
"input.file_not_supported": "Модель не поддерживает этот тип файла", "input.file_not_supported": "Модель не поддерживает этот тип файла",

View File

@ -86,7 +86,7 @@
"input.clear.content": "确定要清除当前会话所有消息吗?", "input.clear.content": "确定要清除当前会话所有消息吗?",
"input.clear.title": "清空消息", "input.clear.title": "清空消息",
"input.collapse": "收起", "input.collapse": "收起",
"input.context_count.tip": "上下文数", "input.context_count.tip": "上下文数 / 最大上下文数",
"input.estimated_tokens.tip": "预估 token 数", "input.estimated_tokens.tip": "预估 token 数",
"input.expand": "展开", "input.expand": "展开",
"input.file_not_supported": "模型不支持此文件类型", "input.file_not_supported": "模型不支持此文件类型",

View File

@ -86,7 +86,7 @@
"input.clear.content": "您想要清除目前話題的所有訊息嗎?", "input.clear.content": "您想要清除目前話題的所有訊息嗎?",
"input.clear.title": "清除所有訊息?", "input.clear.title": "清除所有訊息?",
"input.collapse": "折疊", "input.collapse": "折疊",
"input.context_count.tip": "上下文數", "input.context_count.tip": "上下文數 / 最大上下文數",
"input.estimated_tokens.tip": "預估 Token 數", "input.estimated_tokens.tip": "預估 Token 數",
"input.expand": "展開", "input.expand": "展開",
"input.file_not_supported": "模型不支援此檔案類型", "input.file_not_supported": "模型不支援此檔案類型",

View File

@ -75,7 +75,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
} = useSettings() } = useSettings()
const [expended, setExpend] = useState(false) const [expended, setExpend] = useState(false)
const [estimateTokenCount, setEstimateTokenCount] = useState(0) const [estimateTokenCount, setEstimateTokenCount] = useState(0)
const [contextCount, setContextCount] = useState(0) const [contextCount, setContextCount] = useState({ current: 0, max: 0 })
const generating = useAppSelector((state) => state.runtime.generating) const generating = useAppSelector((state) => state.runtime.generating)
const textareaRef = useRef<TextAreaRef>(null) const textareaRef = useRef<TextAreaRef>(null)
const [files, setFiles] = useState<FileType[]>(_files) const [files, setFiles] = useState<FileType[]>(_files)
@ -503,7 +503,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
}), }),
EventEmitter.on(EVENT_NAMES.ESTIMATED_TOKEN_COUNT, ({ tokensCount, contextCount }) => { EventEmitter.on(EVENT_NAMES.ESTIMATED_TOKEN_COUNT, ({ tokensCount, contextCount }) => {
_setEstimateTokenCount(tokensCount) _setEstimateTokenCount(tokensCount)
setContextCount(contextCount) setContextCount({ current: contextCount.current, max: contextCount.max }) // 现在contextCount是一个对象而不是单个数值
}), }),
EventEmitter.on(EVENT_NAMES.ADD_NEW_TOPIC, addNewTopic), EventEmitter.on(EVENT_NAMES.ADD_NEW_TOPIC, addNewTopic),
EventEmitter.on(EVENT_NAMES.QUOTE_TEXT, (quotedText: string) => { EventEmitter.on(EVENT_NAMES.QUOTE_TEXT, (quotedText: string) => {

View File

@ -9,7 +9,7 @@ import styled from 'styled-components'
type Props = { type Props = {
estimateTokenCount: number estimateTokenCount: number
inputTokenCount: number inputTokenCount: number
contextCount: number contextCount: { current: number; max: number }
ToolbarButton: any ToolbarButton: any
} & React.HTMLAttributes<HTMLDivElement> } & React.HTMLAttributes<HTMLDivElement>
@ -21,12 +21,30 @@ const TokenCount: FC<Props> = ({ estimateTokenCount, inputTokenCount, contextCou
return null return null
} }
const formatMaxCount = (max: number) => {
if (max == 20) {
return (
<span
style={{
fontSize: '16px',
position: 'relative',
top: '1px'
}}>
</span>
)
}
return max.toString()
}
const PopoverContent = () => { const PopoverContent = () => {
return ( return (
<VStack w="150px" background="100%"> <VStack w="185px" background="100%">
<HStack justifyContent="space-between" w="100%"> <HStack justifyContent="space-between" w="100%">
<Text>{t('chat.input.context_count.tip')}</Text> <Text>{t('chat.input.context_count.tip')}</Text>
<Text>{contextCount}</Text> <Text>
{contextCount.current} / {contextCount.max == 20 ? '∞' : contextCount.max}
</Text>
</HStack> </HStack>
<Divider style={{ margin: '5px 0' }} /> <Divider style={{ margin: '5px 0' }} />
<HStack justifyContent="space-between" w="100%"> <HStack justifyContent="space-between" w="100%">
@ -40,7 +58,7 @@ const TokenCount: FC<Props> = ({ estimateTokenCount, inputTokenCount, contextCou
return ( return (
<Container> <Container>
<Popover content={PopoverContent}> <Popover content={PopoverContent}>
<MenuOutlined /> {contextCount} <MenuOutlined /> {contextCount.current} / {formatMaxCount(contextCount.max)}
<Divider type="vertical" style={{ marginTop: 0, marginLeft: 5, marginRight: 5 }} /> <Divider type="vertical" style={{ marginTop: 0, marginLeft: 5, marginRight: 5 }} />
<ArrowUpOutlined /> <ArrowUpOutlined />
{inputTokenCount} / {estimateTokenCount} {inputTokenCount} / {estimateTokenCount}
@ -66,7 +84,7 @@ const Container = styled.div`
font-size: 10px; font-size: 10px;
margin-right: 3px; margin-right: 3px;
} }
@media (max-width: 600px) { @media (max-width: 700px) {
display: none; display: none;
} }
` `

View File

@ -133,6 +133,11 @@ const SettingsTab: FC<Props> = (props) => {
setReasoningEffort(assistant?.settings?.reasoning_effort) setReasoningEffort(assistant?.settings?.reasoning_effort)
}, [assistant]) }, [assistant])
const formatSliderTooltip = (value?: number) => {
if (value === undefined) return ''
return value === 20 ? '∞' : value.toString()
}
return ( return (
<Container className="settings-tab"> <Container className="settings-tab">
<SettingGroup style={{ marginTop: 10 }}> <SettingGroup style={{ marginTop: 10 }}>
@ -176,6 +181,7 @@ const SettingsTab: FC<Props> = (props) => {
onChangeComplete={onContextCountChange} onChangeComplete={onContextCountChange}
value={typeof contextCount === 'number' ? contextCount : 0} value={typeof contextCount === 'number' ? contextCount : 0}
step={1} step={1}
tooltip={{ formatter: formatSliderTooltip }}
/> />
</Col> </Col>
</Row> </Row>

View File

@ -184,6 +184,11 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
return () => updateAssistantSettings({ customParameters: customParametersRef.current }) return () => updateAssistantSettings({ customParameters: customParametersRef.current })
}, []) }, [])
const formatSliderTooltip = (value?: number) => {
if (value === undefined) return ''
return value === 20 ? '∞' : value.toString()
}
return ( return (
<Container> <Container>
<Row align="middle" style={{ marginBottom: 10 }}> <Row align="middle" style={{ marginBottom: 10 }}>
@ -298,6 +303,7 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
value={typeof contextCount === 'number' ? contextCount : 0} value={typeof contextCount === 'number' ? contextCount : 0}
marks={{ 0: '0', 5: '5', 10: '10', 15: '15', 20: t('chat.settings.max') }} marks={{ 0: '0', 5: '5', 10: '10', 15: '15', 20: t('chat.settings.max') }}
step={1} step={1}
tooltip={{ formatter: formatSliderTooltip }}
/> />
</Col> </Col>
<Col span={4}> <Col span={4}>

View File

@ -68,16 +68,26 @@ export function filterUsefulMessages(messages: Message[]): Message[] {
} }
export function getContextCount(assistant: Assistant, messages: Message[]) { export function getContextCount(assistant: Assistant, messages: Message[]) {
const contextCount = assistant?.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT const rawContextCount = assistant?.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT
const _messages = takeRight(messages, contextCount) // 使用与 getAssistantSettings 相同的逻辑处理无限上下文
const clearIndex = _messages.findLastIndex((message) => message.type === 'clear') const maxContextCount = rawContextCount === 20 ? 100000 : rawContextCount
const messagesCount = _messages.length
// 在无限模式下,设置一个合理的高上限而不是处理所有消息
const _messages = rawContextCount === 20 ? takeRight(messages, 1000) : takeRight(messages, maxContextCount)
const clearIndex = _messages.findLastIndex((message) => message.type === 'clear')
let currentContextCount = 0
if (clearIndex === -1) { if (clearIndex === -1) {
return contextCount currentContextCount = _messages.length
} else {
currentContextCount = _messages.length - (clearIndex + 1)
} }
return messagesCount - (clearIndex + 1) return {
current: currentContextCount,
max: rawContextCount
}
} }
export function deleteMessageFiles(message: Message) { export function deleteMessageFiles(message: Message) {

View File

@ -95,7 +95,8 @@ export async function estimateMessagesUsage({
export async function estimateHistoryTokens(assistant: Assistant, msgs: Message[]) { export async function estimateHistoryTokens(assistant: Assistant, msgs: Message[]) {
const { contextCount } = getAssistantSettings(assistant) const { contextCount } = getAssistantSettings(assistant)
const messages = filterMessages(filterContextMessages(takeRight(msgs, contextCount))) const maxContextCount = contextCount
const messages = filterMessages(filterContextMessages(takeRight(msgs, maxContextCount)))
// 有 usage 数据的消息,快速计算总数 // 有 usage 数据的消息,快速计算总数
const uasageTokens = messages const uasageTokens = messages