Skip to content

Commit 70c0c4a

Browse files
committed
updates based on copilot, we've hit diminishing returns
1 parent 5f62bc5 commit 70c0c4a

2 files changed

Lines changed: 46 additions & 3 deletions

File tree

tika-ml/tika-ml-junkdetect/src/main/java/org/apache/tika/ml/junkdetect/JunkDetector.java

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,16 @@ public static JunkDetector load(InputStream rawIs) throws IOException {
353353
f1TablesByScript.put(script, BigramTables.readFrom(dis));
354354
}
355355

356+
requireUsableSigma("scriptTransition", scriptTransitionCalibration);
357+
requireUsableSigma("block", blockCalibration);
358+
requireUsableSigma("control", controlCalibration);
359+
requireUsableSigma("z5", z5Calibration);
360+
requireUsableSigma("z6", z6Calibration);
361+
requireUsableSigma("z9", z9Calibration);
362+
for (Map.Entry<String, float[]> e : calibrations.entrySet()) {
363+
requireUsableSigma("z1[" + e.getKey() + "]", e.getValue());
364+
}
365+
356366
return new JunkDetector(calibrations,
357367
blockTable, blockTableQuant, blockCalibration,
358368
controlCalibration, combinerWeights,
@@ -363,6 +373,22 @@ public static JunkDetector load(InputStream rawIs) throws IOException {
363373
}
364374
}
365375

376+
/**
377+
* Validates a calibration {@code {mu, sigma}} from the model file: sigma is the
378+
* divisor in every z-score, so it must be finite and &gt; 0. Single enforcement
379+
* point for that invariant -- inference divides without re-checking.
380+
*/
381+
static void requireUsableSigma(String name, float[] calibration) throws IOException {
382+
boolean ok = calibration != null && calibration.length >= 2
383+
&& Float.isFinite(calibration[1]) && calibration[1] > 0f;
384+
if (!ok) {
385+
String sigma = (calibration == null || calibration.length < 2)
386+
? "absent" : Float.toString(calibration[1]);
387+
throw new IOException("Invalid model: " + name
388+
+ " calibration sigma must be finite and > 0 but was " + sigma);
389+
}
390+
}
391+
366392
/** Read {@code size} big-endian int16 values as a short[]. */
367393
private static short[] readShortTable(DataInputStream dis, int size) throws IOException {
368394
byte[] raw = dis.readNBytes(size * 2);
@@ -642,7 +668,7 @@ public static final class FeatureComponents {
642668
*/
643669
public float computeZ5LetterAdjacentToMarkRatio(String text) {
644670
double raw = TextQualityFeatures.letterAdjacentToMarkRatio(text);
645-
if (Double.isNaN(raw) || z5Calibration == null || z5Calibration[1] <= 0) {
671+
if (Double.isNaN(raw) || z5Calibration == null) {
646672
return 0f;
647673
}
648674
return ((float) raw - z5Calibration[0]) / z5Calibration[1];
@@ -658,7 +684,7 @@ public float computeZ5LetterAdjacentToMarkRatio(String text) {
658684
*/
659685
public float computeZ6ReplacementRatio(String text) {
660686
double raw = TextQualityFeatures.replacementRatio(text);
661-
if (Double.isNaN(raw) || z6Calibration == null || z6Calibration[1] <= 0) {
687+
if (Double.isNaN(raw) || z6Calibration == null) {
662688
return 0f;
663689
}
664690
// Flip sign: higher replacement = lower quality, so feature is
@@ -676,7 +702,7 @@ public float computeZ6ReplacementRatio(String text) {
676702
*/
677703
public float computeZ9AlternationRatio(String text) {
678704
double raw = TextQualityFeatures.scriptAlternationRatio(text);
679-
if (Double.isNaN(raw) || z9Calibration == null || z9Calibration[1] <= 0) {
705+
if (Double.isNaN(raw) || z9Calibration == null) {
680706
return 0f;
681707
}
682708
// Higher alternation = junkier; (mu - raw) / sigma so clean text → positive z9.

tika-ml/tika-ml-junkdetect/src/test/java/org/apache/tika/ml/junkdetect/JunkDetectorRoundTripTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
*/
1717
package org.apache.tika.ml.junkdetect;
1818

19+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
1920
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
import static org.junit.jupiter.api.Assertions.assertThrows;
2022
import static org.junit.jupiter.api.Assertions.assertTrue;
2123

2224
import java.io.BufferedWriter;
@@ -52,6 +54,21 @@
5254
*/
5355
public class JunkDetectorRoundTripTest {
5456

57+
@Test
58+
void requireUsableSigmaRejectsNonPositiveOrNonFinite() {
59+
assertDoesNotThrow(() -> JunkDetector.requireUsableSigma("ok", new float[]{-3f, 0.5f}));
60+
for (float badSigma : new float[]{0f, -0.1f, Float.NaN,
61+
Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY}) {
62+
assertThrows(IOException.class,
63+
() -> JunkDetector.requireUsableSigma("bad", new float[]{0f, badSigma}),
64+
"sigma=" + badSigma + " must be rejected");
65+
}
66+
assertThrows(IOException.class,
67+
() -> JunkDetector.requireUsableSigma("null", null));
68+
assertThrows(IOException.class,
69+
() -> JunkDetector.requireUsableSigma("short", new float[]{1f}));
70+
}
71+
5572
@Test
5673
void roundTripSeenPairAndUnigramBackoff(@TempDir Path tmp) throws IOException {
5774
// -----------------------------------------------------------------

0 commit comments

Comments
 (0)