diff --git a/ai.py b/ai.py index 405705c..eff6256 100644 --- a/ai.py +++ b/ai.py @@ -1,6 +1,7 @@ import aiohttp import asyncio import json +import re import gconfig try: @@ -10,9 +11,30 @@ except: finally: from config import * + +def parse_error_body(status: int, body: str) -> str: + try: + data = json.loads(body) + if isinstance(data, dict): + err = data.get("error") + if isinstance(err, dict): + return f"{status} {err.get('message') or err.get('status') or err}" + if err: + return f"{status} {err}" + return f"{status} {data.get('message') or body[:200]}" + return f"{status} {body[:200]}" + except Exception: + pass + clean = re.sub(r"<[^>]+>", " ", body).strip() + return f"{status} {clean[:200]}" + + async def make_request(url, headers, payload): async with aiohttp.ClientSession(headers=headers) as session: async with session.post(url, json=payload) as response: + if response.status != 200: + error_body = await response.text() + raise Exception(parse_error_body(response.status, error_body)) if payload.get("stream") == True: async for line in response.content: line = line.decode("utf-8").strip() diff --git a/helpers.py b/helpers.py index 521c9f0..2f7dcfa 100644 --- a/helpers.py +++ b/helpers.py @@ -343,6 +343,36 @@ def parse_response(text: str): "type": "quota", "message": "лимит токенов закончился у провайдера врат. подожди или смени модель.", } + elif "response payload is not completed" in text or "not enough data to satisfy" in text or "server disconnected" in text or "connection reset" in text or "serverdisconnectederror" in text: + return { + "type": "incomplete", + "message": "сервер петух и оборвал ответ на середине. подожди или смени модель.", + } + elif "timeout" in text or "timed out" in text: + return { + "type": "timeout", + "message": "сервер думал слишком долго и умер. подожди или смени модель.", + } + elif "not found" in text or " 404" in text or "404 " in text or "no such model" in text or "does not exist" in text: + return { + "type": "notfound", + "message": "модель не найдена у провайдера. смени модель в настройках.", + } + elif "forbidden" in text or "unauthorized" in text or " 403" in text or "403 " in text or " 401" in text or "401 " in text or "invalid api key" in text or "incorrect api key" in text: + return { + "type": "key", + "message": "ключ или доступ к провайдеру сдох. смени модель или напиши хостеру.", + } + elif " 429" in text or "429 " in text or "exhausted" in text or "quota" in text: + return { + "type": "quota", + "message": "лимит запросов у провайдера закончился. подожди или смени модель.", + } + elif " 500" in text or "500 " in text or " 502" in text or "502 " in text or " 503" in text or "503 " in text or "bad gateway" in text: + return { + "type": "int", + "message": "ошибка на стороне провайдера. подожди или смени модель.", + } else: return { "type": "unknown", diff --git a/supergenerator.py b/supergenerator.py index 0bd8193..7ca6a69 100644 --- a/supergenerator.py +++ b/supergenerator.py @@ -1,3 +1,4 @@ +import json import ai from statistics import * @@ -277,6 +278,7 @@ async def openai_generate_text( if stream: message = "" + stream_error = "" t_counter = 0 counter = 0 counter_2 = 1 @@ -294,6 +296,10 @@ async def openai_generate_text( "type": "error", "text": error["message"] } + if isinstance(chunk, dict) and "choices" not in chunk: + stream_error = str(chunk)[:300] + elif isinstance(chunk, str) and chunk.strip(): + stream_error = chunk.strip()[:300] continue if content: message += content @@ -360,6 +366,13 @@ async def openai_generate_text( print(f"{YELLOW} -- {e}{RESET}") text = message + if not text and stream_error: + error = parse_response(stream_error.lower()) + print(f"{RED} -- {error['type']} - {stream_error}{RESET}") + return { + "type": "error", + "text": error["message"] + } else: async for completion in ai.completions(**alo): pass @@ -383,6 +396,21 @@ async def openai_generate_text( except Exception as e: error = parse_response(str(e).lower()) print(f"{RED} -- {error['type']} - {e}{RESET}") + err_str = str(e) + try: + status_code = int(err_str.split(" ", 1)[0]) + except ValueError: + status_code = 0 + if 400 <= status_code < 500: + debug_alo = {k: v for k, v in alo.items() if k != "api_key"} + return { + "type": "error", + "text": error["message"] + "\n\n" \ + f"модель: `{model}`\n" \ + f"статус: `{status_code}`\n" \ + f"raw: `{err_str[:500]}`\n" \ + f"запрос:\n```{json.dumps(debug_alo, ensure_ascii=False)[:1200]}\n```" + } return { "type": "error", "text": error["message"]