File size: 2,268 Bytes
2d8be88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Pivot-Alpha / Jev-aligned typed decision schema (English).

Jev: unstructured state in → typed probabilistic decisions out.
We are NOT a free-text generator. Each call returns structured decisions
the host program can wire into a workflow.
"""
from __future__ import annotations

from typing import Any, Literal, Optional

Primitive = Literal["choice", "noul", "score"]


def build_typed_decision(
    *,
    decision_id: str,
    primitive: Primitive,
    options: list[str],
    index: int,
    probs: list[float],
    description: Optional[str] = None,
) -> dict[str, Any]:
    if len(options) != len(probs):
        raise ValueError("options/probs length mismatch")
    if not (0 <= index < len(options)):
        raise ValueError("index out of range")
    # named map for program consumption
    prob_map = {str(opt): float(p) for opt, p in zip(options, probs)}
    value = options[index]
    out: dict[str, Any] = {
        "id": decision_id,
        "primitive": primitive,
        "description": description,
        "options": list(options),
        "index": int(index),
        "value": value,
        "probs": prob_map,
        "prob_vector": [float(p) for p in probs],
        "confidence": float(max(probs) if probs else 0.0),
    }
    if primitive == "noul":
        # binary probabilistic decision (yes-mass = prob of first true-like option if present)
        true_aliases = {"true", "yes", "y", "1"}
        true_idx = next((i for i, o in enumerate(options) if str(o).lower() in true_aliases), index)
        out["p_true"] = float(probs[true_idx])
    if primitive == "score":
        # expected score if options are ordered numeric levels; else keep categorical
        try:
            levels = [float(o) for o in options]
            out["expected"] = float(sum(l * p for l, p in zip(levels, probs)))
        except ValueError:
            out["expected"] = None
    return out


def build_response(
    *,
    state: str,
    decisions: list[dict[str, Any]],
    model_id: str = "Pivot-Alpha",
) -> dict[str, Any]:
    return {
        "model": model_id,
        "contract": "unstructured_state_in__typed_probabilistic_decisions_out",
        "state": state,
        "decisions": decisions,
        "schema_version": "pivot-alpha-v1",
    }