"""비용 관리 모델. Phase 8: 사용량 및 구독 관리 """ from dataclasses import dataclass, field from datetime import datetime, UTC from enum import Enum from typing import Optional, Dict, Any import uuid class OperationType(str, Enum): """작업 타입.""" LLM_CALL = "llm_call" # LLM 호출 (토큰 기반) LLM_STREAM = "llm_stream" # 스트리밍 (분 기반) GRAPH_QUERY = "graph_query" # 그래프 쿼리 (노드 기반) STORAGE = "storage" # 저장소 (GB 기반) API_CALL = "api_call" # API 호출 (호출 수) ANALYSIS = "analysis" # 분석 (작업) class SubscriptionTier(str, Enum): """구독 계층.""" FREE = "free" PRO = "pro" ENTERPRISE = "enterprise" @dataclass class Usage: """사용량 기록.""" id: str = field(default_factory=lambda: str(uuid.uuid4())) org_id: str = "" user_id: str = "" operation_type: OperationType = OperationType.API_CALL timestamp: datetime = field(default_factory=lambda: datetime.now(UTC)) quantity: float = 0.0 # 토큰, 노드, GB, 시간 등 cost: float = 0.0 # USD metadata: dict = field(default_factory=dict) def to_dict(self) -> dict: """딕셔너리로 변환.""" return { "id": self.id, "org_id": self.org_id, "user_id": self.user_id, "operation_type": self.operation_type.value, "timestamp": self.timestamp.isoformat(), "quantity": self.quantity, "cost": self.cost, "metadata": self.metadata, } @dataclass class Subscription: """구독 정보.""" org_id: str = "" tier: SubscriptionTier = SubscriptionTier.FREE created_at: datetime = field(default_factory=lambda: datetime.now(UTC)) updated_at: datetime = field(default_factory=lambda: datetime.now(UTC)) auto_renew: bool = True current_month_cost: float = 0.0 monthly_limit: float = 100.0 # USD exceeded_limit: bool = False metadata: dict = field(default_factory=dict) def to_dict(self) -> dict: """딕셔너리로 변환.""" return { "org_id": self.org_id, "tier": self.tier.value, "created_at": self.created_at.isoformat(), "current_month_cost": self.current_month_cost, "monthly_limit": self.monthly_limit, "exceeded_limit": self.exceeded_limit, } @dataclass class UsageStatistics: """사용량 통계.""" period_start: datetime period_end: datetime total_cost: float = 0.0 by_operation_type: Dict[str, float] = field(default_factory=dict) by_user: Dict[str, float] = field(default_factory=dict) api_calls: int = 0 llm_tokens: float = 0 storage_gb: float = 0.0 def to_dict(self) -> dict: """딕셔너리로 변환.""" return { "period_start": self.period_start.isoformat(), "period_end": self.period_end.isoformat(), "total_cost": self.total_cost, "by_operation_type": self.by_operation_type, "by_user": self.by_user, "api_calls": self.api_calls, "llm_tokens": self.llm_tokens, "storage_gb": self.storage_gb, }