q_table_demo/app/models/schemas.py

128 lines
5.1 KiB
Python

"""
API 요청/응답 데이터 모델
"""
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field
from enum import Enum
class CardType(str, Enum):
"""협상 카드 타입"""
C1 = "C1"
C2 = "C2"
C3 = "C3"
C4 = "C4"
class ScenarioType(str, Enum):
"""시나리오 타입"""
A = "A" # S_1
B = "B" # S_4
C = "C" # S_3
D = "D" # S_2
class PriceZoneType(str, Enum):
"""가격 구간 타입"""
PZ1 = "PZ1" # P < A
PZ2 = "PZ2" # A < P < T
PZ3 = "PZ3" # T < P
class ExperienceData(BaseModel):
"""경험 데이터 모델"""
state: str = Field(..., description="현재 상태")
action: CardType = Field(..., description="선택한 행동")
reward: float = Field(..., description="받은 보상")
next_state: str = Field(..., description="다음 상태")
done: bool = Field(..., description="에피소드 종료 여부")
timestamp: float = Field(..., description="타임스탬프")
metadata: Optional[Dict[str, Any]] = Field(default=None, description="추가 메타데이터")
class NegotiationState(BaseModel):
"""협상 상태 모델"""
current_card: CardType = Field(..., description="현재 카드")
scenario: ScenarioType = Field(..., description="시나리오")
price_zone: PriceZoneType = Field(..., description="가격 구간")
@property
def state_id(self) -> str:
"""상태 ID 생성"""
return f"{self.current_card.value}{self.scenario.value}{self.price_zone.value}"
class RewardCalculationRequest(BaseModel):
"""보상 계산 요청 모델"""
scenario: ScenarioType = Field(..., description="시나리오")
price_zone: PriceZoneType = Field(..., description="가격 구간")
anchor_price: float = Field(..., gt=0, description="목표가 (A)")
proposed_price: float = Field(..., gt=0, description="제안가 (P)")
is_end: bool = Field(..., description="협상 종료 여부")
class RewardCalculationResponse(BaseModel):
"""보상 계산 응답 모델"""
reward: float = Field(..., description="계산된 보상")
weight: float = Field(..., description="가중치 W")
scenario_weight: float = Field(..., description="시나리오 가중치 S_n")
price_zone_weight: float = Field(..., description="가격구간 가중치 PZ_n")
price_ratio: float = Field(..., description="가격 비율 A/P")
formula_breakdown: str = Field(..., description="공식 분해")
class QTableState(BaseModel):
"""Q-Table 상태 모델"""
q_table: Dict[str, Dict[str, float]] = Field(..., description="Q-Table 데이터")
update_count: int = Field(..., description="업데이트 횟수")
learning_rate: float = Field(..., description="학습률")
discount_factor: float = Field(..., description="할인율")
class EpisodeGenerationRequest(BaseModel):
"""에피소드 생성 요청 모델"""
num_episodes: int = Field(..., ge=1, le=100, description="생성할 에피소드 수")
max_steps: int = Field(..., ge=1, le=20, description="에피소드당 최대 스텝")
anchor_price: float = Field(..., gt=0, description="목표가")
exploration_rate: float = Field(default=0.4, ge=0, le=1, description="탐험율")
class LearningUpdateRequest(BaseModel):
"""학습 업데이트 요청 모델"""
learning_rate: float = Field(..., ge=0.001, le=1.0, description="학습률")
discount_factor: float = Field(..., ge=0.1, le=0.99, description="할인율")
batch_size: int = Field(default=32, ge=1, le=1000, description="배치 크기")
class FQICQLRequest(BaseModel):
"""FQI+CQL 학습 요청 모델"""
alpha: float = Field(default=1.0, ge=0, description="CQL 보수성 파라미터")
gamma: float = Field(default=0.95, ge=0.1, le=0.99, description="할인율")
batch_size: int = Field(default=32, ge=1, le=1000, description="배치 크기")
num_iterations: int = Field(default=10, ge=1, le=100, description="반복 횟수")
class ActionRecommendationRequest(BaseModel):
"""행동 추천 요청 모델"""
current_state: str = Field(..., description="현재 상태")
use_epsilon_greedy: bool = Field(default=False, description="엡실론 그리디 사용")
epsilon: float = Field(default=0.1, ge=0, le=1, description="엡실론 값")
class ActionRecommendationResponse(BaseModel):
"""행동 추천 응답 모델"""
recommended_action: CardType = Field(..., description="추천 행동")
q_values: Dict[str, float] = Field(..., description="현재 상태의 Q값들")
confidence: float = Field(..., description="추천 신뢰도")
exploration: bool = Field(..., description="탐험 행동 여부")
class SystemStatus(BaseModel):
"""시스템 상태 모델"""
total_experiences: int = Field(..., description="총 경험 데이터 수")
q_table_updates: int = Field(..., description="Q-Table 업데이트 횟수")
unique_states: int = Field(..., description="고유 상태 수")
average_reward: float = Field(..., description="평균 보상")
success_rate: float = Field(..., description="성공률")
last_update: Optional[float] = Field(default=None, description="마지막 업데이트 시간")