""" xAI (Grok) Provider 구현 xAI API는 OpenAI 호환 형식을 사용합니다. """ import asyncio from typing import Optional, List, Dict, Any from ..base import BaseAIProvider, AIProviderType, AIMessage, AIResponse class XAIProvider(BaseAIProvider): """xAI (Grok) API 프로바이더""" BASE_URL = "https://api.x.ai/v1" AVAILABLE_MODELS = [ "grok-beta", "grok-2-1212", "grok-2-vision-1212", ] def __init__(self, api_key: str, model: Optional[str] = None): super().__init__(api_key, model) self._client = None self._async_client = None @property def provider_type(self) -> AIProviderType: return AIProviderType.XAI @property def provider_name(self) -> str: return "xAI (Grok)" @property def default_model(self) -> str: return "grok-beta" @property def available_models(self) -> List[str]: return self.AVAILABLE_MODELS.copy() def initialize(self) -> bool: """xAI 클라이언트 초기화 (OpenAI 호환 API 사용)""" if not self.validate_api_key(): return False try: from openai import OpenAI, AsyncOpenAI self._client = OpenAI( api_key=self._api_key, base_url=self.BASE_URL ) self._async_client = AsyncOpenAI( api_key=self._api_key, base_url=self.BASE_URL ) self._is_initialized = True return True except ImportError: print("OpenAI 라이브러리가 설치되지 않았습니다. pip install openai 를 실행하세요.") return False except Exception as e: print(f"xAI 초기화 실패: {e}") return False def _convert_messages(self, messages: List[AIMessage]) -> List[Dict[str, str]]: """AIMessage를 OpenAI 형식으로 변환""" return [{"role": msg.role, "content": msg.content} for msg in messages] async def chat( self, messages: List[AIMessage], temperature: float = 0.7, max_tokens: Optional[int] = None, **kwargs ) -> AIResponse: """비동기 채팅 요청""" if not self._is_initialized: if not self.initialize(): raise RuntimeError("xAI 초기화 실패") converted_messages = self._convert_messages(messages) params = { "model": self._model, "messages": converted_messages, "temperature": temperature, } if max_tokens: params["max_tokens"] = max_tokens params.update(kwargs) response = await self._async_client.chat.completions.create(**params) return AIResponse( content=response.choices[0].message.content, model=response.model, provider=self.provider_name, usage={ "prompt_tokens": response.usage.prompt_tokens, "completion_tokens": response.usage.completion_tokens, "total_tokens": response.usage.total_tokens, } if response.usage else None, raw_response=response ) def chat_sync( self, messages: List[AIMessage], temperature: float = 0.7, max_tokens: Optional[int] = None, **kwargs ) -> AIResponse: """동기 채팅 요청""" if not self._is_initialized: if not self.initialize(): raise RuntimeError("xAI 초기화 실패") converted_messages = self._convert_messages(messages) params = { "model": self._model, "messages": converted_messages, "temperature": temperature, } if max_tokens: params["max_tokens"] = max_tokens params.update(kwargs) response = self._client.chat.completions.create(**params) return AIResponse( content=response.choices[0].message.content, model=response.model, provider=self.provider_name, usage={ "prompt_tokens": response.usage.prompt_tokens, "completion_tokens": response.usage.completion_tokens, "total_tokens": response.usage.total_tokens, } if response.usage else None, raw_response=response )