diff --git a/flatland/evaluators/aicrowd_helpers.py b/flatland/evaluators/aicrowd_helpers.py index 6e300a266b8fb3030b7ef81c6d1f9ebcf6c3a321..f368c4cc2eee848fc8277ea0df061780ef3187ae 100644 --- a/flatland/evaluators/aicrowd_helpers.py +++ b/flatland/evaluators/aicrowd_helpers.py @@ -7,13 +7,19 @@ import subprocess # Expected Env Variables ############################################################### # Default Values to be provided : +# AICROWD_IS_GRADING : true +# CROWDAI_IS_GRADING : true # S3_BUCKET : aicrowd-production # S3_UPLOAD_PATH_TEMPLATE : misc/flatland-rl-Media/{}.mp4 +# AWS_ACCESS_KEY_ID +# AWS_SECRET_ACCESS_KEY +# http_proxy +# https_proxy ############################################################### AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID", False) AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY", False) -S3_BUCKET = os.getenv("S3_BUCKET", False) -S3_UPLOAD_PATH_TEMPLATE = os.getenv("S3_UPLOAD_PATH_TEMPLATE", False) +S3_BUCKET = os.getenv("S3_BUCKET", "aicrowd-production") +S3_UPLOAD_PATH_TEMPLATE = os.getenv("S3_UPLOAD_PATH_TEMPLATE", "misc/flatland-rl-Media/{}.mp4") def get_boto_client(): @@ -26,6 +32,18 @@ def get_boto_client(): ) +def is_aws_configured(): + if not AWS_ACCESS_KEY_ID or not AWS_SECRET_ACCESS_KEY: + return False + else: + return True + + +def is_grading(): + return os.getenv("CROWDAI_IS_GRADING", False) or \ + os.getenv("AICROWD_IS_GRADING", False) + + def upload_to_s3(localpath): s3 = get_boto_client() if not S3_UPLOAD_PATH_TEMPLATE: @@ -89,10 +107,3 @@ def generate_movie_from_frames(frames_folder): return output_path, thumb_output_path - -def is_grading(): - return os.getenv("CROWDAI_IS_GRADING", False) or \ - os.getenv("AICROWD_IS_GRADING", False) - - - diff --git a/flatland/evaluators/service.py b/flatland/evaluators/service.py index 2853d84c16b9d8fcf1094945745020faf52aefac..235ab78b21be96635922927a9b4e607b122cc09f 100644 --- a/flatland/evaluators/service.py +++ b/flatland/evaluators/service.py @@ -15,12 +15,13 @@ import shutil import timeout_decorator import time import traceback +import crowdai_api m.patch() ######################################################## # CONSTANTS ######################################################## -PER_STEP_TIMEOUT = 5*60 # 5 minutes +PER_STEP_TIMEOUT = 10*60 # 5 minutes class FlatlandRemoteEvaluationService: @@ -77,6 +78,19 @@ class FlatlandRemoteEvaluationService: self.remote_db = remote_db self.remote_password = remote_password self.instantiate_redis_connection_pool() + + # AIcrowd evaluation specific vars + self.oracle_events = crowdai_api.events.CrowdAIEvents(with_oracle=True) + self.evaluation_state = { + "state": "PENDING", + "progress": 0.0, + "simulation_count": 0, + "total_simulation_count": len(self.env_file_paths), + "score": { + "score": 0.0, + "score_secondary": 0.0 + } + } # RailEnv specific variables self.env = False @@ -302,6 +316,20 @@ class FlatlandRemoteEvaluationService: _command_response['payload']['env_file_path'] = False self.send_response(_command_response, command) + ##################################################################### + # Update evaluation state + ##################################################################### + progress = np.clip( + self.simulation_count * 1.0 / len(self.env_file_paths), + 0, 1) + mean_reward = np.mean(self.simulation_rewards) + mean_percentage_complete = np.mean(self.simulation_percentage_complete) + self.evaluation_state["state"] = "IN_PROGRESS" + self.evaluation_state["progress"] = progress + self.evaluation_state["simulation_count"] = self.simulation_count + self.evaluation_state["score"]["score"] = mean_percentage_complete + self.evaluation_state["score"]["score_secondary"] = mean_reward + self.handle_aicrowd_info_event(self.evaluation_state) def handle_env_step(self, command): """ @@ -379,19 +407,33 @@ class FlatlandRemoteEvaluationService: mean_reward = np.mean(self.simulation_rewards) mean_percentage_complete = np.mean(self.simulation_percentage_complete) - # Generate the video - # - # Note, if you had depdency issues due to ffmpeg, you can - # install it by : - # - # conda install -c conda-forge x264 ffmpeg - - print("Generating Video from thumbnails...") - video_output_path, video_thumb_output_path = \ - aicrowd_helpers.generate_movie_from_frames( - self.vizualization_folder_name - ) - print("Videos : ", video_output_path, video_thumb_output_path) + if self.visualize: + # Generate the video + # + # Note, if you had depdency issues due to ffmpeg, you can + # install it by : + # + # conda install -c conda-forge x264 ffmpeg + + print("Generating Video from thumbnails...") + video_output_path, video_thumb_output_path = \ + aicrowd_helpers.generate_movie_from_frames( + self.vizualization_folder_name + ) + print("Videos : ", video_output_path, video_thumb_output_path) + # Upload to S3 if configuration is available + if aicrowd_helpers.is_grading() and aicrowd_helpers.is_aws_configured() and self.visualize: + video_s3_key = aicrowd_helpers.upload_to_s3( + video_output_path + ) + video_thumb_s3_key = aicrowd_helpers.upload_to_s3( + video_thumb_output_path + ) + self.evaluation_state["score"]["media_content_type"] = "video/mp4" + self.evaluation_state["score"]["media_large"] = video_s3_key + self.evaluation_state["score"]["media_thumbnail"] = video_thumb_s3_key + else: + print("[WARNING] Ignoring uploading of video to S3") _command_response = {} _command_response['type'] = messages.FLATLAND_RL.ENV_SUBMIT_RESPONSE @@ -400,7 +442,17 @@ class FlatlandRemoteEvaluationService: _payload['mean_percentage_complete'] = mean_percentage_complete _command_response['payload'] = _payload self.send_response(_command_response, command) - + + ##################################################################### + # Update evaluation state + ##################################################################### + self.evaluation_state["state"] = "FINISHED" + self.evaluation_state["progress"] = 1.0 + self.evaluation_state["simulation_count"] = self.simulation_count + self.evaluation_state["score"]["score"] = mean_percentage_complete + self.evaluation_state["score"]["score_secondary"] = mean_reward + self.handle_aicrowd_success_event(self.evaluation_state) + def report_error(self, error_message, command_response_channel): """ A helper function used to report error back to the client @@ -416,6 +468,27 @@ class FlatlandRemoteEvaluationService: default=m.encode, use_bin_type=True) ) + self.evaluation_state["state"] = "ERROR" + self.evaluation_state["error"] = error_message + self.handle_aicrowd_error_event(self.evaluation_state) + + def handle_aicrowd_info_event(self, payload): + self.oracle_events.register_event( + event_type=self.oracle_events.CROWDAI_EVENT_INFO, + payload=payload + ) + + def handle_aicrowd_success_event(self, payload): + self.oracle_events.register_event( + event_type=self.oracle_events.CROWDAI_EVENT_SUCCESS, + payload=payload + ) + + def handle_aicrowd_error_event(self, payload): + self.oracle_events.register_event( + event_type=self.oracle_events.CROWDAI_EVENT_ERROR, + payload=payload + ) def run(self): """