feat: 更长上下文 (#5963)

* feat: Extended the fillable context length to 100. #5514

Update src/renderer/src/pages/home/Tabs/SettingsTab.tsx

fix: update context length settings and localization for multiple languages

* fix: adjust context count slider limits and behavior based on max contexts setting

* feat: implement event handling for max contexts changes in settings

* feat: update context count handling to use EXTENDED_CONTEXT_LIMIT in settings

* feat: update context count logic to use EXTENDED_CONTEXT_LIMIT when max contexts are enabled

* refactor: remove unused EXTENDED_CONTEXT_LIMIT import from AssistantService

* feat: simplify context count logic with validAndChangeContextCount function

* feat: 移除TokenCount组件中对最大计数为20的特殊处理,简化上下文计数显示逻辑

* refactor: simplify getContextCount logic by removing max context handling

* feat: adjust step value for context count input based on max contexts setting

---------

Co-authored-by: George Zhao <georgezhao@SKJLAB>
This commit is contained in:
George Zhao 2025-05-14 19:37:37 +08:00 committed by GitHub
parent 568fd155c5
commit 577d180e1d
13 changed files with 109 additions and 32 deletions

View File

@ -1,5 +1,6 @@
export const DEFAULT_TEMPERATURE = 1.0
export const DEFAULT_CONTEXTCOUNT = 5
export const EXTENDED_CONTEXT_LIMIT = 100
export const DEFAULT_MAX_TOKENS = 4096
export const DEFAULT_KNOWLEDGE_DOCUMENT_COUNT = 6
export const DEFAULT_KNOWLEDGE_THRESHOLD = 0.0

View File

@ -208,6 +208,7 @@
"settings.context_count": "Context",
"settings.context_count.tip": "The number of previous messages to keep in the context.",
"settings.max": "Max",
"settings.max_contexts": "More Contexts Length",
"settings.max_tokens": "Enable max tokens limit",
"settings.max_tokens.confirm": "Enable max tokens limit",
"settings.max_tokens.confirm_content": "Enable max tokens limit, affects the length of the result. Need to consider the context limit of the model, otherwise an error will be reported",

View File

@ -208,6 +208,7 @@
"settings.context_count": "コンテキスト",
"settings.context_count.tip": "コンテキストに保持する以前のメッセージの数",
"settings.max": "最大",
"settings.max_contexts": "より長いコンテキスト制限",
"settings.max_tokens": "最大トークン制限を有効にする",
"settings.max_tokens.confirm": "最大トークン制限を有効にする",
"settings.max_tokens.confirm_content": "最大トークン制限を有効にすると、モデルが生成できる最大トークン数が制限されます。これにより、返される結果の長さに影響が出る可能性があります。モデルのコンテキスト制限に基づいて設定する必要があります。そうしないとエラーが発生します",

View File

@ -208,6 +208,7 @@
"settings.context_count": "Контекст",
"settings.context_count.tip": "Количество предыдущих сообщений, которые нужно сохранить в контексте.",
"settings.max": "Максимум",
"settings.max_contexts": "Более длительные ограничения контекста",
"settings.max_tokens": "Включить лимит максимальных токенов",
"settings.max_tokens.confirm": "Включить лимит максимальных токенов",
"settings.max_tokens.confirm_content": "Включить лимит максимальных токенов, влияет на длину результата. Нужно учитывать контекст модели, иначе будет ошибка",

View File

@ -222,6 +222,7 @@
"settings.context_count": "上下文数",
"settings.context_count.tip": "要保留在上下文中的消息数量,数值越大,上下文越长,消耗的 token 越多。普通聊天建议 5-10",
"settings.max": "不限",
"settings.max_contexts": "更多上下文长度限制",
"settings.max_tokens": "开启消息长度限制",
"settings.max_tokens.confirm": "开启消息长度限制",
"settings.max_tokens.confirm_content": "开启消息长度限制后,单次交互所用的最大 Token 数, 会影响返回结果的长度。要根据模型上下文限制来设置,否则会报错",

View File

@ -208,6 +208,7 @@
"settings.context_count": "上下文",
"settings.context_count.tip": "在上下文中保留的前幾則訊息。",
"settings.max": "最大",
"settings.max_contexts": "更多上下文長度限制",
"settings.max_tokens": "啟用最大 Token 限制",
"settings.max_tokens.confirm": "啟用訊息長度限制",
"settings.max_tokens.confirm_content": "啟用訊息長度限制後,單次互動所用的最大 Token 數,會影響返回結果的長度。要根據模型上下文限制來設定,否則會發生錯誤。",

View File

@ -22,18 +22,6 @@ const TokenCount: FC<Props> = ({ estimateTokenCount, inputTokenCount, contextCou
}
const formatMaxCount = (max: number) => {
if (max == 20) {
return (
<span
style={{
fontSize: '16px',
position: 'relative',
top: '1px'
}}>
</span>
)
}
return max.toString()
}
@ -43,7 +31,7 @@ const TokenCount: FC<Props> = ({ estimateTokenCount, inputTokenCount, contextCou
<HStack justifyContent="space-between" w="100%">
<Text>{t('chat.input.context_count.tip')}</Text>
<Text>
{contextCount.current} / {contextCount.max == 20 ? '∞' : contextCount.max}
{contextCount.current} / {contextCount.max}
</Text>
</HStack>
<Divider style={{ margin: '5px 0' }} />

View File

@ -5,6 +5,7 @@ import {
DEFAULT_CONTEXTCOUNT,
DEFAULT_MAX_TOKENS,
DEFAULT_TEMPERATURE,
EXTENDED_CONTEXT_LIMIT,
isMac,
isWindows
} from '@renderer/config/constant'
@ -13,6 +14,7 @@ import { useAssistant } from '@renderer/hooks/useAssistant'
import { useSettings } from '@renderer/hooks/useSettings'
import { SettingDivider, SettingRow, SettingRowTitle, SettingSubtitle } from '@renderer/pages/settings'
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { useAppDispatch } from '@renderer/store'
import {
SendMessageShortcut,
@ -51,7 +53,7 @@ import {
TranslateLanguageVarious
} from '@renderer/types'
import { modalConfirm } from '@renderer/utils'
import { Button, Col, InputNumber, Row, Select, Slider, Switch, Tooltip } from 'antd'
import { Button, Col, Divider, InputNumber, Row, Select, Slider, Switch, Tooltip } from 'antd'
import { CircleHelp, RotateCcw, Settings2 } from 'lucide-react'
import { FC, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
@ -67,6 +69,7 @@ const SettingsTab: FC<Props> = (props) => {
const [temperature, setTemperature] = useState(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE)
const [contextCount, setContextCount] = useState(assistant?.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT)
const [enableMaxContexts, setEnableMaxContexts] = useState(assistant?.settings?.enableMaxContexts ?? false)
const [enableMaxTokens, setEnableMaxTokens] = useState(assistant?.settings?.enableMaxTokens ?? false)
const [maxTokens, setMaxTokens] = useState(assistant?.settings?.maxTokens ?? 0)
const [fontSizeValue, setFontSizeValue] = useState(fontSize)
@ -155,10 +158,18 @@ const SettingsTab: FC<Props> = (props) => {
const formatSliderTooltip = (value?: number) => {
if (value === undefined) return ''
return value === 20 ? '∞' : value.toString()
return value.toString()
}
return (
const validAndChangeContextCount = (contextCount, enableMaxContexts, EXTENDED_CONTEXT_LIMIT) => {
if ((typeof contextCount === 'number' ? contextCount : 0) > (enableMaxContexts ? EXTENDED_CONTEXT_LIMIT : 10)) {
return enableMaxContexts ? EXTENDED_CONTEXT_LIMIT : 10
} else {
return typeof contextCount === 'number' ? contextCount : 0
}
}
const container = (
<Container className="settings-tab">
<SettingGroup style={{ marginTop: 10 }}>
<SettingSubtitle style={{ marginTop: 0, display: 'flex', justifyContent: 'space-between' }}>
@ -204,15 +215,31 @@ const SettingsTab: FC<Props> = (props) => {
<Col span={24}>
<Slider
min={0}
max={10}
max={!enableMaxContexts ? 10 : EXTENDED_CONTEXT_LIMIT}
onChange={setContextCount}
onChangeComplete={onContextCountChange}
value={typeof contextCount === 'number' ? contextCount : 0}
step={1}
value={validAndChangeContextCount(contextCount, enableMaxContexts, EXTENDED_CONTEXT_LIMIT)}
step={!enableMaxContexts ? 1 : 10}
tooltip={{ formatter: formatSliderTooltip }}
/>
</Col>
</Row>
<SettingRow>
<SettingRowTitleSmall>{t('chat.settings.max_contexts')}</SettingRowTitleSmall>
<Switch
size="small"
checked={enableMaxContexts}
onChange={(checked) => {
setEnableMaxContexts(checked)
updateAssistantSettings({ enableMaxContexts: checked })
if (!checked && contextCount > 10) {
setContextCount(10)
onUpdateAssistantSettings({ contextCount: 10 })
}
}}
/>
</SettingRow>
<Divider style={{ margin: '10px 0' }} />
<SettingRow>
<SettingRowTitleSmall>{t('models.stream_output')}</SettingRowTitleSmall>
<Switch
@ -627,6 +654,22 @@ const SettingsTab: FC<Props> = (props) => {
</SettingGroup>
</Container>
)
EventEmitter.on(EVENT_NAMES.MAX_CONTEXTS_CHANGED, ({ check, context }): any => {
setEnableMaxContexts(check)
updateAssistantSettings({ enableMaxContexts: check })
// Ensure contextCount is within the new valid range
let newContextCount = context
if (!check && newContextCount > 10) {
newContextCount = 10
} else if (check && newContextCount > EXTENDED_CONTEXT_LIMIT) {
newContextCount = EXTENDED_CONTEXT_LIMIT
}
setContextCount(newContextCount)
onUpdateAssistantSettings({ contextCount: newContextCount })
})
return container
}
const Container = styled(Scrollbar)`

View File

@ -2,8 +2,9 @@ import { DeleteOutlined, PlusOutlined, QuestionCircleOutlined } from '@ant-desig
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
import { HStack } from '@renderer/components/Layout'
import SelectModelPopup from '@renderer/components/Popups/SelectModelPopup'
import { DEFAULT_CONTEXTCOUNT, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
import { DEFAULT_CONTEXTCOUNT, DEFAULT_TEMPERATURE, EXTENDED_CONTEXT_LIMIT } from '@renderer/config/constant'
import { SettingRow } from '@renderer/pages/settings'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { Assistant, AssistantSettingCustomParameters, AssistantSettings } from '@renderer/types'
import { modalConfirm } from '@renderer/utils'
import { Button, Col, Divider, Input, InputNumber, Row, Select, Slider, Switch, Tooltip } from 'antd'
@ -21,6 +22,7 @@ interface Props {
const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateAssistantSettings }) => {
const [temperature, setTemperature] = useState(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE)
const [contextCount, setContextCount] = useState(assistant?.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT)
const [enableMaxContexts, setEnableMaxContexts] = useState(assistant?.settings?.enableMaxContexts ?? false)
const [enableMaxTokens, setEnableMaxTokens] = useState(assistant?.settings?.enableMaxTokens ?? false)
const [maxTokens, setMaxTokens] = useState(assistant?.settings?.maxTokens ?? 0)
const [streamOutput, setStreamOutput] = useState(assistant?.settings?.streamOutput ?? true)
@ -31,6 +33,10 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
assistant?.settings?.customParameters ?? []
)
const onUpdateAssistantSettings = (settings: Partial<AssistantSettings>) => {
updateAssistantSettings(settings)
}
const customParametersRef = useRef(customParameters)
customParametersRef.current = customParameters
@ -181,7 +187,15 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
const formatSliderTooltip = (value?: number) => {
if (value === undefined) return ''
return value === 20 ? '∞' : value.toString()
return value.toString()
}
const validAndChangeContextCount = (contextCount, enableMaxContexts, EXTENDED_CONTEXT_LIMIT) => {
if ((typeof contextCount === 'number' ? contextCount : 0) > (enableMaxContexts ? EXTENDED_CONTEXT_LIMIT : 10)) {
return enableMaxContexts ? EXTENDED_CONTEXT_LIMIT : 10
} else {
return typeof contextCount === 'number' ? contextCount : 0
}
}
return (
@ -292,26 +306,28 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
<Col span={20}>
<Slider
min={0}
max={20}
max={!enableMaxContexts ? 10 : EXTENDED_CONTEXT_LIMIT}
onChange={setContextCount}
onChangeComplete={onContextCountChange}
value={typeof contextCount === 'number' ? contextCount : 0}
marks={{ 0: '0', 5: '5', 10: '10', 15: '15', 20: t('chat.settings.max') }}
step={1}
value={validAndChangeContextCount(contextCount, enableMaxContexts, EXTENDED_CONTEXT_LIMIT)}
step={!enableMaxContexts ? 1 : 10}
tooltip={{ formatter: formatSliderTooltip }}
/>
</Col>
<Col span={4}>
<InputNumber
min={0}
max={20}
step={1}
max={!enableMaxContexts ? 10 : EXTENDED_CONTEXT_LIMIT}
step={!enableMaxContexts ? 1 : 10}
value={contextCount}
changeOnBlur
onChange={(value) => {
if (!isNull(value)) {
setContextCount(value)
setTimeout(() => updateAssistantSettings({ contextCount: value }), 500)
setTimeout(() => {
updateAssistantSettings({ contextCount: value })
onUpdateAssistantSettings({ contextCount: value })
}, 500)
}
}}
style={{ width: '100%' }}
@ -319,6 +335,27 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
</Col>
</Row>
<Divider style={{ margin: '10px 0' }} />
<SettingRow style={{ minHeight: 30 }}>
<HStack alignItems="center">
<Label>{t('chat.settings.max_contexts')}</Label>
</HStack>
<Switch
checked={enableMaxContexts}
onChange={(checked) => {
setEnableMaxContexts(checked)
updateAssistantSettings({ enableMaxContexts: checked })
if (!checked && contextCount > 10) {
setContextCount(10)
onUpdateAssistantSettings({ contextCount: 10 })
}
EventEmitter.emit(EVENT_NAMES.MAX_CONTEXTS_CHANGED, {
check: checked,
context: contextCount
})
}}
/>
</SettingRow>
<Divider style={{ margin: '10px 0' }} />
<SettingRow style={{ minHeight: 30 }}>
<HStack alignItems="center">
<Label>{t('chat.settings.max_tokens')}</Label>

View File

@ -102,7 +102,8 @@ export const getAssistantSettings = (assistant: Assistant): AssistantSettings =>
}
return {
contextCount: contextCount === 20 ? 100000 : contextCount,
enableMaxContexts: assistant?.settings?.enableMaxContexts ?? false,
contextCount: contextCount,
temperature: assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE,
topP: assistant?.settings?.topP ?? 1,
enableMaxTokens: assistant?.settings?.enableMaxTokens ?? false,

View File

@ -26,5 +26,6 @@ export const EVENT_NAMES = {
ADD_NEW_TOPIC: 'ADD_NEW_TOPIC',
RESEND_MESSAGE: 'RESEND_MESSAGE',
SHOW_MODEL_SELECTOR: 'SHOW_MODEL_SELECTOR',
QUOTE_TEXT: 'QUOTE_TEXT'
QUOTE_TEXT: 'QUOTE_TEXT',
MAX_CONTEXTS_CHANGED: 'MAX_CONTEXTS_CHANGED'
}

View File

@ -41,9 +41,9 @@ export {
export function getContextCount(assistant: Assistant, messages: Message[]) {
const rawContextCount = assistant?.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT
const maxContextCount = rawContextCount === 20 ? 100000 : rawContextCount
const maxContextCount = rawContextCount
const _messages = rawContextCount === 20 ? takeRight(messages, 1000) : takeRight(messages, maxContextCount)
const _messages = takeRight(messages, maxContextCount)
const clearIndex = _messages.findLastIndex((message) => message.type === 'clear')

View File

@ -51,6 +51,7 @@ export const EFFORT_RATIO: EffortRatio = {
export type AssistantSettings = {
contextCount: number
enableMaxContexts: boolean
temperature: number
topP: number
maxTokens: number | undefined