fix(agent): prefer remote image for qwen fallback vision parsing
This commit is contained in:
parent
ee9350eb0b
commit
86e914709f
@ -371,11 +371,16 @@ async function buildAnalyzerVisionImagesByMode(params: {
|
||||
return buildAnalyzerVisionImages(urls);
|
||||
}
|
||||
|
||||
async function getQwen3VlFallbackImageInput(imageUrls?: string[]): Promise<string | null> {
|
||||
async function getQwen3VlFallbackImageCandidates(imageUrls?: string[]): Promise<string[]> {
|
||||
const firstImageUrl = (imageUrls || []).find((url) => isHttpUrl(url));
|
||||
if (!firstImageUrl) return null;
|
||||
if (!firstImageUrl) return [];
|
||||
|
||||
const candidates: string[] = [firstImageUrl];
|
||||
const inlineDataUrl = await toAnalyzerDataUrl(firstImageUrl);
|
||||
return inlineDataUrl || firstImageUrl;
|
||||
if (inlineDataUrl) {
|
||||
candidates.push(inlineDataUrl);
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
async function analyzeWithHardcodedQwen3VlFallback(params: {
|
||||
@ -388,8 +393,8 @@ async function analyzeWithHardcodedQwen3VlFallback(params: {
|
||||
}): Promise<AnalysisResult | null> {
|
||||
if (!params.hasImage) return null;
|
||||
|
||||
const imageInput = await getQwen3VlFallbackImageInput(params.imageUrls);
|
||||
if (!imageInput) {
|
||||
const imageCandidates = await getQwen3VlFallbackImageCandidates(params.imageUrls);
|
||||
if (imageCandidates.length === 0) {
|
||||
console.warn(
|
||||
`[Smart Analyzer] qwen3-vl fallback skipped: no valid image url (${params.reason})`,
|
||||
);
|
||||
@ -421,22 +426,29 @@ async function analyzeWithHardcodedQwen3VlFallback(params: {
|
||||
console.warn(
|
||||
`[Smart Analyzer] Primary analysis failed, fallback to hardcoded qwen3-vl (${params.reason})`,
|
||||
);
|
||||
const { text: fallbackText, model } = await callQwen3Vl({
|
||||
imageUrl: imageInput,
|
||||
prompt,
|
||||
temperature: 0.1,
|
||||
maxTokens: 360,
|
||||
timeoutMs: ANALYZER_TIMEOUT_MS,
|
||||
retries: 1,
|
||||
});
|
||||
const parsed = parseAnalysisResultFromModelText(
|
||||
fallbackText,
|
||||
params.text,
|
||||
params.hasImage,
|
||||
);
|
||||
if (parsed) {
|
||||
console.log(`[Smart Analyzer] qwen3-vl fallback success: ${model}`);
|
||||
return parsed;
|
||||
for (const imageInput of imageCandidates) {
|
||||
const inputMode = imageInput.startsWith("data:image/") ? "inline" : "remote";
|
||||
try {
|
||||
const { text: fallbackText, model } = await callQwen3Vl({
|
||||
imageUrl: imageInput,
|
||||
prompt,
|
||||
temperature: 0.1,
|
||||
maxTokens: 360,
|
||||
timeoutMs: ANALYZER_TIMEOUT_MS,
|
||||
retries: 1,
|
||||
});
|
||||
const parsed = parseAnalysisResultFromModelText(
|
||||
fallbackText,
|
||||
params.text,
|
||||
params.hasImage,
|
||||
);
|
||||
if (parsed) {
|
||||
console.log(`[Smart Analyzer] qwen3-vl fallback success: ${model}, input=${inputMode}`);
|
||||
return parsed;
|
||||
}
|
||||
} catch (attemptError) {
|
||||
console.warn(`[Smart Analyzer] qwen3-vl fallback attempt failed: input=${inputMode}`, attemptError);
|
||||
}
|
||||
}
|
||||
console.warn("[Smart Analyzer] qwen3-vl fallback returned unparsable content");
|
||||
return null;
|
||||
@ -451,8 +463,8 @@ async function summarizeWithHardcodedQwen3VlFallback(params: {
|
||||
context?: string;
|
||||
imageUrls?: string[];
|
||||
}): Promise<string | null> {
|
||||
const imageInput = await getQwen3VlFallbackImageInput(params.imageUrls);
|
||||
if (!imageInput) return null;
|
||||
const imageCandidates = await getQwen3VlFallbackImageCandidates(params.imageUrls);
|
||||
if (imageCandidates.length === 0) return null;
|
||||
|
||||
const prompt = [
|
||||
"你是图像观察助手。只描述图片可见内容,不要写执行过程,不要推测用户意图。",
|
||||
@ -466,18 +478,25 @@ async function summarizeWithHardcodedQwen3VlFallback(params: {
|
||||
try {
|
||||
const { callQwen3Vl } = await import("./qwen3-vl");
|
||||
console.warn("[Smart Analyzer] Visual summary fallback to hardcoded qwen3-vl");
|
||||
const { text, model } = await callQwen3Vl({
|
||||
imageUrl: imageInput,
|
||||
prompt,
|
||||
temperature: 0.1,
|
||||
maxTokens: 140,
|
||||
timeoutMs: ANALYZER_TIMEOUT_MS,
|
||||
retries: 1,
|
||||
});
|
||||
const normalized = normalizeVisualSummaryText(text);
|
||||
if (normalized && !isWeakVisualSummary(normalized)) {
|
||||
console.log(`[Smart Analyzer] qwen3-vl summary fallback success: ${model}`);
|
||||
return normalized;
|
||||
for (const imageInput of imageCandidates) {
|
||||
const inputMode = imageInput.startsWith("data:image/") ? "inline" : "remote";
|
||||
try {
|
||||
const { text, model } = await callQwen3Vl({
|
||||
imageUrl: imageInput,
|
||||
prompt,
|
||||
temperature: 0.1,
|
||||
maxTokens: 140,
|
||||
timeoutMs: ANALYZER_TIMEOUT_MS,
|
||||
retries: 1,
|
||||
});
|
||||
const normalized = normalizeVisualSummaryText(text);
|
||||
if (normalized && !isWeakVisualSummary(normalized)) {
|
||||
console.log(`[Smart Analyzer] qwen3-vl summary fallback success: ${model}, input=${inputMode}`);
|
||||
return normalized;
|
||||
}
|
||||
} catch (attemptError) {
|
||||
console.warn(`[Smart Analyzer] qwen3-vl summary fallback attempt failed: input=${inputMode}`, attemptError);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user