전 저장소 리팩터링과 SSOT 정비

This commit is contained in:
Yun Chan 2026-07-15 21:31:30 +09:00
parent 14ecbd4e7d
commit 3dfddcac6f
173 changed files with 19679 additions and 6952 deletions

View file

@ -19,8 +19,12 @@ from .store import InProcSession, TurnRecord, store
logger = logging.getLogger(__name__)
_LIVE_COACH_RECHARGE_MIN_RAPPORT = 0.35
_LIVE_COACH_RECHARGE_MIN_OPENNESS_GAIN = 0.02
_LIVE_COACH_RECHARGE_MIN_RAPPORT = 0.15
_LIVE_COACH_RECHARGE_NEUTRAL_MIN_RAPPORT = 0.35
_LIVE_COACH_RECHARGE_MIN_OPENNESS_GAIN = 0.01
# 페이싱 충전: 평가 신호와 무관하게 N턴마다 1개. 코칭이 가장 필요한(잘 못 풀리는)
# 학습자가 3개 소진 후 영영 코칭을 못 받는 순감 구조를 막는다(2026-07-13 회의 후속).
_LIVE_COACH_PACING_RECHARGE_EVERY_TURNS = 6
class SessionAccessError(str, Enum):
@ -187,25 +191,42 @@ def should_recharge_live_coach_credit(
before: state_machine.SessionState,
after: state_machine.SessionState,
) -> tuple[bool, str]:
"""Good-score recharge gate based on stored evaluator/state-machine evidence."""
if not isinstance(evaluation, dict):
return False, ""
if evaluation.get("appropriateness") != "pos":
return False, ""
try:
rapport = float(evaluation.get("rapport_signal") or 0)
except (TypeError, ValueError):
rapport = 0.0
if rapport < _LIVE_COACH_RECHARGE_MIN_RAPPORT:
return False, ""
"""좋은 발화 충전 + 진행 페이싱 충전 게이트.
기존 3 AND(appropriateness==pos + rapport>=0.35 + 단계전환/개방도+0.02)
실사용에서 충전이 사실상 불가능해 코칭이 3 만에 죽었다. 완화된 성과 충전에
페이싱 충전을 더해, 잘하는 학습자는 빨리·모두가 주기적으로 충전받게 한다.
"""
appropriateness = evaluation.get("appropriateness") if isinstance(evaluation, dict) else None
rapport = 0.0
if isinstance(evaluation, dict):
try:
rapport = float(evaluation.get("rapport_signal") or 0)
except (TypeError, ValueError):
rapport = 0.0
openness_gain = float(after.effective_openness or 0) - float(before.effective_openness or 0)
stage_changed = after.stage != before.stage
if not stage_changed and openness_gain < _LIVE_COACH_RECHARGE_MIN_OPENNESS_GAIN:
return False, ""
if stage_changed:
return True, "좋은 발화로 내담자 단계가 열려 코칭 기회 1개를 충전했습니다."
return True, "좋은 발화 뒤 내담자 개방도가 올라 코칭 기회 1개를 충전했습니다."
if appropriateness == "pos" and rapport >= _LIVE_COACH_RECHARGE_MIN_RAPPORT:
if stage_changed:
return True, "좋은 발화로 내담자 단계가 열려 코칭 기회 1개를 충전했습니다."
if openness_gain >= _LIVE_COACH_RECHARGE_MIN_OPENNESS_GAIN:
return True, "좋은 발화 뒤 내담자 개방도가 올라 코칭 기회 1개를 충전했습니다."
if (
appropriateness == "neutral"
and rapport >= _LIVE_COACH_RECHARGE_NEUTRAL_MIN_RAPPORT
and openness_gain > 0
):
return True, "안정적인 라포 신호로 코칭 기회 1개를 충전했습니다."
# 페이싱 충전 — 평가 실패(evaluation=None)여도 회기 진행 자체로 충전된다.
turn_seq = int(after.turn_seq or 0)
if turn_seq > 0 and turn_seq % _LIVE_COACH_PACING_RECHARGE_EVERY_TURNS == 0:
return (
True,
f"회기가 {_LIVE_COACH_PACING_RECHARGE_EVERY_TURNS}턴 진행되어 코칭 기회 1개를 충전했습니다.",
)
return False, ""
async def maybe_recharge_live_coach_credit(