mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-05-20 21:30:28 +08:00
feat: 优化上下文窗口配置逻辑
This commit is contained in:
@@ -58,11 +58,13 @@ export function getProviderDefinitionById(id: string): ProviderDefinition | null
|
||||
return getBuiltinProviderById(id) || loadCustomProviders().find((p) => p.id === id) || null
|
||||
}
|
||||
|
||||
/** 按 providerId + modelId 查找模型定义(内置优先,再查自定义) */
|
||||
/** 按 providerId + modelId 查找模型定义(内置优先,再查自定义,最后跨 provider 兜底) */
|
||||
export function findModelDefinition(providerId: string, modelId: string): ModelDefinition | null {
|
||||
return (
|
||||
getBuiltinModelById(providerId, modelId) ||
|
||||
loadCustomModels().find((m) => m.providerId === providerId && m.id === modelId) ||
|
||||
BUILTIN_MODELS.find((m) => m.id === modelId) ||
|
||||
loadCustomModels().find((m) => m.id === modelId) ||
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
@@ -85,7 +85,9 @@ const contextTokens = computed(() => {
|
||||
|
||||
const modelContextWindow = computed(() => {
|
||||
if (!activeConfig.value) return 128000
|
||||
const model = llmStore.getModelById(activeConfig.value.provider, activeConfig.value.model)
|
||||
const model =
|
||||
llmStore.getModelById(activeConfig.value.provider, activeConfig.value.model) ||
|
||||
llmStore.findModelAcrossProviders(activeConfig.value.model)
|
||||
return model?.contextWindow ?? 128000
|
||||
})
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ const {
|
||||
canFetchModels,
|
||||
showEditModelDialog,
|
||||
editModelContextWindow,
|
||||
editModelName,
|
||||
selectProvider,
|
||||
onConnectionModeChange,
|
||||
openAddModelDialog,
|
||||
@@ -225,6 +226,13 @@ function closeModal() {
|
||||
}}
|
||||
</span>
|
||||
</p>
|
||||
<p
|
||||
v-if="formData.model && !selectedModelContextWindow"
|
||||
class="mt-1 flex items-center gap-1 text-xs text-red-500 dark:text-red-400"
|
||||
>
|
||||
<UIcon name="i-heroicons-exclamation-triangle" class="h-3.5 w-3.5 shrink-0" />
|
||||
{{ t('settings.aiConfig.modal.contextWindowMissing') }}
|
||||
</p>
|
||||
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<button
|
||||
@@ -305,7 +313,7 @@ function closeModal() {
|
||||
</label>
|
||||
|
||||
<UITabs v-if="modelTabItems.length > 0" v-model="formData.model" :items="modelTabItems" size="xs" />
|
||||
<p v-else class="flex items-center gap-1 text-xs text-amber-500 dark:text-amber-400">
|
||||
<p v-else class="flex items-center gap-1 text-xs text-red-500 dark:text-red-400">
|
||||
<UIcon name="i-heroicons-exclamation-triangle" class="h-3.5 w-3.5 shrink-0" />
|
||||
{{ t('settings.aiConfig.modal.modelRequired') }}
|
||||
</p>
|
||||
@@ -320,6 +328,13 @@ function closeModal() {
|
||||
}}
|
||||
</span>
|
||||
</p>
|
||||
<p
|
||||
v-if="formData.model && !selectedModelContextWindow"
|
||||
class="mt-1 flex items-center gap-1 text-xs text-red-500 dark:text-red-400"
|
||||
>
|
||||
<UIcon name="i-heroicons-exclamation-triangle" class="h-3.5 w-3.5 shrink-0" />
|
||||
{{ t('settings.aiConfig.modal.contextWindowMissing') }}
|
||||
</p>
|
||||
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<button
|
||||
@@ -424,7 +439,7 @@ function closeModal() {
|
||||
</label>
|
||||
|
||||
<UITabs v-if="modelTabItems.length > 0" v-model="formData.model" :items="modelTabItems" size="xs" />
|
||||
<p v-else class="flex items-center gap-1 text-xs text-amber-500 dark:text-amber-400">
|
||||
<p v-else class="flex items-center gap-1 text-xs text-red-500 dark:text-red-400">
|
||||
<UIcon name="i-heroicons-exclamation-triangle" class="h-3.5 w-3.5 shrink-0" />
|
||||
{{ t('settings.aiConfig.modal.modelRequired') }}
|
||||
</p>
|
||||
@@ -439,6 +454,13 @@ function closeModal() {
|
||||
}}
|
||||
</span>
|
||||
</p>
|
||||
<p
|
||||
v-if="formData.model && !selectedModelContextWindow"
|
||||
class="mt-1 flex items-center gap-1 text-xs text-red-500 dark:text-red-400"
|
||||
>
|
||||
<UIcon name="i-heroicons-exclamation-triangle" class="h-3.5 w-3.5 shrink-0" />
|
||||
{{ t('settings.aiConfig.modal.contextWindowMissing') }}
|
||||
</p>
|
||||
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<button
|
||||
@@ -687,6 +709,17 @@ function closeModal() {
|
||||
</label>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">{{ formData.model }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('settings.aiConfig.modal.customModelDisplayName') }}
|
||||
<span class="font-normal text-gray-400">{{ t('settings.aiConfig.modal.optional') }}</span>
|
||||
</label>
|
||||
<UInput
|
||||
v-model="editModelName"
|
||||
class="w-full"
|
||||
:placeholder="formData.model || t('settings.aiConfig.modal.customModelDisplayNamePlaceholder')"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('settings.aiConfig.modal.contextWindow') }}
|
||||
|
||||
@@ -157,7 +157,8 @@ export function useAIConfigForm(props: {
|
||||
const selectedModelContextWindow = computed(() => {
|
||||
if (!formData.value.model) return undefined
|
||||
const providerId = formData.value.provider || 'openai-compatible'
|
||||
const model = llmStore.getModelById(providerId, formData.value.model)
|
||||
const model =
|
||||
llmStore.getModelById(providerId, formData.value.model) || llmStore.findModelAcrossProviders(formData.value.model)
|
||||
return model?.contextWindow
|
||||
})
|
||||
|
||||
@@ -373,7 +374,7 @@ export function useAIConfigForm(props: {
|
||||
const providerId = formData.value.provider || 'openai-compatible'
|
||||
remoteModels.value = result.models.map((m) => {
|
||||
if (m.contextWindow) return m
|
||||
const catalogModel = llmStore.getModelById(providerId, m.id)
|
||||
const catalogModel = llmStore.getModelById(providerId, m.id) || llmStore.findModelAcrossProviders(m.id)
|
||||
return catalogModel?.contextWindow ? { ...m, contextWindow: catalogModel.contextWindow } : m
|
||||
})
|
||||
} else {
|
||||
@@ -391,6 +392,24 @@ export function useAIConfigForm(props: {
|
||||
if (!compatModels.value.some((m) => m.id === model.id)) {
|
||||
compatModels.value.push({ id: model.id, name: model.name })
|
||||
}
|
||||
const providerId = formData.value.provider || 'openai-compatible'
|
||||
if (model.contextWindow && !llmStore.getModelById(providerId, model.id)?.contextWindow) {
|
||||
try {
|
||||
await window.llmApi.addCustomModel({
|
||||
id: model.id,
|
||||
providerId,
|
||||
name: model.name,
|
||||
contextWindow: model.contextWindow,
|
||||
capabilities: ['chat'],
|
||||
recommendedFor: [],
|
||||
description: '',
|
||||
status: 'stable',
|
||||
})
|
||||
await llmStore.refreshConfigs()
|
||||
} catch {
|
||||
// already exists
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const providerId = formData.value.provider || 'openai-compatible'
|
||||
if (!catalogModels.value.some((m) => m.id === model.id)) {
|
||||
@@ -468,6 +487,7 @@ export function useAIConfigForm(props: {
|
||||
|
||||
const showEditModelDialog = ref(false)
|
||||
const editModelContextWindow = ref<number | undefined>(undefined)
|
||||
const editModelName = ref('')
|
||||
|
||||
function openEditModelDialog() {
|
||||
const modelId = formData.value.model
|
||||
@@ -475,6 +495,7 @@ export function useAIConfigForm(props: {
|
||||
const providerId = formData.value.provider || 'openai-compatible'
|
||||
const model = llmStore.getModelById(providerId, modelId)
|
||||
editModelContextWindow.value = model?.contextWindow ?? undefined
|
||||
editModelName.value = model?.name ?? ''
|
||||
showEditModelDialog.value = true
|
||||
}
|
||||
|
||||
@@ -483,9 +504,25 @@ export function useAIConfigForm(props: {
|
||||
if (!modelId) return
|
||||
const providerId = formData.value.provider || 'openai-compatible'
|
||||
try {
|
||||
await window.llmApi.updateCustomModel(providerId, modelId, {
|
||||
const updates: Record<string, unknown> = {
|
||||
contextWindow: editModelContextWindow.value || undefined,
|
||||
})
|
||||
}
|
||||
if (editModelName.value.trim()) {
|
||||
updates.name = editModelName.value.trim()
|
||||
}
|
||||
const result = await window.llmApi.updateCustomModel(providerId, modelId, updates)
|
||||
if (!result.success) {
|
||||
await window.llmApi.addCustomModel({
|
||||
id: modelId,
|
||||
providerId,
|
||||
name: editModelName.value.trim() || modelId,
|
||||
contextWindow: editModelContextWindow.value || undefined,
|
||||
capabilities: ['chat'],
|
||||
recommendedFor: [],
|
||||
description: '',
|
||||
status: 'stable',
|
||||
})
|
||||
}
|
||||
await llmStore.refreshConfigs()
|
||||
} catch (error) {
|
||||
console.error('编辑模型失败:', error)
|
||||
@@ -768,6 +805,7 @@ export function useAIConfigForm(props: {
|
||||
// 编辑模型
|
||||
showEditModelDialog,
|
||||
editModelContextWindow,
|
||||
editModelName,
|
||||
|
||||
// 方法
|
||||
selectProvider,
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
"contextWindow": "Context Window",
|
||||
"contextWindowPlaceholder": "e.g. 128000",
|
||||
"contextWindowHint": "Maximum context tokens supported by this model (used for context compression)",
|
||||
"contextWindowMissing": "Context window not set, will use default. Click \"Edit Model\" to set it manually",
|
||||
"modelRequired": "Add at least one model to save",
|
||||
"modelCapabilities": "Model Capabilities",
|
||||
"apiFormat": "API Format",
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
"contextWindow": "コンテキストウィンドウ",
|
||||
"contextWindowPlaceholder": "例: 128000",
|
||||
"contextWindowHint": "モデルがサポートする最大コンテキストトークン数(コンテキスト圧縮に使用)",
|
||||
"contextWindowMissing": "コンテキストウィンドウが未設定です。デフォルト値が使用されます。「モデル編集」から手動で設定してください",
|
||||
"modelRequired": "少なくとも 1 つのモデルを追加してから保存してください",
|
||||
"modelCapabilities": "モデル能力ラベル",
|
||||
"apiFormat": "API インターフェース",
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
"contextWindow": "上下文窗口",
|
||||
"contextWindowPlaceholder": "如 128000",
|
||||
"contextWindowHint": "模型支持的最大上下文 token 数(用于上下文压缩)",
|
||||
"contextWindowMissing": "未设置上下文窗口,将使用默认值,建议点击「编辑模型」手动填写",
|
||||
"modelCapabilities": "模型能力标注",
|
||||
"modelRequired": "至少添加一个模型才能保存",
|
||||
"apiFormat": "API 接口类型",
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
"contextWindow": "上下文視窗",
|
||||
"contextWindowPlaceholder": "如 128000",
|
||||
"contextWindowHint": "模型支援的最大上下文 token 數(用於上下文壓縮)",
|
||||
"contextWindowMissing": "未設定上下文視窗,將使用預設值,建議點擊「編輯模型」手動填寫",
|
||||
"modelRequired": "至少新增一個模型才能儲存",
|
||||
"modelCapabilities": "模型能力標註",
|
||||
"apiFormat": "API 介面類型",
|
||||
|
||||
@@ -67,6 +67,10 @@ export const useLLMStore = defineStore('llm', () => {
|
||||
return modelCatalog.value.find((m) => m.providerId === providerId && m.id === modelId)
|
||||
}
|
||||
|
||||
function findModelAcrossProviders(modelId: string): ModelDefinition | undefined {
|
||||
return modelCatalog.value.find((m) => m.id === modelId)
|
||||
}
|
||||
|
||||
// ============ 方法 ============
|
||||
|
||||
async function init() {
|
||||
@@ -144,5 +148,6 @@ export const useLLMStore = defineStore('llm', () => {
|
||||
getProviderById,
|
||||
getModelsByProviderId,
|
||||
getModelById,
|
||||
findModelAcrossProviders,
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user