fix(ecommerce): 502 bug - vision model upgrade + MIME normalization + fallback
- Upgrade VISION_MODEL to qwen3.7-plus (latest, confirmed working with image_url) - Add VISION_FALLBACK_MODEL = qwen-vl-plus for retry on "image format" errors - Normalize upload MIME types: unsupported formats (HEIC/AVIF) fall back to image/png to prevent server saving as .bin which DashScope can't read - Server-side: add image/avif, image/heic, image/heif to MIME_EXTENSIONS Root cause: DashScope returned "image format is illegal" when uploaded images had unrecognized MIME types → saved as .bin → DashScope couldn't decode. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { buildApiUrl, buildAuthHeaders } from "./serverConnection";
|
||||
|
||||
const TEXT_MODEL = "qwen-max";
|
||||
const VISION_MODEL = "qwen3.6-plus";
|
||||
const VISION_MODEL = "qwen3.7-plus";
|
||||
const VISION_FALLBACK_MODEL = "qwen-vl-plus";
|
||||
|
||||
export interface AdVideoUserConfig {
|
||||
platform: string;
|
||||
@@ -149,30 +150,39 @@ async function visionChat(
|
||||
...imageUrls.map((url) => ({ type: "image_url", image_url: { url } })),
|
||||
{ type: "text", text },
|
||||
];
|
||||
const timeoutSignal = AbortSignal.timeout(60000);
|
||||
const combinedSignal = signal
|
||||
? AbortSignal.any([signal, timeoutSignal])
|
||||
: timeoutSignal;
|
||||
const res = await fetch(buildApiUrl("ai/chat"), {
|
||||
method: "POST",
|
||||
headers: buildAuthHeaders(),
|
||||
body: JSON.stringify({
|
||||
model: VISION_MODEL,
|
||||
messages: [
|
||||
{ role: "system", content: systemPrompt },
|
||||
{ role: "user", content },
|
||||
],
|
||||
stream: false,
|
||||
temperature: 0.3,
|
||||
}),
|
||||
signal: combinedSignal,
|
||||
});
|
||||
if (!res.ok) throw new Error(`图片理解调用失败 (${res.status})`);
|
||||
const payload = await res.json();
|
||||
const out: string =
|
||||
payload?.content ?? payload?.choices?.[0]?.message?.content ?? payload?.text ?? "";
|
||||
if (!out) throw new Error("图片理解未返回有效内容");
|
||||
return out;
|
||||
const messages = [
|
||||
{ role: "system", content: systemPrompt },
|
||||
{ role: "user", content },
|
||||
];
|
||||
|
||||
for (const model of [VISION_MODEL, VISION_FALLBACK_MODEL]) {
|
||||
const timeoutSignal = AbortSignal.timeout(60000);
|
||||
const combinedSignal = signal
|
||||
? AbortSignal.any([signal, timeoutSignal])
|
||||
: timeoutSignal;
|
||||
try {
|
||||
const res = await fetch(buildApiUrl("ai/chat"), {
|
||||
method: "POST",
|
||||
headers: buildAuthHeaders(),
|
||||
body: JSON.stringify({ model, messages, stream: false, temperature: 0.3 }),
|
||||
signal: combinedSignal,
|
||||
});
|
||||
if (!res.ok) {
|
||||
const errBody = await res.text().catch(() => "");
|
||||
if (model === VISION_MODEL && errBody.includes("image format")) continue;
|
||||
throw new Error(`图片理解调用失败 (${res.status})`);
|
||||
}
|
||||
const payload = await res.json();
|
||||
const out: string =
|
||||
payload?.content ?? payload?.choices?.[0]?.message?.content ?? payload?.text ?? "";
|
||||
if (!out) throw new Error("图片理解未返回有效内容");
|
||||
return out;
|
||||
} catch (err) {
|
||||
if (model === VISION_MODEL && err instanceof Error && err.message?.includes("图片理解调用失败")) continue;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
throw new Error("图片理解调用失败,所有模型均不可用");
|
||||
}
|
||||
|
||||
const IMAGE_UNDERSTANDING_PROMPT = `你是电商产品图片分析专家。请分析用户提供的产品图片,识别产品主体、外观、颜色、材质、形状、尺寸感、品牌标识、关键部件、可视化卖点和适合展示的镜头角度。请用简洁的中文段落描述,不要编造图片中看不到的信息。`;
|
||||
|
||||
Reference in New Issue
Block a user