fix: 优化发送错误时图片大喷射

This commit is contained in:
KawaiiYusora
2025-03-14 00:09:07 +08:00
parent 32c6d7ea55
commit 50ce8cf521

View File

@@ -185,7 +185,7 @@ class LLM_request:
elif response.status in policy["abort_codes"]: elif response.status in policy["abort_codes"]:
logger.error(f"错误码: {response.status} - {error_code_mapping.get(response.status)}") logger.error(f"错误码: {response.status} - {error_code_mapping.get(response.status)}")
if response.status == 403: if response.status == 403:
#只针对硅基流动的V3和R1进行降级处理 # 只针对硅基流动的V3和R1进行降级处理
if self.model_name.startswith( if self.model_name.startswith(
"Pro/deepseek-ai") and self.base_url == "https://api.siliconflow.cn/v1/": "Pro/deepseek-ai") and self.base_url == "https://api.siliconflow.cn/v1/":
old_model_name = self.model_name old_model_name = self.model_name
@@ -228,7 +228,7 @@ class LLM_request:
try: try:
chunk = json.loads(data_str) chunk = json.loads(data_str)
if flag_delta_content_finished: if flag_delta_content_finished:
usage = chunk.get("usage", None) # 获取tokn用量 usage = chunk.get("usage", None) # 获取tokn用量
else: else:
delta = chunk["choices"][0]["delta"] delta = chunk["choices"][0]["delta"]
delta_content = delta.get("content") delta_content = delta.get("content")
@@ -236,7 +236,7 @@ class LLM_request:
delta_content = "" delta_content = ""
accumulated_content += delta_content accumulated_content += delta_content
# 检测流式输出文本是否结束 # 检测流式输出文本是否结束
finish_reason = chunk["choices"][0].get("finish_reason") finish_reason = chunk["choices"][0].get("finish_reason")
if finish_reason == "stop": if finish_reason == "stop":
usage = chunk.get("usage", None) usage = chunk.get("usage", None)
if usage: if usage:
@@ -254,7 +254,8 @@ class LLM_request:
content = re.sub(r'<think>.*?</think>', '', content, flags=re.DOTALL).strip() content = re.sub(r'<think>.*?</think>', '', content, flags=re.DOTALL).strip()
# 构造一个伪result以便调用自定义响应处理器或默认处理器 # 构造一个伪result以便调用自定义响应处理器或默认处理器
result = { result = {
"choices": [{"message": {"content": content, "reasoning_content": reasoning_content}}], "usage": usage} "choices": [{"message": {"content": content, "reasoning_content": reasoning_content}}],
"usage": usage}
return response_handler(result) if response_handler else self._default_response_handler( return response_handler(result) if response_handler else self._default_response_handler(
result, user_id, request_type, endpoint) result, user_id, request_type, endpoint)
else: else:
@@ -270,6 +271,9 @@ class LLM_request:
await asyncio.sleep(wait_time) await asyncio.sleep(wait_time)
else: else:
logger.critical(f"请求失败: {str(e)}") logger.critical(f"请求失败: {str(e)}")
if image_base64:
payload["messages"][0]["content"][1]["image_url"][
"url"] = f"data:image/{image_format.lower()};base64,{image_base64[:10]}...{image_base64[-10:]}"
logger.critical(f"请求头: {await self._build_headers(no_key=True)} 请求体: {payload}") logger.critical(f"请求头: {await self._build_headers(no_key=True)} 请求体: {payload}")
raise RuntimeError(f"API请求失败: {str(e)}") raise RuntimeError(f"API请求失败: {str(e)}")
@@ -307,7 +311,8 @@ class LLM_request:
"role": "user", "role": "user",
"content": [ "content": [
{"type": "text", "text": prompt}, {"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": f"data:image/{image_format.lower()};base64,{image_base64}"}} {"type": "image_url",
"image_url": {"url": f"data:image/{image_format.lower()};base64,{image_base64}"}}
] ]
} }
], ],
@@ -452,6 +457,7 @@ class LLM_request:
) )
return embedding return embedding
def compress_base64_image_by_scale(base64_data: str, target_size: int = 0.8 * 1024 * 1024) -> str: def compress_base64_image_by_scale(base64_data: str, target_size: int = 0.8 * 1024 * 1024) -> str:
"""压缩base64格式的图片到指定大小 """压缩base64格式的图片到指定大小
Args: Args:
@@ -465,7 +471,7 @@ def compress_base64_image_by_scale(base64_data: str, target_size: int = 0.8 * 10
image_data = base64.b64decode(base64_data) image_data = base64.b64decode(base64_data)
# 如果已经小于目标大小,直接返回原图 # 如果已经小于目标大小,直接返回原图
if len(image_data) <= 2*1024*1024: if len(image_data) <= 2 * 1024 * 1024:
return base64_data return base64_data
# 将字节数据转换为图片对象 # 将字节数据转换为图片对象
@@ -490,7 +496,7 @@ def compress_base64_image_by_scale(base64_data: str, target_size: int = 0.8 * 10
for frame_idx in range(img.n_frames): for frame_idx in range(img.n_frames):
img.seek(frame_idx) img.seek(frame_idx)
new_frame = img.copy() new_frame = img.copy()
new_frame = new_frame.resize((new_width//2, new_height//2), Image.Resampling.LANCZOS) # 动图折上折 new_frame = new_frame.resize((new_width // 2, new_height // 2), Image.Resampling.LANCZOS) # 动图折上折
frames.append(new_frame) frames.append(new_frame)
# 保存到缓冲区 # 保存到缓冲区
@@ -516,7 +522,7 @@ def compress_base64_image_by_scale(base64_data: str, target_size: int = 0.8 * 10
# 获取压缩后的数据并转换为base64 # 获取压缩后的数据并转换为base64
compressed_data = output_buffer.getvalue() compressed_data = output_buffer.getvalue()
logger.success(f"压缩图片: {original_width}x{original_height} -> {new_width}x{new_height}") logger.success(f"压缩图片: {original_width}x{original_height} -> {new_width}x{new_height}")
logger.info(f"压缩前大小: {len(image_data)/1024:.1f}KB, 压缩后大小: {len(compressed_data)/1024:.1f}KB") logger.info(f"压缩前大小: {len(image_data) / 1024:.1f}KB, 压缩后大小: {len(compressed_data) / 1024:.1f}KB")
return base64.b64encode(compressed_data).decode('utf-8') return base64.b64encode(compressed_data).decode('utf-8')
@@ -525,4 +531,3 @@ def compress_base64_image_by_scale(base64_data: str, target_size: int = 0.8 * 10
import traceback import traceback
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
return base64_data return base64_data