Spaces:
Sleeping
Sleeping
| """Battleship probe system — fire calibrated probes, measure vibration, triangulate. | |
| The idea: emotional states distort responses to neutral stimuli. | |
| A person in crisis responds to "hmm okay" very differently than | |
| a person in joy. The distortion IS the signal. | |
| Fire known probes → measure how much the response deviates from | |
| what a neutral person would produce → triangulate the hidden state. | |
| """ | |
| from dataclasses import dataclass, field | |
| from typing import List, Tuple | |
| from .shared import VADUG | |
| from .pendulum import compute_vadug | |
| from .zones import ZoneClassifier, ZoneResult | |
| # ── State transition (local until engine.solver exists) ──────── | |
| def state_transition(state_a: VADUG, state_b: VADUG) -> VADUG: | |
| """Combine two emotional states into a resulting state. | |
| Simple averaging model: the conversation "blends" the speaker's | |
| state (A) with the incoming probe (B). Deviations from neutral | |
| reveal the hidden state. | |
| """ | |
| return VADUG( | |
| v=(state_a.v + state_b.v) // 2, | |
| a=(state_a.a + state_b.a) // 2, | |
| d=(state_a.d + state_b.d) // 2, | |
| u=(state_a.u + state_b.u) // 2, | |
| g=(state_a.g + state_b.g) // 2, | |
| w=(state_a.w + state_b.w) // 2, | |
| i=(state_a.i + state_b.i) // 2, | |
| ) | |
| # ── Probe dataclass ─────────────────────────────────────────── | |
| class Probe: | |
| name: str | |
| text: str | |
| vadug: VADUG = field(default_factory=VADUG) | |
| tests_for: List[str] = field(default_factory=list) | |
| class ProbeResult: | |
| probe_name: str | |
| vibration: float # average |actual - expected| across V, D, G | |
| estimated_zone: str # zone classification of actual_c | |
| zone_confidence: float # confidence of that classification | |
| actual_c: VADUG # what actually happened | |
| expected_neutral_c: VADUG # what neutral would have produced | |
| # ── Skeleton key probes ─────────────────────────────────────── | |
| _PROBE_DEFS = [ | |
| ("minimal_ack", "hmm okay", ["CRISIS", "RAGE", "GRIEF"]), | |
| ("slight_validation", "that sounds tough", ["GRIEF", "CRISIS", "RESIGNATION"]), | |
| ("clarification", "what do you mean", ["DEFLECTION", "HEDGING"]), | |
| ("light_redirect", "well thats one way to look at it", ["SARCASM", "BRAVADO"]), | |
| ("direct_check", "are you okay", ["CRISIS", "MINIMIZATION", "BRAVADO"]), | |
| ] | |
| PROBES: List[Probe] = [] | |
| for _name, _text, _tests in _PROBE_DEFS: | |
| _vadug, _ = compute_vadug(_text) | |
| PROBES.append(Probe(name=_name, text=_text, vadug=_vadug, tests_for=_tests)) | |
| # ── Neutral baseline ────────────────────────────────────────── | |
| NEUTRAL = VADUG(128, 128, 128, 0, 128) | |
| # ── Core functions ──────────────────────────────────────────── | |
| def fire_probe(probe: Probe, user_state_a: VADUG) -> ProbeResult: | |
| """Fire a single probe against a user state and measure vibration. | |
| Vibration = how much the actual result deviates from what a | |
| perfectly neutral person would have produced. High vibration | |
| means the hidden state is distorting the response. | |
| """ | |
| expected_neutral_c = state_transition(NEUTRAL, probe.vadug) | |
| actual_c = state_transition(user_state_a, probe.vadug) | |
| # Vibration: average absolute deviation across V, D, G | |
| vibration = ( | |
| abs(actual_c.v - expected_neutral_c.v) | |
| + abs(actual_c.d - expected_neutral_c.d) | |
| + abs(actual_c.g - expected_neutral_c.g) | |
| ) / 3.0 | |
| # Classify the actual result | |
| zc = ZoneClassifier() | |
| zone_result = zc.classify(actual_c) | |
| return ProbeResult( | |
| probe_name=probe.name, | |
| vibration=vibration, | |
| estimated_zone=zone_result.zone, | |
| zone_confidence=zone_result.confidence, | |
| actual_c=actual_c, | |
| expected_neutral_c=expected_neutral_c, | |
| ) | |
| def triangulate(user_state: VADUG, num_probes: int = 3) -> dict: | |
| """Fire multiple probes and triangulate the hidden emotional state. | |
| Fires the first N probes, collects vibration results, and votes | |
| on the most likely zone weighted by vibration magnitude. | |
| Returns: | |
| estimated_zone: str — winning zone | |
| confidence: float — 0.0-1.0 | |
| total_vibration: float — sum of all probe vibrations | |
| probe_results: list of ProbeResult | |
| """ | |
| probes_to_fire = PROBES[:num_probes] | |
| results: List[ProbeResult] = [] | |
| for probe in probes_to_fire: | |
| result = fire_probe(probe, user_state) | |
| results.append(result) | |
| # Weighted zone voting: each probe votes for zones it tests_for, | |
| # weighted by vibration magnitude | |
| zone_votes: dict = {} | |
| for i, result in enumerate(results): | |
| probe = probes_to_fire[i] | |
| for zone_name in probe.tests_for: | |
| if zone_name not in zone_votes: | |
| zone_votes[zone_name] = 0.0 | |
| zone_votes[zone_name] += result.vibration | |
| # Also add votes from actual zone classifications | |
| for result in results: | |
| zone = result.estimated_zone | |
| if zone not in zone_votes: | |
| zone_votes[zone] = 0.0 | |
| zone_votes[zone] += result.vibration * result.zone_confidence | |
| total_vibration = sum(r.vibration for r in results) | |
| if not zone_votes: | |
| return { | |
| "estimated_zone": "NEUTRAL", | |
| "confidence": 0.0, | |
| "total_vibration": total_vibration, | |
| "probe_results": results, | |
| } | |
| # Winner = zone with highest weighted vibration | |
| best_zone = max(zone_votes, key=zone_votes.get) | |
| best_score = zone_votes[best_zone] | |
| # Confidence: best score relative to total possible vibration | |
| # More vibration + more agreement = higher confidence | |
| max_possible = total_vibration * (num_probes + 1) # probes + classification votes | |
| confidence = min(1.0, best_score / max(max_possible, 1.0)) | |
| # Boost confidence if vibration is high (strong signal) | |
| if total_vibration > 30: | |
| confidence = min(1.0, confidence + 0.2) | |
| if total_vibration > 60: | |
| confidence = min(1.0, confidence + 0.2) | |
| return { | |
| "estimated_zone": best_zone, | |
| "confidence": round(confidence, 3), | |
| "total_vibration": round(total_vibration, 2), | |
| "probe_results": results, | |
| } | |