修复RUXA比例参数并禁止Base64入参
This commit is contained in:
parent
48f062897b
commit
55c41f7b45
@ -178,6 +178,55 @@ function injectHistoryImagesToLastUserMessage(
|
|||||||
* 因为这些 provider 内部会自行处理图片上传到 S3
|
* 因为这些 provider 内部会自行处理图片上传到 S3
|
||||||
*/
|
*/
|
||||||
async function convertMessagesWithImages(messages: ChatMessage[], providerType: string) {
|
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 格式传输图片
|
// 所有 provider 都使用 URL 格式传输图片
|
||||||
// gemini-image 和 huanke-gemini 内部会将 Base64 转换为 S3 URL
|
// gemini-image 和 huanke-gemini 内部会将 Base64 转换为 S3 URL
|
||||||
// 这里不再进行 Base64 转换,直接返回标准格式
|
// 这里不再进行 Base64 转换,直接返回标准格式
|
||||||
@ -1252,7 +1301,9 @@ export async function POST(request: Request) {
|
|||||||
|
|
||||||
const tryGenerateImage = async (modelIdToUse: string, isRetry: boolean) => {
|
const tryGenerateImage = async (modelIdToUse: string, isRetry: boolean) => {
|
||||||
// 转换消息(阿里生图支持 URL,会自动上传 base64)
|
// 转换消息(阿里生图支持 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 获取图片,传递模型显示名称
|
// 调用 doGenerate 获取图片,传递模型显示名称
|
||||||
const result = await (languageModel as any).doGenerate({
|
const result = await (languageModel as any).doGenerate({
|
||||||
|
|||||||
@ -20,8 +20,8 @@ interface UploadedImage {
|
|||||||
original: string;
|
original: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_ASPECT_RATIO = "1:1";
|
const DEFAULT_ASPECT_RATIO = "auto";
|
||||||
const DEFAULT_RESOLUTION = "1K";
|
const DEFAULT_RESOLUTION = "1k";
|
||||||
const DEFAULT_OUTPUT_FORMAT = "png";
|
const DEFAULT_OUTPUT_FORMAT = "png";
|
||||||
const POLL_INTERVAL_MS = 2000;
|
const POLL_INTERVAL_MS = 2000;
|
||||||
const POLL_MAX_ATTEMPTS = 60;
|
const POLL_MAX_ATTEMPTS = 60;
|
||||||
@ -50,17 +50,30 @@ function joinApiPath(baseURL: string, path: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function normalizeAspectRatio(aspectRatio?: string) {
|
function normalizeAspectRatio(aspectRatio?: string) {
|
||||||
if (!aspectRatio || aspectRatio === "auto") return DEFAULT_ASPECT_RATIO;
|
if (!aspectRatio) return DEFAULT_ASPECT_RATIO;
|
||||||
return aspectRatio;
|
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) {
|
function normalizeResolution(imageSize?: string) {
|
||||||
if (!imageSize) return DEFAULT_RESOLUTION;
|
if (!imageSize) return DEFAULT_RESOLUTION;
|
||||||
const normalized = imageSize.toUpperCase();
|
const normalized = imageSize.trim().toLowerCase();
|
||||||
if (["1K", "2K", "4K"].includes(normalized)) return normalized;
|
if (["1k", "2k", "4k"].includes(normalized)) return normalized;
|
||||||
return DEFAULT_RESOLUTION;
|
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 {
|
function extractTaskId(payload: any): string | undefined {
|
||||||
return (
|
return (
|
||||||
payload?.taskId ||
|
payload?.taskId ||
|
||||||
@ -107,9 +120,14 @@ function extractPromptAndImages(messages: Array<{ role: string; content: any }>)
|
|||||||
const imageUrls: string[] = [];
|
const imageUrls: string[] = [];
|
||||||
|
|
||||||
const pushImageUrl = (url?: string) => {
|
const pushImageUrl = (url?: string) => {
|
||||||
if (!url || !url.startsWith("http")) return;
|
if (!url) return;
|
||||||
if (!imageUrls.includes(url)) {
|
const normalized = String(url).trim();
|
||||||
imageUrls.push(url);
|
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 { prompt, imageUrls } = extractPromptAndImages(options.messages);
|
||||||
const aspectRatio = normalizeAspectRatio(options.imageParams?.aspectRatio);
|
const aspectRatio = normalizeAspectRatio(options.imageParams?.aspectRatio);
|
||||||
const resolution = normalizeResolution(options.imageParams?.imageSize);
|
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 activeModelId = options.overrideModelId || modelId;
|
||||||
|
|
||||||
const createEndpoint = joinApiPath(baseURL, "/api/v1/tasks/create");
|
const createEndpoint = joinApiPath(baseURL, "/api/v1/tasks/create");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user