206 lines
7.4 KiB
TypeScript
206 lines
7.4 KiB
TypeScript
/**
|
||
* 火山引擎视频模型快速配置API
|
||
* 用于批量添加预设模型
|
||
*/
|
||
|
||
import { NextResponse } from 'next/server';
|
||
import { auth } from '@/app/(auth)/auth';
|
||
import { db } from '@/lib/db';
|
||
import { aiModel } from '@/lib/db/schema';
|
||
import { VOLCANO_VIDEO_MODEL_PRESETS } from '@/lib/ai/volcano-video-models';
|
||
import { eq } from 'drizzle-orm';
|
||
|
||
/**
|
||
* 获取火山引擎视频模型预设列表
|
||
*/
|
||
export async function GET(request: Request) {
|
||
try {
|
||
const session = await auth();
|
||
|
||
if (!session?.user || session.user.type !== 'admin') {
|
||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||
}
|
||
|
||
return NextResponse.json({
|
||
presets: VOLCANO_VIDEO_MODEL_PRESETS,
|
||
});
|
||
|
||
} catch (error: any) {
|
||
console.error('[Volcano Video Models API] GET error:', error);
|
||
return NextResponse.json(
|
||
{ error: error.message || 'Failed to fetch model presets' },
|
||
{ status: 500 }
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 批量添加火山引擎视频模型
|
||
* POST body: {
|
||
* providerId: string,
|
||
* modelIds?: string[], // 可选:只添加指定的模型ID
|
||
* models?: Array<{modelId, displayName, description}> // 可选:自定义模型配置
|
||
* }
|
||
*/
|
||
export async function POST(request: Request) {
|
||
try {
|
||
const session = await auth();
|
||
|
||
if (!session?.user || session.user.type !== 'admin') {
|
||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||
}
|
||
|
||
const body = await request.json();
|
||
const { providerId, modelIds, models: customModels } = body;
|
||
|
||
if (!providerId) {
|
||
return NextResponse.json(
|
||
{ error: 'Provider ID is required' },
|
||
{ status: 400 }
|
||
);
|
||
}
|
||
|
||
// 🆕 如果提供了自定义模型配置(通常只有主模型),需要补充所有子模型
|
||
let modelsToAdd;
|
||
if (customModels && Array.isArray(customModels)) {
|
||
// 检查是否只传了主模型
|
||
const hasMasterOnly = customModels.length === 1 && customModels[0].modelId === 'volcano-video-master';
|
||
|
||
if (hasMasterOnly) {
|
||
// 🎯 只传了主模型,需要补充所有子模型
|
||
const masterModelConfig = customModels[0];
|
||
const masterPreset = VOLCANO_VIDEO_MODEL_PRESETS.find(p => p.modelId === 'volcano-video-master');
|
||
|
||
// 获取主模型
|
||
const masterModel = {
|
||
...masterPreset,
|
||
displayName: masterModelConfig.displayName || masterPreset?.displayName || '火山引擎视频',
|
||
description: masterModelConfig.description || masterPreset?.description || '',
|
||
};
|
||
|
||
// 获取所有子模型(使用预设配置)
|
||
const subModels = VOLCANO_VIDEO_MODEL_PRESETS.filter(p => p.isSubModel);
|
||
|
||
// 组合:主模型 + 所有子模型
|
||
modelsToAdd = [masterModel, ...subModels];
|
||
|
||
console.log(`[Volcano Video Models] ℹ️ 添加主模型和 ${subModels.length} 个子模型`);
|
||
} else {
|
||
// 使用自定义配置,但需要从预设中获取完整的capabilities和defaultParams
|
||
modelsToAdd = customModels.map(customModel => {
|
||
let preset = VOLCANO_VIDEO_MODEL_PRESETS.find(p => p.modelId === customModel.modelId);
|
||
|
||
if (!preset) {
|
||
const baseModelId = customModel.modelId.split('-').slice(0, 4).join('-');
|
||
preset = VOLCANO_VIDEO_MODEL_PRESETS.find(p => p.modelId.startsWith(baseModelId));
|
||
|
||
if (preset) {
|
||
console.log(`[Volcano Video Models] ⚠️ 模型ID "${customModel.modelId}" 未找到精确匹配,使用相似配置: ${preset.modelId}`);
|
||
} else {
|
||
console.warn(`[Volcano Video Models] ⚠️ 模型ID "${customModel.modelId}" 未找到预设配置,将使用默认配置`);
|
||
preset = VOLCANO_VIDEO_MODEL_PRESETS[0];
|
||
}
|
||
}
|
||
|
||
return {
|
||
...preset,
|
||
modelId: customModel.modelId,
|
||
displayName: customModel.displayName || preset?.displayName || customModel.modelId,
|
||
description: customModel.description || preset?.description || '',
|
||
};
|
||
}).filter(Boolean);
|
||
}
|
||
} else {
|
||
// 使用预设模型,可以通过modelIds过滤
|
||
const selectedModelIds = modelIds || VOLCANO_VIDEO_MODEL_PRESETS.map(p => p.modelId);
|
||
modelsToAdd = VOLCANO_VIDEO_MODEL_PRESETS.filter(p => selectedModelIds.includes(p.modelId));
|
||
}
|
||
|
||
const addedModels = [];
|
||
const errors = [];
|
||
|
||
for (const preset of modelsToAdd) {
|
||
if (!preset) {
|
||
errors.push({ modelId: 'unknown', error: 'Invalid model configuration' });
|
||
continue;
|
||
}
|
||
|
||
try {
|
||
// 检查模型是否已存在
|
||
const existing = await db.query.aiModel.findFirst({
|
||
where: eq(aiModel.modelId, preset.modelId),
|
||
});
|
||
|
||
if (existing) {
|
||
errors.push({ modelId: preset.modelId, error: 'Model already exists' });
|
||
continue;
|
||
}
|
||
|
||
// 添加模型
|
||
const [newModel] = await db.insert(aiModel).values({
|
||
providerId,
|
||
modelId: preset.modelId,
|
||
displayName: preset.displayName,
|
||
description: preset.description,
|
||
supportsVision: preset.supportsVision,
|
||
supportsImageGen: preset.supportsImageGen,
|
||
isEnabled: true,
|
||
isDefault: false,
|
||
sortOrder: preset.sortOrder,
|
||
capabilities: preset.capabilities,
|
||
defaultParams: preset.defaultParams,
|
||
isSubModel: preset.isSubModel || false, // 🆕 保存子模型标记
|
||
parentModelId: preset.parentModelId ? null : null, // 🆕 父模型ID(第一次添加时为null,稍后通过UPDATE关联)
|
||
}).returning();
|
||
|
||
addedModels.push(newModel);
|
||
console.log(`[Volcano Video Models API] ✅ Added model: ${preset.displayName}`);
|
||
|
||
} catch (error: any) {
|
||
console.error(`[Volcano Video Models API] ❌ Failed to add ${preset.modelId}:`, error);
|
||
errors.push({ modelId: preset.modelId, error: error.message });
|
||
}
|
||
}
|
||
|
||
// 🆕 更新子模型的parentModelId,关联到主模型
|
||
try {
|
||
// ✅ 查找主模型(isSubModel=false的那个),支持自定义modelId
|
||
const masterModel = addedModels.find(m => !m.isSubModel);
|
||
if (masterModel) {
|
||
// ✅ 查找所有子模型(isSubModel=true)
|
||
const subModels = addedModels.filter(m => m.isSubModel);
|
||
|
||
if (subModels.length > 0) {
|
||
for (const subModel of subModels) {
|
||
await db.update(aiModel)
|
||
.set({ parentModelId: masterModel.id })
|
||
.where(eq(aiModel.id, subModel.id));
|
||
}
|
||
|
||
console.log(`[Volcano Video Models API] ✅ 已关联 ${subModels.length} 个子模型到主模型 (${masterModel.displayName})`);
|
||
}
|
||
} else {
|
||
console.warn('[Volcano Video Models API] ⚠️ 未找到主模型,跳过子模型关联');
|
||
}
|
||
} catch (updateError) {
|
||
console.error('[Volcano Video Models API] ⚠️ 更新parentModelId失败:', updateError);
|
||
// 不影响主流程,仅记录错误
|
||
}
|
||
|
||
return NextResponse.json({
|
||
success: true,
|
||
addedCount: addedModels.length,
|
||
addedModels,
|
||
errors: errors.length > 0 ? errors : undefined,
|
||
});
|
||
|
||
} catch (error: any) {
|
||
console.error('[Volcano Video Models API] POST error:', error);
|
||
return NextResponse.json(
|
||
{ error: error.message || 'Failed to add models' },
|
||
{ status: 500 }
|
||
);
|
||
}
|
||
}
|
||
|