mitai-jinkendo/backend/data_layer/prompt_output_compact.py
Lars 6756dc60f3
All checks were successful
Deploy Development / deploy (push) Successful in 55s
Build Test / pytest-backend (push) Successful in 5s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 16s
feat: enhance session metrics handling in activity summaries
- Integrated compact JSON payload generation for session metrics in `get_training_sessions_recent_weeks_data`.
- Updated the registration of activity session insights to reflect the new compact format for session metrics.
- Improved documentation to clarify the structure and semantics of the session metrics in the JSON output.
- Added normalization for prompt numbers to ensure consistent formatting in the metrics.
2026-04-18 10:24:44 +02:00

103 lines
3.0 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 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