修复RUXA比例参数并禁止Base64入参
This commit is contained in:
parent
48f062897b
commit
55c41f7b45
@ -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({
|
||||
|
||||
@ -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");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user