"""chat 라우터 프로토콜 (대화형 /chat, P7 슬라이스).""" from typing import List, Optional from pydantic import Field from common.models.gmodel import Req_WebPacketProtocol, Res_WebPacketProtocol class Req_Chat(Req_WebPacketProtocol): """대화 한 턴. session_id 없으면 새 협상 시작(아래 컨텍스트로). tenant 는 헤더로만.""" session_id: Optional[str] = Field(None, description="없으면 새 세션 생성") rq_type: str = Field("재협상", description="재협상 | 재견적") user_input: Optional[str] = Field(None, description="버튼 선택 텍스트 또는 가격(price 모드)") # 새 세션 시작 시 협상 컨텍스트 (옵션, 기본값 제공) revenue_amount: float = 20_000_000 distribution_code: str = "A" partner_count: int = 1 acceptance_ratio: float = 0.05 # 갑(KT/iMK)이 직접 입력. anchor < target. anchor 기본 제안값 = target*(1-0.01). target_price: float = 10000 # KT 목표 매입가 anchor_price: float = 9900 # KT 앵커링가(목표가보다 낮음). 제시가 ≤ anchor → 우선협상 class Res_Chat(Res_WebPacketProtocol): session_id: Optional[str] = None step: Optional[str] = None client_step: Optional[str] = None script: Optional[str] = None input_mode: Optional[str] = None input_options: Optional[List[str]] = None chat_end: bool = False outcome: Optional[str] = None # 가격협상 턴에서 선택된 협상 카드 + 학습 메타 card_id: Optional[str] = None policy: Optional[str] = None q_value: Optional[float] = None updated_q: Optional[float] = None visit_count: Optional[int] = None reward_total: Optional[float] = None