런타임 계약과 학습자 흐름 보강
This commit is contained in:
parent
f456b8997a
commit
206018b088
56 changed files with 4306 additions and 1008 deletions
|
|
@ -90,6 +90,16 @@ class PersonaStateContext:
|
|||
affect_state: dict[str, float] = field(default_factory=dict)
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class TurnMemory:
|
||||
"""L2/L4/L6 turn memory inputs assembled before persona prompt rendering."""
|
||||
|
||||
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)
|
||||
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════════
|
||||
# L0 — 역할 + 안전 가드레일 + 도식노출금지 (전 페르소나 공통, cache 대상)
|
||||
# ════════════════════════════════════════════════════════════════════════════
|
||||
|
|
@ -228,10 +238,7 @@ def build_turn_messages(
|
|||
state: PersonaStateContext,
|
||||
learner_text_masked: 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,
|
||||
) -> list[EngineMessage]:
|
||||
"""한 턴의 EngineMessage[] 조립 (L0~L6).
|
||||
|
|
@ -240,15 +247,14 @@ def build_turn_messages(
|
|||
card : 불변 페르소나(L0+L1)
|
||||
state : state_machine 산출 상태(L3)
|
||||
learner_text_masked : PII 마스킹된 수련생 발화(L5)
|
||||
recall_summary : 회기 시작 회상(L2-EP, 큰그림→세부 요약). CCD/정답 미포함.
|
||||
pinned_facts : 무손실 사실 hard-pin(L4). "자기 기억"으로만 표현.
|
||||
recent_turns : [{speaker, text}] 최근 K턴 버퍼(L6 직전 맥락)
|
||||
kb_behavior_cues : KB 증상 '행동단서'만(본문 비노출, sensitivity<=1)
|
||||
memory : 회상/고정 사실/최근 턴/KB 행동단서 묶음
|
||||
theory_mode : 회기 이론모드. 내담자 반응 프레이밍에만 사용.
|
||||
|
||||
반환 messages 순서: system(L0+L1, cache) → system(L2/L3/L4, cache 미설정) →
|
||||
assistant/user 히스토리 → user(이번 발화). 게이트웨이가 마지막 user 를 stdin 으로.
|
||||
assistant/user 최근 턴 기록 → user(이번 발화).
|
||||
현재 Python gateway split boundary 는 system 묶음과 마지막 user payload 만 소비한다.
|
||||
"""
|
||||
memory = memory or TurnMemory()
|
||||
messages: list[EngineMessage] = []
|
||||
|
||||
# L0+L1 — 정적, cache_control 대상
|
||||
|
|
@ -256,10 +262,10 @@ def build_turn_messages(
|
|||
|
||||
# L2 — 회상 + KB 행동단서 (회기 내 1회 로드, 캐시 친화)
|
||||
l2_parts: list[str] = []
|
||||
if recall_summary:
|
||||
l2_parts.append(f"[L2 회상 — 지난 맥락(큰그림→세부, 정답/평가 미포함)]\n{recall_summary}")
|
||||
if kb_behavior_cues:
|
||||
cues = "\n".join(f"- {c}" for c in kb_behavior_cues)
|
||||
if memory.recall_summary:
|
||||
l2_parts.append(f"[L2 회상 — 지난 맥락(큰그림→세부, 정답/평가 미포함)]\n{memory.recall_summary}")
|
||||
if memory.kb_behavior_cues:
|
||||
cues = "\n".join(f"- {c}" for c in memory.kb_behavior_cues)
|
||||
l2_parts.append(f"[L2 증상 행동단서(본문 비노출, 이렇게 '행동'으로만 드러난다)]\n{cues}")
|
||||
if l2_parts:
|
||||
messages.append(EngineMessage(role="system", content="\n\n".join(l2_parts), cache=True))
|
||||
|
|
@ -282,20 +288,20 @@ def build_turn_messages(
|
|||
messages.append(EngineMessage(role="system", content=theory_guidance, cache=False))
|
||||
|
||||
# L4 — pinned fact hard-pin (무손실, "자기 기억"으로만)
|
||||
if pinned_facts:
|
||||
pinned = "\n".join(f"- {f}" for f in pinned_facts)
|
||||
if memory.pinned_facts:
|
||||
pinned = "\n".join(f"- {f}" for f in memory.pinned_facts)
|
||||
messages.append(EngineMessage(
|
||||
role="system",
|
||||
content=("[L4 고정 사실 — 당신이 *이미 말했거나 사실인* 것. 모순되게 말하지 말 것]\n" + pinned),
|
||||
cache=False,
|
||||
))
|
||||
|
||||
# L6 — 직전 K턴 맥락 (히스토리). 게이트웨이가 단발이면 system 뒤 맥락으로 직렬화.
|
||||
if recent_turns:
|
||||
for t in recent_turns:
|
||||
# L6 — 직전 K턴 맥락. 현재 Python gateway 는 마지막 user payload 만 보내므로
|
||||
# non-system history records 는 요청 계약상 보존하고, 별도 prompt 동작 변경에서 소비한다.
|
||||
if memory.recent_turns:
|
||||
for t in memory.recent_turns:
|
||||
role = "assistant" if t.get("speaker") == "counselor" else "user"
|
||||
# 내담자(자기) 과거 발화는 assistant, 상담자 발화는 user 로 매핑하면
|
||||
# 게이트웨이가 [이전 상담자/내담자 발화]로 직렬화한다.
|
||||
# 내담자(자기) 과거 발화는 assistant, 상담자 발화는 user 로 매핑한다.
|
||||
messages.append(EngineMessage(role=role, content=t.get("text", ""), cache=False))
|
||||
|
||||
# L5 — 이번 수련생 발화 (마스킹 후)
|
||||
|
|
@ -476,6 +482,7 @@ def get_seed_persona(code: str) -> Optional[PersonaCard]:
|
|||
__all__ = [
|
||||
"PersonaCard",
|
||||
"PersonaStateContext",
|
||||
"TurnMemory",
|
||||
"L0_SAFETY",
|
||||
"build_persona_system_text",
|
||||
"build_turn_messages",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue