Jev 기반 내담자 감정 상태와 응답 일관성 개선

This commit is contained in:
Yun Chan 2026-09-22 21:32:26 +09:00
parent 77f8421818
commit 8344bc2ad2
23 changed files with 3384 additions and 25 deletions

View file

@ -92,6 +92,38 @@ class Settings(BaseSettings):
default=None,
validation_alias="VIGNETTE_LIVE_CLIENT_PROVIDER",
)
client_affect_provider: Literal["legacy", "jev"] = Field(
default="legacy",
validation_alias="VIGNETTE_CLIENT_AFFECT_PROVIDER",
)
typesafe_api_key: SecretStr = Field(
default=SecretStr(""),
validation_alias="TYPESAFE_API_KEY",
)
openrouter_api_key: SecretStr = Field(
default=SecretStr(""),
validation_alias="OPENROUTER_API_KEY",
)
jev_provider: Literal["openrouter", "typesafe"] = Field(
default="openrouter",
validation_alias="VIGNETTE_JEV_PROVIDER",
)
jev_model: str = Field(
default="~typesafe/jev-latest",
validation_alias="VIGNETTE_JEV_MODEL",
)
jev_timeout_seconds: float = Field(
default=1.2,
ge=0.1,
le=10.0,
validation_alias="VIGNETTE_JEV_TIMEOUT_SECONDS",
)
jev_min_confidence: float = Field(
default=0.65,
ge=0.0,
le=1.0,
validation_alias="VIGNETTE_JEV_MIN_CONFIDENCE",
)
engine_timeout: float = 120.0 # SSE 롱리브드 (50분 상담 대비, 스트림은 무제한 별도)
engine_connect_timeout: float = 10.0
admin_usage_budget_usd: float = Field(
@ -568,6 +600,16 @@ class Settings(BaseSettings):
@model_validator(mode="after")
def validate_non_dev_runtime_flags(self) -> "Settings":
jev_key = (
self.openrouter_api_key
if self.jev_provider == "openrouter"
else self.typesafe_api_key
)
if self.client_affect_provider == "jev" and not jev_key.get_secret_value().strip():
raise ValueError(
f"{'OPENROUTER_API_KEY' if self.jev_provider == 'openrouter' else 'TYPESAFE_API_KEY'} "
"must be configured when VIGNETTE_CLIENT_AFFECT_PROVIDER=jev"
)
gateway_secret = self.engine_gateway_shared_secret.get_secret_value().strip()
if gateway_secret and (
len(gateway_secret) < 32