Your Name 1a9f453a20
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
fix: use correct function names for AI model queries
2026-01-24 20:23:41 +08:00

151 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextResponse } from "next/server";
import { auth } from "@/app/(auth)/auth";
import { getEnabledAiModelsWithProvider, getAiProviderById } from "@/lib/db/queries";
import { createGeminiImage } from "@/lib/ai/providers/gemini-image";
import { createAlibabaImage } from "@/lib/ai/providers/alibaba-image";
export const maxDuration = 120;
interface GenerateImageRequest {
prompt: string;
negativePrompt?: string;
model?: string; // 模型 ID
aspectRatio?: string; // 宽高比 "1:1", "16:9" 等
imageCount?: number; // 生成数量
referenceImage?: string; // 参考图片(用于图生图)
}
export async function POST(request: Request) {
try {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json(
{ success: false, error: "未登录" },
{ status: 401 }
);
}
const body: GenerateImageRequest = await request.json();
const { prompt, negativePrompt, model, aspectRatio = "1:1", imageCount = 1, referenceImage } = body;
if (!prompt) {
return NextResponse.json(
{ success: false, error: "请输入提示词" },
{ status: 400 }
);
}
// 获取可用的图片生成模型(筛选 supportsImageGen 的模型)
const allModels = await getEnabledAiModelsWithProvider();
const imageModels = allModels.filter(m => m.model.supportsImageGen);
if (!imageModels || imageModels.length === 0) {
return NextResponse.json(
{ success: false, error: "暂无可用的图片生成模型" },
{ status: 400 }
);
}
// 选择模型(如果指定了 model,使用指定的;否则使用默认的)
let selectedModel = model
? imageModels.find(m => m.model.modelId === model)
: imageModels.find(m => m.model.isDefault) || imageModels[0];
if (!selectedModel) {
selectedModel = imageModels[0];
}
const provider = await getAiProviderById({ id: selectedModel.model.providerId });
if (!provider) {
return NextResponse.json(
{ success: false, error: "模型提供商配置错误" },
{ status: 500 }
);
}
// 计算尺寸
const sizeMap: Record<string, { width: number; height: number }> = {
"1:1": { width: 1024, height: 1024 },
"3:2": { width: 1536, height: 1024 },
"2:3": { width: 1024, height: 1536 },
"4:3": { width: 1365, height: 1024 },
"3:4": { width: 1024, height: 1365 },
"16:9": { width: 1820, height: 1024 },
"9:16": { width: 1024, height: 1820 },
};
const size = sizeMap[aspectRatio] || sizeMap["1:1"];
// 构建消息
const messages = [
{
role: "user" as const,
content: prompt,
}
];
// 图片参数
const imageParams = {
aspectRatio,
imageSize: `${size.width}x${size.height}`,
imageCount,
negativePrompt,
};
let result;
// 根据提供商类型调用不同的生成器
if (provider.type === "gemini") {
const geminiProvider = createGeminiImage({
apiKey: provider.apiKey,
baseURL: provider.baseUrl,
});
result = await geminiProvider.doGenerate({
messages,
modelId: selectedModel.model.modelId,
imageParams,
});
} else if (provider.type === "alibaba-image") {
const alibabaProvider = createAlibabaImage({
apiKey: provider.apiKey,
baseURL: provider.baseUrl,
});
result = await alibabaProvider.doGenerate({
messages,
modelId: selectedModel.model.modelId,
imageParams,
referenceImage,
});
} else {
return NextResponse.json(
{ success: false, error: "不支持的图片生成模型类型" },
{ status: 400 }
);
}
if (result.images && result.images.length > 0) {
return NextResponse.json({
success: true,
data: {
images: result.images,
model: selectedModel.model.displayName,
prompt,
}
});
} else {
return NextResponse.json(
{ success: false, error: "图片生成失败" },
{ status: 500 }
);
}
} catch (error) {
console.error("[Canvas Generate Image] Error:", error);
return NextResponse.json(
{ success: false, error: error instanceof Error ? error.message : "生成失败" },
{ status: 500 }
);
}
}