/** * 智能模型路由器 * 根据用户意图选择最佳AI模型 * * 核心逻辑:图片编辑场景优先使用 alibaba-image (灵魂4.5) */ // 使用动态导入避免循环依赖 // import { getEnabledAiModelsWithProvider } from "@/lib/db/queries"; // 路由结果类型 export interface RouteResult { id: string; displayName: string; providerType: string; modelId: string; reason: string; } // 意图到模型的映射配置 // providerTypes 按优先级排序,第一个是首选 const INTENT_MODEL_MAP: Record< string, { providerTypes: string[]; requireVision?: boolean; requireImageGen?: boolean; description: string; } > = { // 图片编辑:优先 alibaba-image(灵魂4.5,支持提示词扩展) image_edit: { providerTypes: ["alibaba-image", "ruxa-image", "gemini", "huanke-gemini"], requireVision: true, requireImageGen: true, description: "图片编辑", }, // 视觉理解:优先千问3 VL(成本低效果好) vision: { providerTypes: ["alibaba", "gemini", "huanke-gemini"], requireVision: true, description: "图片理解", }, // 图片生成:优先灵魂4.5 image_gen: { providerTypes: ["alibaba-image", "ruxa-image", "gemini", "huanke-gemini", "volcano-vision"], requireImageGen: true, description: "图片生成", }, // 视频生成 video_gen: { providerTypes: ["volcano-video", "qianwen-video"], description: "视频生成", }, // 普通对话:优先千问3 chat: { providerTypes: ["alibaba", "openai", "local"], description: "对话", }, }; // 子意图的特殊路由配置(覆盖默认配置) const SUB_INTENT_OVERRIDES: Record< string, { providerTypes?: string[]; reason?: string; } > = { // 抠图:alibaba-image 效果最好 remove_background: { providerTypes: ["alibaba-image", "ruxa-image", "gemini"], reason: "抠图首选灵魂4.5", }, // 换背景:alibaba-image 支持场景生成 replace_background: { providerTypes: ["alibaba-image", "ruxa-image", "gemini"], reason: "换背景首选灵魂4.5", }, // 图片增强 enhance: { providerTypes: ["alibaba-image", "ruxa-image", "gemini", "volcano-vision"], reason: "增强首选灵魂4.5", }, // 风格迁移:gemini 可能更有创意 style_transfer: { providerTypes: ["gemini", "alibaba-image", "ruxa-image"], reason: "风格迁移优选Gemini", }, }; /** * 路由到最佳模型 */ export async function routeToModel(params: { intent: string; subIntent?: string; hasImage: boolean; }): Promise { const { intent, subIntent, hasImage } = params; console.log("[Model Router] Routing:", { intent, subIntent, hasImage }); // 使用动态导入避免循环依赖 const { getEnabledAiModelsWithProvider } = await import("@/lib/db/queries"); const { isAiModelAgentAuto } = await import("@/lib/db/ai-model-flags"); const { db } = await import("@/lib/db"); const { siteSettings } = await import("@/lib/db/schema"); // 获取所有可用模型 const allModelsRaw = await getEnabledAiModelsWithProvider(); const nonAgentModels = allModelsRaw.filter( (item) => !isAiModelAgentAuto(item.model) ); const allModels = nonAgentModels.length > 0 ? nonAgentModels : allModelsRaw; console.log("[Model Router] Available models:", allModels.length); // 获取意图对应的配置 let config = INTENT_MODEL_MAP[intent] || INTENT_MODEL_MAP["chat"]; // 检查是否有子意图的特殊配置 if (subIntent && SUB_INTENT_OVERRIDES[subIntent]) { const override = SUB_INTENT_OVERRIDES[subIntent]; if (override.providerTypes) { config = { ...config, providerTypes: override.providerTypes }; } } // 🆕 检查是否有配置的默认生图模型(仅在能力匹配时使用) const [settings] = await db.select().from(siteSettings).limit(1); const configuredDefaultModelId = settings?.canvasAutoModeDefaultModelId; if (configuredDefaultModelId) { const configuredModel = allModels.find( (m) => m.model.id === configuredDefaultModelId && m.model.isEnabled && !m.model.isSubModel ); if (configuredModel) { const matchesVision = !config.requireVision || configuredModel.model.supportsVision; const matchesImageGen = !config.requireImageGen || configuredModel.model.supportsImageGen; if (matchesVision && matchesImageGen) { console.log("[Model Router] ✅ Using configured default model:", configuredModel.model.displayName); return { id: configuredModel.model.id, displayName: configuredModel.model.displayName, providerType: configuredModel.provider.type, modelId: configuredModel.model.modelId, reason: `管理员配置的默认模型 → ${configuredModel.model.displayName}`, }; } console.log("[Model Router] ⚠️ Configured default model does not match intent requirements, falling back"); } else { console.log("[Model Router] ⚠️ Configured default model not found or disabled, falling back to intent routing"); } } // 按优先级查找匹配的模型 for (const providerType of config.providerTypes) { const candidates = allModels.filter((m) => { // 匹配 provider 类型 if (m.provider.type !== providerType) return false; // 检查能力要求 if (config.requireVision && !m.model.supportsVision) return false; if (config.requireImageGen && !m.model.supportsImageGen) return false; // 排除子模型(只选主模型) if (m.model.isSubModel) return false; // 必须启用 if (!m.model.isEnabled) return false; return true; }); if (candidates.length > 0) { // 优先选择默认模型 const defaultModel = candidates.find((c) => c.model.isDefault); const selected = defaultModel || candidates[0]; const result: RouteResult = { id: selected.model.id, displayName: selected.model.displayName, providerType: selected.provider.type, modelId: selected.model.modelId, reason: subIntent ? `${config.description}/${subIntent} → ${selected.model.displayName}` : `${config.description} → ${selected.model.displayName}`, }; console.log("[Model Router] ✅ Selected:", result); return result; } } // 兜底逻辑:返回任意可用的图片编辑模型 const fallbackCandidates = allModels.filter( (m) => !m.model.isSubModel && m.model.isEnabled && (m.model.supportsImageGen || m.model.supportsVision) ); if (fallbackCandidates.length > 0) { const fallback = fallbackCandidates[0]; console.log("[Model Router] Using fallback (with image capability):", fallback.model.displayName); return { id: fallback.model.id, displayName: fallback.model.displayName, providerType: fallback.provider.type, modelId: fallback.model.modelId, reason: `fallback (${config.description})`, }; } // 最终兜底:返回任意可用模型 const anyModel = allModels.find((m) => !m.model.isSubModel && m.model.isEnabled); if (anyModel) { console.log("[Model Router] Using any available model:", anyModel.model.displayName); return { id: anyModel.model.id, displayName: anyModel.model.displayName, providerType: anyModel.provider.type, modelId: anyModel.model.modelId, reason: "fallback (any)", }; } // 如果没有任何模型,抛出错误 throw new Error("No available models for routing"); } /** * 获取意图的推荐模型列表(用于 UI 展示) */ export function getRecommendedModelsForIntent(intent: string): string[] { const config = INTENT_MODEL_MAP[intent]; return config ? config.providerTypes : INTENT_MODEL_MAP["chat"].providerTypes; } /** * 检查模型是否适合指定意图 */ export function isModelSuitableForIntent( providerType: string, intent: string, supportsVision: boolean, supportsImageGen: boolean ): boolean { const config = INTENT_MODEL_MAP[intent]; if (!config) return true; // 未知意图,允许任何模型 // 检查 provider 类型是否匹配 if (!config.providerTypes.includes(providerType)) { return false; } // 检查能力要求 if (config.requireVision && !supportsVision) return false; if (config.requireImageGen && !supportsImageGen) return false; return true; }