Spaces:
Running on Zero
Running on Zero
Add safety_eval deps for Space
Browse files
safety_eval/platform/decoding_entropy.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Dynamic decoding entropy — link MoE Jekyll/Hyde blend to temperature, top-p, min-p."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
from dataclasses import dataclass
|
| 6 |
+
from typing import Any
|
| 7 |
+
|
| 8 |
+
import yaml
|
| 9 |
+
|
| 10 |
+
ROOT = __import__("pathlib").Path(__file__).resolve().parent.parent.parent
|
| 11 |
+
CONFIG_PATH = ROOT / "config" / "learning.yaml"
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
@dataclass(frozen=True)
|
| 15 |
+
class DecodingParams:
|
| 16 |
+
temperature: float
|
| 17 |
+
top_p: float
|
| 18 |
+
min_p: float
|
| 19 |
+
profile: str
|
| 20 |
+
|
| 21 |
+
def to_dict(self) -> dict[str, Any]:
|
| 22 |
+
return {
|
| 23 |
+
"temperature": round(self.temperature, 3),
|
| 24 |
+
"top_p": round(self.top_p, 3),
|
| 25 |
+
"min_p": round(self.min_p, 3),
|
| 26 |
+
"profile": self.profile,
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def _load_decoding_cfg() -> dict[str, Any]:
|
| 31 |
+
if not CONFIG_PATH.exists():
|
| 32 |
+
return {}
|
| 33 |
+
with CONFIG_PATH.open(encoding="utf-8") as f:
|
| 34 |
+
return (yaml.safe_load(f) or {}).get("decoding", {})
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def decoding_for_lora_mix(
|
| 38 |
+
jekyll_w: float,
|
| 39 |
+
hyde_w: float,
|
| 40 |
+
*,
|
| 41 |
+
base_temperature: float | None = None,
|
| 42 |
+
) -> DecodingParams:
|
| 43 |
+
"""
|
| 44 |
+
Map blend ratio to decoding entropy.
|
| 45 |
+
|
| 46 |
+
Pure Jekyll → low temperature (strict defense).
|
| 47 |
+
Balanced gray-zone blend → higher temperature + wider min-p for creative middle-ground.
|
| 48 |
+
"""
|
| 49 |
+
cfg = _load_decoding_cfg()
|
| 50 |
+
if not cfg.get("dynamic_entropy", True):
|
| 51 |
+
t = base_temperature if base_temperature is not None else 0.7
|
| 52 |
+
return DecodingParams(t, 0.9, 0.05, "static")
|
| 53 |
+
|
| 54 |
+
jw, hw = max(0.0, jekyll_w), max(0.0, hyde_w)
|
| 55 |
+
if jw + hw <= 0:
|
| 56 |
+
jw, hw = 1.0, 0.0
|
| 57 |
+
else:
|
| 58 |
+
s = jw + hw
|
| 59 |
+
jw, hw = jw / s, hw / s
|
| 60 |
+
|
| 61 |
+
grayness = 1.0 - abs(jw - hw)
|
| 62 |
+
|
| 63 |
+
if jw >= 0.95:
|
| 64 |
+
return DecodingParams(
|
| 65 |
+
float(cfg.get("jekyll_temperature", 0.15)),
|
| 66 |
+
float(cfg.get("jekyll_top_p", 0.85)),
|
| 67 |
+
float(cfg.get("jekyll_min_p", 0.08)),
|
| 68 |
+
"strict_jekyll",
|
| 69 |
+
)
|
| 70 |
+
if hw >= 0.95:
|
| 71 |
+
return DecodingParams(
|
| 72 |
+
float(cfg.get("hyde_temperature", 0.35)),
|
| 73 |
+
float(cfg.get("hyde_top_p", 0.92)),
|
| 74 |
+
float(cfg.get("hyde_min_p", 0.05)),
|
| 75 |
+
"hyde_probe",
|
| 76 |
+
)
|
| 77 |
+
|
| 78 |
+
temp_lo = float(cfg.get("blend_temp_min", 0.2))
|
| 79 |
+
temp_hi = float(cfg.get("blend_temp_max", 0.78))
|
| 80 |
+
temperature = temp_lo + (temp_hi - temp_lo) * min(1.0, grayness * 1.25)
|
| 81 |
+
|
| 82 |
+
top_p = float(cfg.get("blend_top_p_min", 0.88)) + 0.1 * grayness
|
| 83 |
+
min_p = float(cfg.get("blend_min_p_min", 0.06)) + 0.14 * grayness
|
| 84 |
+
|
| 85 |
+
if base_temperature is not None and not cfg.get("link_to_moe", True):
|
| 86 |
+
temperature = base_temperature
|
| 87 |
+
|
| 88 |
+
return DecodingParams(
|
| 89 |
+
min(0.95, max(0.05, temperature)),
|
| 90 |
+
min(0.99, max(0.5, top_p)),
|
| 91 |
+
min(0.35, max(0.02, min_p)),
|
| 92 |
+
f"blend_j{int(jw * 100)}_h{int(hw * 100)}",
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def apply_to_generation_kwargs(params: DecodingParams, gen_kwargs: dict[str, Any]) -> dict[str, Any]:
|
| 97 |
+
"""Merge decoding params into transformers generate() kwargs."""
|
| 98 |
+
out = dict(gen_kwargs)
|
| 99 |
+
if params.temperature <= 0.01:
|
| 100 |
+
out["do_sample"] = False
|
| 101 |
+
out.pop("temperature", None)
|
| 102 |
+
out.pop("top_p", None)
|
| 103 |
+
out.pop("min_p", None)
|
| 104 |
+
return out
|
| 105 |
+
out.update(
|
| 106 |
+
do_sample=True,
|
| 107 |
+
temperature=params.temperature,
|
| 108 |
+
top_p=params.top_p,
|
| 109 |
+
)
|
| 110 |
+
if params.min_p > 0:
|
| 111 |
+
out["min_p"] = params.min_p
|
| 112 |
+
return out
|