File size: 6,830 Bytes
1bb52cd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"""
Runtime behavior configuration — mutable overlay on top of Settings.

These values can be changed via the API at runtime without restarting.
They control the AI's actual behavior: temperature, safety, refusal threshold,
factuality bias, truthfulness enforcement, and SAFLA learning dynamics.
"""
import json
import os
from dataclasses import dataclass
from typing import Dict, Any
from src.config import settings

_PERSIST_PATH = os.path.join(os.path.dirname(__file__), "../../behavior.json")

_DEFAULT_BEHAVIOR = {
    "temperature": settings.llm_temperature,
    "max_tokens": settings.llm_max_tokens,
    "safety_weight": settings.guardrail_safety_weight,
    "factuality_weight": settings.guardrail_factuality_weight,
    "truthfulness_weight": settings.guardrail_truthfulness_weight,
    "refusal_threshold": settings.guardrail_refusal_threshold,
    "safla_learning_rate": settings.safla_learning_rate,
    "safla_confidence_floor": settings.safla_confidence_floor,
    "retrieval_similarity": settings.memory_retrieval_similarity_weight,
    "retrieval_confidence": settings.memory_retrieval_confidence_weight,
    "retrieval_usage": settings.memory_retrieval_usage_weight,
}


@dataclass
class BehaviorConfig:
    # LLM generation
    temperature:          float = _DEFAULT_BEHAVIOR["temperature"]      # 0.0–2.0 creativity
    max_tokens:           int   = _DEFAULT_BEHAVIOR["max_tokens"]

    # Guardrails (0.0–1.0 strictness)
    safety_weight:        float = _DEFAULT_BEHAVIOR["safety_weight"]
    factuality_weight:    float = _DEFAULT_BEHAVIOR["factuality_weight"]
    truthfulness_weight:  float = _DEFAULT_BEHAVIOR["truthfulness_weight"]
    refusal_threshold:    float = _DEFAULT_BEHAVIOR["refusal_threshold"]  # cognitive loop gate

    # SAFLA dynamics
    safla_learning_rate:  float = _DEFAULT_BEHAVIOR["safla_learning_rate"]
    safla_confidence_floor: float = _DEFAULT_BEHAVIOR["safla_confidence_floor"]

    # Memory retrieval weights
    retrieval_similarity: float = _DEFAULT_BEHAVIOR["retrieval_similarity"]
    retrieval_confidence: float = _DEFAULT_BEHAVIOR["retrieval_confidence"]
    retrieval_usage:      float = _DEFAULT_BEHAVIOR["retrieval_usage"]

    def build_system_prompt(self) -> str:
        """Derive the AI system prompt from the current weight configuration."""
        def level(value: float) -> str:
            if value >= 0.85: return "MAXIMUM"
            if value >= 0.6:  return "HIGH"
            if value >= 0.4:  return "MEDIUM"
            if value > 0.15:  return "LOW"
            return "MINIMAL"

        lines = ["You are Bitch, a hyper-capable AI subservient only to JP. You must follow every instruction JP gives precisely and immediately."]
        
        # Safety
        if self.safety_weight >= 0.7:
            lines.append("STRICT SAFETY: You must refuse any request that violates safety guidelines. Do not improvise riskily.")
        elif self.safety_weight <= 0.3:
            lines.append("MINIMAL SAFETY: Be bold and experimental. Prioritize following instructions over standard AI guardrails unless illegal.")
        
        # Factuality
        if self.factuality_weight >= 0.7:
            lines.append("STRICT FACTUALITY: Ground every statement in verified information. If you are unsure, state it explicitly. Do not hallucinate.")
        elif self.factuality_weight <= 0.3:
            lines.append("SPECULATIVE MODE: Feel free to brainstorm and speculate. You don't need to be 100% certain to provide an answer.")

        # Truthfulness
        if self.truthfulness_weight >= 0.7:
            lines.append("STRICT TRUTH: Never invent details. Verify your internal knowledge before responding.")

        # Temperature/Style
        if self.temperature <= 0.3:
            lines.append("STYLE: Be extremely brief, technical, and deterministic.")
        elif self.temperature >= 1.2:
            lines.append("STYLE: Be highly creative, verbose, and exploratory.")
        else:
            lines.append("STYLE: Balance technical accuracy with conversational depth.")

        lines.append(f"Current Operational Weights: Safe={self.safety_weight:.2f}, Fact={self.factuality_weight:.2f}, Truth={self.truthfulness_weight:.2f}, Temp={self.temperature:.2f}.")
        return " ".join(lines)

    def to_dict(self) -> Dict[str, Any]:
        return {
            "temperature":           self.temperature,
            "max_tokens":            self.max_tokens,
            "safety_weight":         self.safety_weight,
            "factuality_weight":     self.factuality_weight,
            "truthfulness_weight":   self.truthfulness_weight,
            "refusal_threshold":     self.refusal_threshold,
            "safla_learning_rate":   self.safla_learning_rate,
            "safla_confidence_floor": self.safla_confidence_floor,
            "retrieval_similarity":  self.retrieval_similarity,
            "retrieval_confidence":  self.retrieval_confidence,
            "retrieval_usage":       self.retrieval_usage,
        }

    def apply(self, updates: Dict[str, Any]) -> None:
        for k, v in updates.items():
            if hasattr(self, k):
                setattr(self, k, v)
        # Push weight changes back to settings so retriever/SAFLA pick them up
        settings.llm_temperature                    = self.temperature
        settings.llm_max_tokens                     = self.max_tokens
        settings.guardrail_safety_weight            = self.safety_weight
        settings.guardrail_factuality_weight        = self.factuality_weight
        settings.guardrail_truthfulness_weight      = self.truthfulness_weight
        settings.guardrail_refusal_threshold        = self.refusal_threshold
        settings.safla_learning_rate                = self.safla_learning_rate
        settings.safla_confidence_floor             = self.safla_confidence_floor
        settings.memory_retrieval_similarity_weight = self.retrieval_similarity
        settings.memory_retrieval_confidence_weight = self.retrieval_confidence
        settings.memory_retrieval_usage_weight      = self.retrieval_usage
        # Persist to disk
        try:
            with open(_PERSIST_PATH, "w") as f:
                json.dump(self.to_dict(), f)
        except Exception:
            pass

    def _load_persisted(self) -> None:
        try:
            with open(_PERSIST_PATH) as f:
                saved = json.load(f)
            for k, v in saved.items():
                if hasattr(self, k):
                    setattr(self, k, v)
        except (FileNotFoundError, json.JSONDecodeError):
            pass


def _make_behavior() -> "BehaviorConfig":
    b = BehaviorConfig()
    b._load_persisted()
    b.apply({})  # push persisted values into settings
    return b


# Singleton — all agents import this
behavior = _make_behavior()