- Remove manual rename and save buttons from canvas header - Add auto-save logic with debounce - Add AI auto-titling and thumbnail generation based on canvas content - Add CanvasFileList sidebar for managing canvases - Direct entry to new canvas from top navigation - Add new API endpoint for auto-titling
80 lines
3.2 KiB
TypeScript
80 lines
3.2 KiB
TypeScript
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";
|
||
|
||
export async function POST(request: NextRequest) {
|
||
try {
|
||
const session = await auth();
|
||
if (!session?.user?.id) {
|
||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||
}
|
||
|
||
const { imageUrl } = await request.json();
|
||
|
||
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" });
|
||
|
||
// 默认使用通义千问 (Alibaba) 配置,如果未配置则尝试其他
|
||
// 这里为了简化,我们假设系统中配置了支持视觉的模型。
|
||
// 在实际生产中,最好在前端指定一个确定的视觉模型ID传过来。
|
||
|
||
// 构造 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 });
|
||
}
|
||
|
||
const openai = createOpenAI({
|
||
apiKey: apiKey,
|
||
baseURL: baseURL,
|
||
});
|
||
|
||
const { text } = await generateText({
|
||
model: openai("qwen-vl-max"), // 尝试使用 qwen-vl-max
|
||
messages: [
|
||
{
|
||
role: 'user',
|
||
content: [
|
||
{ type: 'text', text: prompt },
|
||
{ type: 'image', image: imageUrl },
|
||
],
|
||
},
|
||
],
|
||
});
|
||
|
||
return NextResponse.json({ title: text.trim() });
|
||
|
||
} catch (error) {
|
||
console.error("Auto-title error:", error);
|
||
// 失败时返回默认标题,不报错中断流程
|
||
return NextResponse.json({ title: "新画布" });
|
||
}
|
||
}
|