From e647fd299ea412cb62a7c71c6a9c06415bc3bf1a Mon Sep 17 00:00:00 2001 From: chenyzhang Date: Thu, 11 Apr 2024 14:44:45 +0800 Subject: [PATCH 1/5] support both yaml and yml postfix --- .../promptflow/_utils/flow_utils.py | 19 +++++++++++++------ .../sdk_cli_test/e2etests/test_flow_test.py | 8 +++++++- .../tests/sdk_cli_test/unittests/test_flow.py | 8 +++++++- .../entry.py | 0 .../flow.flex.yaml | 0 .../multiple_flex_yaml/flow.flex.yml | 1 + .../mutiple_flow_yaml/flow.dag.yaml | 16 ---------------- .../mutiple_flow_yaml/hello_world.py | 6 ------ .../eager_flows/simple_with_yml/entry.py | 7 +++++++ .../eager_flows/simple_with_yml/flow.flex.yml | 1 + 10 files changed, 36 insertions(+), 30 deletions(-) rename src/promptflow/tests/test_configs/eager_flows/{mutiple_flow_yaml => multiple_flex_yaml}/entry.py (100%) rename src/promptflow/tests/test_configs/eager_flows/{mutiple_flow_yaml => multiple_flex_yaml}/flow.flex.yaml (100%) create mode 100644 src/promptflow/tests/test_configs/eager_flows/multiple_flex_yaml/flow.flex.yml delete mode 100644 src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/flow.dag.yaml delete mode 100644 src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/hello_world.py create mode 100644 src/promptflow/tests/test_configs/eager_flows/simple_with_yml/entry.py create mode 100644 src/promptflow/tests/test_configs/eager_flows/simple_with_yml/flow.flex.yml diff --git a/src/promptflow-core/promptflow/_utils/flow_utils.py b/src/promptflow-core/promptflow/_utils/flow_utils.py index bfa46cf0706..153f4385801 100644 --- a/src/promptflow-core/promptflow/_utils/flow_utils.py +++ b/src/promptflow-core/promptflow/_utils/flow_utils.py @@ -2,6 +2,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # --------------------------------------------------------- import hashlib +import itertools import json import os import re @@ -87,13 +88,19 @@ def resolve_flow_path( if flow_path.is_dir(): flow_folder = flow_path - dag_file_exist = (flow_folder / FLOW_DAG_YAML).is_file() - flex_file_exist = (flow_folder / FLOW_FLEX_YAML).is_file() - flow_file = FLOW_FLEX_YAML if flex_file_exist else FLOW_DAG_YAML - if dag_file_exist and flex_file_exist: + flow_file = FLOW_DAG_YAML + flow_file_num = 0 + for flow_name, suffix in itertools.product([FLOW_DAG_YAML, FLOW_FLEX_YAML], [".yaml", ".yml"]): + flow_file_name = flow_name.replace(".yaml", suffix) + if (flow_folder / flow_file_name).is_file(): + flow_file_num += 1 + flow_file = flow_file_name + + if flow_file_num > 1: raise ValidationException( - f"Both {FLOW_DAG_YAML} and {FLOW_FLEX_YAML} exist in {flow_path}. " - f"Please specify a file or remove the extra YAML.", + f"Both {FLOW_DAG_YAML}/{FLOW_DAG_YAML.replace('.yaml', '.yml')} " + f"and {FLOW_FLEX_YAML}/{FLOW_FLEX_YAML.replace('.yaml', '.yml')} exist in {flow_path}. " + f"Please specify a file or remove the extra YAML/YML.", privacy_info=[str(flow_path)], ) elif flow_path.is_file() or flow_path.suffix.lower() in FLOW_FILE_SUFFIX: diff --git a/src/promptflow/tests/sdk_cli_test/e2etests/test_flow_test.py b/src/promptflow/tests/sdk_cli_test/e2etests/test_flow_test.py index 0ac2ed10f7f..8e5c4ee071d 100644 --- a/src/promptflow/tests/sdk_cli_test/e2etests/test_flow_test.py +++ b/src/promptflow/tests/sdk_cli_test/e2etests/test_flow_test.py @@ -275,7 +275,13 @@ def test_eager_flow_test(self): def test_eager_flow_test_with_yaml(self): clear_module_cache("entry") - flow_path = Path(f"{EAGER_FLOWS_DIR}/simple_with_yaml/").absolute() + flow_path = Path(f"{EAGER_FLOWS_DIR}/simple_with_yml/").absolute() + result = _client._flows._test(flow=flow_path, inputs={"input_val": "val1"}) + assert result.run_info.status.value == "Completed" + + def test_eager_flow_test_with_yml(self): + clear_module_cache("entry") + flow_path = Path(f"{EAGER_FLOWS_DIR}/simple_with_yml/").absolute() result = _client._flows._test(flow=flow_path, inputs={"input_val": "val1"}) assert result.run_info.status.value == "Completed" diff --git a/src/promptflow/tests/sdk_cli_test/unittests/test_flow.py b/src/promptflow/tests/sdk_cli_test/unittests/test_flow.py index d9022df731b..2ca106513d8 100644 --- a/src/promptflow/tests/sdk_cli_test/unittests/test_flow.py +++ b/src/promptflow/tests/sdk_cli_test/unittests/test_flow.py @@ -71,7 +71,13 @@ def test_multiple_flow_load(self): with pytest.raises(ValidationException) as e: load_flow(EAGER_FLOWS_DIR / "multiple_flow_yaml") - assert "Both flow.dag.yaml and flow.flex.yaml exist in " in str(e.value) + assert "Both flow.dag.yaml/flow.dag.yml and flow.flex.yaml/flow.flex.yml exist in " in str(e.value) + + def test_multiple_flex_load(self): + with pytest.raises(ValidationException) as e: + load_flow(EAGER_FLOWS_DIR / "multiple_flex_yaml") + + assert "Both flow.dag.yaml/flow.dag.yml and flow.flex.yaml/flow.flex.yml exist in " in str(e.value) def test_specify_flow_load(self): load_flow(EAGER_FLOWS_DIR / "multiple_flow_yaml" / "flow.dag.yaml") diff --git a/src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/entry.py b/src/promptflow/tests/test_configs/eager_flows/multiple_flex_yaml/entry.py similarity index 100% rename from src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/entry.py rename to src/promptflow/tests/test_configs/eager_flows/multiple_flex_yaml/entry.py diff --git a/src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/flow.flex.yaml b/src/promptflow/tests/test_configs/eager_flows/multiple_flex_yaml/flow.flex.yaml similarity index 100% rename from src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/flow.flex.yaml rename to src/promptflow/tests/test_configs/eager_flows/multiple_flex_yaml/flow.flex.yaml diff --git a/src/promptflow/tests/test_configs/eager_flows/multiple_flex_yaml/flow.flex.yml b/src/promptflow/tests/test_configs/eager_flows/multiple_flex_yaml/flow.flex.yml new file mode 100644 index 00000000000..7f255e988c9 --- /dev/null +++ b/src/promptflow/tests/test_configs/eager_flows/multiple_flex_yaml/flow.flex.yml @@ -0,0 +1 @@ +entry: entry:my_flow \ No newline at end of file diff --git a/src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/flow.dag.yaml b/src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/flow.dag.yaml deleted file mode 100644 index 0d20088a874..00000000000 --- a/src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/flow.dag.yaml +++ /dev/null @@ -1,16 +0,0 @@ -inputs: - name: - type: string - default: hod -outputs: - result: - type: string - reference: ${hello_world.output} -nodes: -- name: hello_world - type: python - source: - type: code - path: hello_world.py - inputs: - name: ${inputs.name} diff --git a/src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/hello_world.py b/src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/hello_world.py deleted file mode 100644 index e0fa71d6796..00000000000 --- a/src/promptflow/tests/test_configs/eager_flows/mutiple_flow_yaml/hello_world.py +++ /dev/null @@ -1,6 +0,0 @@ -from promptflow import tool - - -@tool -def hello_world(name: str) -> str: - return f"Hello World {name}!" diff --git a/src/promptflow/tests/test_configs/eager_flows/simple_with_yml/entry.py b/src/promptflow/tests/test_configs/eager_flows/simple_with_yml/entry.py new file mode 100644 index 00000000000..7c62d1ce52b --- /dev/null +++ b/src/promptflow/tests/test_configs/eager_flows/simple_with_yml/entry.py @@ -0,0 +1,7 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +def my_flow(input_val: str = "gpt") -> str: + """Simple flow without yaml.""" + return f"Hello world! {input_val}" diff --git a/src/promptflow/tests/test_configs/eager_flows/simple_with_yml/flow.flex.yml b/src/promptflow/tests/test_configs/eager_flows/simple_with_yml/flow.flex.yml new file mode 100644 index 00000000000..7f255e988c9 --- /dev/null +++ b/src/promptflow/tests/test_configs/eager_flows/simple_with_yml/flow.flex.yml @@ -0,0 +1 @@ +entry: entry:my_flow \ No newline at end of file From 0bfe82a5271d71209e4db5d2696081617ee0f161 Mon Sep 17 00:00:00 2001 From: chenyzhang Date: Thu, 11 Apr 2024 15:13:05 +0800 Subject: [PATCH 2/5] support both yaml and yml postfix --- .../promptflow/_utils/flow_utils.py | 14 +++++++------- src/promptflow-devkit/promptflow/_cli/_pf/_run.py | 6 +++--- .../tests/sdk_cli_test/unittests/test_flow.py | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/promptflow-core/promptflow/_utils/flow_utils.py b/src/promptflow-core/promptflow/_utils/flow_utils.py index 153f4385801..1a798141573 100644 --- a/src/promptflow-core/promptflow/_utils/flow_utils.py +++ b/src/promptflow-core/promptflow/_utils/flow_utils.py @@ -89,18 +89,18 @@ def resolve_flow_path( if flow_path.is_dir(): flow_folder = flow_path flow_file = FLOW_DAG_YAML - flow_file_num = 0 + flow_file_list = [] for flow_name, suffix in itertools.product([FLOW_DAG_YAML, FLOW_FLEX_YAML], [".yaml", ".yml"]): flow_file_name = flow_name.replace(".yaml", suffix) if (flow_folder / flow_file_name).is_file(): - flow_file_num += 1 - flow_file = flow_file_name + flow_file_list.append(flow_file_name) - if flow_file_num > 1: + if len(flow_file_list) == 1: + flow_file = flow_file_list[0] + elif len(flow_file_list) > 1: raise ValidationException( - f"Both {FLOW_DAG_YAML}/{FLOW_DAG_YAML.replace('.yaml', '.yml')} " - f"and {FLOW_FLEX_YAML}/{FLOW_FLEX_YAML.replace('.yaml', '.yml')} exist in {flow_path}. " - f"Please specify a file or remove the extra YAML/YML.", + f"Multiple files {', '.join(flow_file_list)} exist in {flow_path}. " + f"Please specify a file or remove the extra YAML and YML.", privacy_info=[str(flow_path)], ) elif flow_path.is_file() or flow_path.suffix.lower() in FLOW_FILE_SUFFIX: diff --git a/src/promptflow-devkit/promptflow/_cli/_pf/_run.py b/src/promptflow-devkit/promptflow/_cli/_pf/_run.py index 700d681fa34..cf39d78256f 100644 --- a/src/promptflow-devkit/promptflow/_cli/_pf/_run.py +++ b/src/promptflow-devkit/promptflow/_cli/_pf/_run.py @@ -43,9 +43,9 @@ def add_run_parser(subparsers): - run_parser = subparsers.add_parser("run", - description="A CLI tool to manage runs for prompt flow.", - help="Manage runs.") + run_parser = subparsers.add_parser( + "run", description="A CLI tool to manage runs for prompt flow.", help="Manage runs." + ) subparsers = run_parser.add_subparsers() add_run_create(subparsers) # add_run_cancel(subparsers) diff --git a/src/promptflow/tests/sdk_cli_test/unittests/test_flow.py b/src/promptflow/tests/sdk_cli_test/unittests/test_flow.py index 2ca106513d8..a1bcaf1c0ba 100644 --- a/src/promptflow/tests/sdk_cli_test/unittests/test_flow.py +++ b/src/promptflow/tests/sdk_cli_test/unittests/test_flow.py @@ -71,13 +71,13 @@ def test_multiple_flow_load(self): with pytest.raises(ValidationException) as e: load_flow(EAGER_FLOWS_DIR / "multiple_flow_yaml") - assert "Both flow.dag.yaml/flow.dag.yml and flow.flex.yaml/flow.flex.yml exist in " in str(e.value) + assert "Multiple files flow.dag.yaml, flow.flex.yaml exist in " in str(e.value) def test_multiple_flex_load(self): with pytest.raises(ValidationException) as e: load_flow(EAGER_FLOWS_DIR / "multiple_flex_yaml") - assert "Both flow.dag.yaml/flow.dag.yml and flow.flex.yaml/flow.flex.yml exist in " in str(e.value) + assert "Multiple files flow.flex.yaml, flow.flex.yml exist in " in str(e.value) def test_specify_flow_load(self): load_flow(EAGER_FLOWS_DIR / "multiple_flow_yaml" / "flow.dag.yaml") From 2972850521023e628c913a025e77af29b698aeb0 Mon Sep 17 00:00:00 2001 From: chenyzhang Date: Thu, 11 Apr 2024 15:14:24 +0800 Subject: [PATCH 3/5] support both yaml and yml postfix --- src/promptflow-devkit/promptflow/_cli/_pf/_run.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/promptflow-devkit/promptflow/_cli/_pf/_run.py b/src/promptflow-devkit/promptflow/_cli/_pf/_run.py index cf39d78256f..700d681fa34 100644 --- a/src/promptflow-devkit/promptflow/_cli/_pf/_run.py +++ b/src/promptflow-devkit/promptflow/_cli/_pf/_run.py @@ -43,9 +43,9 @@ def add_run_parser(subparsers): - run_parser = subparsers.add_parser( - "run", description="A CLI tool to manage runs for prompt flow.", help="Manage runs." - ) + run_parser = subparsers.add_parser("run", + description="A CLI tool to manage runs for prompt flow.", + help="Manage runs.") subparsers = run_parser.add_subparsers() add_run_create(subparsers) # add_run_cancel(subparsers) From 3ac730021e173e5254f33bfcd358d5cd53fab827 Mon Sep 17 00:00:00 2001 From: chenyzhang Date: Thu, 11 Apr 2024 16:25:51 +0800 Subject: [PATCH 4/5] update test --- src/promptflow/tests/sdk_cli_test/e2etests/test_flow_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/promptflow/tests/sdk_cli_test/e2etests/test_flow_test.py b/src/promptflow/tests/sdk_cli_test/e2etests/test_flow_test.py index 8e5c4ee071d..4f0e0f0d837 100644 --- a/src/promptflow/tests/sdk_cli_test/e2etests/test_flow_test.py +++ b/src/promptflow/tests/sdk_cli_test/e2etests/test_flow_test.py @@ -275,7 +275,7 @@ def test_eager_flow_test(self): def test_eager_flow_test_with_yaml(self): clear_module_cache("entry") - flow_path = Path(f"{EAGER_FLOWS_DIR}/simple_with_yml/").absolute() + flow_path = Path(f"{EAGER_FLOWS_DIR}/simple_with_yaml/").absolute() result = _client._flows._test(flow=flow_path, inputs={"input_val": "val1"}) assert result.run_info.status.value == "Completed" From 815a5c18009939ba538ca950ab70a060a1f4aa7f Mon Sep 17 00:00:00 2001 From: chenyzhang Date: Thu, 11 Apr 2024 17:51:15 +0800 Subject: [PATCH 5/5] update code --- src/promptflow-core/promptflow/_utils/flow_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/promptflow-core/promptflow/_utils/flow_utils.py b/src/promptflow-core/promptflow/_utils/flow_utils.py index 1a798141573..1e9506852e6 100644 --- a/src/promptflow-core/promptflow/_utils/flow_utils.py +++ b/src/promptflow-core/promptflow/_utils/flow_utils.py @@ -100,7 +100,7 @@ def resolve_flow_path( elif len(flow_file_list) > 1: raise ValidationException( f"Multiple files {', '.join(flow_file_list)} exist in {flow_path}. " - f"Please specify a file or remove the extra YAML and YML.", + f"Please specify a file or remove the extra YAML file.", privacy_info=[str(flow_path)], ) elif flow_path.is_file() or flow_path.suffix.lower() in FLOW_FILE_SUFFIX: