- Introduced `format_scalar_for_prompt_text` function to standardize the representation of scalar values in activity summaries and details. - Updated `get_activity_summary` and `get_activity_detail` functions to utilize the new formatting for improved readability. - Added normalization for float values in session metrics to prevent excessively long representations. - Enhanced unit tests to verify the new formatting and normalization behavior.
128 lines
3.8 KiB
Python
128 lines
3.8 KiB
Python
"""
|
|
Kompakte Zahlen- und JSON-Aufbereitung für KI-Platzhalter (Token sparen).
|
|
|
|
- Floats: sinnvolle Nachkommastellen je nach Größenordnung (kleine Werte <0,1 mehr Präzision).
|
|
- ≥10 meist ganzzahlig; Prozent/Verhältnisse über denselben Mechanismus lesbar.
|
|
- Rekursiv auf dict/list-Strukturen vor json.dumps in _safe_json anwendbar.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
from decimal import Decimal
|
|
from typing import Any
|
|
|
|
|
|
def compact_float_for_prompt(x: float) -> float | int:
|
|
"""
|
|
Reduziert unnötige Nachkommastellen; erhält kleine Beträge (<0,1) mit mehr Stellen.
|
|
"""
|
|
if not math.isfinite(x):
|
|
return x
|
|
ax = abs(x)
|
|
if ax == 0.0:
|
|
return 0
|
|
if ax >= 100.0:
|
|
return int(round(x))
|
|
if ax >= 10.0:
|
|
return int(round(x))
|
|
if ax >= 1.0:
|
|
r = round(x, 2)
|
|
return int(r) if abs(r - int(round(r))) < 1e-6 else r
|
|
if ax >= 0.1:
|
|
r = round(x, 2)
|
|
return int(r) if abs(r - int(round(r))) < 1e-6 else r
|
|
if ax >= 0.01:
|
|
return round(x, 3)
|
|
return round(x, 4)
|
|
|
|
|
|
def normalize_prompt_number(x: Any) -> Any:
|
|
"""int/Decimal/float kompakt; Rest unverändert."""
|
|
if x is None:
|
|
return None
|
|
if isinstance(x, bool):
|
|
return x
|
|
if isinstance(x, int) and not isinstance(x, bool):
|
|
return x
|
|
if isinstance(x, Decimal):
|
|
try:
|
|
xf = float(x)
|
|
except Exception:
|
|
return x
|
|
return compact_float_for_prompt(xf)
|
|
if isinstance(x, float):
|
|
return compact_float_for_prompt(x)
|
|
return x
|
|
|
|
|
|
def compact_json_payload_for_prompts(obj: Any) -> Any:
|
|
"""
|
|
Tiefe Kopie mit kompakten Zahlen (dicts/list/tuples rekursiv).
|
|
Strings und dict-Keys werden nicht verändert.
|
|
"""
|
|
if obj is None:
|
|
return None
|
|
if isinstance(obj, dict):
|
|
return {k: compact_json_payload_for_prompts(v) for k, v in obj.items()}
|
|
if isinstance(obj, (list, tuple)):
|
|
t = [compact_json_payload_for_prompts(v) for v in obj]
|
|
return tuple(t) if isinstance(obj, tuple) else t
|
|
return normalize_prompt_number(obj)
|
|
|
|
|
|
def format_scalar_for_prompt_text(x: Any) -> str:
|
|
"""
|
|
Kurzdarstellung für Text-Platzhalter (activity_detail, Tabellen, …).
|
|
Nutzt dieselbe Komprimierung wie JSON (normalize_prompt_number).
|
|
"""
|
|
if x is None:
|
|
return "—"
|
|
if isinstance(x, bool):
|
|
return "ja" if x else "nein"
|
|
if isinstance(x, str):
|
|
return x
|
|
n = normalize_prompt_number(x)
|
|
if isinstance(n, bool):
|
|
return "ja" if n else "nein"
|
|
if isinstance(n, int) and not isinstance(n, bool):
|
|
return str(n)
|
|
if isinstance(n, float):
|
|
if not math.isfinite(n):
|
|
return str(n)
|
|
if abs(n - round(n)) < 1e-9:
|
|
return str(int(round(n)))
|
|
return str(n)
|
|
return str(n)
|
|
|
|
|
|
def session_metrics_list_to_key_value_compact(metrics: list[Any] | None) -> dict[str, Any]:
|
|
"""
|
|
Session-Metriken für KI-JSON: nur key → Wert (keine wiederholten Namen/Beschreibungen).
|
|
|
|
Semantik: {{training_parameters_glossary_md}} im Prompt ergänzen.
|
|
"""
|
|
out: dict[str, Any] = {}
|
|
for m in metrics or []:
|
|
if not isinstance(m, dict):
|
|
continue
|
|
k = m.get("key")
|
|
if not k:
|
|
continue
|
|
v = m.get("value")
|
|
dt = (m.get("data_type") or "").lower()
|
|
if v is None:
|
|
out[str(k)] = None
|
|
continue
|
|
if dt == "integer":
|
|
try:
|
|
out[str(k)] = int(v)
|
|
except (TypeError, ValueError):
|
|
out[str(k)] = normalize_prompt_number(v)
|
|
elif dt == "boolean":
|
|
out[str(k)] = bool(v)
|
|
elif dt == "string":
|
|
out[str(k)] = str(v)
|
|
else:
|
|
out[str(k)] = normalize_prompt_number(v)
|
|
return out
|