전 저장소 리팩터링과 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

@ -41,13 +41,13 @@ from ..contracts.engine_gateway import (
StreamTokenEvent,
)
from . import guardrail, persona, state_machine
from .llm_audit import LlmAuditHook, generate_with_audit, record_llm_audit
from .persona import PersonaCard, PersonaStateContext, TurnMemory
from .state_machine import SessionState, Stage
from .state_machine import SessionState
# 평가 훅 타입: U_t(수련생 마스킹 발화) + 내담자응답 + 상태 → 평가 결과(dict)
# Features evaluator 가 이 시그니처에 맞춰 함수를 주입한다(여기선 호출만).
EvalHook = Callable[["TurnContext", str], Awaitable[Optional[dict]]]
LlmAuditHook = Callable[[dict[str, Any]], Awaitable[None]]
def turn_evaluation_error_payload(ctx: "TurnContext", error: BaseException | str) -> dict[str, Any]:
@ -253,20 +253,7 @@ async def run_turn_generate(
reply = ""
safety_flagged = ctx.crisis is not None and ctx.crisis.escalate
for attempt in range(2):
started = time.perf_counter()
resp = await engine.generate(req)
latency_ms = int((time.perf_counter() - started) * 1000)
await _record_llm_audit(
audit_hook,
session_id=ctx.session_id,
provider=resp.provider,
model=resp.model,
tokens_in=resp.tokens_in,
tokens_out=resp.tokens_out,
cost_usd=resp.cost_usd,
inference_geo=resp.inference_geo,
latency_ms=latency_ms,
)
resp = await generate_with_audit(engine, req, audit_hook)
# 5) 출력 가드레일 — 수단 차단 + persona 품질 재생성
guard = guardrail.sanitize_client_reply(
@ -451,7 +438,7 @@ async def run_turn_stream(
yield StreamEvent("token", {"text": guard.text})
latency_ms = int((time.perf_counter() - started) * 1000)
await _record_llm_audit(
await record_llm_audit(
audit_hook,
session_id=ctx.session_id,
provider=str(stream_meta.get("provider") or engine.engine_mode),
@ -493,18 +480,6 @@ async def run_turn_stream(
yield StreamEvent("error", {"detail": str(e)})
async def _record_llm_audit(
audit_hook: Optional[LlmAuditHook],
**payload: Any,
) -> None:
if audit_hook is None:
return
try:
await audit_hook(payload)
except Exception:
return
def _optional_str(value: Any) -> Optional[str]:
if value is None:
return None