// server/utils/openai.ts import OpenAI from "openai"; import type { BaseOptions, IImageGenerateData } from "#shared/types/openai"; const IMAGE_GENERATION_URL = "https://api.qflink.xyz/v1/images/generations"; const IMAGE_GENERATION_MODEL = "gpt-image-2"; const IMAGE_GENERATION_SIZE = "1024x1024"; interface IImageGenerationResponse { /** 上游创建时间 */ created?: number; /** 上游图片生成结果列表 */ data?: Array<{ /** 上游返回的修订提示词,可能为空 */ revised_prompt?: string; /** 生成图片地址 */ url?: string; }>; } /** 通用 AI 调用函数(支持文本 / 图文 / 多模态) */ export const askAI = async ({ apiKey, model, baseURL, input }: BaseOptions & { input: OpenAI.Responses.ResponseCreateParams["input"]; }) => { const client = new OpenAI({ apiKey, baseURL }); return await client.responses.create({ model, input }); }; /** 调用文本模型 */ export const askText = async ( options: BaseOptions & { text: string; } ) => { const res = await askAI({ ...options, input: options.text }); return res.output_text; }; /** * 调用视觉模型:输入「文本 + 图片」,输出文本 * * 分辨率参数说明: * * | 值 | 含义 | * |------|--------------------------| * | low | 低分辨率(更快、更省成本) | * | high | 高分辨率(更精准) | * | auto | 自动选择 | * */ export const askVision = async ( options: BaseOptions & { text: string; image: string; detail?: "low" | "high" | "auto"; } ) => { // 如果图片不是 URL,也不是 data URL,就当成 base64 处理,自动补全 data URL 前缀 const normalizeImage = (img: string) => { if (img.startsWith("http")) return img; if (!img.startsWith("data:")) { return `data:image/png;base64,${img}`; } return img; }; const res = await askAI({ ...options, input: [ { role: "user", content: [ { type: "input_text", text: options.text }, { type: "input_image", image_url: normalizeImage(options.image), detail: options.detail || "auto" } ] } ] }); return res.output_text; }; /** 调用图片生成接口,完整 API Key 只在服务端使用 */ export const askImg = async ({ apiKey, prompt }: { apiKey: string; prompt: string; }): Promise => { const result = await $fetch(IMAGE_GENERATION_URL, { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }, body: { model: IMAGE_GENERATION_MODEL, prompt, size: IMAGE_GENERATION_SIZE } }); const image = result.data?.[0]; if (!image?.url) { throw new Error("图片生成失败"); } return { imageUrl: image.url, revisedPrompt: image.revised_prompt }; }; /** 调用流式接口 */ export const askStream = async ( options: BaseOptions & { input: OpenAI.Responses.ResponseCreateParams["input"]; } ) => { const client = new OpenAI({ apiKey: options.apiKey, baseURL: options.baseURL }); const stream = await client.responses.stream({ model: options.model, input: options.input }); return stream; };