fix: auto-title API 使用数据库配置的千问VL模型

1. 从数据库查找支持视觉的模型(qwen-vl 系列)
2. 使用对应 provider 的配置调用 API
3. 添加详细日志便于调试

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Your Name 2026-02-01 12:51:00 +08:00
parent 3bac27265b
commit 517d8e493c

View File

@ -1,63 +1,64 @@
import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/app/(auth)/auth";
import { createOpenAI } from "@ai-sdk/openai";
import { generateText } from "ai";
import { getSystemSetting } from "@/lib/db/queries";
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 });
}
// 获取 AI 配置
const aiProviderConfig = await getSystemSetting({ key: "ai_provider_config" });
const modelsConfig = await getSystemSetting({ key: "ai_models_config" });
// 从数据库获取支持视觉的模型(查找包含 qwen-vl 或 vision 的模型)
const models = await getEnabledAiModelsWithProvider();
console.log("[Auto-title] Available models count:", models.length);
// 默认使用通义千问 (Alibaba) 配置,如果未配置则尝试其他
// 这里为了简化,我们假设系统中配置了支持视觉的模型。
// 在实际生产中,最好在前端指定一个确定的视觉模型ID传过来。
// 查找千问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个字概括这张图片的主体内容,作为文件标题。直接返回标题,不要包含任何标点符号或其他文字。";
// 这里我们尝试使用环境变量中的配置,或者从数据库读取的配置初始化模型
// 为了确保稳定性,这里建议使用一个支持视觉的兜底模型配置
// 假设系统中有配置好的 'qwen-vl-max' 或类似模型
// 临时方案:直接使用 fetch 调用通义千问 API (如果使用了兼容 OpenAI 的接口)
// 或者使用项目现有的 provider 逻辑。
// 由于我看不到完整的 provider 实现细节,我将使用项目中已有的 /api/chat 逻辑的简化版
// 但为了更直接,我们这里模拟一个简单的视觉模型调用,或者利用 ai-sdk 的标准特性
// ⚠️ 注意:这里需要确保您的环境变量中有 ALIBABA_API_KEY 或者对应的配置
// 如果项目中统一使用了 provider 管理,最好复用。
// 为了不破坏现有架构,我们这里简化处理:
// 如果您有特定的 vision model ID,请替换这里。
// 这里的 fallback 逻辑需要根据您的实际 .env 配置来调整。
const apiKey = process.env.ALIBABA_API_KEY || process.env.OPENAI_API_KEY;
const baseURL = process.env.ALIBABA_BASE_URL || "https://dashscope.aliyuncs.com/compatible-mode/v1";
if (!apiKey) {
return NextResponse.json({ title: "未命名画布" }, { status: 200 });
}
// 使用数据库配置的 provider
const openai = createOpenAI({
apiKey: apiKey,
baseURL: baseURL,
apiKey: provider.apiKey,
baseURL: provider.baseUrl,
});
const { text } = await generateText({
model: openai("qwen-vl-max"), // 尝试使用 qwen-vl-max
model: openai(visionModel.modelId),
messages: [
{
role: 'user',
@ -69,10 +70,11 @@ export async function POST(request: NextRequest) {
],
});
console.log("[Auto-title] Generated title:", text.trim());
return NextResponse.json({ title: text.trim() });
} catch (error) {
console.error("Auto-title error:", error);
console.error("[Auto-title] Error:", error);
// 失败时返回默认标题,不报错中断流程
return NextResponse.json({ title: "新画布" });
}