-
Notifications
You must be signed in to change notification settings - Fork 671
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
[BUG] Union types fail for e.g. two different dataclasses #5489
Comments
The issue arises because Flyte's backend cannot unambiguously select a variant from the union type when validating the workflow. This is due to the Would you like more detailed steps on how to address this issue or further explanation on the underlying mechanics? Sources: This is an AI-generated response and your feedback is appreciated! Please leave a 👍 if this is helpful and 👎 if it is not. Mention @RunLLM to ask follow-up questions. See runllm.com for more! |
@RunLLM Can I work on this issue ? |
The issue arises because Flyte's backend cannot unambiguously select a variant from the union type when validating the workflow. This is due to the Would you like more detailed steps on how to address this issue or further explanation on the underlying mechanics? Sources: This is an AI-generated response and your feedback is appreciated! Please leave a 👍 if this is helpful and 👎 if it is not. Mention @RunLLM to ask follow-up questions. See runllm.com for more! |
We're in the process of revisiting the dataclass transformer and will include this in the process. A good point raised during today's contributor meeting is that simply adding the tags to the struct message is not enough as that would break inheritance. |
@fg91 {"dataclass_path": f"{python_type.__module__}.{python_type.__qualname__}} Thank you so much. |
This doesn't account for inheritance, correct? Or am I overlooking something? |
@fg91 We can use |
The hard part is that now |
from typing import Union
from dataclasses import dataclass
from flytekit import task, workflow
@dataclass
class A:
a: int
@dataclass
class B:
b: int
@dataclass
class C(B):
c: int
@task
def foo(inp: Union[A, B]):
print(inp)
@workflow
def wf():
foo(inp=C(b=1, c=1))
if __name__ == "__main__":
print(C.mro())
wf() Output: [<class '__main__.C'>, <class '__main__.B'>, <class 'object'>]
B(b=1) So yes, I agree, if we serialized the output of I'm thinking whether one further complication is that depending on whether a class is defined in the main module or imported, it might be called This problem exists regardless of whether we want to support inheritance or not, also when we just write the class itself into the tag. At the top of my head, I don't have a solution for this unfortunately, do you @Future-Outlier? In my opinion it is a must for us to solve the issue that the union checker can't distinguish between any two types that use protobuf struct as literal but I think it would be fair to exclude inheritance - if it makes our lives easier - as long as there is a comprehensible error returned by flyteadmin when registering. |
Thank you for the reply, I don't have a solution about this yet.
I will think about the alternatives. |
Isn't there a json schema that's published alongside dataclasses that we can rely on? can we push compat checking to that level? That is if you're checking to see if type X is compatible with type Y:
I don't like the idea of propeller's compiler checking python mro using string matches. That sounds incredibly error prone and replete with edge cases (changing file names, changing type name, root import location, probably missing more). |
Agree 👍 |
goal by @wild-endeavor # upstream
@dataclass
class A:
a: int
# downstream
@dataclass
class A:
a: int
b: Optional[int] This case should work. |
@Future-Outlier @wild-endeavor Agree with the the example with one small addition: I would be really nice if the solution wasn't tailor made for the dataclass type transformer but generalizable to every transformer that uses protobuf struct as transport. We defined internal type transformers that use structs and hence suffer from the same problem and it would be nice to be able to apply the same fix there 🙇 |
related to #5318 |
Since this fix by @wild-endeavor in flytekit, the minimal reproducing example from the issue description doesn't fail anymore. I don't understand why because I confirmed with a debugger that the However, this example still doesn't work: @dataclass_json
@dataclass
class A:
a: int
@dataclass_json
@dataclass
class B:
b: int
@task
def bar() -> A:
return A(a=1)
@task
def foo(inp: Union[A, B]):
print(inp)
@workflow
def wf():
v = bar()
foo(inp=v) |
My friend @mao3267 is investigating this, and I'll support him to push this happen. |
…yteorg#5489-dataclass-mismatch Signed-off-by: mao3267 <[email protected]>
….com/mao3267/flyte into fix/flyteorg#5489-dataclass-mismatch
Describe the bug
The workflow works when executing locally with
python wf.py
but fails to register with flyteadmin:Expected behavior
As a python developer using Flyte, I would expect this workflow to work.
Additional context to reproduce
The root cause for this error is the following:
When validating the workflow in the backend, here, the so-called
unionTypeChecker
checks whether one of the union variants (hereA
orB
) can unambiguously be chosen:For our example above,
AreTypesCastable(upstreamType, x)
yieldstrue
for both union variantsA
andB
which causes theunionTypeChecker
to fail.The reason that for both
A
andB
the checkAreTypesCastable(upstreamType, x)
results intrue
is the following:Here, the so-called
trivialChecker
which is called for both union variantsA
andB
compares whether the passed inputB
matches the respective variant:Since there are no tags that solve the ambiguity and all metadata is ignored, the final string comparison for both union variants
A
andB
is always"simple:STRUCT metadata:{} annotation:{} structure:{}" == "simple:STRUCT metadata:{} annotation:{} structure:{}"
meaning that we cannot determine whether the union variantA
orB
is the correct match for the passed valueB
.Screenshots
No response
Are you sure this issue hasn't been raised already?
Have you read the Code of Conduct?
The text was updated successfully, but these errors were encountered: