|
29 | 29 | log_connection_failure, |
30 | 30 | ) |
31 | 31 | from astrbot.core.utils.string_utils import normalize_and_dedupe_strings |
| 32 | +from astrbot.core.utils.image_utils import encode_image_to_base64_url |
32 | 33 |
|
33 | 34 | from ..register import register_provider_adapter |
34 | 35 |
|
@@ -192,6 +193,13 @@ def _ensure_client(self) -> None: |
192 | 193 | need_reinit = True |
193 | 194 | else: |
194 | 195 | try: |
| 196 | + # 注意:此处直接访问了 openai 库的私有属性 `_client`, |
| 197 | + # 依赖其内部实现(httpx.AsyncClient 实例暴露的 is_closed 属性)。 |
| 198 | + # 这一做法存在脆弱性——若 openai 库未来版本调整了内部结构, |
| 199 | + # 此处可能在没有任何报错的情况下静默失效。 |
| 200 | + # 目前 openai SDK 尚未提供检查底层连接是否已关闭的公开 API(或者是我不知道)。 |
| 201 | + # 若未来 SDK 提供了类似 self.client.is_closed() 的公开方法, |
| 202 | + # 应及时将此处替换为对应的公开接口。 |
195 | 203 | if self.client._client.is_closed: |
196 | 204 | need_reinit = True |
197 | 205 | except AttributeError: |
@@ -1021,29 +1029,19 @@ def _detect_mime_type(header_bytes: bytes) -> str: |
1021 | 1029 | return "image/jpeg" |
1022 | 1030 |
|
1023 | 1031 | async def encode_image_bs64(self, image_url: str) -> str: |
1024 | | - """将图片转换为 base64,自动检测实际MIME类型""" |
1025 | | - if image_url.startswith("base64://"): |
1026 | | - raw_b64 = image_url[len("base64://"):] |
1027 | | - # 从 base64 数据中解码前几个字节来检测实际格式 |
1028 | | - try: |
1029 | | - # 取足够的 base64 字符来解码出至少 16 字节的原始数据 |
1030 | | - sample = raw_b64[:32] |
1031 | | - # 确保 base64 填充正确 |
1032 | | - missing_padding = len(sample) % 4 |
1033 | | - if missing_padding: |
1034 | | - sample += '=' * (4 - missing_padding) |
1035 | | - header_bytes = base64.b64decode(sample) |
1036 | | - mime_type = self._detect_mime_type(header_bytes) |
1037 | | - except Exception: |
1038 | | - mime_type = "image/jpeg" |
1039 | | - return f"data:{mime_type};base64,{raw_b64}" |
1040 | | - |
1041 | | - with open(image_url, "rb") as f: |
1042 | | - header_bytes = f.read(16) |
1043 | | - mime_type = self._detect_mime_type(header_bytes) |
1044 | | - f.seek(0) |
1045 | | - image_bs64 = base64.b64encode(f.read()).decode("utf-8") |
1046 | | - return f"data:{mime_type};base64,{image_bs64}" |
| 1032 | + """将图片转换为 base64 Data URL,自动检测实际 MIME 类型。 |
| 1033 | +
|
| 1034 | + 委托给公共工具函数 encode_image_to_base64_url 实现, |
| 1035 | + 消除与 ProviderRequest 之间的重复逻辑。原实现硬编码 |
| 1036 | + image/jpeg,会导致 PNG 等格式在严格校验的接口上报错。 |
| 1037 | +
|
| 1038 | + Args: |
| 1039 | + image_url: 本地文件路径,或以 "base64://" 开头的 base64 字符串。 |
| 1040 | +
|
| 1041 | + Returns: |
| 1042 | + 形如 "data:image/png;base64,..." 的 Data URL 字符串。 |
| 1043 | + """ |
| 1044 | + return await encode_image_to_base64_url(image_url) |
1047 | 1045 |
|
1048 | 1046 | async def terminate(self): |
1049 | 1047 | if self.client: |
|
0 commit comments