""" AI Provider 기본 클래스 정의 모든 AI 프로바이더는 이 기본 클래스를 상속받아 구현합니다. """ from abc import ABC, abstractmethod from typing import Optional, Dict, Any, List from dataclasses import dataclass from enum import Enum class AIProviderType(Enum): """지원하는 AI 프로바이더 타입""" OPENAI = "openai" OPENROUTER = "openrouter" GEMINI = "gemini" XAI = "xai" @dataclass class AIMessage: """AI 메시지 데이터 클래스""" role: str # 'system', 'user', 'assistant' content: str @dataclass class AIResponse: """AI 응답 데이터 클래스""" content: str model: str provider: str usage: Optional[Dict[str, int]] = None raw_response: Optional[Any] = None class BaseAIProvider(ABC): """ AI Provider 추상 기본 클래스 모든 AI 프로바이더는 이 클래스를 상속받아 구현해야 합니다. """ def __init__(self, api_key: str, model: Optional[str] = None): """ Args: api_key: API 키 model: 사용할 모델명 (None이면 기본 모델 사용) """ self._api_key = api_key self._model = model or self.default_model self._is_initialized = False @property @abstractmethod def provider_type(self) -> AIProviderType: """프로바이더 타입 반환""" pass @property @abstractmethod def provider_name(self) -> str: """프로바이더 이름 반환""" pass @property @abstractmethod def default_model(self) -> str: """기본 모델명 반환""" pass @property @abstractmethod def available_models(self) -> List[str]: """사용 가능한 모델 목록 반환""" pass @property def model(self) -> str: """현재 사용 중인 모델명""" return self._model @model.setter def model(self, value: str): """모델 변경""" self._model = value @property def api_key(self) -> str: """API 키 (마스킹된 값)""" if self._api_key: return self._api_key[:8] + "..." + self._api_key[-4:] return "" def update_api_key(self, api_key: str): """API 키 업데이트""" self._api_key = api_key self._is_initialized = False @abstractmethod def initialize(self) -> bool: """ 프로바이더 초기화 (클라이언트 생성 등) Returns: 초기화 성공 여부 """ pass @abstractmethod async def chat( self, messages: List[AIMessage], temperature: float = 0.7, max_tokens: Optional[int] = None, **kwargs ) -> AIResponse: """ 채팅 요청 (비동기) Args: messages: 대화 메시지 리스트 temperature: 응답 다양성 (0.0 ~ 1.0) max_tokens: 최대 토큰 수 **kwargs: 추가 파라미터 Returns: AI 응답 """ pass @abstractmethod def chat_sync( self, messages: List[AIMessage], temperature: float = 0.7, max_tokens: Optional[int] = None, **kwargs ) -> AIResponse: """ 채팅 요청 (동기) Args: messages: 대화 메시지 리스트 temperature: 응답 다양성 (0.0 ~ 1.0) max_tokens: 최대 토큰 수 **kwargs: 추가 파라미터 Returns: AI 응답 """ pass def validate_api_key(self) -> bool: """API 키 유효성 검사 (간단한 형식 체크)""" return bool(self._api_key and len(self._api_key) > 10) def __repr__(self): return f"{self.__class__.__name__}(model={self._model}, initialized={self._is_initialized})"