diff --git a/api/utils/api_utils.py b/api/utils/api_utils.py index 9b0b481e3..30cf12aae 100644 --- a/api/utils/api_utils.py +++ b/api/utils/api_utils.py @@ -56,6 +56,30 @@ from rag.utils.mcp_tool_call_conn import MCPToolCallSession, close_multiple_mcp_ requests.models.complexjson.dumps = functools.partial(json.dumps, cls=CustomJSONEncoder) +def serialize_for_json(obj): + """ + Recursively serialize objects to make them JSON serializable. + Handles ModelMetaclass and other non-serializable objects. + """ + if hasattr(obj, '__dict__'): + # For objects with __dict__, try to serialize their attributes + try: + return {key: serialize_for_json(value) for key, value in obj.__dict__.items() + if not key.startswith('_')} + except (AttributeError, TypeError): + return str(obj) + elif hasattr(obj, '__name__'): + # For classes and metaclasses, return their name + return f"<{obj.__module__}.{obj.__name__}>" if hasattr(obj, '__module__') else f"<{obj.__name__}>" + elif isinstance(obj, (list, tuple)): + return [serialize_for_json(item) for item in obj] + elif isinstance(obj, dict): + return {key: serialize_for_json(value) for key, value in obj.items()} + elif isinstance(obj, (str, int, float, bool)) or obj is None: + return obj + else: + # Fallback: convert to string representation + return str(obj) def request(**kwargs): sess = requests.Session() @@ -128,7 +152,11 @@ def server_error_response(e): except BaseException: pass if len(e.args) > 1: - return get_json_result(code=settings.RetCode.EXCEPTION_ERROR, message=repr(e.args[0]), data=e.args[1]) + try: + serialized_data = serialize_for_json(e.args[1]) + return get_json_result(code= settings.RetCode.EXCEPTION_ERROR, message=repr(e.args[0]), data=serialized_data) + except Exception: + return get_json_result(code=settings.RetCode.EXCEPTION_ERROR, message=repr(e.args[0]), data=None) if repr(e).find("index_not_found_exception") >= 0: return get_json_result(code=settings.RetCode.EXCEPTION_ERROR, message="No chunk found, please upload file and parse it.")