-
Notifications
You must be signed in to change notification settings - Fork 173
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
Save output model to output_dir #1430
base: main
Are you sure you want to change the base?
Changes from all commits
9af78ca
7a25bdc
25a255a
ac96d58
a5627bb
cb7ae1e
9007c08
9b0fdb0
17b1121
0c8d07e
be8af11
cd59774
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -14,7 +14,14 @@ | |||
|
||||
from olive.cli.constants import CONDA_CONFIG | ||||
from olive.common.user_module_loader import UserModuleLoader | ||||
from olive.common.utils import hardlink_copy_dir, hash_dict, hf_repo_exists, set_nested_dict_value, unescaped_str | ||||
from olive.common.utils import ( | ||||
hardlink_copy_dir, | ||||
hardlink_copy_file, | ||||
hash_dict, | ||||
hf_repo_exists, | ||||
set_nested_dict_value, | ||||
unescaped_str, | ||||
) | ||||
from olive.hardware.accelerator import AcceleratorSpec | ||||
from olive.hardware.constants import DEVICE_TO_EXECUTION_PROVIDERS | ||||
from olive.resource_path import OLIVE_RESOURCE_ANNOTATIONS, find_all_resources | ||||
|
@@ -416,36 +423,33 @@ def save_output_model(config: Dict, output_model_dir: Union[str, Path]): | |||
|
||||
This assumes a single accelerator workflow. | ||||
""" | ||||
run_output_path = Path(config["output_dir"]) / "output_model" | ||||
if not any(run_output_path.rglob("model_config.json")): | ||||
# there must be an run_output_path with at least one model_config.json | ||||
run_output_path = Path(config["output_dir"]) | ||||
model_config_path = run_output_path / "model_config.json" | ||||
if not model_config_path.exists(): | ||||
print("Command failed. Please set the log_level to 1 for more detailed logs.") | ||||
return | ||||
|
||||
output_model_dir = Path(output_model_dir).resolve() | ||||
|
||||
# hardlink/copy the output model to the output_model_dir | ||||
hardlink_copy_dir(run_output_path, output_model_dir) | ||||
|
||||
# need to update the local path in the model_config.json | ||||
# should the path be relative or absolute? relative makes it easy to move the output | ||||
# around but the path needs to be updated when the model config is used | ||||
for model_config_file in output_model_dir.rglob("model_config.json"): | ||||
with model_config_file.open("r") as f: | ||||
model_config = json.load(f) | ||||
|
||||
all_resources = find_all_resources(model_config) | ||||
for resource_key, resource_path in all_resources.items(): | ||||
resource_path_str = resource_path.get_path() | ||||
if resource_path_str.startswith(str(run_output_path)): | ||||
set_nested_dict_value( | ||||
model_config, | ||||
resource_key, | ||||
resource_path_str.replace(str(run_output_path), str(output_model_dir)), | ||||
) | ||||
|
||||
with model_config_file.open("w") as f: | ||||
json.dump(model_config, f, indent=4) | ||||
with model_config_path.open("r") as f: | ||||
model_config = json.load(f) | ||||
|
||||
all_resources = find_all_resources(model_config) | ||||
for resource_key, resource_path in all_resources.items(): | ||||
src_path = Path(resource_path.get_path()).resolve() | ||||
if src_path.is_dir(): | ||||
hardlink_copy_dir(src_path, output_model_dir / src_path) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this is correct. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah true! I forgot to update this! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please also check how the outputs for a graph capture for with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Like I described in the previous comment, I think it will be easier to just make saving the footprint, etc opt-in in the workflow config. that way, even for cli, we can just use the final output dir and not need to do any of this copy and path update. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My intention is copying additional files to output folder as they are also a part of the output model. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the additional files get copied twice in this. Once is as part of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are all additional files stored in the model path? I kinda remember it can be everywhere depending on the pass who created it. Was this logic updated before? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is stored in model path normally. some passes like modelbuilder with metadata saves it in a different folder but that was because we weren't sure if should copy/hardlink the existing model files. But both the pass carry forward https://github.com/microsoft/Olive/blob/main/olive/passes/olive_pass.py#L274 and cache model save have always saved in model_path Line 451 in 0db2d72
Since the output of a workflow goes through the cache model save, the additional files are already in model_path resources for onnx models. this is different for composite models where they are saved in output_dir. So i think it's less hacky to just save the cli output directly in |
||||
else: | ||||
hardlink_copy_file(src_path, output_model_dir) | ||||
|
||||
set_nested_dict_value( | ||||
model_config, | ||||
resource_key, | ||||
str(output_model_dir / src_path.name), | ||||
) | ||||
output_model_config_path = output_model_dir / "model_config.json" | ||||
with output_model_config_path.open("w") as f: | ||||
json.dump(model_config, f, indent=4) | ||||
|
||||
print(f"Command succeeded. Output model saved to {output_model_dir}") | ||||
|
||||
|
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.
btw without this
output_model
nesting, now the output of the cli would also have the footprint and other files copied over even though they mean nothing to the user of the cli and is messy+confusing. I think we might need an option to disable saving these files like you mentioned once before.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 make it opt-in to save the extra files instead of opt-out. most users only care about the final output model.
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.
Good call! I don't think users need those files. We should only copy model files here.