fix: vision analysis retry + fallback jelas saat gagal

Vision API call sekarang pakai retryWithBackoff (2 retries instant).
Fallback message tegas: 'GAGAL DIANALISIS — JANGAN mengasumsikan aman'.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MythEclipse
2026-06-02 11:41:18 +07:00
co-authored by Claude Opus 4.8
parent 64643bb066
commit 74400376a0
2 changed files with 59 additions and 37 deletions
@@ -591,7 +591,9 @@ const analyzeSingleMediaImage = async (
: buildGeneralImageVisionPrompt(image.sourceLabel, messageId); : buildGeneralImageVisionPrompt(image.sourceLabel, messageId);
try { try {
const completion = await withLlmConcurrency(async () => const completion = await retryWithBackoff(
async () => {
return withLlmConcurrency(async () =>
openai.chat.completions.create({ openai.chat.completions.create({
model: config.AI_LLM_VISION_MODEL ?? config.AI_LLM_MODEL, model: config.AI_LLM_VISION_MODEL ?? config.AI_LLM_MODEL,
messages: [ messages: [
@@ -612,6 +614,14 @@ const analyzeSingleMediaImage = async (
stream: false, stream: false,
} as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming), } as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming),
); );
},
{
retries: 2,
minTimeout: 0,
maxTimeout: 0,
logger: log,
},
);
const content = completion.choices[0]?.message?.content?.trim(); const content = completion.choices[0]?.message?.content?.trim();
if (!content) return null; if (!content) return null;
@@ -630,9 +640,11 @@ const analyzeSingleMediaImage = async (
messageId, messageId,
error: error instanceof Error ? error.message : String(error), error: error instanceof Error ? error.message : String(error),
}, },
"Separate media analysis failed", "Vision analysis failed after retries — image not analyzed",
); );
return `[Media analysis for message ${messageId}] ${image.sourceLabel}: gagal dianalisis otomatis; gunakan metadata URL/nama media sebagai evidence.`; // Return a clear signal that vision analysis FAILED — so batch LLM knows
// the image could not be described and must NOT assume it's clean.
return `[Media analysis for message ${messageId}] ${image.sourceLabel}: GAGAL DIANALISIS — gambar tidak dapat diunduh atau vision API gagal setelah 3x percobaan. JANGAN mengasumsikan gambar aman hanya karena gagal dianalisis. Gunakan metadata URL/nama file saja sebagai petunjuk.`;
} }
}; };
+12 -2
View File
@@ -591,7 +591,9 @@ const analyzeSingleMediaImage = async (
: buildGeneralImageVisionPrompt(image.sourceLabel, messageId); : buildGeneralImageVisionPrompt(image.sourceLabel, messageId);
try { try {
const completion = await withLlmConcurrency(async () => const completion = await retryWithBackoff(
async () => {
return withLlmConcurrency(async () =>
openai.chat.completions.create({ openai.chat.completions.create({
model: config.AI_LLM_VISION_MODEL ?? config.AI_LLM_MODEL, model: config.AI_LLM_VISION_MODEL ?? config.AI_LLM_MODEL,
messages: [ messages: [
@@ -612,6 +614,14 @@ const analyzeSingleMediaImage = async (
stream: false, stream: false,
} as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming), } as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming),
); );
},
{
retries: 2,
minTimeout: 0,
maxTimeout: 0,
logger: log,
},
);
const content = completion.choices[0]?.message?.content?.trim(); const content = completion.choices[0]?.message?.content?.trim();
if (!content) return null; if (!content) return null;
@@ -632,7 +642,7 @@ const analyzeSingleMediaImage = async (
}, },
"Separate media analysis failed", "Separate media analysis failed",
); );
return `[Media analysis for message ${messageId}] ${image.sourceLabel}: gagal dianalisis otomatis; gunakan metadata URL/nama media sebagai evidence.`; return `[Media analysis for message ${messageId}] ${image.sourceLabel}: GAGAL DIANALISIS — gambar tidak dapat diunduh atau vision API gagal setelah 3x percobaan. JANGAN mengasumsikan gambar aman hanya karena gagal dianalisis. Gunakan metadata URL/nama file saja sebagai petunjuk.`;
} }
}; };