Text API 客户端封装类
| 38 | |
| 39 | |
| 40 | class TextChatClient: |
| 41 | """Text API 客户端封装类""" |
| 42 | |
| 43 | def __init__(self, api_key: str = None, base_url: str = None, endpoint_type: str = None): |
| 44 | self.api_key = api_key |
| 45 | if not self.api_key: |
| 46 | raise ValueError( |
| 47 | "Text API Key 未配置。\n" |
| 48 | "解决方案:在系统设置页面编辑文本生成服务商,填写 API Key" |
| 49 | ) |
| 50 | |
| 51 | self.base_url = (base_url or "https://api.openai.com").rstrip('/') |
| 52 | if self.base_url.endswith('/v1'): |
| 53 | self.base_url = self.base_url[:-3] |
| 54 | |
| 55 | # 支持自定义端点路径 |
| 56 | endpoint = endpoint_type or '/v1/chat/completions' |
| 57 | # 确保端点以 / 开头 |
| 58 | if not endpoint.startswith('/'): |
| 59 | endpoint = '/' + endpoint |
| 60 | self.chat_endpoint = f"{self.base_url}{endpoint}" |
| 61 | |
| 62 | def _encode_image_to_base64(self, image_data: bytes) -> str: |
| 63 | """将图片数据编码为 base64""" |
| 64 | return base64.b64encode(image_data).decode('utf-8') |
| 65 | |
| 66 | def _build_content_with_images( |
| 67 | self, |
| 68 | text: str, |
| 69 | images: List[Union[bytes, str]] = None |
| 70 | ) -> Union[str, List[dict]]: |
| 71 | """ |
| 72 | 构建包含图片的 content |
| 73 | |
| 74 | Args: |
| 75 | text: 文本内容 |
| 76 | images: 图片列表,可以是 bytes(图片数据)或 str(URL) |
| 77 | |
| 78 | Returns: |
| 79 | 如果没有图片,返回纯文本;有图片则返回多模态内容列表 |
| 80 | """ |
| 81 | if not images: |
| 82 | return text |
| 83 | |
| 84 | content = [{"type": "text", "text": text}] |
| 85 | |
| 86 | for img in images: |
| 87 | if isinstance(img, bytes): |
| 88 | # 压缩图片到 200KB 以内 |
| 89 | compressed_img = compress_image(img, max_size_kb=200) |
| 90 | # 图片数据,转为 base64 data URL |
| 91 | base64_data = self._encode_image_to_base64(compressed_img) |
| 92 | image_url = f"data:image/png;base64,{base64_data}" |
| 93 | else: |
| 94 | # 已经是 URL |
| 95 | image_url = img |
| 96 | |
| 97 | content.append({ |
no outgoing calls
no test coverage detected