修复RUXA比例参数并禁止Base64入参

This commit is contained in:
Your Name 2026-02-07 20:47:22 +08:00
parent 48f062897b
commit 55c41f7b45
2 changed files with 80 additions and 11 deletions

View File

@ -178,6 +178,55 @@ function injectHistoryImagesToLastUserMessage(
* 因为这些 provider 内部会自行处理图片上传到 S3
*/
async function convertMessagesWithImages(messages: ChatMessage[], providerType: string) {
if (providerType === "ruxa-image") {
const convertedMessages = [];
for (const message of messages) {
const content: any[] = [];
for (const part of message.parts) {
const partAny = part as any;
if (partAny.type === "text" && partAny.text) {
content.push({
type: "text",
text: partAny.text,
});
continue;
}
const candidateUrl =
partAny.type === "file"
? (partAny.url || partAny.data)
: partAny.type === "image"
? (partAny.image || partAny.url)
: partAny.type === "image_url"
? partAny.image_url?.url
: undefined;
if (!candidateUrl || typeof candidateUrl !== "string") continue;
if (candidateUrl.startsWith("data:")) {
throw new Error("RUXA 不支持 Base64 图片传输,请先上传图片后再编辑");
}
if (!candidateUrl.startsWith("http")) continue;
content.push({
type: "image_url",
image_url: {
url: candidateUrl,
},
});
}
convertedMessages.push({
role: message.role,
content: content.length === 1 && content[0].type === "text" ? content[0].text : content,
});
}
return convertedMessages;
}
// 所有 provider 都使用 URL 格式传输图片
// gemini-image 和 huanke-gemini 内部会将 Base64 转换为 S3 URL
// 这里不再进行 Base64 转换,直接返回标准格式
@ -1252,7 +1301,9 @@ export async function POST(request: Request) {
const tryGenerateImage = async (modelIdToUse: string, isRetry: boolean) => {
// 转换消息(阿里生图支持 URL,会自动上传 base64)
const modelMessages = await convertMessagesWithImages(messagesForAlibaba, "alibaba-image");
const providerForConvert =
(languageModel as any).provider === "ruxa-image" ? "ruxa-image" : "alibaba-image";
const modelMessages = await convertMessagesWithImages(messagesForAlibaba, providerForConvert);
// 调用 doGenerate 获取图片,传递模型显示名称
const result = await (languageModel as any).doGenerate({

View File

@ -20,8 +20,8 @@ interface UploadedImage {
original: string;
}
const DEFAULT_ASPECT_RATIO = "1:1";
const DEFAULT_RESOLUTION = "1K";
const DEFAULT_ASPECT_RATIO = "auto";
const DEFAULT_RESOLUTION = "1k";
const DEFAULT_OUTPUT_FORMAT = "png";
const POLL_INTERVAL_MS = 2000;
const POLL_MAX_ATTEMPTS = 60;
@ -50,17 +50,30 @@ function joinApiPath(baseURL: string, path: string) {
}
function normalizeAspectRatio(aspectRatio?: string) {
if (!aspectRatio || aspectRatio === "auto") return DEFAULT_ASPECT_RATIO;
return aspectRatio;
if (!aspectRatio) return DEFAULT_ASPECT_RATIO;
const normalized = aspectRatio.trim().toLowerCase();
if (normalized === "auto") return "auto";
const ratio = aspectRatio.trim();
if (["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"].includes(ratio)) {
return ratio;
}
return DEFAULT_ASPECT_RATIO;
}
function normalizeResolution(imageSize?: string) {
if (!imageSize) return DEFAULT_RESOLUTION;
const normalized = imageSize.toUpperCase();
if (["1K", "2K", "4K"].includes(normalized)) return normalized;
const normalized = imageSize.trim().toLowerCase();
if (["1k", "2k", "4k"].includes(normalized)) return normalized;
return DEFAULT_RESOLUTION;
}
function normalizeOutputFormat(outputFormat?: string): "png" | "jpg" {
if (!outputFormat) return DEFAULT_OUTPUT_FORMAT;
const normalized = outputFormat.trim().toLowerCase();
if (normalized === "jpg" || normalized === "jpeg") return "jpg";
return "png";
}
function extractTaskId(payload: any): string | undefined {
return (
payload?.taskId ||
@ -107,9 +120,14 @@ function extractPromptAndImages(messages: Array<{ role: string; content: any }>)
const imageUrls: string[] = [];
const pushImageUrl = (url?: string) => {
if (!url || !url.startsWith("http")) return;
if (!imageUrls.includes(url)) {
imageUrls.push(url);
if (!url) return;
const normalized = String(url).trim();
if (normalized.startsWith("data:")) {
throw new Error("RUXA 不支持 Base64 图片传输,请先上传图片后再编辑");
}
if (!normalized.startsWith("http")) return;
if (!imageUrls.includes(normalized)) {
imageUrls.push(normalized);
}
};
@ -325,7 +343,7 @@ export function createRuxaImage({ apiKey, baseURL }: RuxaImageConfig) {
const { prompt, imageUrls } = extractPromptAndImages(options.messages);
const aspectRatio = normalizeAspectRatio(options.imageParams?.aspectRatio);
const resolution = normalizeResolution(options.imageParams?.imageSize);
const outputFormat = options.imageParams?.outputFormat || DEFAULT_OUTPUT_FORMAT;
const outputFormat = normalizeOutputFormat(options.imageParams?.outputFormat);
const activeModelId = options.overrideModelId || modelId;
const createEndpoint = joinApiPath(baseURL, "/api/v1/tasks/create");