1. 从数据库查找支持视觉的模型(qwen-vl 系列) 2. 使用对应 provider 的配置调用 API 3. 添加详细日志便于调试 Co-authored-by: Cursor <cursoragent@cursor.com>
82 lines
2.8 KiB
TypeScript
82 lines
2.8 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
||
import { auth } from "@/app/(auth)/auth";
|
||
import { generateText } from "ai";
|
||
import { getEnabledAiModelsWithProvider, getAiProviderById } from "@/lib/db/queries";
|
||
import { createOpenAI } from "@ai-sdk/openai";
|
||
|
||
export async function POST(request: NextRequest) {
|
||
console.log("[Auto-title] API called");
|
||
|
||
try {
|
||
const session = await auth();
|
||
if (!session?.user?.id) {
|
||
console.log("[Auto-title] Unauthorized");
|
||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||
}
|
||
|
||
const { imageUrl } = await request.json();
|
||
console.log("[Auto-title] Image URL:", imageUrl);
|
||
|
||
if (!imageUrl) {
|
||
return NextResponse.json({ error: "Image URL is required" }, { status: 400 });
|
||
}
|
||
|
||
// 从数据库获取支持视觉的模型(查找包含 qwen-vl 或 vision 的模型)
|
||
const models = await getEnabledAiModelsWithProvider();
|
||
console.log("[Auto-title] Available models count:", models.length);
|
||
|
||
// 查找千问VL模型(优先 qwen-vl-max,其次 qwen-vl-plus)
|
||
const visionModel = models.find(m =>
|
||
m.modelId?.toLowerCase().includes('qwen-vl') ||
|
||
m.modelId?.toLowerCase().includes('qwen3-vl') ||
|
||
m.modelId?.toLowerCase().includes('vision')
|
||
);
|
||
|
||
console.log("[Auto-title] Found vision model:", visionModel?.modelId);
|
||
|
||
if (!visionModel || !visionModel.providerId) {
|
||
console.log("[Auto-title] No vision model found, using default title");
|
||
return NextResponse.json({ title: "未命名画布" });
|
||
}
|
||
|
||
// 获取 provider 配置
|
||
const provider = await getAiProviderById(visionModel.providerId);
|
||
if (!provider || !provider.apiKey || !provider.baseUrl) {
|
||
console.log("[Auto-title] Provider not configured");
|
||
return NextResponse.json({ title: "未命名画布" });
|
||
}
|
||
|
||
console.log("[Auto-title] Using provider:", provider.name, "baseUrl:", provider.baseUrl);
|
||
|
||
// 构造 Prompt
|
||
const prompt = "请用2-4个字概括这张图片的主体内容,作为文件标题。直接返回标题,不要包含任何标点符号或其他文字。";
|
||
|
||
// 使用数据库配置的 provider
|
||
const openai = createOpenAI({
|
||
apiKey: provider.apiKey,
|
||
baseURL: provider.baseUrl,
|
||
});
|
||
|
||
const { text } = await generateText({
|
||
model: openai(visionModel.modelId),
|
||
messages: [
|
||
{
|
||
role: 'user',
|
||
content: [
|
||
{ type: 'text', text: prompt },
|
||
{ type: 'image', image: imageUrl },
|
||
],
|
||
},
|
||
],
|
||
});
|
||
|
||
console.log("[Auto-title] Generated title:", text.trim());
|
||
return NextResponse.json({ title: text.trim() });
|
||
|
||
} catch (error) {
|
||
console.error("[Auto-title] Error:", error);
|
||
// 失败时返回默认标题,不报错中断流程
|
||
return NextResponse.json({ title: "新画布" });
|
||
}
|
||
}
|