<@U06RKAMK0UC> I have the following workflow: ```@...
# ask-ai
s
@ancient-wolf-19325 I have the following workflow:
Copy code
@workflow()
def pipeline(feature: Literal["outcome", "score"]) -> None:
    """Run the whole pipeline for training and evaluating the model. `feature` is only allowed to be `outcome` or `score`."""
    if feature == "outcome":
            training_config = training_config_outcome
    elif feature == "score":
            training_config = training_config_score
    else:
        raise ValueError(f"Invalid feature: {feature}")
Since Flyte gives me an error here because "ValueError: Cannot perform truth value testing, This is a limitation in python." I changed the code in a way to access a dictionary instead:
Copy code
training_configs = {
    "outcome": training_config_outcome,
    "score": training_config_score,
}

@workflow()
def pipeline(feature: Literal["outcome", "score"]) -> None:
    """Run the whole pipeline for training and evaluating the model. `feature` is only allowed to be `outcome` or `score`."""
    training_config = training_configs[feature]
But now the error is just
KeyError: Promise(node:.feature.[])
. Why could that be the case and how do I fix it?
j
It seems likely that the issue arises because Flyte workflows use promises, which are placeholders for values that are not yet computed. When you try to access
training_configs[feature]
,
feature
is a promise, not a direct value, leading to a
KeyError
. In Flyte, you cannot directly use promises in dictionary lookups or conditionals as you would with regular Python values. To resolve this, you can use Flyte's conditional constructs to handle the logic. Here's an example of how you might modify your workflow:
Copy code
from flytekit import conditional, workflow

@workflow
def pipeline(feature: str) -> None:
    training_config = conditional("choose_training_config") \
        .if_(feature == "outcome").then(training_config_outcome) \
        .else_().then(training_config_score)
This approach uses Flyte's
conditional
construct to select the appropriate
training_config
based on the value of
feature
. Would you like more detail on how to implement this or any other aspect of Flyte workflows? Sources: - https://github.com/flyteorg/flyte/issues/5473 - https://docs.flyte.org/en/latest/user_guide/flyte_fundamentals/tasks_workflows_and_launch_plans.html#workflows-versus-tasks-under-the-hood 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.
s
@ancient-wolf-19325 I created a separate task that gets the training_config now. I have another issue now: The input
feature
in my code is a string (of type
Literal
) which is also supposed to be used as directory for a posix path:
Copy code
@workflow()
def pipeline(feature: Literal["outcome", "score"]) -> None:
    """Run the whole pipeline for training and evaluating the model. `feature` is only allowed to be `outcome` or `score`."""
    training_config = get_training_config(feature)
    output_directory = Path(ROOT_DIR) / "data" / feature / fl.current_context().execution_date.strftime("%Y-%m-%d--%H-%M-%S")
But I get the following error:
TypeError: unsupported operand type(s) for /: 'PosixPath' and 'Promise'
How do I fix this?
j
The error occurs because
feature
is a promise, not a direct string value, and you cannot use promises directly in operations like path concatenation. To resolve this, you need to evaluate the promise before using it in the path construction. You can achieve this by using a task to handle the path construction. Here's an example:
Copy code
from flytekit import task, workflow
from pathlib import Path

@task
def construct_output_directory(feature: str, root_dir: str, execution_date: str) -> str:
    return str(Path(root_dir) / "data" / feature / execution_date)

@workflow
def pipeline(feature: str) -> None:
    training_config = get_training_config(feature)
    execution_date = fl.current_context().execution_date.strftime("%Y-%m-%d--%H-%M-%S")
    output_directory = construct_output_directory(feature=feature, root_dir=ROOT_DIR, execution_date=execution_date)
This approach uses a task to construct the path, ensuring that the promise is resolved before the path operation. Would you like more detail on this solution or any other aspect of Flyte workflows? Sources: - https://docs.flyte.org/en/latest/user_guide/flyte_fundamentals/tasks_workflows_and_launch_plans.html#workflows-versus-tasks-under-the-hood 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.