"""negotiation 라우터 프로토콜 (backend Protocol 규약: Req_/Res_ + result: ErrorInfo).""" from typing import List, Optional from pydantic import BaseModel, Field from common.models.gmodel import Req_WebPacketProtocol, Res_WebPacketProtocol class Req_NegotiationStep(Req_WebPacketProtocol): """한 협상 라운드 관측치. tenant 는 본문에 없음(헤더 X-Tenant-ID 로만, 위조 방지).""" # 이산 상태 산출 입력 revenue_amount: float = Field(..., description="매출액(원)") distribution_code: str = Field("A", description="유통 구조 외부 코드 (테넌트 code_map)") partner_count: int = Field(1, description="파트너사 수") acceptance_ratio: float = Field(..., description="가격 수용률 0~1") input_price: float = Field(..., description="현재 제시/입력 가격") anchor_price: float = Field(..., description="앵커(시작) 가격") target_price: float = Field(..., description="목표 가격") # 시퀀스/보상 round_number: int = Field(1, description="협상 라운드(turn)") outcome: str = Field("ongoing", description="ongoing | success | failure") # 세션/에피소드 (HTTP 무상태 — 클라이언트가 사용한 action 을 전달해 중복 방지) session_id: Optional[str] = Field(None, description="협상 세션 uuid (없으면 생성)") used_action_ids: Optional[List[int]] = Field(None, description="이미 제시한 action(중복방지 마스킹)") log: bool = Field(True, description="learning.experience_logs 에 기록할지") learn: bool = Field(True, description="Q-Table 온라인 갱신 + 영속화 여부") # 중첩 뷰는 result/msg 가 필요 없으므로 순수 BaseModel. class StateView(BaseModel): revenue_idx: int = 0 distribution_idx: int = 0 partner_idx: int = 0 acceptance_idx: int = 0 price_zone_idx: int = 0 class RewardView(BaseModel): price_reward: float = 0.0 end_reward: float = 0.0 penalty: float = 0.0 weight: float = 0.0 total: float = 0.0 class Res_NegotiationStep(Res_WebPacketProtocol): tenant_id: Optional[str] = None company_id: Optional[str] = None session_id: Optional[str] = None state_index: Optional[int] = None state: Optional[StateView] = None action_id: Optional[int] = None card_id: Optional[str] = None propensity: Optional[float] = None available_actions: Optional[List[int]] = None reward: Optional[RewardView] = None logged: bool = False # 학습 가시화: 선택 시점 Q, UCB 점수, 갱신 후 Q, 이 state-action 누적 방문수, 정책명 policy: Optional[str] = None q_value: Optional[float] = None ucb_score: Optional[float] = None updated_q: Optional[float] = None visit_count: Optional[int] = None learned: bool = False