Files
aiartstudio/server/utils/openai.ts
T
2026-04-25 19:14:58 +08:00

153 lines
3.3 KiB
TypeScript

// 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<IImageGenerateData> => {
const result = await $fetch<IImageGenerationResponse>(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;
};