"""
Tiiny 客户端 - 支持真实 API 调用
"""

import logging
import json
import requests
import socket
import urllib.parse
from typing import Optional, List, Union, Dict, Any, Iterator
import time
import uuid

logger = logging.getLogger(__name__)


class ChatMessage:
    """聊天消息类"""
    def __init__(self, role: str, content: str):
        self.role = role
        self.content = content


class Choice:
    """聊天响应选项类"""
    def __init__(self, index: int, message: ChatMessage, finish_reason: str):
        self.index = index
        self.message = message
        self.finish_reason = finish_reason


class ChatCompletionResponse:
    """聊天完成响应"""
    def __init__(self, choices: List[Dict], model: str, id: str = None, created: int = None, usage: Dict = None):
        self.id = id or f"chatcmpl-{uuid.uuid4().hex[:8]}"
        self.created = created or int(time.time())
        self.model = model
        self.choices = choices
        self.usage = usage


class RerankRequest:
    """Rerank 请求 helper"""
    def __init__(self, client):
        self._client = client
        
    def create(self, model: str, query: str, documents: List[str], top_k: Optional[int] = None) -> Dict[str, Any]:
        """
        创建 Rerank 请求
        """
        return self._client._create_rerank_request(model, query, documents, top_k)


class EmbeddingsRequest:
    """Embeddings 请求 helper"""
    def __init__(self, client):
        self._client = client
        
    def create(self, model: str, input: Union[str, List[str]]) -> Dict[str, Any]:
        """
        创建 Embedding 请求
        """
        return self._client._create_embedding_request(model, input)

class ImagesRequest:
    """Images 请求 helper"""
    def __init__(self, client):
        self._client = client
        
    def generate(self, model: str, prompt: str, **kwargs) -> Iterator[Dict[str, Any]]:
        """
        生成图片 (流式)
        """
        return self._client._create_image_generation_request(model, prompt, **kwargs)

class TranscriptionsRequest:
    """Audio Transcriptions 请求 helper"""
    def __init__(self, client):
        self._client = client
        
    def create(self, model: str, file: Any, **kwargs) -> Union[Dict[str, Any], str]:
        """
        创建转录请求
        """
        return self._client._create_transcription_request(model, file, **kwargs)

class AudioRequest:
    """Audio 请求 helper"""
    def __init__(self, client):
        self.transcriptions = TranscriptionsRequest(client)

class TiinyDevice:
    """
    Tiiny 设备管理类
    提供设备连接检测、API密钥获取和基础URL获取功能
    """
    
    def __init__(self, device_ip: str = "fd00:7:7:7::1", device_port: int =80):
        """
        初始化Tiiny设备
        
        Args:
            device_ip: 设备IP地址，默认为 fd00:7:7:7::1
            device_port: 设备端口，默认为 80
        """
        self.device_ip = device_ip
        self.device_port = device_port
        self.base_url = f"[{device_ip}]:{device_port}"
        
    def is_connected(self) -> bool:
        """
        判断设备是否连接
        
        Returns:
            bool: True表示已连接，False表示未连接
        """
        try:
            # 创建socket连接
            sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
            sock.settimeout(3)  # 3秒超时
            
            # 尝试连接到设备的8888端口
            result = sock.connect_ex((self.device_ip, self.device_port))
            sock.close()
            
            if result == 0:
                logger.info(f"Device {self.device_ip}:{self.device_port} connected successfully")
                return True
            else:
                logger.warning(f"Device {self.device_ip}:{self.device_port} connection failed, error code: {result}")
                return False
                
        except socket.timeout:
            logger.error(f"Connection to {self.device_ip}:{self.device_port} timed out")
            return False
        except socket.gaierror as e:
            logger.error(f"Unable to resolve address {self.device_ip}: {e}")
            return False
        except Exception as e:
            logger.error(f"Error connecting to {self.device_ip}:{self.device_port}: {e}")
            return False
    
    def get_api_key(self, master_password: str) -> Optional[str]:
        """
        获取API密钥
        
        Args:
            master_password: 主密码
            
        Returns:
            str: API密钥，如果获取失败返回None
        """
        try:
            url = f"http://{self.base_url}/api/v1/account/auth"
            
            # 准备请求数据
            data = {
                "password": master_password
            }
            
            # 设置请求头
            headers = {
                "Content-Type": "application/json",
                "Accept": "application/json"
            }
            
            logger.info(f"Requesting API key from {url}")
            
            # 发送POST请求
            response = requests.post(
                url,
                headers=headers,
                json=data,
                timeout=10
            )
            
            # 检查响应状态
            response.raise_for_status()
            
            # 解析响应
            result = response.json()
            logger.debug(f"Auth response: {json.dumps(result, ensure_ascii=False)}")
            
            # 检查响应状态
            if result.get("status") == "ok":
                auth_key = result.get("auth_key")
                if auth_key:
                    logger.info("API key retrieved successfully")
                    return auth_key
                else:
                    logger.error("field auth_key not found in response")
                    return None
            else:
                logger.error(f"Authentication failed: {result.get('message', 'unknown error')}")
                return None
                
        except requests.exceptions.RequestException as e:
            logger.error(f"Failed to request API key: {e}")
            return None
        except json.JSONDecodeError as e:
            logger.error(f"Failed to parse response JSON: {e}")
            return None
        except Exception as e:
            logger.error(f"Error occurred while retrieving API key: {e}")
            return None
    
    def get_models(self, api_key: Optional[str] = None, master_password: Optional[str] = None) -> List[str]:
        """
        获取设备上可用的模型列表
        
        Args:
            api_key: API密钥，如果提供则直接使用
            master_password: 主密码，如果未提供api_key则使用此密码获取
            
        Returns:
            List[str]: 模型ID列表，如果获取失败返回空列表
        """
        try:
            # 如果没有提供API密钥，但提供了主密码，先获取API密钥
            if not api_key and master_password:
                logger.info("API key not provided, using master password to retrieve")
                api_key = self.get_api_key(master_password)
                if not api_key:
                    logger.error("Unable to retrieve API key, failed to get model list")
                    return []
            
            if not api_key:
                logger.error("API key or master password is required to get model list")
                return []
            
            url = f"http://{self.base_url}/api/v1/models/"
            
            # 设置请求头，包含Authorization
            headers = {
                "Accept": "application/json",
                "Authorization": f"Bearer {api_key}"
            }
            
            logger.info(f"Requesting model list from {url}")
            
            # 发送GET请求
            response = requests.get(
                url,
                headers=headers,
                timeout=10
            )
            
            # 检查响应状态
            response.raise_for_status()
            
            # 解析响应
            result = response.json()
            logger.debug(f"Model list response: {json.dumps(result, ensure_ascii=False)}")
            
            # 提取模型ID列表
            models = []
            data_list = result.get("data", [])
            for model_info in data_list:
                model_id = model_info.get("id")
                if model_id:
                    models.append(model_id)
            
            logger.info(f"Successfully retrieved {len(models)} models")
            return models
                
        except requests.exceptions.RequestException as e:
            logger.error(f"Failed to request model list: {e}")
            return []
        except json.JSONDecodeError as e:
            logger.error(f"Failed to parse response JSON: {e}")
            return []
        except Exception as e:
            logger.error(f"Error occurred while getting model list: {e}")
            return []
    
    def start_model(self, model_id: str, api_key: Optional[str] = None, master_password: Optional[str] = None) -> bool:
        """
        启动指定的模型
        
        Args:
            model_id: 模型ID（如从get_models()获取的ID）
            api_key: API密钥，如果提供则直接使用
            master_password: 主密码，如果未提供api_key则使用此密码获取
            
        Returns:
            bool: True表示启动成功，False表示启动失败
        """
        try:
            # 如果没有提供API密钥，但提供了主密码，先获取API密钥
            if not api_key and master_password:
                logger.info("API key not provided, using master password to retrieve")
                api_key = self.get_api_key(master_password)
                if not api_key:
                    logger.error("Unable to retrieve API key, failed to start model")
                    return False
            
            if not api_key:
                logger.error("API key or master password is required to start model")
                return False
            
            # 对model_id进行URL编码
            encoded_model_id = urllib.parse.quote(model_id, safe='')
            url = f"http://{self.base_url}/api/v1/models/{encoded_model_id}/start"
            
            # 设置请求头，包含Authorization
            headers = {
                "Accept": "application/json",
                "Authorization": f"Bearer {api_key}"
            }
            
            logger.info(f"Starting model: {model_id}")
            logger.debug(f"Request URL: {url}")
            
            # 发送POST请求
            response = requests.post(
                url,
                headers=headers,
                timeout=30  # 启动模型可能需要更长时间
            )
            
            # 检查响应状态
            response.raise_for_status()
            
            # 解析响应
            result = response.json()
            logger.debug(f"Start model response: {json.dumps(result, ensure_ascii=False)}")
            
            # 检查响应状态
            if result.get("status") == "ok" or response.status_code == 200:
                logger.info(f"Model {model_id} start request accepted, waiting for loading to complete...")
                
                # 轮询进度
                progress_url = f"http://{self.base_url}/api/v1/models/{encoded_model_id}/get_progress"
                
                # 最多等待 300 秒
                max_wait_time = 300
                start_time = time.time()
                
                while time.time() - start_time < max_wait_time:
                    try:
                        time.sleep(1)
                        
                        prog_response = requests.get(
                            progress_url,
                            headers=headers,
                            timeout=10
                        )
                        
                        if prog_response.status_code == 200:
                            prog_result = prog_response.json()
                            progress = prog_result.get("progress", 0)
                            logger.info(f"Model loading progress: {progress}%")
                            
                            if int(progress) >= 100:
                                logger.info(f"Model {model_id} started successfully")
                                return True
                        
                    except Exception as e:
                        logger.warning(f"Error checking progress: {e}")
                
                logger.error(f"Model {model_id} failed to load within {max_wait_time} seconds")
                return False
            else:
                logger.error(f"Model {model_id} failed to start: {result.get('message', 'unknown error')}")
                return False
                
        except requests.exceptions.RequestException as e:
            logger.error(f"Start model request failed: {e}")
            return False
        except json.JSONDecodeError as e:
            logger.error(f"Failed to parse response JSON: {e}")
            return False
        except Exception as e:
            logger.error(f"Error occurred while starting model: {e}")
            return False
    
    def stop_model(self, model_id: str, api_key: Optional[str] = None, master_password: Optional[str] = None) -> bool:
        """
        停止指定的模型
        
        Args:
            model_id: 模型ID
            api_key: API密钥，如果提供则直接使用
            master_password: 主密码，如果未提供api_key则使用此密码获取
            
        Returns:
            bool: True表示停止成功，False表示停止失败
        """
        try:
            # 如果没有提供API密钥，但提供了主密码，先获取API密钥
            if not api_key and master_password:
                logger.info("API key not provided, using master password to retrieve")
                api_key = self.get_api_key(master_password)
                if not api_key:
                    logger.error("Unable to retrieve API key, failed to stop model")
                    return False
            
            if not api_key:
                logger.error("API key or master password is required to stop model")
                return False
            
            # 对model_id进行URL编码
            encoded_model_id = urllib.parse.quote(model_id, safe='')
            url = f"http://{self.base_url}/api/v1/models/{encoded_model_id}/stop"
            
            # 设置请求头，包含Authorization
            headers = {
                "Accept": "application/json",
                "Authorization": f"Bearer {api_key}"
            }
            
            logger.info(f"Stopping model: {model_id}")
            logger.debug(f"Request URL: {url}")
            
            # 发送POST请求
            response = requests.post(
                url,
                headers=headers,
                timeout=30
            )
            
            # 检查响应状态
            response.raise_for_status()
            
            # 解析响应
            result = response.json()
            logger.debug(f"Stop model response: {json.dumps(result, ensure_ascii=False)}")
            
            # 检查响应状态
            if result.get("status") == "ok" or response.status_code == 200:
                logger.info(f"Model {model_id} stopped successfully")
                return True
            else:
                logger.error(f"Model {model_id} failed to stop: {result.get('message', 'unknown error')}")
                return False
                
        except requests.exceptions.RequestException as e:
            logger.error(f"Stop model request failed: {e}")
            return False
        except json.JSONDecodeError as e:
            logger.error(f"Failed to parse response JSON: {e}")
            return False
        except Exception as e:
            logger.error(f"Error occurred while stopping model: {e}")
            return False
    
    def get_npu_status(self, api_key: Optional[str] = None, master_password: Optional[str] = None) -> List[Dict[str, Any]]:
        """
        获取NPU状态信息
        
        Args:
            api_key: API密钥
            master_password: 主密码，如果未提供api_key则使用此密码获取
            
        Returns:
            List[Dict[str, Any]]: NPU信息列表，包含名称、利用率、内存使用(MB)、内存总量(MB)和内存使用百分比
        """
        try:
            # 如果没有提供API密钥，但提供了主密码，先获取API密钥
            if not api_key and master_password:
                api_key = self.get_api_key(master_password)
            
            if not api_key:
                logger.error("API key or master password is required to get NPU status")
                return []

            url = f"http://{self.base_url}/api/v1/sys/status"
            
            headers = {
                "Accept": "application/json",
                "Authorization": f"Bearer {api_key}"
            }
            
            logger.info(f"Requesting system status from {url}")
            
            response = requests.get(url, headers=headers, timeout=10)
            response.raise_for_status()
            
            result = response.json()
            npus = result.get("npus", [])
            
            npu_status_list = []
            for npu in npus:
                memory_used = npu.get("memory_used_mb", 0)
                memory_total = npu.get("memory_total_mb", 0)
                
                memory_percent = 0.0
                if memory_total > 0:
                    memory_percent = round((memory_used / memory_total) * 100, 2)
                
                npu_info = {
                    "name": npu.get("name", "Unknown NPU"),
                    "utilization_percent": npu.get("utilization_percent", 0),
                    "memory_used_mb": memory_used,
                    "memory_total_mb": memory_total,
                    "memory_usage_percent": memory_percent
                }
                npu_status_list.append(npu_info)
                
            return npu_status_list
            
        except Exception as e:
            logger.error(f"Failed to get NPU status: {e}")
            return []

    def get_url(self) -> str:
        """
        获取设备URL
        
        Returns:
            str: 设备的完整URL
        """
        return f"http://{self.base_url}"


class TiinyClient:
    """
    Tiiny 客户端 - 支持真实 API 调用
    """
    
    def __init__(
        self, 
        api_key: Optional[str] = None,
        base_url: str = "http://localhost:8000",
        timeout: float = 3600.0
    ):
        """
        初始化客户端
        
        Args:
            api_key: API 密钥
            base_url: API 基础 URL
            timeout: 请求超时时间（秒）
        """
        self.api_key = api_key
        self.base_url = base_url.rstrip('/')
        self.timeout = timeout
        
        # 设置请求头
        self.headers = {
            "Content-Type": "application/json",
            "Accept": "application/json",
        }
        
        if api_key:
            self.headers["Authorization"] = f"Bearer {api_key}"
        
        # 简化的 chat 接口
        self.chat = self
        
        # Rerank 接口
        self.rerank = RerankRequest(self)
        
        # Embeddings 接口
        self.embeddings = EmbeddingsRequest(self)

        # Images 接口
        self.images = ImagesRequest(self)

        # Audio 接口
        self.audio = AudioRequest(self)
    
    @property
    def completions(self):
        """OpenAI 兼容的 completions 接口"""
        return self
    
    def _create_rerank_request(self, model: str, query: str, documents: List[str], top_k: Optional[int] = None) -> Dict[str, Any]:
        """发送 Rerank 请求"""
        try:
            url = f"{self.base_url}/v1/rerank"
            
            data = {
                "model": model,
                "query": query,
                "documents": documents
            }
            if top_k is not None:
                data["top_k"] = top_k
                
            logger.info(f"Sending rerank request to: {url}")
            logger.debug(f"Request data: {json.dumps(data, ensure_ascii=False)}")
            
            response = requests.post(
                url,
                headers=self.headers,
                json=data,
                timeout=self.timeout
            )
            
            response.raise_for_status()
            result = response.json()
            logger.debug(f"Rerank response: {json.dumps(result, ensure_ascii=False)}")
            
            return result
            
        except requests.exceptions.RequestException as e:
            logger.error(f"Rerank request failed: {e}")
            raise Exception(f"Rerank request failed: {e}")
            
    def _create_embedding_request(self, model: str, input: Union[str, List[str]], encoding_format: str = "float") -> Dict[str, Any]:
        """发送 Embedding 请求"""
        try:
            url = f"{self.base_url}/v1/embeddings"
            
            data = {
                "model": model,
                "input": input,
                "encoding_format": encoding_format
            }
            
            logger.info(f"Sending embedding request to: {url}")
            
            response = requests.post(
                url,
                headers=self.headers,
                json=data,
                timeout=self.timeout
            )
            
            response.raise_for_status()
            result = response.json()
            logger.debug(f"Embedding response: {json.dumps(result, ensure_ascii=False)}")
            
            return result
            
        except requests.exceptions.RequestException as e:
            logger.error(f"Embedding request failed: {e}")
            raise Exception(f"Embedding request failed: {e}")

    def _create_image_generation_request(self, model: str, prompt: str, **kwargs) -> Iterator[Dict[str, Any]]:
        """发送图片生成请求 (流式)"""
        try:
            url = f"{self.base_url}/v1/image/generate/stream"
            
            data = {
                "model": model,
                "prompt": prompt,
                "negative_prompt": kwargs.get("negative_prompt", ""),
                "width": kwargs.get("width", 512),
                "height": kwargs.get("height", 512),
                "seed": kwargs.get("seed", -1),
                "steps": kwargs.get("steps", 20),
                "cfg_scale": kwargs.get("cfg_scale", 7),
                "batch_size": kwargs.get("batch_size", 1),
                "upscale": kwargs.get("upscale", 1)
            }
            
            logger.info(f"Sending image generation request to: {url}")
            logger.debug(f"Request data: {json.dumps(data, ensure_ascii=False)}")
            
            response = requests.post(
                url,
                headers=self.headers,
                json=data,
                timeout=None, # timeout usually needed to be long or None for streaming
                stream=True
            )
            
            response.raise_for_status()
            
            for line in response.iter_lines():
                if line:
                    line = line.decode('utf-8')
                    if line.startswith('data: '):
                        data_str = line[6:]  # 移除 'data: ' 前缀
                        if data_str.strip() == '[DONE]':
                            break
                        try:
                            chunk = json.loads(data_str)
                            yield chunk
                        except json.JSONDecodeError:
                            logger.warning(f"Unable to parse streaming data: {data_str}")
                            continue

        except requests.exceptions.RequestException as e:
            logger.error(f"Image generation request failed: {e}")
            raise Exception(f"Image generation request failed: {e}")

    def _create_transcription_request(self, model: str, file: Any, **kwargs) -> Union[Dict[str, Any], str]:
        """发送音频转录请求"""
        try:
            url = f"{self.base_url}/v1/audio/transcriptions"
            
            # 准备 form data
            data = {"model": model}
            # 将所有kwargs作为form fields
            data.update(kwargs)
            
            # 准备文件
            files = None
            opened_file = None
            
            if isinstance(file, str):
                import os
                if os.path.exists(file):
                    opened_file = open(file, "rb")
                    filename = os.path.basename(file)
                    files = {"file": (filename, opened_file)}
                else:
                    raise FileNotFoundError(f"File not found: {file}")
            else:
                # 假设是文件对象
                filename = getattr(file, "name", "audio.wav")
                files = {"file": (filename, file)}

            # 处理 Headers: multipart/form-data 不应该有 Content-Type: application/json
            request_headers = self.headers.copy()
            if "Content-Type" in request_headers:
                del request_headers["Content-Type"]
            
            logger.info(f"Sending transcription request to: {url}")
            logger.debug(f"Request data: {json.dumps(data, ensure_ascii=False)}")
            
            try:
                response = requests.post(
                    url,
                    headers=request_headers,
                    data=data,
                    files=files,
                    timeout=kwargs.get("timeout", self.timeout)
                )
                
                response.raise_for_status()
                
                # 根据 response_format 处理返回值
                if kwargs.get("response_format") in ["text", "vtt", "srt"]:
                    return response.text
                else:
                    return response.json()
            finally:
                if opened_file:
                    opened_file.close()
            
        except requests.exceptions.RequestException as e:
            logger.error(f"Transcription request failed: {e}")
            raise Exception(f"Transcription request failed: {e}")
    
    
    def create(
        self,
        model: str,
        messages: List[Union[Dict[str, str], Any]],
        max_tokens: Optional[int] = None,
        temperature: Optional[float] = None,
        top_p: Optional[float] = None,
        stream: bool = False,
        stop: Optional[Union[str, List[str]]] = None,
        presence_penalty: Optional[float] = None,
        frequency_penalty: Optional[float] = None,
        **kwargs
    ) -> Union[ChatCompletionResponse, Iterator[Dict[str, Any]]]:
        """
        创建聊天完成（真实 API 调用）
        
        Args:
            model: 模型名称
            messages: 消息列表
            max_tokens: 最大令牌数
            temperature: 温度参数
            stream: 是否流式输出
            其他参数保留兼容性
            
        Returns:
            ChatCompletionResponse 或流式迭代器
        """
        # 构建请求数据
        data = {
            "model": model,
            "messages": self._format_messages(messages),
            "stream": stream
        }
        
        # 添加可选参数
        if max_tokens is not None:
            data["max_tokens"] = max_tokens
        if temperature is not None:
            data["temperature"] = temperature
        if top_p is not None:
            data["top_p"] = top_p
        if stop is not None:
            data["stop"] = stop
        if presence_penalty is not None:
            data["presence_penalty"] = presence_penalty
        if frequency_penalty is not None:
            data["frequency_penalty"] = frequency_penalty
        
        # 添加其他参数
        data.update(kwargs)
        
        if stream:
            return self._stream_request(data)
        else:
            return self._create_request(data)
    
    def _format_messages(self, messages: List[Union[Dict[str, str], Any]]) -> List[Dict[str, str]]:
        """格式化消息列表"""
        formatted = []
        for msg in messages:
            if isinstance(msg, dict):
                formatted.append({
                    "role": msg.get("role", "user"),
                    "content": msg.get("content", "")
                })
            else:
                # 如果是 ChatMessage 对象
                formatted.append({
                    "role": msg.role,
                    "content": msg.content
                })
        return formatted
    
    def _create_request(self, data: Dict[str, Any]) -> ChatCompletionResponse:
        """发送非流式请求"""
        try:
            url = f"{self.base_url}/v1/chat/completions"
            logger.info(f"Sending request to: {url}")
            logger.debug(f"Request data: {json.dumps(data, ensure_ascii=False)}")
            
            response = requests.post(
                url,
                headers=self.headers,
                json=data,
                timeout=self.timeout
            )
            
            # 检查响应状态
            response.raise_for_status()
            
            # 解析响应
            result = response.json()
            logger.debug(f"Response data: {json.dumps(result, ensure_ascii=False)}")
            
            # 转换为标准格式
            choices = []
            for choice in result.get("choices", []):
                message_data = choice.get("message", {})
                choices.append(Choice(
                    index=choice.get("index", 0),
                    message=ChatMessage(
                        role=message_data.get("role", "assistant"),
                        content=message_data.get("content", "")
                    ),
                    finish_reason=choice.get("finish_reason", "stop")
                ))
            
            return ChatCompletionResponse(
                choices=choices,
                model=result.get("model", data["model"]),
                id=result.get("id"),
                created=result.get("created"),
                usage=result.get("usage")
            )
            
        except requests.exceptions.RequestException as e:
            logger.error(f"API request failed: {e}")
            raise Exception(f"API request failed: {e}")
        except Exception as e:
            logger.error(f"Failed to process response: {e}")
            raise Exception(f"Failed to process response: {e}")
    
    def _stream_request(self, data: Dict[str, Any]) -> Iterator[Dict[str, Any]]:
        """发送流式请求"""
        try:
            url = f"{self.base_url}/v1/chat/completions"
            logger.info(f"Sending streaming request to: {url}")
            
            response = requests.post(
                url,
                headers=self.headers,
                json=data,
                timeout=self.timeout,
                stream=True
            )
            
            response.raise_for_status()
            
            # 处理流式响应
            for line in response.iter_lines():
                if line:
                    line = line.decode('utf-8')
                    if line.startswith('data: '):
                        data_str = line[6:]  # 移除 'data: ' 前缀
                        if data_str.strip() == '[DONE]':
                            break
                        try:
                            chunk = json.loads(data_str)
                            yield chunk
                        except json.JSONDecodeError:
                            logger.warning(f"Unable to parse streaming data: {data_str}")
                            continue
            
        except requests.exceptions.RequestException as e:
            logger.error(f"Streaming API request failed: {e}")
            raise Exception(f"Streaming API request failed: {e}")
        except Exception as e:
            logger.error(f"Failed to process streaming response: {e}")
            raise Exception(f"Failed to process streaming response: {e}")
    
    def close(self):
        """关闭客户端"""
        pass


# OpenAI 风格的别名
OpenAI = TiinyClient
Client = TiinyClient