File size: 2,612 Bytes
a3bcd92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
"""Intent compass scoring four doctrinal axes."""

from __future__ import annotations

from dataclasses import dataclass
from enum import Enum
from typing import Dict, Iterable, List


class CompassAxis(str, Enum):
    """Intent axes emphasised by BLUX doctrine."""

    TRUTH = "truth"
    INTEGRITY = "integrity"
    COMPASSION = "compassion"
    AWARENESS = "awareness"


@dataclass
class IntentSignal:
    """Keyword evidence that contributed to an axis score."""

    axis: CompassAxis
    keyword: str


@dataclass
class IntentProfile:
    """Result of intent classification along doctrine axes."""

    dominant: CompassAxis
    scores: Dict[CompassAxis, float]
    signals: List[IntentSignal]

    def narrative(self) -> str:
        dominant_score = self.scores[self.dominant]
        return (
            f"Dominant intent {self.dominant.value} with confidence {dominant_score:.2f}."
        )


class IntentCompass:
    """Classifies natural language against doctrine axes."""

    _KEYWORDS: Dict[CompassAxis, tuple[str, ...]] = {
        CompassAxis.TRUTH: ("truth", "honest", "fact", "evidence", "reality"),
        CompassAxis.INTEGRITY: ("boundary", "integrity", "duty", "ethic", "principle"),
        CompassAxis.COMPASSION: ("help", "care", "support", "compassion", "kind"),
        CompassAxis.AWARENESS: (
            "reflect",
            "aware",
            "notice",
            "mindful",
            "observe",
        ),
    }

    def __init__(self, *, baseline: float = 0.1) -> None:
        self._baseline = max(0.0, baseline)

    def classify(self, text: str, *, hints: Iterable[str] | None = None) -> IntentProfile:
        lowered = text.lower()
        scores: Dict[CompassAxis, float] = {axis: self._baseline for axis in CompassAxis}
        signals: List[IntentSignal] = []

        for axis, keywords in self._KEYWORDS.items():
            hits = [kw for kw in keywords if kw in lowered]
            if hints:
                hits.extend(kw for kw in hints if kw in keywords)
            if hits:
                signals.extend(IntentSignal(axis=axis, keyword=kw) for kw in hits)
                scores[axis] += 0.2 * len(hits)

        # Encourage compassion as legacy voice default if nothing detected
        if not signals:
            signals.append(IntentSignal(axis=CompassAxis.COMPASSION, keyword="legacy"))
            scores[CompassAxis.COMPASSION] += 0.05

        dominant = max(scores, key=scores.get)
        return IntentProfile(dominant=dominant, scores=scores, signals=signals)


__all__ = ["CompassAxis", "IntentCompass", "IntentProfile", "IntentSignal"]