-
Notifications
You must be signed in to change notification settings - Fork 123
SIM RFC: AI selector backend #3569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SIM RFC: AI selector backend #3569
Conversation
| file_path = os.path.join(AISelectorConstants.AI_FOLDER, selected_ai) | ||
| # Default to our full system if it is selected or the selected binary doesn't exist | ||
| if selected_ai == AISelectorConstants.FULLSYSTEM_DISPLAY_NAME or not os.path.isfile(file_path): | ||
| return AISelectorConstants.FULLSYSTEM_PATH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to log some flag to indicate that our AI is being used instead of the specified one? It may not always be immediately clear if we are using the correct AI, and we should want to know when we have failed to specify the correct one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense imo. Do you think we should only do this when we read/load the AI in, or when we write as well? I was thinking there's not really any point to do it when we write to the TOML, but I'm not sure.
Also, I'm using the logging module for this, would like to clarify if that's right?
|
|
||
| # Return a dictionary of colour to the path string | ||
| saved_ais = { | ||
| "Blue": saved_blue, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or here we directly use AISelectorConstants.X_TOML_FIELD as keys
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(wait sorry i'll reply to the other comments in a bit, ty for catching all these) yeah that makes a lot of sense, code would be a lot cleaner too. i'll keep it as a dictionary and do this
(oh lmao didn't see the comment under this, nvm i'll do that instead)
| else: | ||
| # Remove all white space and return | ||
| #TODO not sure if that is necessary, but probably doesn't hurt? | ||
| return "".join(file_path.split()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can remove only leading and trailing whitespaces by using .split(), just to prevent the whitespaces in the path from being removed.
I don't think this is necessary, because we generated the path in the code by combining AI_FOLDER and filename. However I think its good to be more defensive and leave it in. So if somebody edits the TOML file and leaves a white space we can catch it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what I was thinking too, ty. I'll just remove leading and trailing whitespaces for now
| "Yellow": saved_yellow | ||
| } | ||
|
|
||
| #TODO not sure if this should be a dictionary or something like a tuple |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A dictionary works. I think the code will be more clean and safe if we use a new data class (say AIConfig) with two fields instead of a dictionary, and we pass the object. This also allows us to save configs more easily (if we need to in the future).
|
|
||
| AI_FOLDER = "/opt/tbotspython/external_ai" | ||
| CONFIG_FILE_PATH = AI_FOLDER + "/ai_config.toml" | ||
| FULLSYSTEM_DISPLAY_NAME = "Default Fullsystem" #TODO is there a better name? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine
| AI_FOLDER = "/opt/tbotspython/external_ai" | ||
| CONFIG_FILE_PATH = AI_FOLDER + "/ai_config.toml" | ||
| FULLSYSTEM_DISPLAY_NAME = "Default Fullsystem" #TODO is there a better name? | ||
| FULLSYSTEM_PATH = "software/unix_full_system" #TODO is this right? Should I use absolute path? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure. For my part software/unix_full_sytem works but I think its more safe to have an absolute path. I'm not sure how to do it for bazel though so perhaps someone else can answer this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ig the main reason for the selector is to initialize thunderscope_main so if it works for you, i think it should work? i'll keep it for now
|
left some comments |
|
Also the autoref game test is failing because you will need to add ai_selector.py to the as a dependency to the thunderscope_main.py build target |
nycrat
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey Adrian, I left like a bunch of nits, but one main thing is that we are using Runtime instead of AI, so you should rename some of the functions and variables accordingly.
Also there is an issue in the RuntimeLoader file where cached_runtimes is being used incorrectly.
Other than that, it generally looks good
src/software/thunderscope/binary_context_managers/runtime_manager.py
Outdated
Show resolved
Hide resolved
src/software/thunderscope/binary_context_managers/runtime_loader.py
Outdated
Show resolved
Hide resolved
src/software/thunderscope/binary_context_managers/runtime_loader.py
Outdated
Show resolved
Hide resolved
| # Display logging message when using default FullSystem | ||
| if config.chosen_blue_name == RuntimeManagerConstants.RUNTIME_CONFIG_PATH: | ||
| logging.info("TBots FullSystem selected for blue side.") | ||
| if config.chosen_yellow_name == RuntimeManagerConstants.RUNTIME_CONFIG_PATH: | ||
| logging.info("TBots FullSystem selected for yellow side.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I don't think this logging is necessary, would like to hear from others
| file.write(selected_ais) | ||
| except (PermissionError, NotADirectoryError): | ||
| logging.error("Could not access the configuration file.") | ||
| pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Get rid of pass, its only used in Python as a placeholder
| def _create_runtime_config(self) -> None: | ||
| """Creates the runtime configuration file on disk and throws an error upon failure.""" | ||
| # TODO Not sure if this function really has an use, since python open() creates a new file by default if it | ||
| # doesn't exist | ||
| pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, I think this can just be deleted
| selected_ais = ( | ||
| f'{RuntimeManagerConstants.RUNTIME_CONFIG_BLUE_KEY} = "{blue_path}"\n' | ||
| f'{RuntimeManagerConstants.RUNTIME_CONFIG_YELLOW_KEY} = "{yellow_path}"\n' | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Is there a function in the toml library that serializes a dict so that we don't need to use fstrings to manually do it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tomllib is only used for reading, and I couldn't find a easier module that supported writing (I think most of the options were third party software and I didn't really want to do that).
| logging.info("TBots FullSystem selected for yellow side.") | ||
|
|
||
| # Cache runtimes | ||
| self.cached_runtimes = config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE: this cached_runtimes is being used in two different ways which causes an error. There should be a separate cached_runtimes and cached_config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yikes not sure what I was thinking there lmao, tysm
nycrat
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functionality seems good 👍
And I know this isn't a part of this PR, but I would just note that there is a "Current Commit" and "localhost" option in the UI which both represent the default unix_full_system binary. I think the "Current Commit" option which is added in gl_gamecontroller_toolbar.py should be taken out.
| ) | ||
|
|
||
| # Check if paths are valid runtimes | ||
| if not self._is_valid_runtime(config.chosen_blue_path): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, I think it makes sense here, and also log the selected binary that couldn't be found
src/software/thunderscope/binary_context_managers/runtime_loader.py
Outdated
Show resolved
Hide resolved
| if os.path.isfile(runtime_path) and os.access(runtime_path, os.X_OK): | ||
| return True | ||
| return False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can just return the expression in the if statement since it evaluates to a boolean anyways
environment_setup/setup_software.sh
Outdated
| sudo touch /opt/tbotspython/external_runtimes/runtime_config.toml | ||
| sudo chown -R $USER:$USER /opt/tbotspython/external_runtimes/ | ||
|
|
||
| sudo chmod 600 /opt/tbotspython/external_runtimes/runtime_config.toml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we just make this file dynamically and give perms for the entire folder? Is this a good idea @Lmh-java @sauravbanna ? I'm not that knowledgeable on Linux perms
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah not sure if this line is necessary, the toml library will probably make the file if not exists anyway upon first write.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh on an related note, would either of you happen to know if making the toml file without sudo chmod will make it non-executable? I couldn't find any good resources, though a week ago I did (manually) make a external runtime folder in opt/tbotspython to test it out and iirc it was executable (though I don't think this test reflects the setup script in tbots). (I was thinking of making it non-executable so I could filter it out when fetching the list of runtimes)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have limited context, but
When you touch to create a file, it creates a file with permission 644 and the owner being the current user (in this case sudo).
Line 149 transfers the ownership of the file to the current user ($USER). So now it is 644 under the current user. 644 means the file owner has read and write access and other users will have read access.
Line 151 makes the file permission mask to be 600, which get rids of the access of other users, but the current user can still read and write. Therefore, line 151 might not be needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Iirc, if you give the permission to the entire folder and make the folder owned by the current user, then files created in that folder later will have no problems. But I think you might need more experiments on that. I am only 70% sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense ty, got rid of the stuff in setupsoftwaresh then
environment_setup/setup_software.sh
Outdated
| sudo touch /opt/tbotspython/external_runtimes/runtime_config.toml | ||
| sudo chown -R $USER:$USER /opt/tbotspython/external_runtimes/ | ||
|
|
||
| sudo chmod 600 /opt/tbotspython/external_runtimes/runtime_config.toml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah not sure if this line is necessary, the toml library will probably make the file if not exists anyway upon first write.
| RuntimeManagerConstants.RUNTIME_CONFIG_BLUE_KEY | ||
| in selected_runtime_dict.keys() | ||
| ): | ||
| config.chosen_blue_path = selected_runtime_dict[ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we start with the default blue/yellow fullsystem paths anyway in the RuntimeConfig() object, why not just check self._is_valid_runtime here itself? so we only update the runtime path if it exists + is a valid runtime, avoiding setting the config paths back to default in lines 109-112
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes a lot of sense, I'll do that ty
| except (FileNotFoundError, PermissionError, NotADirectoryError): | ||
| logging.warning( | ||
| f"Folder for external runtimes {RuntimeManagerConstants.EXTERNAL_RUNTIMES_PATH} could not be accessed." | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't log this, instead, we should check if the dir exists, and then create it if its missing. This is shared functionality, refer to #3575 for implementation in the superclass
…time_manager.py to make directory)
|
Changes done in latest commits (hopefully this helps with review a bit):
tysm Eric for helping me a lot! |
7e5ba76 to
e5abbd7
Compare
nycrat
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Description
Testing Done
Resolved Issues
resolves #3557
Length Justification and Key Files to Review
Review Checklist
It is the reviewers responsibility to also make sure every item here has been covered
.hfile) should have a javadoc style comment at the start of them. For examples, see the functions defined inthunderbots/software/geom. Similarly, all classes should have an associated Javadoc comment explaining the purpose of the class.TODO(or similar) statements should either be completed or associated with a github issue