Adjust image model failover timing

This commit is contained in:
134 2026-06-12 17:24:13 +08:00
parent d24eedc578
commit 1b79f788b5
2 changed files with 57 additions and 7 deletions

View File

@ -25,6 +25,7 @@ interface UploadedImage {
const DEFAULT_IMAGE_SIZE = "2K";
const DEFAULT_TIMEOUT_MS = 300000;
const LONG_RUNNING_COMFLY_TIMEOUT_MS = 590000;
const OPENAI_IMAGE_MIN_TOTAL_PIXELS = 3_686_400;
const OPENAI_IMAGE_DIMENSION_MULTIPLE = 16;
const BLTCY_HOST_REGEX = /(^|\.)bltcy\.ai$/i;
@ -216,6 +217,13 @@ function resolveProviderImageSize(
return resolveOpenAISize(aspectRatio, imageSize);
}
function resolveRequestTimeoutMs(baseURL: string, imageSize?: "1K" | "2K" | "4K") {
if (isComflyBaseURL(baseURL) && imageSize === "4K") {
return LONG_RUNNING_COMFLY_TIMEOUT_MS;
}
return DEFAULT_TIMEOUT_MS;
}
function normalizeQuality(value?: string) {
const normalized = String(value || "").trim().toLowerCase();
if (normalized === "low" || normalized === "medium" || normalized === "high") {
@ -453,9 +461,10 @@ async function requestOpenAIImageGeneration(params: {
typeof aspectRatio === "string" && aspectRatio.trim() && aspectRatio !== "auto"
? aspectRatio.trim()
: undefined;
const timeoutMs = resolveRequestTimeoutMs(baseURL, imageSizeLabel);
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try {
if (imageUrls.length > 0) {
@ -588,6 +597,7 @@ export function createOpenAIImage({ apiKey, baseURL }: OpenAIImageConfig) {
promptAspectRatio: promptAspectRatio || undefined,
imageSize,
resolutionMode: isComflyBaseURL(baseURL) ? "longest-edge" : "pixel-area",
timeoutMs: resolveRequestTimeoutMs(baseURL, imageSize),
useBltcyImageCompatParams: shouldUseBltcyImageCompatParams(baseURL),
imageCount: imageUrls.length,
baseURL: normalizeBaseURL(baseURL),

View File

@ -89,6 +89,22 @@ export function classifyAiModelHealthFailure(error: unknown): {
};
}
if (
normalized.includes("fetch failed") ||
normalized.includes("econnreset") ||
normalized.includes("econnrefused") ||
normalized.includes("socket hang up") ||
normalized.includes("networkerror") ||
normalized.includes("network error")
) {
return {
eventType: "unavailable",
severity: "warning",
counted: false,
reason: "transport_failure_no_provider_response",
};
}
if (
normalized.includes("model not exist") ||
normalized.includes("model_not_found") ||
@ -133,9 +149,9 @@ export function classifyAiModelHealthFailure(error: unknown): {
) {
return {
eventType: "timeout",
severity: "critical",
counted: true,
reason: "timeout",
severity: "warning",
counted: false,
reason: "timeout_without_provider_response",
};
}
@ -150,8 +166,7 @@ export function classifyAiModelHealthFailure(error: unknown): {
normalized.includes("no available channel") ||
normalized.includes("no supported channel") ||
normalized.includes("service unavailable") ||
normalized.includes("fetch failed") ||
normalized.includes("econnreset")
normalized.includes("temporarily unavailable")
) {
return {
eventType: "unavailable",
@ -184,7 +199,32 @@ export function classifyAiModelHealthFailure(error: unknown): {
}
export function shouldFailoverAiModelError(error: unknown) {
return classifyAiModelHealthFailure(error).counted;
const classification = classifyAiModelHealthFailure(error);
if (!classification.counted) return false;
const normalized = getErrorMessage(error).toLowerCase();
if (classification.eventType === "timeout" || classification.eventType === "download_error") {
return false;
}
if (classification.eventType === "invalid_model" || classification.eventType === "quota") {
return true;
}
if (classification.eventType === "unavailable") {
return (
/(?:^|\D)(?:429|500|502|503|504)(?:\D|$)/.test(normalized) ||
normalized.includes("no available channel") ||
normalized.includes("no supported channel") ||
normalized.includes("service unavailable") ||
normalized.includes("temporarily unavailable") ||
normalized.includes("model maintenance") ||
normalized.includes("maintenance") ||
normalized.includes("修复中") ||
normalized.includes("系统繁忙") ||
normalized.includes("无可用渠道")
);
}
return /(?:^|\D)[45]\d\d(?:\D|$)/.test(normalized);
}
function buildMetadata(value?: Record<string, unknown>) {