perf: optional orjson JSON codec behind ENABLE_ORJSON (#27583)
Swap the JSON encoder/decoder used across the backend from stdlib json to orjson when ENABLE_ORJSON is set — HTTP request bodies, JSONResponse bodies, upstream provider responses, SSE chunks, and socket.io/Redis payloads. The flag defaults to off, in which case the app uses stdlib json and engineio's codec verbatim, so default behaviour is unchanged. - json_codec exports JSONCodec (stdlib json or the orjson codec) and SOCKETIO_JSON (engineio's codec or the orjson codec); call sites import JSONCodec and stay implementation-agnostic - apply_orjson_http_json() is a no-op when the flag is off, leaving starlette's Request.json / JSONResponse.render untouched - the orjson codec falls back to the stdlib for inputs orjson rejects (non-str dict keys, ints beyond 64 bits, NaN literals) - orjson is imported only when the flag is on - FastAPI(default_response_class=...) is deliberately not used: an explicit default disables the Pydantic direct-to-bytes fast path for response_model routes
This commit is contained in:
1 parent
602004dd5f
commit
72fdf238a8
13 files changed
+176
-51
No files matched your search
@@ -42,6 +42,7 @@ from open_webui.utils.access_control import check_model_access
|
||||
from open_webui.utils.auth import get_admin_user, get_verified_user
|
||||
from open_webui.utils.headers import get_custom_headers, include_user_info_headers
|
||||
from open_webui.utils.model_ids import strip_provider_model_prefix
|
||||
from open_webui.utils.json_codec import JSONCodec
|
||||
from open_webui.utils.misc import calculate_sha256
|
||||
from open_webui.utils.payload import (
|
||||
apply_model_params_to_body_ollama,
|
||||
@@ -86,7 +87,7 @@ async def send_get_request(
|
||||
ssl=AIOHTTP_CLIENT_SESSION_SSL,
|
||||
timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST),
|
||||
) as r:
|
||||
return await r.json()
|
||||
return await r.json(loads=JSONCodec.loads)
|
||||
except Exception as exc:
|
||||
log.error(f'Connection error: {exc}')
|
||||
return None
|
||||
@@ -137,7 +138,7 @@ async def send_request(
|
||||
|
||||
if not r.ok:
|
||||
try:
|
||||
res = await r.json()
|
||||
res = await r.json(loads=JSONCodec.loads)
|
||||
await publish_model_provider_request_failed(
|
||||
request,
|
||||
actor=user,
|
||||
@@ -179,7 +180,7 @@ async def send_request(
|
||||
)
|
||||
else:
|
||||
try:
|
||||
return await r.json()
|
||||
return await r.json(loads=JSONCodec.loads)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
@@ -270,12 +271,12 @@ async def verify_connection(
|
||||
) as r:
|
||||
if r.status != 200:
|
||||
detail = f'HTTP Error: {r.status}'
|
||||
res = await r.json()
|
||||
res = await r.json(loads=JSONCodec.loads)
|
||||
if 'error' in res:
|
||||
detail = f'External Error: {res["error"]}'
|
||||
raise Exception(detail)
|
||||
|
||||
return await r.json()
|
||||
return await r.json(loads=JSONCodec.loads)
|
||||
except aiohttp.ClientError as exc:
|
||||
log.exception(f'Client error: {exc}')
|
||||
raise HTTPException(status_code=500, detail=ERROR_MESSAGES.SERVER_CONNECTION_ERROR)
|
||||
|
||||
@@ -44,6 +44,7 @@ from open_webui.utils.access_control import check_model_access, has_connection_a
|
||||
from open_webui.utils.anthropic import get_anthropic_models, is_anthropic_url
|
||||
from open_webui.utils.auth import get_admin_user, get_verified_user
|
||||
from open_webui.utils.headers import get_custom_headers, include_user_info_headers
|
||||
from open_webui.utils.json_codec import JSONCodec
|
||||
from open_webui.utils.model_ids import strip_provider_model_prefix
|
||||
from open_webui.utils.misc import (
|
||||
convert_logit_bias_input_to_json,
|
||||
@@ -112,7 +113,7 @@ async def send_get_request(
|
||||
cookies=cookies,
|
||||
ssl=AIOHTTP_CLIENT_SESSION_SSL,
|
||||
) as response:
|
||||
return await response.json()
|
||||
return await response.json(loads=JSONCodec.loads)
|
||||
except Exception as e:
|
||||
# Handle connection error here
|
||||
log.error(f'Connection error: {e}')
|
||||
@@ -357,7 +358,7 @@ async def count_anthropic_tokens(request: Request, form_data: dict, user: UserMo
|
||||
)
|
||||
|
||||
try:
|
||||
response_data = await response.json()
|
||||
response_data = await response.json(loads=JSONCodec.loads)
|
||||
except Exception:
|
||||
response_data = await response.text()
|
||||
|
||||
@@ -509,7 +510,7 @@ async def speech(request: Request, user=Depends(get_verified_user)):
|
||||
detail = None
|
||||
if r is not None:
|
||||
try:
|
||||
res = await r.json()
|
||||
res = await r.json(loads=JSONCodec.loads)
|
||||
if 'error' in res:
|
||||
detail = f'External: {res["error"]}'
|
||||
except Exception:
|
||||
@@ -763,14 +764,14 @@ async def get_models(request: Request, url_idx: int | None = None, user=Depends(
|
||||
if r.status != 200:
|
||||
error_detail = f'HTTP Error: {r.status}'
|
||||
try:
|
||||
res = await r.json()
|
||||
res = await r.json(loads=JSONCodec.loads)
|
||||
if 'error' in res:
|
||||
error_detail = f'External Error: {res["error"]}'
|
||||
except Exception:
|
||||
pass
|
||||
raise Exception(error_detail)
|
||||
|
||||
response_data = await r.json()
|
||||
response_data = await r.json(loads=JSONCodec.loads)
|
||||
|
||||
if 'api.openai.com' in url:
|
||||
response_data['data'] = [
|
||||
@@ -853,7 +854,7 @@ async def verify_connection(
|
||||
ssl=AIOHTTP_CLIENT_SESSION_SSL,
|
||||
) as r:
|
||||
try:
|
||||
response_data = await r.json()
|
||||
response_data = await r.json(loads=JSONCodec.loads)
|
||||
except Exception:
|
||||
response_data = await r.text()
|
||||
|
||||
@@ -879,7 +880,7 @@ async def verify_connection(
|
||||
ssl=AIOHTTP_CLIENT_SESSION_SSL,
|
||||
) as r:
|
||||
try:
|
||||
response_data = await r.json()
|
||||
response_data = await r.json(loads=JSONCodec.loads)
|
||||
except Exception:
|
||||
response_data = await r.text()
|
||||
|
||||
@@ -1417,7 +1418,7 @@ async def generate_chat_completion(
|
||||
)
|
||||
else:
|
||||
try:
|
||||
response = await r.json()
|
||||
response = await r.json(loads=JSONCodec.loads)
|
||||
except Exception as e:
|
||||
log.error(e)
|
||||
response = await r.text()
|
||||
@@ -1529,7 +1530,7 @@ async def embeddings(request: Request, form_data: dict, user):
|
||||
)
|
||||
else:
|
||||
try:
|
||||
response_data = await r.json()
|
||||
response_data = await r.json(loads=JSONCodec.loads)
|
||||
except Exception:
|
||||
response_data = await r.text()
|
||||
|
||||
@@ -1656,7 +1657,7 @@ async def responses(
|
||||
)
|
||||
else:
|
||||
try:
|
||||
response_data = await r.json()
|
||||
response_data = await r.json(loads=JSONCodec.loads)
|
||||
except Exception:
|
||||
response_data = await r.text()
|
||||
|
||||
@@ -1778,7 +1779,7 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
|
||||
)
|
||||
else:
|
||||
try:
|
||||
response_data = await r.json()
|
||||
response_data = await r.json(loads=JSONCodec.loads)
|
||||
except Exception:
|
||||
response_data = await r.text()
|
||||
|
||||
|
||||
Reference in new issue
Block a user