Просмотр исходного кода

fix: prevent length normalizer from destroying chapter content

- sanitizeNormalizedContent: if stripCommonWrappers removes >50% of
  content, fall back to full LLM output (regex was too aggressive)
- sanitizeNormalizedContent: if strip result is empty (wrapper-only
  response), fall back to original chapter content
- runner: reject normalize result if finalCount < 25% of original
  (safety net against catastrophic content loss like 2612->795)
Ma 7 месяцев назад
Родитель
Сommit
14bf764756

+ 5 - 1
packages/core/src/agents/length-normalizer.ts

@@ -139,7 +139,11 @@ ${input.chapterContent}`;
 
     const stripped = this.stripCommonWrappers(trimmed);
     if (stripped !== undefined) {
-      return stripped || fallbackContent;
+      // Empty after stripping = response was only wrapper text, use original
+      if (!stripped) return fallbackContent;
+      // Guard: if stripping removed more than 50% of content, the regex was too aggressive.
+      if (stripped.length < trimmed.length * 0.5) return trimmed;
+      return stripped;
     }
 
     return trimmed;

+ 14 - 0
packages/core/src/pipeline/runner.ts

@@ -1807,6 +1807,20 @@ ${matrix}`,
       chapterIntent: params.chapterIntent,
     });
 
+    // Safety net: if normalizer output is less than 25% of original, it was too destructive.
+    // Reject and keep original content.
+    if (normalized.finalCount < writerCount * 0.25) {
+      this.logWarn(this.languageFromLengthSpec(params.lengthSpec), {
+        zh: `字数归一化被拒绝:第${params.chapterNumber}章 ${writerCount} -> ${normalized.finalCount}(砍了${Math.round((1 - normalized.finalCount / writerCount) * 100)}%,超过安全阈值)`,
+        en: `Length normalization rejected for chapter ${params.chapterNumber}: ${writerCount} -> ${normalized.finalCount} (cut ${Math.round((1 - normalized.finalCount / writerCount) * 100)}%, exceeds safety threshold)`,
+      });
+      return {
+        content: params.chapterContent,
+        wordCount: writerCount,
+        applied: false,
+      };
+    }
+
     this.logInfo(this.languageFromLengthSpec(params.lengthSpec), {
       zh: `审计前字数归一化:第${params.chapterNumber}章 ${writerCount} -> ${normalized.finalCount}`,
       en: `Length normalization before audit for chapter ${params.chapterNumber}: ${writerCount} -> ${normalized.finalCount}`,