feat: 完善模型能力识别与验证

- 自动识别模型类型、视觉、推理和工具能力并保留手动覆盖

- 使用 AgentScope 工具与视觉探测并统一管理端配置反馈
This commit is contained in:
2026-07-27 19:40:23 +08:00
parent 0dc5c3ca55
commit 567fd12706
21 changed files with 1059 additions and 378 deletions

View File

@@ -0,0 +1,35 @@
import { describe, expect, it } from 'vitest';
import { getDefaultModelAbility, handleTagClick } from '../model-ability';
describe('model ability labels', () => {
it('只保留当前可用的视觉、推理和工具能力', () => {
const abilities = getDefaultModelAbility();
expect(abilities.map((item) => item.field)).toEqual([
'supportThinking',
'supportTool',
'supportImage',
]);
});
it('支持手动切换自动识别的能力', () => {
const abilities = getDefaultModelAbility();
const toolAbility = abilities.find((item) => item.field === 'supportTool');
const formData = {
supportImage: false,
supportThinking: false,
supportTool: false,
};
expect(toolAbility).toBeDefined();
if (!toolAbility) {
throw new Error('缺少工具能力标签');
}
handleTagClick(toolAbility, formData);
expect(toolAbility.selected).toBe(true);
expect(formData.supportTool).toBe(true);
});
});

View File

@@ -6,7 +6,7 @@ import {
} from '../model-verification';
describe('model verification helpers', () => {
it('双阶段通过时返回成功状态', () => {
it('验证通过时返回统一成功文案', () => {
expect(
resolveModelVerificationFeedback(
{
@@ -17,12 +17,12 @@ describe('model verification helpers', () => {
),
).toEqual({
dimension: undefined,
message: '验证成功',
message: '验证通过',
status: 'success',
});
});
it('基础连接通过但流式失败时返回警告状态', () => {
it('旧版部分通过结果也收敛为统一成功文案', () => {
const feedback = resolveModelVerificationFeedback(
{
data: {
@@ -34,9 +34,9 @@ describe('model verification helpers', () => {
'chatModel',
);
expect(feedback.status).toBe('warning');
expect(feedback.message).toContain('流式响应不可用');
expect(getVerifyButtonText('warning')).toBe('流式不可用');
expect(feedback.status).toBe('success');
expect(feedback.message).toBe('验证通过');
expect(getVerifyButtonText('warning')).toBe('验证通过');
});
it('向量模型验证保留维度结果', () => {
@@ -47,7 +47,7 @@ describe('model verification helpers', () => {
),
).toEqual({
dimension: 1024,
message: '验证成功向量维度1024',
message: '验证通过',
status: 'success',
});
});

View File

@@ -1,13 +1,6 @@
import { $t } from '#/locales';
export type BooleanField =
| 'supportAudio'
| 'supportImage'
| 'supportImageB64Only'
| 'supportThinking'
| 'supportTool'
| 'supportToolMessage'
| 'supportVideo';
export type BooleanField = 'supportImage' | 'supportThinking' | 'supportTool';
export interface ModelAbilityItem {
activeType: 'danger' | 'info' | 'primary' | 'success' | 'warning';
@@ -39,14 +32,6 @@ export const getDefaultModelAbility = (): ModelAbilityItem[] => [
selected: false,
field: 'supportTool',
},
{
label: $t('llm.modelAbility.supportVideo'),
value: 'video',
defaultType: 'info',
activeType: 'success',
selected: false,
field: 'supportVideo',
},
{
label: $t('llm.modelAbility.supportImage'),
value: 'image',
@@ -55,30 +40,6 @@ export const getDefaultModelAbility = (): ModelAbilityItem[] => [
selected: false,
field: 'supportImage',
},
{
label: $t('llm.modelAbility.supportAudio'),
value: 'audio',
defaultType: 'info',
activeType: 'success',
selected: false,
field: 'supportAudio',
},
{
label: $t('llm.modelAbility.supportImageB64Only'),
value: 'imageB64',
defaultType: 'info',
activeType: 'success',
selected: false,
field: 'supportImageB64Only',
},
{
label: $t('llm.modelAbility.supportToolMessage'),
value: 'toolMessage',
defaultType: 'info',
activeType: 'success',
selected: true,
field: 'supportToolMessage',
},
];
/**
@@ -108,7 +69,7 @@ export const getTagsSelectedStatus = (
*/
export const syncTagSelectedStatus = (
modelAbility: ModelAbilityItem[],
formData: Record<BooleanField, boolean>,
formData: Record<BooleanField, boolean | null>,
): void => {
modelAbility.forEach((tag) => {
tag.selected = formData[tag.field] ?? false;
@@ -121,9 +82,8 @@ export const syncTagSelectedStatus = (
* @param formData 表单数据对象
*/
export const handleTagClick = (
// modelAbility: ModelAbilityItem[],
item: ModelAbilityItem,
formData: Record<BooleanField, boolean>,
formData: Record<BooleanField, boolean | null>,
): void => {
// 切换标签选中状态
item.selected = !item.selected;
@@ -152,7 +112,4 @@ export const getAllBooleanFields = (): BooleanField[] => [
'supportThinking',
'supportTool',
'supportImage',
'supportImageB64Only',
'supportVideo',
'supportAudio',
];

View File

@@ -19,12 +19,9 @@ interface ModelVerificationResponse {
message?: string;
}
const STREAMING_UNAVAILABLE_MESSAGE =
'连接成功,流式响应不可用,可关闭智能体的模型流式响应。';
export function resolveModelVerificationFeedback(
response: ModelVerificationResponse,
modelType: string,
_modelType: string,
): ModelVerificationFeedback {
if (response.errorCode !== 0) {
return {
@@ -33,13 +30,6 @@ export function resolveModelVerificationFeedback(
};
}
if (response.data?.status === 'PARTIAL') {
return {
message: response.data.message || STREAMING_UNAVAILABLE_MESSAGE,
status: 'warning',
};
}
if (response.data?.status === 'FAILED') {
return {
message: response.data.message || '验证失败',
@@ -50,10 +40,7 @@ export function resolveModelVerificationFeedback(
const dimension = response.data?.dimension;
return {
dimension,
message:
modelType === 'embeddingModel' && dimension
? `验证成功,向量维度:${dimension}`
: response.data?.message || '验证成功',
message: '验证通过',
status: 'success',
};
}
@@ -63,10 +50,10 @@ export function getVerifyButtonText(status: VerifyButtonStatus): string {
return '验证中';
}
if (status === 'success') {
return '验证成功';
return '验证通过';
}
if (status === 'warning') {
return '流式不可用';
return '验证通过';
}
if (status === 'error') {
return '验证失败';