fix: align canvas auto-title model routing with agent multimodal
This commit is contained in:
parent
4524bc6d9f
commit
7141704f65
@ -1,8 +1,64 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { auth } from "@/app/(auth)/auth";
|
||||
import { generateText } from "ai";
|
||||
import { getEnabledAiModelsWithProvider } from "@/lib/db/queries";
|
||||
import {
|
||||
getAgentAiModelWithProvider,
|
||||
getEnabledAiModelsWithProvider,
|
||||
} from "@/lib/db/queries";
|
||||
import { getLanguageModelById } from "@/lib/ai/dynamic-provider";
|
||||
import { isAiModelMultimodal } from "@/lib/db/ai-model-flags";
|
||||
|
||||
const BLOCKED_PROVIDER_TYPES = new Set([
|
||||
"fal-video",
|
||||
"qianwen-video",
|
||||
"volcano-video",
|
||||
"doubao-video",
|
||||
"alibaba-image",
|
||||
"ruxa-image",
|
||||
"fal-image",
|
||||
"volcano-vision",
|
||||
]);
|
||||
|
||||
type VisionModelItem = Awaited<ReturnType<typeof getEnabledAiModelsWithProvider>>[number];
|
||||
|
||||
function isVisionCandidate(item: VisionModelItem) {
|
||||
const providerType = String(item.provider?.type || "");
|
||||
if (BLOCKED_PROVIDER_TYPES.has(providerType)) return false;
|
||||
|
||||
if (item.model.supportsVision) return true;
|
||||
if (isAiModelMultimodal(item.model)) return true;
|
||||
|
||||
const modelText = `${item.model.modelId || ""} ${item.model.displayName || ""}`.toLowerCase();
|
||||
if (/vl|vision|多模态|glm-4v|gpt-4o|doubao-seed-2-0|seed-2-0/.test(modelText)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function scoreVisionCandidate(item: VisionModelItem) {
|
||||
let score = 0;
|
||||
const providerType = String(item.provider?.type || "");
|
||||
if (isAiModelMultimodal(item.model)) score += 220;
|
||||
if (item.model.supportsVision) score += 160;
|
||||
if (providerType === "volcano-multimodal") score += 80;
|
||||
if (providerType === "zhipu") score += 50;
|
||||
if (providerType === "alibaba") score += 40;
|
||||
if (providerType === "custom") score += 30;
|
||||
if (item.model.isDefault) score += 20;
|
||||
score -= Math.max(0, item.model.sortOrder ?? 0);
|
||||
return score;
|
||||
}
|
||||
|
||||
function pickAutoTitleModel(allModels: VisionModelItem[], agentModel: VisionModelItem | undefined) {
|
||||
if (agentModel && isVisionCandidate(agentModel)) {
|
||||
return agentModel;
|
||||
}
|
||||
|
||||
const candidates = allModels.filter((item) => isVisionCandidate(item));
|
||||
if (candidates.length === 0) return null;
|
||||
return [...candidates].sort((a, b) => scoreVisionCandidate(b) - scoreVisionCandidate(a))[0];
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
console.log("[Auto-title] API called");
|
||||
@ -21,42 +77,25 @@ export async function POST(request: NextRequest) {
|
||||
return NextResponse.json({ error: "Image URL is required" }, { status: 400 });
|
||||
}
|
||||
|
||||
const blockedProviderTypes = new Set([
|
||||
"fal-video",
|
||||
"qianwen-video",
|
||||
"volcano-video",
|
||||
"doubao-video",
|
||||
]);
|
||||
|
||||
// 从数据库获取支持视觉的模型(优先使用 supportsVision)
|
||||
// 从数据库获取视觉模型,优先使用 AGENT 多模态模型
|
||||
const modelsData = await getEnabledAiModelsWithProvider();
|
||||
const agentModel = await getAgentAiModelWithProvider();
|
||||
|
||||
console.log("[Auto-title] Available models count:", modelsData.length);
|
||||
console.log("[Auto-title] All model IDs:", modelsData.map(m => m.model.modelId));
|
||||
|
||||
let visionModelData = modelsData.find(
|
||||
(m) => m.model.supportsVision && !blockedProviderTypes.has(String(m.provider?.type || "")),
|
||||
);
|
||||
if (!visionModelData) {
|
||||
// 兼容旧配置:根据模型名称兜底匹配
|
||||
visionModelData = modelsData.find(m => {
|
||||
if (blockedProviderTypes.has(String(m.provider?.type || ""))) {
|
||||
return false;
|
||||
}
|
||||
const id = m.model.modelId?.toLowerCase() || '';
|
||||
const name = m.model.displayName?.toLowerCase() || '';
|
||||
return id.includes('qwen-vl') ||
|
||||
id.includes('qwen3-vl') ||
|
||||
id.includes('qwen2.5-vl') ||
|
||||
id.includes('vision') ||
|
||||
name.includes('vl') ||
|
||||
name.includes('视觉');
|
||||
});
|
||||
}
|
||||
|
||||
console.log("[Auto-title] Found vision model:", visionModelData?.model.modelId, visionModelData?.model.displayName);
|
||||
|
||||
const visionModelData = pickAutoTitleModel(modelsData, agentModel);
|
||||
|
||||
console.log("[Auto-title] Selected vision model:", {
|
||||
modelId: visionModelData?.model.modelId,
|
||||
displayName: visionModelData?.model.displayName,
|
||||
providerType: visionModelData?.provider?.type,
|
||||
usedAgentModel: Boolean(agentModel && visionModelData && agentModel.model.id === visionModelData.model.id),
|
||||
isMultimodal: Boolean(visionModelData && isAiModelMultimodal(visionModelData.model)),
|
||||
});
|
||||
|
||||
if (!visionModelData) {
|
||||
console.log("[Auto-title] No vision model found, using default title");
|
||||
console.log("[Auto-title] No compatible vision model found, using default title");
|
||||
return NextResponse.json({ title: "未命名画布" });
|
||||
}
|
||||
|
||||
@ -82,7 +121,7 @@ export async function POST(request: NextRequest) {
|
||||
},
|
||||
],
|
||||
temperature: 0.2,
|
||||
maxTokens: 50,
|
||||
maxOutputTokens: 50,
|
||||
});
|
||||
|
||||
let title = (text || "").trim();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user