런타임 계약과 학습자 흐름 보강

This commit is contained in:
Yun Chan 2026-06-29 08:12:14 +09:00
parent f456b8997a
commit 206018b088
56 changed files with 4306 additions and 1008 deletions

View file

@ -32,6 +32,7 @@ from ..engine_client import (
StreamRequest,
)
from ..contracts.engine_gateway import (
ENGINE_GATEWAY_DEFAULT_MODEL_SENTINEL,
ENGINE_GATEWAY_SSE_DONE,
ENGINE_GATEWAY_SSE_ERROR,
EngineGatewaySseDecodeError,
@ -40,7 +41,7 @@ from ..contracts.engine_gateway import (
StreamTokenEvent,
)
from . import guardrail, persona, state_machine
from .persona import PersonaCard, PersonaStateContext
from .persona import PersonaCard, PersonaStateContext, TurnMemory
from .state_machine import SessionState, Stage
# 평가 훅 타입: U_t(수련생 마스킹 발화) + 내담자응답 + 상태 → 평가 결과(dict)
@ -63,10 +64,7 @@ class TurnContext:
state_after: Optional[SessionState] = None
messages: list[EngineMessage] = field(default_factory=list)
# 회상/메모리 주입(memory.RecallContext 에서 옴)
recall_summary: Optional[str] = None
pinned_facts: list[str] = field(default_factory=list)
recent_turns: list[dict[str, str]] = field(default_factory=list)
kb_behavior_cues: list[str] = field(default_factory=list)
memory: TurnMemory = field(default_factory=TurnMemory)
# 회기 이론모드(학습자 선택: humanistic|cbt|integrative). 평가 이론부합·생성 프레이밍에 사용.
theory_mode: Optional[str] = None
@ -113,10 +111,7 @@ def prepare_turn(
card: PersonaCard,
state: SessionState,
learner_text: str,
recall_summary: Optional[str] = None,
pinned_facts: Optional[list[str]] = None,
recent_turns: Optional[list[dict[str, str]]] = None,
kb_behavior_cues: Optional[list[str]] = None,
memory: Optional[TurnMemory] = None,
theory_mode: Optional[str] = None,
eval_rapport_signal: Optional[float] = None,
) -> TurnContext:
@ -125,16 +120,19 @@ def prepare_turn(
eval_rapport_signal 주어지면(평가 AI fast-loop 신호) 그걸 쓰고, 없으면
state_machine 경량 휴리스틱으로 라포 신호를 추정한다.
"""
turn_memory = memory or TurnMemory()
ctx = TurnContext(
session_id=session_id,
case_id=case_id,
persona=card,
state_before=state,
learner_text_raw=learner_text,
recall_summary=_mask_optional_text(recall_summary),
pinned_facts=_mask_text_list(pinned_facts),
recent_turns=_mask_recent_turns(recent_turns),
kb_behavior_cues=list(kb_behavior_cues or []),
memory=TurnMemory(
recall_summary=_mask_optional_text(turn_memory.recall_summary),
pinned_facts=_mask_text_list(turn_memory.pinned_facts),
recent_turns=_mask_recent_turns(turn_memory.recent_turns),
kb_behavior_cues=list(turn_memory.kb_behavior_cues or []),
),
theory_mode=theory_mode,
)
@ -169,10 +167,7 @@ def prepare_turn(
card,
ctx.to_state_context(),
ctx.learner_text_masked,
recall_summary=ctx.recall_summary,
pinned_facts=ctx.pinned_facts,
recent_turns=ctx.recent_turns,
kb_behavior_cues=ctx.kb_behavior_cues,
memory=ctx.memory,
theory_mode=ctx.theory_mode,
)
return ctx
@ -388,7 +383,11 @@ async def run_turn_stream(
audit_hook,
session_id=ctx.session_id,
provider=str(stream_meta.get("provider") or engine.engine_mode),
model=str(stream_meta.get("model") or engine.default_model or "gateway-default"),
model=str(
stream_meta.get("model")
or engine.default_model
or ENGINE_GATEWAY_DEFAULT_MODEL_SENTINEL
),
tokens_in=_safe_int(stream_meta.get("tokens_in")),
tokens_out=_safe_int(stream_meta.get("tokens_out")),
cost_usd=_safe_float(stream_meta.get("cost_usd")),
@ -405,7 +404,11 @@ async def run_turn_stream(
"turn_seq": st.turn_seq,
"safety_flagged": flagged,
"llm_provider": str(stream_meta.get("provider") or engine.engine_mode),
"model": str(stream_meta.get("model") or engine.default_model or "gateway-default"),
"model": str(
stream_meta.get("model")
or engine.default_model
or ENGINE_GATEWAY_DEFAULT_MODEL_SENTINEL
),
"tokens_in": _safe_int(stream_meta.get("tokens_in")),
"tokens_out": _safe_int(stream_meta.get("tokens_out")),
"cost_usd": _safe_float(stream_meta.get("cost_usd")),
@ -454,6 +457,7 @@ __all__ = [
"EvalHook",
"LlmAuditHook",
"TurnContext",
"TurnMemory",
"TurnResult",
"StreamEvent",
"prepare_turn",