fix(gateway): mediaAnalysis ffprobe path, fallback error-log, generic closer sanitize
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m47s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 4m11s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 11m36s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m47s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 4m11s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 11m36s
Audit log produksi (sejak deploy13:38) menemukan 3 isu:
1. mediaDownloader.ts spawn /usr/bin/ffprobe + /usr/bin/ffmpeg (path keras) —
ENOENT di Nix karena binary cuma di ffmpeg-headless closure. Pakai
PATH-resolved ('ffprobe'/'ffmpeg') seperti voice-recording module
(ffmpegProcess.ts/transmitter.ts) — 5 media warning hilang.
2. individualFallbackProcessor log error 'Success' di level50 tiap fallback
BERHASIL (logModerationError dengan new Error('Success')) — ganti
logger.info dengan verdict yang sama; error log cuma untuk error asli.
3. moderationResponseParser: strip frasa penutup generik ('Tidak ada
indikasi pelanggaran.') yang masih sering dikeluarkan LLM walau prompt
melarang (277/1486 analisis mengandung frasa, termasuk hari ini).
sanitizeGenericCleanCloser hanya mencocok frasa di AKHIR, teks substantif
tetap utuh. Unit test: 6/6 pass.
This commit is contained in:
@@ -155,13 +155,16 @@ async function processIndividualFallback(
|
||||
}
|
||||
|
||||
const resultSummary = analysisResult.results[0];
|
||||
logModerationError([messageId], config.AI_LLM_MODEL, new Error("Success"), {
|
||||
phase: "individual_fallback",
|
||||
status: resultSummary?.status,
|
||||
flags: resultSummary?.flags,
|
||||
severity: resultSummary?.severity,
|
||||
confidence: resultSummary?.confidence,
|
||||
});
|
||||
logger.info(
|
||||
{
|
||||
phase: "individual_fallback",
|
||||
status: resultSummary?.status,
|
||||
flags: resultSummary?.flags,
|
||||
severity: resultSummary?.severity,
|
||||
confidence: resultSummary?.confidence,
|
||||
},
|
||||
`Individual fallback moderation complete for ${messageId} (${resultSummary?.status})`,
|
||||
);
|
||||
|
||||
individualConsecutiveErrors = 0;
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ async function extractVideoFrames(
|
||||
try {
|
||||
await writeFile(inputPath, videoBytes);
|
||||
const { stdout: durationStr } = await execFileAsync(
|
||||
"/usr/bin/ffprobe",
|
||||
"ffprobe",
|
||||
[
|
||||
"-v",
|
||||
"error",
|
||||
@@ -213,7 +213,7 @@ async function extractVideoFrames(
|
||||
const duration = parseFloat(durationStr.trim()) || 1;
|
||||
const fps = (3 / duration).toFixed(6);
|
||||
await execFileAsync(
|
||||
"/usr/bin/ffmpeg",
|
||||
"ffmpeg",
|
||||
[
|
||||
"-i",
|
||||
inputPath,
|
||||
|
||||
@@ -157,6 +157,22 @@ export function sanitizeErrorMessage(
|
||||
return `Analisis gagal dan memerlukan pemeriksaan manual. Error code: MOD_${Date.now().toString(36).slice(0, 6)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip generic clean-verdict closing phrases the LLM sometimes appends
|
||||
* ("Tidak ada indikasi pelanggaran.") even when it already described the
|
||||
* message content specifically. Keeps the substance, drops the boilerplate.
|
||||
* Only matches a TRAILING standalone phrase — never mid-analysis text.
|
||||
*/
|
||||
export const GENERIC_CLEAN_CLOSER =
|
||||
/\s*(?:(?:tidak ada (?:indikasi|tanda|temuan)(?: adanya)? pelanggaran(?: kebijakan| aturan)?)|(?:tidak ada (?:indikasi|tanda|temuan)(?: konten| pesan)? (?:yang )?melanggar)|(?:pesan (?:dianggap|tergolong|dinilai) bersih)|(?:tidak ditemukan (?:adanya )?pelanggaran))\.?\s*$/i;
|
||||
|
||||
export function sanitizeGenericCleanCloser(analysis: string): string {
|
||||
if (!analysis) return analysis;
|
||||
const cleaned = analysis.replace(GENERIC_CLEAN_CLOSER, "").trim();
|
||||
// Drop a dangling separator the removal may have left behind.
|
||||
return cleaned.replace(/(\s[.\-–—]\s*)$/, "").trim();
|
||||
}
|
||||
|
||||
export function parseModerationResponse(
|
||||
content: string,
|
||||
targetIds: string[],
|
||||
@@ -250,7 +266,7 @@ export function parseModerationResponse(
|
||||
status: status as "clean" | "warn" | "flagged",
|
||||
flags: flags ?? [],
|
||||
score: normalizedScore,
|
||||
analysis: coalescedAnalysis,
|
||||
analysis: sanitizeGenericCleanCloser(coalescedAnalysis),
|
||||
categories: categories ?? flags ?? [],
|
||||
severity: normalizedSeverity,
|
||||
confidence: normalizedConfidence,
|
||||
|
||||
Reference in New Issue
Block a user