fix(frontend): narrow VLLM model filter to vision-capable chat models

Restrict supports_vision inclusion to KnowledgeQA models, extract
filterModelsByType for unit tests, and re-filter when modelType changes.
This commit is contained in:
wizardchen
2026-08-20 14:49:47 +08:00
committed by lyingbug
parent 4e11782438
commit 359ac2af5e
3 changed files with 62 additions and 12 deletions
+5 -12
View File
@@ -47,6 +47,7 @@ import { ref, computed, watch, onMounted } from 'vue'
import { listModels, type ModelConfig } from '@/api/model'
import { MessagePlugin } from 'tdesign-vue-next'
import { useI18n } from 'vue-i18n'
import { filterModelsByType } from './modelSelectorFilter'
interface Props {
modelType: 'KnowledgeQA' | 'Embedding' | 'Rerank' | 'VLLM' | 'ASR'
@@ -84,18 +85,10 @@ const modelDisplayName = (model: ModelConfig) => {
return displayName || model.name
}
const filterModels = (allModels: ModelConfig[]) => {
if (props.modelType === 'VLLM') {
return allModels.filter(m => (m.type === props.modelType || m.parameters.supports_vision === true))
}
return allModels.filter(m => m.type === props.modelType)
}
// 监听 allModels 变化,自动过滤当前类型的模型
watch(() => props.allModels, (newModels) => {
// 监听 allModels / modelType 变化,自动过滤当前类型的模型
watch(() => [props.allModels, props.modelType] as const, ([newModels]) => {
if (newModels && Array.isArray(newModels)) {
models.value = filterModels(newModels)
models.value = filterModelsByType(newModels, props.modelType)
}
}, { immediate: true })
@@ -116,7 +109,7 @@ const loadModels = async () => {
const result = await listModels()
// 前端按类型筛选模型
if (result && Array.isArray(result)) {
models.value = filterModels(result)
models.value = filterModelsByType(result, props.modelType)
} else {
models.value = []
}
@@ -0,0 +1,39 @@
import assert from 'node:assert/strict'
import test from 'node:test'
import type { ModelConfig } from '@/api/model'
import { filterModelsByType } from './modelSelectorFilter.ts'
function model(overrides: Partial<ModelConfig> & Pick<ModelConfig, 'id' | 'type'>): ModelConfig {
return {
name: overrides.name ?? overrides.id!,
source: 'remote',
parameters: {},
...overrides,
}
}
const fixtures: ModelConfig[] = [
model({ id: 'vllm-1', type: 'VLLM' }),
model({ id: 'chat-vision', type: 'KnowledgeQA', parameters: { supports_vision: true } }),
model({ id: 'chat-text', type: 'KnowledgeQA' }),
model({ id: 'embed-vision', type: 'Embedding', parameters: { supports_vision: true } }),
model({ id: 'embed-1', type: 'Embedding' }),
]
test('VLLM selector includes native VLLM and vision-capable chat models', () => {
const ids = filterModelsByType(fixtures, 'VLLM').map((m) => m.id)
assert.deepEqual(ids, ['vllm-1', 'chat-vision'])
})
test('VLLM selector excludes non-vision chat and other types even with supports_vision', () => {
const ids = filterModelsByType(fixtures, 'VLLM')
assert.ok(!ids.some((m) => m.id === 'chat-text'))
assert.ok(!ids.some((m) => m.id === 'embed-vision'))
})
test('non-VLLM selectors still filter strictly by type', () => {
const ids = filterModelsByType(fixtures, 'KnowledgeQA').map((m) => m.id)
assert.deepEqual(ids, ['chat-vision', 'chat-text'])
})
@@ -0,0 +1,18 @@
import type { ModelConfig } from '@/api/model'
export type ModelSelectorType = ModelConfig['type']
export function filterModelsByType(
allModels: ModelConfig[],
modelType: ModelSelectorType,
): ModelConfig[] {
if (modelType === 'VLLM') {
return allModels.filter(
(m) =>
m.type === 'VLLM' ||
(m.type === 'KnowledgeQA' && m.parameters?.supports_vision === true),
)
}
return allModels.filter((m) => m.type === modelType)
}