Bläddra i källkod

feat: forward upstream OpenAI errors

Juan Calderon-Perez 2 månader sedan
förälder
incheckning
2ae7584686
1 ändrade filer med 59 tillägg och 57 borttagningar
  1. 59 57
      backend/open_webui/routers/openai.py

+ 59 - 57
backend/open_webui/routers/openai.py

@@ -2,17 +2,15 @@ import asyncio
 import hashlib
 import json
 import logging
-from pathlib import Path
-from typing import Literal, Optional, overload
+from typing import Optional
 
 import aiohttp
 from aiocache import cached
 import requests
 from urllib.parse import quote
 
-from fastapi import Depends, FastAPI, HTTPException, Request, APIRouter
-from fastapi.middleware.cors import CORSMiddleware
-from fastapi.responses import FileResponse, StreamingResponse
+from fastapi import Depends, HTTPException, Request, APIRouter
+from fastapi.responses import FileResponse, StreamingResponse, JSONResponse, PlainTextResponse
 from pydantic import BaseModel
 from starlette.background import BackgroundTask
 
@@ -31,7 +29,7 @@ from open_webui.env import (
 from open_webui.models.users import UserModel
 
 from open_webui.constants import ERROR_MESSAGES
-from open_webui.env import ENV, SRC_LOG_LEVELS
+from open_webui.env import SRC_LOG_LEVELS
 
 
 from open_webui.utils.payload import (
@@ -595,15 +593,17 @@ async def verify_connection(
                     headers=headers,
                     ssl=AIOHTTP_CLIENT_SESSION_SSL,
                 ) as r:
+                    try:
+                        response_data = await r.json()
+                    except Exception:
+                        response_data = await r.text()
+
                     if r.status != 200:
-                        # Extract response error details if available
-                        error_detail = f"HTTP Error: {r.status}"
-                        res = await r.json()
-                        if "error" in res:
-                            error_detail = f"External Error: {res['error']}"
-                        raise Exception(error_detail)
-
-                    response_data = await r.json()
+                        if isinstance(response_data, (dict, list)):
+                            return JSONResponse(status_code=r.status, content=response_data)
+                        else:
+                            return PlainTextResponse(status_code=r.status, content=response_data)
+
                     return response_data
             else:
                 headers["Authorization"] = f"Bearer {key}"
@@ -613,15 +613,17 @@ async def verify_connection(
                     headers=headers,
                     ssl=AIOHTTP_CLIENT_SESSION_SSL,
                 ) as r:
+                    try:
+                        response_data = await r.json()
+                    except Exception:
+                        response_data = await r.text()
+
                     if r.status != 200:
-                        # Extract response error details if available
-                        error_detail = f"HTTP Error: {r.status}"
-                        res = await r.json()
-                        if "error" in res:
-                            error_detail = f"External Error: {res['error']}"
-                        raise Exception(error_detail)
-
-                    response_data = await r.json()
+                        if isinstance(response_data, (dict, list)):
+                            return JSONResponse(status_code=r.status, content=response_data)
+                        else:
+                            return PlainTextResponse(status_code=r.status, content=response_data)
+
                     return response_data
 
         except aiohttp.ClientError as e:
@@ -632,8 +634,9 @@ async def verify_connection(
             )
         except Exception as e:
             log.exception(f"Unexpected error: {e}")
-            error_detail = f"Unexpected error: {str(e)}"
-            raise HTTPException(status_code=500, detail=error_detail)
+            raise HTTPException(
+                status_code=500, detail="Open WebUI: Server Connection Error"
+            )
 
 
 def get_azure_allowed_params(api_version: str) -> set[str]:
@@ -883,21 +886,19 @@ async def generate_chat_completion(
                 log.error(e)
                 response = await r.text()
 
-            r.raise_for_status()
+            if r.status >= 400:
+                if isinstance(response, (dict, list)):
+                    return JSONResponse(status_code=r.status, content=response)
+                else:
+                    return PlainTextResponse(status_code=r.status, content=response)
+
             return response
     except Exception as e:
         log.exception(e)
 
-        detail = None
-        if isinstance(response, dict):
-            if "error" in response:
-                detail = f"{response['error']['message'] if 'message' in response['error'] else response['error']}"
-        elif isinstance(response, str):
-            detail = response
-
         raise HTTPException(
             status_code=r.status if r else 500,
-            detail=detail if detail else "Open WebUI: Server Connection Error",
+            detail="Open WebUI: Server Connection Error",
         )
     finally:
         if not streaming:
@@ -951,7 +952,7 @@ async def embeddings(request: Request, form_data: dict, user):
                 ),
             },
         )
-        r.raise_for_status()
+
         if "text/event-stream" in r.headers.get("Content-Type", ""):
             streaming = True
             return StreamingResponse(
@@ -963,21 +964,23 @@ async def embeddings(request: Request, form_data: dict, user):
                 ),
             )
         else:
-            response_data = await r.json()
+            try:
+                response_data = await r.json()
+            except Exception:
+                response_data = await r.text()
+
+            if r.status >= 400:
+                if isinstance(response_data, (dict, list)):
+                    return JSONResponse(status_code=r.status, content=response_data)
+                else:
+                    return PlainTextResponse(status_code=r.status, content=response_data)
+
             return response_data
     except Exception as e:
         log.exception(e)
-        detail = None
-        if r is not None:
-            try:
-                res = await r.json()
-                if "error" in res:
-                    detail = f"External: {res['error']['message'] if 'message' in res['error'] else res['error']}"
-            except Exception:
-                detail = f"External: {e}"
         raise HTTPException(
             status_code=r.status if r else 500,
-            detail=detail if detail else "Open WebUI: Server Connection Error",
+            detail="Open WebUI: Server Connection Error",
         )
     finally:
         if not streaming:
@@ -1043,7 +1046,6 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
             headers=headers,
             ssl=AIOHTTP_CLIENT_SESSION_SSL,
         )
-        r.raise_for_status()
 
         # Check if response is SSE
         if "text/event-stream" in r.headers.get("Content-Type", ""):
@@ -1057,24 +1059,24 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
                 ),
             )
         else:
-            response_data = await r.json()
+            try:
+                response_data = await r.json()
+            except Exception:
+                response_data = await r.text()
+
+            if r.status >= 400:
+                if isinstance(response_data, (dict, list)):
+                    return JSONResponse(status_code=r.status, content=response_data)
+                else:
+                    return PlainTextResponse(status_code=r.status, content=response_data)
+
             return response_data
 
     except Exception as e:
         log.exception(e)
-
-        detail = None
-        if r is not None:
-            try:
-                res = await r.json()
-                log.error(res)
-                if "error" in res:
-                    detail = f"External: {res['error']['message'] if 'message' in res['error'] else res['error']}"
-            except Exception:
-                detail = f"External: {e}"
         raise HTTPException(
             status_code=r.status if r else 500,
-            detail=detail if detail else "Open WebUI: Server Connection Error",
+            detail="Open WebUI: Server Connection Error",
         )
     finally:
         if not streaming: