-
Notifications
You must be signed in to change notification settings - Fork 250
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
Make ObjectSpec hashable if an arg value is a list #1771
Conversation
When tags is passed as args parameter into any Scenario object. It fails to to create hash because of List object. Issue : stanford-crfm#1768
Couple of questions:
|
Another request - could you use an if-else branch instead of a ternary expression, for readability? |
I have created MyGenericScenario class with tags as a list. I see there is another class GrammerScenario which takes tags as comma separated string and split them as list inside the class init(). Actually tags are list data only.
Here is the run_specs.py changes (note the tags here):
Because ScenarioSpec takes ObjectSpec as arguement, it fails for list object. I guess the best fix would be: Let me know your thoughts on it.
|
If this looks more generic, I will commit the changes with if-else branches |
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.
Thank you for the clarification. This looks like a reasonable use case.
I have two requests for changes, and then we can merge the code after they are addressed.
Hi @bidyapati-p are you still working on this? Otherwise, I will make the requested corrections to this PR and merge it. |
src/helm/common/object_spec.py
Outdated
return hash((self.class_name, tuple((k, self.args[k]) for k in sorted(self.args.keys())))) | ||
t = tuple() | ||
for k in sorted(self.args.keys()): | ||
t = t + ((k, tuple(self.args[k])),) |
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.
Unfortunately this now breaks on non-list values because tuple(self.args[k])
doesn't work if self.args[k]
is not a list:
from helm.common.object_spec import ObjectSpec
o = ObjectSpec("myclass", {"myarg": 42})
hash(o)
Error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/yifanmai/oss/helm/src/helm/common/object_spec.py", line 18, in __hash__
t = t + ((k, tuple(self.args[k])),)
TypeError: 'int' object is not iterable
Could we do something like this instead?
def __hash__(self):
def get_arg_value(key: str) -> Any:
value = self.args[key]
# lists are not hashable, so convert them to tuples
if isinstance(value, list):
return tuple(value)
return value
args_tuple = tuple((k, get_arg_value(k)) for k in sorted(self.args.keys()))
return hash((self.class_name, args_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.
My bad, I should run few test.
The new code you suggest is again specific to List and premitive data type, which is good enough for our usecase, which will either have list of strings or a single string.
It works in these 2 datatype, however, it fails for dict.
o = ObjectSpec("myclass", {"myarg": {"a":1}})
hash(o)
Do you think this could have been a better solution for other data types as well for future proof? I was suggesting the same earlier too.
from typing import Hashable
def __hash__(self):
def get_arg_value(key: str) -> Any:
value = self.args[key]
# convert all the non-hashable objects into string
if not isinstance(value, Hashable):
return value.__str__()
return value
args_tuple = tuple((k, get_arg_value(k)) for k in sorted(self.args.keys()))
return hash((self.class_name, args_tuple))
tested with int, string, list, dict
still fails for : |
Test cases: o = ObjectSpec("myclass", {"myarg": 10}) o = ObjectSpec("myclass", {"myarg": [10, 20, 30]}) o = ObjectSpec("myclass", {"myarg": {"aa": [1,2,3]}}) o = ObjectSpec("myclass", {"myarg": {"aa": {"bb":[1,2,3]}}}) o = ObjectSpec("myclass", {"myarg": [1,2,3,[4,5,6,[7,8,9]]]}) |
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.
Looks good, thanks again!
When tags is passed as args parameter into any Scenario object. It fails to to create hash because of List object.
Fixes #1768