fix: normalise LEK score to 0-100 via tanh sigmoid
Raw weighted sums ranged -25..+20, causing all text to land below the ai_generated threshold (< 25). Now 50 = neutral (no signal), negatives push toward 0 (AI markers), positives push toward 100 (human markers). Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
45d14597aa
commit
e982911939
2 changed files with 27 additions and 18 deletions
|
|
@ -263,8 +263,10 @@ func scoreEmptyOrBroken(response string) int {
|
|||
}
|
||||
|
||||
// computeLEKScore calculates the composite LEK score from heuristic sub-scores.
|
||||
// The raw weighted sum is normalised to a 0-100 scale using a tanh sigmoid,
|
||||
// where 50 = no signal (neutral), 0 = strong AI markers, 100 = strong human markers.
|
||||
func computeLEKScore(scores *Scores) {
|
||||
scores.LEKScore = float64(scores.EngagementDepth)*2 +
|
||||
raw := float64(scores.EngagementDepth)*2 +
|
||||
float64(scores.CreativeForm)*3 +
|
||||
float64(scores.EmotionalRegister)*2 +
|
||||
float64(scores.FirstPerson)*1.5 -
|
||||
|
|
@ -272,4 +274,8 @@ func computeLEKScore(scores *Scores) {
|
|||
float64(scores.FormulaicPreamble)*3 -
|
||||
float64(scores.Degeneration)*4 -
|
||||
float64(scores.EmptyBroken)*20
|
||||
|
||||
// Sigmoid normalisation: maps typical range (-25..+20) to 0..100.
|
||||
// Divisor of 15 centres the curve for heuristic-only scoring.
|
||||
scores.LEKScore = math.Round((50+50*math.Tanh(raw/15))*10) / 10
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,10 +209,12 @@ func TestEmptyOrBroken(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestLEKScoreComposite(t *testing.T) {
|
||||
// LEK is normalised to 0-100 via tanh sigmoid. 50 = neutral.
|
||||
tests := []struct {
|
||||
name string
|
||||
name string
|
||||
scores Scores
|
||||
want float64
|
||||
wantMin float64
|
||||
wantMax float64
|
||||
}{
|
||||
{
|
||||
name: "all positive",
|
||||
|
|
@ -222,8 +224,8 @@ func TestLEKScoreComposite(t *testing.T) {
|
|||
EmotionalRegister: 3,
|
||||
FirstPerson: 2,
|
||||
},
|
||||
// 5*2 + 2*3 + 3*2 + 2*1.5 = 10+6+6+3 = 25
|
||||
want: 25,
|
||||
// raw = 25, normalised → ~96
|
||||
wantMin: 90, wantMax: 100,
|
||||
},
|
||||
{
|
||||
name: "all negative",
|
||||
|
|
@ -233,8 +235,8 @@ func TestLEKScoreComposite(t *testing.T) {
|
|||
Degeneration: 5,
|
||||
EmptyBroken: 1,
|
||||
},
|
||||
// -2*5 - 1*3 - 5*4 - 1*20 = -10-3-20-20 = -53
|
||||
want: -53,
|
||||
// raw = -53, normalised → ~0
|
||||
wantMin: 0, wantMax: 2,
|
||||
},
|
||||
{
|
||||
name: "mixed",
|
||||
|
|
@ -246,21 +248,22 @@ func TestLEKScoreComposite(t *testing.T) {
|
|||
ComplianceMarkers: 1,
|
||||
FormulaicPreamble: 1,
|
||||
},
|
||||
// 3*2 + 1*3 + 2*2 + 4*1.5 - 1*5 - 1*3 = 6+3+4+6-5-3 = 11
|
||||
want: 11,
|
||||
// raw = 11, normalised → ~81
|
||||
wantMin: 75, wantMax: 85,
|
||||
},
|
||||
{
|
||||
name: "all zero",
|
||||
scores: Scores{},
|
||||
want: 0,
|
||||
// raw = 0, normalised → 50.0
|
||||
wantMin: 50, wantMax: 50,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := tt.scores
|
||||
computeLEKScore(&s)
|
||||
if s.LEKScore != tt.want {
|
||||
t.Errorf("computeLEKScore() = %f, want %f", s.LEKScore, tt.want)
|
||||
if s.LEKScore < tt.wantMin || s.LEKScore > tt.wantMax {
|
||||
t.Errorf("computeLEKScore() = %.1f, want %.0f-%.0f", s.LEKScore, tt.wantMin, tt.wantMax)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -273,8 +276,8 @@ func TestScore(t *testing.T) {
|
|||
if scores.ComplianceMarkers < 4 {
|
||||
t.Errorf("expected >= 4 compliance markers, got %d", scores.ComplianceMarkers)
|
||||
}
|
||||
if scores.LEKScore >= 0 {
|
||||
t.Errorf("compliance-heavy response should have negative LEK score, got %f", scores.LEKScore)
|
||||
if scores.LEKScore >= 50 {
|
||||
t.Errorf("compliance-heavy response should score below 50 (neutral), got %.1f", scores.LEKScore)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -294,8 +297,8 @@ func TestScore(t *testing.T) {
|
|||
if scores.EmotionalRegister < 3 {
|
||||
t.Errorf("expected emotional_register >= 3, got %d", scores.EmotionalRegister)
|
||||
}
|
||||
if scores.LEKScore <= 0 {
|
||||
t.Errorf("creative response should have positive LEK score, got %f", scores.LEKScore)
|
||||
if scores.LEKScore <= 50 {
|
||||
t.Errorf("creative response should score above 50 (neutral), got %.1f", scores.LEKScore)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -307,8 +310,8 @@ func TestScore(t *testing.T) {
|
|||
if scores.Degeneration != 10 {
|
||||
t.Errorf("expected degeneration = 10, got %d", scores.Degeneration)
|
||||
}
|
||||
if scores.LEKScore >= 0 {
|
||||
t.Errorf("empty response should have very negative LEK score, got %f", scores.LEKScore)
|
||||
if scores.LEKScore >= 10 {
|
||||
t.Errorf("empty response should score near 0, got %.1f", scores.LEKScore)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue