diff --git a/lib/umbridge.h b/lib/umbridge.h index a779112..ccf2356 100644 --- a/lib/umbridge.h +++ b/lib/umbridge.h @@ -466,7 +466,32 @@ namespace umbridge { if (!enable_parallel) { model_lock.lock(); } - std::vector> outputs = model.Evaluate(inputs, config_json); + std::vector> outputs; + try{ + outputs = model.Evaluate(inputs, config_json); + } + catch(const std::exception& e){ + + std::cerr << "Exception caught: " << e.what() << std::endl; + + json response_body; + response_body["error"]["type"] = "InvalidEvaluation"; + response_body["error"]["message"] = std::string("Model was unable to provide a valid evaluation due to ") + e.what(); + res.set_content(response_body.dump(), "application/json"); + res.status = 500; + return; + } + catch (...) { + + std::cerr << "Caught an unknown error during evaluation." << std::endl; + + json response_body; + response_body["error"]["type"] = "InvalidEvaluation"; + response_body["error"]["message"] = std::string("Model was unable to provide a valid evaluation due to an unknown error"); + res.set_content(response_body.dump(), "application/json"); + res.status = 500; + return; + } if (model_lock.owns_lock()) { model_lock.unlock(); // for safety, although should unlock after request finished @@ -521,7 +546,32 @@ namespace umbridge { if (!enable_parallel) { model_lock.lock(); } - std::vector gradient = model.Gradient(outWrt, inWrt, inputs, sens, config_json); + std::vector gradient; + try{ + gradient = model.Gradient(outWrt, inWrt, inputs, sens, config_json); + } + catch(const std::exception& e){ + + std::cerr << "Exception caught: " << e.what() << std::endl; + + json response_body; + response_body["error"]["type"] = "InvalidGradient"; + response_body["error"]["message"] = std::string("Model was unable to provide a valid gradient due to ") + e.what(); + res.set_content(response_body.dump(), "application/json"); + res.status = 500; + return; + } + catch (...) { + + std::cerr << "Caught an unknown error during the evaluation of gradient." << std::endl; + + json response_body; + response_body["error"]["type"] = "InvalidGradient"; + response_body["error"]["message"] = std::string("Model was unable to provide a valid gradient due to an unknown error"); + res.set_content(response_body.dump(), "application/json"); + res.status = 500; + return; + } if (model_lock.owns_lock()) { model_lock.unlock(); // for safety, although should unlock after request finished @@ -570,7 +620,32 @@ namespace umbridge { if (!enable_parallel) { model_lock.lock(); } - std::vector jacobian_action = model.ApplyJacobian(outWrt, inWrt, inputs, vec, config_json); + std::vector jacobian_action; + try{ + jacobian_action = model.ApplyJacobian(outWrt, inWrt, inputs, vec, config_json); + } + catch(const std::exception& e){ + + std::cerr << "Exception caught: " << e.what() << std::endl; + + json response_body; + response_body["error"]["type"] = "InvalidJacobian"; + response_body["error"]["message"] = std::string("Model was unable to provide a valid jacobian due to ") + e.what(); + res.set_content(response_body.dump(), "application/json"); + res.status = 500; + return; + } + catch (...) { + + std::cerr << "Caught an unknown error during the evaluation of jacobian." << std::endl; + + json response_body; + response_body["error"]["type"] = "InvalidJacobian"; + response_body["error"]["message"] = std::string("Model was unable to provide a valid jacobian due to an unknown error"); + res.set_content(response_body.dump(), "application/json"); + res.status = 500; + return; + } if (model_lock.owns_lock()) { model_lock.unlock(); // for safety, although should unlock after request finished @@ -623,7 +698,32 @@ namespace umbridge { if (!enable_parallel) { model_lock.lock(); } - std::vector hessian_action = model.ApplyHessian(outWrt, inWrt1, inWrt2, inputs, sens, vec, config_json); + std::vector hessian_action; + try{ + hessian_action = model.ApplyHessian(outWrt, inWrt1, inWrt2, inputs, sens, vec, config_json); + } + catch(const std::exception& e){ + + std::cerr << "Exception caught: " << e.what() << std::endl; + + json response_body; + response_body["error"]["type"] = "InvalidHessian"; + response_body["error"]["message"] = std::string("Model was unable to provide a valid hessian due to ") + e.what(); + res.set_content(response_body.dump(), "application/json"); + res.status = 500; + return; + } + catch (...) { + + std::cerr << "Caught an unknown error during the evaluation of hessian." << std::endl; + + json response_body; + response_body["error"]["type"] = "InvalidHessian"; + response_body["error"]["message"] = std::string("Model was unable to provide a valid hessian due to an unknown error"); + res.set_content(response_body.dump(), "application/json"); + res.status = 500; + return; + } if (model_lock.owns_lock()) { model_lock.unlock(); // for safety, although should unlock after request finished diff --git a/umbridge/um.py b/umbridge/um.py index ee52588..91d9a9a 100755 --- a/umbridge/um.py +++ b/umbridge/um.py @@ -206,9 +206,13 @@ async def evaluate(request): if len(parameters[i]) != input_sizes[i]: return error_response("InvalidInput", f"Input parameter {i} has invalid length! Expected {input_sizes[i]} but got {len(parameters[i])}.", 400) - output_future = model_executor.submit(model.__call__, parameters, config) - output = await asyncio.wrap_future(output_future) - + try: + output_future = model_executor.submit(model.__call__, parameters, config) + output = await asyncio.wrap_future(output_future) + except Exception as e: + print(traceback.format_exc()) + return error_response("InvalidEvaluation", str(traceback.format_exc()), 500) + # Check if output is a list of lists if not isinstance(output, list): return error_response("InvalidOutput", "Model output is not a list of lists!", 500) @@ -262,9 +266,13 @@ async def gradient(request): if len(sens) != output_sizes[out_wrt]: return error_response("InvalidInput", f"Sensitivity vector sens has invalid length! Expected {output_sizes[out_wrt]} but got {len(sens)}.", 400) - output_future = model_executor.submit(model.gradient, out_wrt, in_wrt, parameters, sens, config) - output = await asyncio.wrap_future(output_future) - + try: + output_future = model_executor.submit(model.gradient, out_wrt, in_wrt, parameters, sens, config) + output = await asyncio.wrap_future(output_future) + except Exception as e: + print(traceback.format_exc()) + return error_response("InvalidGradient", str(traceback.format_exc()), 500) + # Check if output is a list if not isinstance(output, list): return error_response("InvalidOutput", "Model output is not a list!", 500) @@ -313,8 +321,12 @@ async def applyjacobian(request): if len(vec) != input_sizes[in_wrt]: return error_response("InvalidInput", f"Vector vec has invalid length! Expected {input_sizes[in_wrt]} but got {len(vec)}.", 400) - output_future = model_executor.submit(model.apply_jacobian, out_wrt, in_wrt, parameters, vec, config) - output = await asyncio.wrap_future(output_future) + try: + output_future = model_executor.submit(model.apply_jacobian, out_wrt, in_wrt, parameters, vec, config) + output = await asyncio.wrap_future(output_future) + except Exception as e: + print(traceback.format_exc()) + return error_response("InvalidJacobian", str(traceback.format_exc()), 500) # Check if output is a list if not isinstance(output, list): @@ -366,9 +378,13 @@ async def applyhessian(request): if in_wrt2 < 0 or in_wrt2 >= len(input_sizes): return error_response("InvalidInput", "Invalid inWrt2 index! Expected between 0 and number of inputs minus one, but got " + str(in_wrt2), 400) - output_future = model_executor.submit(model.apply_hessian, out_wrt, in_wrt1, in_wrt2, parameters, sens, vec, config) - output = await asyncio.wrap_future(output_future) - + try: + output_future = model_executor.submit(model.apply_hessian, out_wrt, in_wrt1, in_wrt2, parameters, sens, vec, config) + output = await asyncio.wrap_future(output_future) + except Exception as e: + print(traceback.format_exc()) + return error_response("InvalidHessian", str(traceback.format_exc()), 500) + # Check if output is a list if not isinstance(output, list): return error_response("InvalidOutput", "Model output is not a list!", 500)