import { experimental_generateImage as generateImage, generateText } from "ai"; import { createOpenAI } from "@ai-sdk/openai"; import { createXai } from "@ai-sdk/xai"; import type { ImageModelV1 } from "@ai-sdk/provider"; import type { ProviderApiKeys } from "./keys"; import { resolveApiKey } from "./keys"; import { getModel } from "./provider"; import { sanitizePromptText } from "@/lib/utils"; function getImageModel(aiProvider: string, apiKeys: ProviderApiKeys): ImageModelV1 { const xaiKey = resolveApiKey("xai", apiKeys); const openaiKey = resolveApiKey("openai", apiKeys); if (aiProvider === "openai" && openaiKey) { return createOpenAI({ apiKey: openaiKey }).image("dall-e-3"); } if (xaiKey) { return createXai({ apiKey: xaiKey }).image("grok-2-image"); } if (openaiKey) { return createOpenAI({ apiKey: openaiKey }).image("dall-e-3"); } throw new Error("請在設定頁填入 xAI 或 OpenAI API key 以使用 AI 生圖"); } async function buildImagePrompt(input: { text: string; hook?: string | null; imageBrief?: string | null; angle?: string | null; aiProvider: string; aiModel: string; apiKeys: ProviderApiKeys; }): Promise { const model = getModel(input.aiProvider, input.aiModel, input.apiKeys); const context = sanitizePromptText( [ input.angle ? `切角:${input.angle}` : "", input.hook ? `開頭:${input.hook}` : "", input.imageBrief ? `配圖說明:${input.imageBrief}` : "", `貼文:${input.text}`, ] .filter(Boolean) .join("\n") ); const { text } = await generateText({ model, system: "You write concise English prompts for social media image generation. Output only the prompt, no markdown.", prompt: `Create one image generation prompt for a Threads post visual. Requirements: - Warm, modern, mobile-friendly composition - No real celebrity faces or logos - Minimal readable text on image (prefer no text) - Match the mood of this Traditional Chinese post ${context}`, }); const prompt = text.trim(); if (!prompt) { throw new Error("無法產生繪圖提示詞"); } return prompt.slice(0, 1200); } export async function generateDraftImage(input: { text: string; hook?: string | null; imageBrief?: string | null; angle?: string | null; aiProvider: string; aiModel: string; apiKeys: ProviderApiKeys; }) { const prompt = await buildImagePrompt(input); const model = getImageModel(input.aiProvider, input.apiKeys); const { image } = await generateImage({ model, prompt, aspectRatio: "1:1", }); return { image, prompt }; }