From f3df018fae44618bd42acbe25881be06eae6bdd9 Mon Sep 17 00:00:00 2001 From: Honglin Date: Wed, 6 Dec 2023 15:26:18 +0800 Subject: [PATCH 1/8] [SDK/CLI] Remove experiment name for remote flow run case (#1392) # Description No longer need to send experiment name when creating azure run with remote flow, it was a workaround when server side required this parameter, but now it's optional. # All Promptflow Contribution checklist: - [ ] **The pull request does not introduce [breaking changes].** - [ ] **CHANGELOG is updated for new features, bug fixes or other significant changes.** - [ ] **I have read the [contribution guidelines](../CONTRIBUTING.md).** - [ ] **Create an issue and link to the pull request to get dedicated review from promptflow team. Learn more: [suggested workflow](../CONTRIBUTING.md#suggested-workflow).** ## General Guidelines and Best Practices - [ ] Title of the pull request is clear and informative. - [ ] There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, [see this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md). ### Testing Guidelines - [ ] Pull request includes test coverage for the included changes. --- .../promptflow/_sdk/entities/_run.py | 1 - ...wRun_test_run_bulk_with_registry_flow.yaml | 120 +-- ...lowRun_test_run_bulk_with_remote_flow.yaml | 715 ++++++++++-------- 3 files changed, 444 insertions(+), 392 deletions(-) diff --git a/src/promptflow/promptflow/_sdk/entities/_run.py b/src/promptflow/promptflow/_sdk/entities/_run.py index 6aa4bf2e164..af1aff1298d 100644 --- a/src/promptflow/promptflow/_sdk/entities/_run.py +++ b/src/promptflow/promptflow/_sdk/entities/_run.py @@ -150,7 +150,6 @@ def __init__( self._lineage_id = None if self._use_remote_flow: self._flow_name = parse_remote_flow_pattern(flow) - self._experiment_name = self._flow_name self._lineage_id = self._flow_name # default run name: flow directory name + timestamp self.name = name or self._generate_run_name() diff --git a/src/promptflow/tests/test_configs/recordings/test_run_operations_TestFlowRun_test_run_bulk_with_registry_flow.yaml b/src/promptflow/tests/test_configs/recordings/test_run_operations_TestFlowRun_test_run_bulk_with_registry_flow.yaml index 76868cccfc0..6d5187f4c96 100644 --- a/src/promptflow/tests/test_configs/recordings/test_run_operations_TestFlowRun_test_run_bulk_with_registry_flow.yaml +++ b/src/promptflow/tests/test_configs/recordings/test_run_operations_TestFlowRun_test_run_bulk_with_registry_flow.yaml @@ -5,12 +5,12 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.1 azsdk-python-mgmt-machinelearningservices/0.1.0 - Python/3.10.13 (Windows-10-10.0.22631-SP0) + - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.0 azsdk-python-mgmt-machinelearningservices/0.1.0 + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000 response: @@ -39,7 +39,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.020' + - '0.019' status: code: 200 message: OK @@ -49,12 +49,12 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.1 azsdk-python-mgmt-machinelearningservices/0.1.0 - Python/3.10.13 (Windows-10-10.0.22631-SP0) + - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.0 azsdk-python-mgmt-machinelearningservices/0.1.0 + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/datastores?count=30&isDefault=true&orderByAsc=false response: @@ -91,7 +91,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.065' + - '0.085' status: code: 200 message: OK @@ -101,12 +101,12 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.1 azsdk-python-mgmt-machinelearningservices/0.1.0 - Python/3.10.13 (Windows-10-10.0.22631-SP0) + - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.0 azsdk-python-mgmt-machinelearningservices/0.1.0 + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/datastores/workspaceblobstore response: @@ -143,7 +143,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.060' + - '0.076' status: code: 200 message: OK @@ -153,14 +153,14 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - '0' User-Agent: - - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.1 azsdk-python-mgmt-machinelearningservices/0.1.0 - Python/3.10.13 (Windows-10-10.0.22631-SP0) + - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.0 azsdk-python-mgmt-machinelearningservices/0.1.0 + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: POST uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/datastores/workspaceblobstore/listSecrets response: @@ -184,7 +184,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.070' + - '0.091' status: code: 200 message: OK @@ -194,15 +194,15 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - azsdk-python-storage-blob/12.19.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-blob/12.18.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 05:45:09 GMT + - Tue, 05 Dec 2023 10:59:47 GMT x-ms-version: - - '2023-11-03' + - '2023-08-03' method: HEAD uri: https://fake_account_name.blob.core.windows.net/fake-container-name/LocalUpload/000000000000000000000000000000000000/simple_hello_world.jsonl response: @@ -234,7 +234,7 @@ interactions: x-ms-meta-version: - 2266d840-3ecd-4a91-9e63-8d57e7b0a62e x-ms-version: - - '2023-11-03' + - '2023-08-03' status: code: 200 message: OK @@ -244,15 +244,15 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - azsdk-python-storage-blob/12.19.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-blob/12.18.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 05:45:10 GMT + - Tue, 05 Dec 2023 10:59:48 GMT x-ms-version: - - '2023-11-03' + - '2023-08-03' method: HEAD uri: https://fake_account_name.blob.core.windows.net/fake-container-name/az-ml-artifacts/000000000000000000000000000000000000/simple_hello_world.jsonl response: @@ -268,14 +268,13 @@ interactions: x-ms-error-code: - BlobNotFound x-ms-version: - - '2023-11-03' + - '2023-08-03' status: code: 404 message: The specified blob does not exist. - request: body: '{"flowDefinitionResourceId": "azureml://registries/promptflow-preview/models/simple_hello_world/versions/202311241", - "runId": "name", "runDisplayName": "name", "runExperimentName": "", "batchDataInput": - {"dataUri": "azureml://datastores/workspaceblobstore/paths/LocalUpload/000000000000000000000000000000000000/simple_hello_world.jsonl"}, + "runId": "name", "runDisplayName": "name", "batchDataInput": {"dataUri": "azureml://datastores/workspaceblobstore/paths/LocalUpload/000000000000000000000000000000000000/simple_hello_world.jsonl"}, "inputsMapping": {"name": "${data.name}"}, "connections": {}, "environmentVariables": {}, "runtimeName": "fake-runtime-name", "sessionId": "000000000000000000000000000000000000000000000000", "flowLineageId": "0000000000000000000000000000000000000000000000000000000000000000", @@ -284,16 +283,16 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - - '660' + - '615' Content-Type: - application/json User-Agent: - promptflow-sdk/0.0.1 promptflow/0.0.1 azsdk-python-azuremachinelearningdesignerserviceclient/unknown - Python/3.10.13 (Windows-10-10.0.22631-SP0) + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: POST uri: https://eastus.api.azureml.ms/flow/api/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/BulkRuns/submit response: @@ -311,7 +310,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '11.191' + - '14.145' status: code: 200 message: OK @@ -322,7 +321,7 @@ interactions: Accept: - '*/*' Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: @@ -335,34 +334,34 @@ interactions: uri: https://eastus.api.azureml.ms/history/v1.0/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/rundata response: body: - string: '{"runMetadata": {"runNumber": 1701323118, "rootRunId": "name", "createdUtc": - "2023-11-30T05:45:18.0097542+00:00", "createdBy": {"userObjectId": "00000000-0000-0000-0000-000000000000", - "userPuId": null, "userIdp": "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", - "userAltSecId": null, "userIss": "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", - "userTenantId": "00000000-0000-0000-0000-000000000000", "userName": "4cbd0e2e-aae4-4099-b4ba-94d3a4910587", - "upn": null}, "userId": "00000000-0000-0000-0000-000000000000", "token": null, - "tokenExpiryTimeUtc": null, "error": null, "warnings": null, "revision": 3, - "statusRevision": 1, "runUuid": "50291e12-5d87-4711-9f36-95ca333cb507", "parentRunUuid": - null, "rootRunUuid": "50291e12-5d87-4711-9f36-95ca333cb507", "lastStartTimeUtc": + string: '{"runMetadata": {"runNumber": 1701773992, "rootRunId": "name", "createdUtc": + "2023-12-05T10:59:52.9671136+00:00", "createdBy": {"userObjectId": "00000000-0000-0000-0000-000000000000", + "userPuId": "10032000324F7449", "userIdp": null, "userAltSecId": null, "userIss": + "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", "userTenantId": + "00000000-0000-0000-0000-000000000000", "userName": "Honglin Du", "upn": null}, + "userId": "00000000-0000-0000-0000-000000000000", "token": null, "tokenExpiryTimeUtc": + null, "error": null, "warnings": null, "revision": 3, "statusRevision": 1, + "runUuid": "43f6dd3a-b9cf-4cd9-8f3f-0fe03c249e68", "parentRunUuid": null, + "rootRunUuid": "43f6dd3a-b9cf-4cd9-8f3f-0fe03c249e68", "lastStartTimeUtc": null, "currentComputeTime": "00:00:00", "computeDuration": null, "effectiveStartTimeUtc": null, "lastModifiedBy": {"userObjectId": "00000000-0000-0000-0000-000000000000", - "userPuId": null, "userIdp": "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", - "userAltSecId": null, "userIss": "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", - "userTenantId": "00000000-0000-0000-0000-000000000000", "userName": "4cbd0e2e-aae4-4099-b4ba-94d3a4910587", - "upn": null}, "lastModifiedUtc": "2023-11-30T05:45:22.7839171+00:00", "duration": - null, "cancelationReason": null, "currentAttemptId": 1, "runId": "name", "parentRunId": - null, "experimentId": "e57eb79e-3e83-45f1-810c-ee22c20b2ebd", "status": "Preparing", + "userPuId": "10032000324F7449", "userIdp": null, "userAltSecId": null, "userIss": + "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", "userTenantId": + "00000000-0000-0000-0000-000000000000", "userName": "Honglin Du", "upn": null}, + "lastModifiedUtc": "2023-12-05T11:00:03.4532896+00:00", "duration": null, + "cancelationReason": null, "currentAttemptId": 1, "runId": "name", "parentRunId": + null, "experimentId": "8ed8abac-3b31-48a5-9fa1-81b7fe487f46", "status": "Preparing", "startTimeUtc": null, "endTimeUtc": null, "scheduleId": null, "displayName": "name", "name": null, "dataContainerId": "dcid.name", "description": null, "hidden": false, "runType": "azureml.promptflow.FlowRun", "runTypeV2": {"orchestrator": - null, "traits": [], "attribution": "PromptFlow", "computeType": "MIR_v2"}, - "properties": {"azureml.promptflow.runtime_name": "demo-mir", "azureml.promptflow.runtime_version": - "20231011.v2", "azureml.promptflow.definition_file_name": "flow.dag.yaml", + null, "traits": [], "attribution": "PromptFlow", "computeType": "AmlcDsi"}, + "properties": {"azureml.promptflow.runtime_name": "hod-ci", "azureml.promptflow.runtime_version": + "20231114.v2", "azureml.promptflow.definition_file_name": "flow.dag.yaml", "azureml.promptflow.session_id": "simple_hello_world", "azureml.promptflow.flow_lineage_id": "simple_hello_world", "azureml.promptflow.flow_definition_resource_id": "azureml://registries/promptflow-preview/models/simple_hello_world/versions/202311241", "azureml.promptflow.input_data": "azureml://datastores/workspaceblobstore/paths/LocalUpload/79f088fae0e502653c43146c9682f425/simple_hello_world.jsonl", "azureml.promptflow.inputs_mapping": "{\"name\":\"${data.name}\"}", "_azureml.evaluation_run": - "promptflow.BatchRun", "azureml.promptflow.snapshot_id": "f100f503-ad80-4976-8c2a-fcbef4189bfb"}, + "promptflow.BatchRun", "azureml.promptflow.snapshot_id": "08c2b30f-de87-4183-9733-38e6cc01614e"}, "parameters": {}, "actionUris": {}, "scriptName": null, "target": null, "uniqueChildRunComputeTargets": [], "tags": {}, "settings": {}, "services": {}, "inputDatasets": [], "outputDatasets": [], "runDefinition": null, "jobSpecification": null, "primaryMetricName": @@ -373,7 +372,18 @@ interactions: "Tool": null, "Path": "hello_world.py"}, "Inputs": {"name": "${inputs.name}"}, "Tool": "hello_world.py", "Reduce": false, "Activate": null, "Comment": null, "Api": null, "Provider": null, "Connection": null, "Module": null}], "Tools": - [], "Codes": null, "Inputs": {"name": {"name": null, "type": "string", "default": + [{"Name": "hello_world.py", "Type": "python", "Inputs": {"name": {"Name": + null, "Type": ["string"], "Default": null, "Description": null, "Enum": null, + "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": + null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, + "is_multi_select": false, "generated_by": null, "input_type": "default", "advanced": + null, "ui_hints": null}}, "Outputs": null, "Description": null, "connection_type": + null, "Module": null, "class_name": null, "Source": "hello_world.py", "LkgCode": + null, "Code": null, "Function": "hello_world", "action_type": null, "provider_config": + null, "function_config": null, "Icon": null, "Category": null, "Tags": null, + "is_builtin": false, "package": null, "package_version": null, "default_prompt": + null, "enable_kwargs": false, "deprecated_tools": null, "tool_state": "stable"}], + "Codes": null, "Inputs": {"name": {"name": null, "type": "string", "default": "hod", "description": null, "is_chat_input": false, "is_chat_history": null}}, "Outputs": {"result": {"name": null, "type": "string", "description": null, "reference": "${hello_world.output}", "evaluation_only": false, "is_chat_output": @@ -382,7 +392,7 @@ interactions: connection: - keep-alive content-length: - - '4751' + - '5980' content-type: - application/json; charset=utf-8 strict-transport-security: @@ -394,7 +404,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.067' + - '0.066' status: code: 200 message: OK diff --git a/src/promptflow/tests/test_configs/recordings/test_run_operations_TestFlowRun_test_run_bulk_with_remote_flow.yaml b/src/promptflow/tests/test_configs/recordings/test_run_operations_TestFlowRun_test_run_bulk_with_remote_flow.yaml index 31a221586a5..532cd64ebe1 100644 --- a/src/promptflow/tests/test_configs/recordings/test_run_operations_TestFlowRun_test_run_bulk_with_remote_flow.yaml +++ b/src/promptflow/tests/test_configs/recordings/test_run_operations_TestFlowRun_test_run_bulk_with_remote_flow.yaml @@ -5,12 +5,12 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.1 azsdk-python-mgmt-machinelearningservices/0.1.0 - Python/3.10.13 (Windows-10-10.0.22631-SP0) + - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.0 azsdk-python-mgmt-machinelearningservices/0.1.0 + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000 response: @@ -39,7 +39,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.028' + - '0.016' status: code: 200 message: OK @@ -49,12 +49,12 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.1 azsdk-python-mgmt-machinelearningservices/0.1.0 - Python/3.10.13 (Windows-10-10.0.22631-SP0) + - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.0 azsdk-python-mgmt-machinelearningservices/0.1.0 + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/datastores?count=30&isDefault=true&orderByAsc=false response: @@ -91,7 +91,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.192' + - '0.690' status: code: 200 message: OK @@ -101,12 +101,12 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.1 azsdk-python-mgmt-machinelearningservices/0.1.0 - Python/3.10.13 (Windows-10-10.0.22631-SP0) + - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.0 azsdk-python-mgmt-machinelearningservices/0.1.0 + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/datastores/workspaceworkingdirectory response: @@ -143,7 +143,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.119' + - '0.095' status: code: 200 message: OK @@ -153,14 +153,14 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - '0' User-Agent: - - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.1 azsdk-python-mgmt-machinelearningservices/0.1.0 - Python/3.10.13 (Windows-10-10.0.22631-SP0) + - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.0 azsdk-python-mgmt-machinelearningservices/0.1.0 + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: POST uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/datastores/workspaceworkingdirectory/listSecrets response: @@ -184,7 +184,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.175' + - '0.119' status: code: 200 message: OK @@ -194,15 +194,15 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - '0' User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:00 GMT + - Tue, 05 Dec 2023 10:56:36 GMT x-ms-file-attributes: - none x-ms-file-creation-time: @@ -218,7 +218,7 @@ interactions: response: body: string: "\uFEFFResourceAlreadyExistsThe - specified resource already exists.\nRequestId:36651d1b-101a-0092-0c3c-23895a000000\nTime:2023-11-30T03:23:01.9203520Z" + specified resource already exists.\nRequestId:35dacde5-701a-0094-7d69-27bae5000000\nTime:2023-12-05T10:56:37.3581303Z" headers: content-length: - '228' @@ -239,15 +239,15 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - '0' User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:03 GMT + - Tue, 05 Dec 2023 10:56:38 GMT x-ms-file-attributes: - none x-ms-file-creation-time: @@ -263,7 +263,7 @@ interactions: response: body: string: "\uFEFFResourceAlreadyExistsThe - specified resource already exists.\nRequestId:48f5f8cc-201a-0020-583c-23762b000000\nTime:2023-11-30T03:23:04.1583823Z" + specified resource already exists.\nRequestId:491391cb-901a-008c-7869-276582000000\nTime:2023-12-05T10:56:39.4121529Z" headers: content-length: - '228' @@ -284,15 +284,15 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - '0' User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:04 GMT + - Tue, 05 Dec 2023 10:56:39 GMT x-ms-file-attributes: - none x-ms-file-creation-time: @@ -308,7 +308,7 @@ interactions: response: body: string: "\uFEFFResourceAlreadyExistsThe - specified resource already exists.\nRequestId:b2132212-301a-0085-2f3c-232051000000\nTime:2023-11-30T03:23:05.2104584Z" + specified resource already exists.\nRequestId:07987b55-a01a-0011-1b69-279738000000\nTime:2023-12-05T10:56:40.3924879Z" headers: content-length: - '228' @@ -329,15 +329,15 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - '0' User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:05 GMT + - Tue, 05 Dec 2023 10:56:40 GMT x-ms-file-attributes: - none x-ms-file-creation-time: @@ -353,7 +353,7 @@ interactions: response: body: string: "\uFEFFResourceAlreadyExistsThe - specified resource already exists.\nRequestId:4f70e241-901a-0068-623c-236b1c000000\nTime:2023-11-30T03:23:06.2891015Z" + specified resource already exists.\nRequestId:32f9902e-501a-010a-3b69-275736000000\nTime:2023-12-05T10:56:41.3991353Z" headers: content-length: - '228' @@ -374,13 +374,13 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:06 GMT + - Tue, 05 Dec 2023 10:56:41 GMT x-ms-version: - '2023-08-03' method: GET @@ -388,7 +388,7 @@ interactions: response: body: string: "\uFEFFResourceNotFoundThe - specified resource does not exist.\nRequestId:b72fdf44-201a-0042-453c-23b40c000000\nTime:2023-11-30T03:23:07.3454774Z" + specified resource does not exist.\nRequestId:32f99034-501a-010a-3d69-275736000000\nTime:2023-12-05T10:56:41.5902945Z" headers: content-length: - '223' @@ -409,15 +409,15 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - '0' User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:07 GMT + - Tue, 05 Dec 2023 10:56:41 GMT x-ms-file-attributes: - none x-ms-file-creation-time: @@ -437,21 +437,21 @@ interactions: content-length: - '0' last-modified: - - Thu, 30 Nov 2023 03:23:08 GMT + - Tue, 05 Dec 2023 10:56:41 GMT server: - Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0 x-ms-file-attributes: - Directory x-ms-file-change-time: - - '2023-11-30T03:23:08.3727365Z' + - '2023-12-05T10:56:41.7825172Z' x-ms-file-creation-time: - - '2023-11-30T03:23:08.3727365Z' + - '2023-12-05T10:56:41.7825172Z' x-ms-file-id: - - '13835150371309223936' + - '11529355156491599872' x-ms-file-last-write-time: - - '2023-11-30T03:23:08.3727365Z' + - '2023-12-05T10:56:41.7825172Z' x-ms-file-parent-id: - - '10088082484072808448' + - '16141029853385195520' x-ms-request-server-encrypted: - 'true' x-ms-version: @@ -465,17 +465,17 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - '0' User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-content-length: - '14' x-ms-date: - - Thu, 30 Nov 2023 03:23:08 GMT + - Tue, 05 Dec 2023 10:56:41 GMT x-ms-file-attributes: - none x-ms-file-creation-time: @@ -497,21 +497,21 @@ interactions: content-length: - '0' last-modified: - - Thu, 30 Nov 2023 03:23:09 GMT + - Tue, 05 Dec 2023 10:56:41 GMT server: - Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0 x-ms-file-attributes: - Archive x-ms-file-change-time: - - '2023-11-30T03:23:09.4221265Z' + - '2023-12-05T10:56:41.9846284Z' x-ms-file-creation-time: - - '2023-11-30T03:23:09.4221265Z' + - '2023-12-05T10:56:41.9846284Z' x-ms-file-id: - - '13835115186937135104' + - '16141041174918987776' x-ms-file-last-write-time: - - '2023-11-30T03:23:09.4221265Z' + - '2023-12-05T10:56:41.9846284Z' x-ms-file-parent-id: - - '13835150371309223936' + - '11529355156491599872' x-ms-request-server-encrypted: - 'true' x-ms-version: @@ -527,7 +527,7 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: @@ -537,9 +537,9 @@ interactions: Content-Type: - application/octet-stream User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:09 GMT + - Tue, 05 Dec 2023 10:56:42 GMT x-ms-range: - bytes=0-13 x-ms-version: @@ -557,11 +557,11 @@ interactions: content-md5: - nYmkCopuDuFj82431amzZw== last-modified: - - Thu, 30 Nov 2023 03:23:10 GMT + - Tue, 05 Dec 2023 10:56:42 GMT server: - Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0 x-ms-file-last-write-time: - - '2023-11-30T03:23:10.4675328Z' + - '2023-12-05T10:56:42.1907230Z' x-ms-request-server-encrypted: - 'true' x-ms-version: @@ -575,17 +575,17 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - '0' User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-content-length: - '250' x-ms-date: - - Thu, 30 Nov 2023 03:23:10 GMT + - Tue, 05 Dec 2023 10:56:42 GMT x-ms-file-attributes: - none x-ms-file-creation-time: @@ -607,21 +607,21 @@ interactions: content-length: - '0' last-modified: - - Thu, 30 Nov 2023 03:23:11 GMT + - Tue, 05 Dec 2023 10:56:42 GMT server: - Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0 x-ms-file-attributes: - Archive x-ms-file-change-time: - - '2023-11-30T03:23:11.5109482Z' + - '2023-12-05T10:56:42.3848686Z' x-ms-file-creation-time: - - '2023-11-30T03:23:11.5109482Z' + - '2023-12-05T10:56:42.3848686Z' x-ms-file-id: - - '13835185555681312768' + - '10376433651884752896' x-ms-file-last-write-time: - - '2023-11-30T03:23:11.5109482Z' + - '2023-12-05T10:56:42.3848686Z' x-ms-file-parent-id: - - '13835150371309223936' + - '11529355156491599872' x-ms-request-server-encrypted: - 'true' x-ms-version: @@ -638,7 +638,7 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: @@ -648,9 +648,9 @@ interactions: Content-Type: - application/octet-stream User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:11 GMT + - Tue, 05 Dec 2023 10:56:42 GMT x-ms-range: - bytes=0-249 x-ms-version: @@ -668,11 +668,11 @@ interactions: content-md5: - CT1FTZp5JScB8fq+HjnINw== last-modified: - - Thu, 30 Nov 2023 03:23:12 GMT + - Tue, 05 Dec 2023 10:56:42 GMT server: - Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0 x-ms-file-last-write-time: - - '2023-11-30T03:23:12.5752717Z' + - '2023-12-05T10:56:42.5859852Z' x-ms-request-server-encrypted: - 'true' x-ms-version: @@ -686,17 +686,17 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - '0' User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-content-length: - '105' x-ms-date: - - Thu, 30 Nov 2023 03:23:12 GMT + - Tue, 05 Dec 2023 10:56:42 GMT x-ms-file-attributes: - none x-ms-file-creation-time: @@ -718,21 +718,21 @@ interactions: content-length: - '0' last-modified: - - Thu, 30 Nov 2023 03:23:13 GMT + - Tue, 05 Dec 2023 10:56:42 GMT server: - Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0 x-ms-file-attributes: - Archive x-ms-file-change-time: - - '2023-11-30T03:23:13.6286436Z' + - '2023-12-05T10:56:42.7821222Z' x-ms-file-creation-time: - - '2023-11-30T03:23:13.6286436Z' + - '2023-12-05T10:56:42.7821222Z' x-ms-file-id: - - '13835071206472024064' + - '14988119670312140800' x-ms-file-last-write-time: - - '2023-11-30T03:23:13.6286436Z' + - '2023-12-05T10:56:42.7821222Z' x-ms-file-parent-id: - - '13835150371309223936' + - '11529355156491599872' x-ms-request-server-encrypted: - 'true' x-ms-version: @@ -747,7 +747,7 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: @@ -757,9 +757,9 @@ interactions: Content-Type: - application/octet-stream User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:13 GMT + - Tue, 05 Dec 2023 10:56:42 GMT x-ms-range: - bytes=0-104 x-ms-version: @@ -777,11 +777,11 @@ interactions: content-md5: - fGMkkiZAjGs8PW/AMiYppA== last-modified: - - Thu, 30 Nov 2023 03:23:14 GMT + - Tue, 05 Dec 2023 10:56:42 GMT server: - Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0 x-ms-file-last-write-time: - - '2023-11-30T03:23:14.7716222Z' + - '2023-12-05T10:56:42.9782607Z' x-ms-request-server-encrypted: - 'true' x-ms-version: @@ -797,33 +797,34 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - - '280' + - '247' Content-Type: - application/json User-Agent: - promptflow-sdk/0.0.1 promptflow/0.0.1 azsdk-python-azuremachinelearningdesignerserviceclient/unknown - Python/3.10.13 (Windows-10-10.0.22631-SP0) + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: POST uri: https://eastus.api.azureml.ms/flow/api/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/Flows response: body: - string: '{"eTag": {}, "flowId": "c3dee562-21a4-424d-9964-9c00b3cf913b", "flowName": - "flow_display_name", "description": "test flow description", "tags": {"owner": - "sdk-test"}, "flowType": "Default", "experimentId": "00000000-0000-0000-0000-000000000000", - "createdDate": "2023-11-30T03:23:17.7518505Z", "lastModifiedDate": "2023-11-30T03:23:17.7518505Z", - "owner": {"userObjectId": "4e60fbf3-0338-41a8-bed5-fc341be556f8", "userTenantId": - "00000000-0000-0000-0000-000000000000", "userName": "4cbd0e2e-aae4-4099-b4ba-94d3a4910587"}, - "flowResourceId": "azureml://locations/eastus/workspaces/00000/flows/c3dee562-21a4-424d-9964-9c00b3cf913b", + string: '{"eTag": {}, "studioPortalEndpoint": "https://ml.azure.com/prompts/flow/3e123da1-f9a5-4c91-9234-8d9ffbb39ff5/8d1dba7e-b1a9-45d7-96d2-e5f08b3ffff1/details?wsid=/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/00000/providers/Microsoft.MachineLearningServices/workspaces/promptflow-eastus", + "flowId": "8d1dba7e-b1a9-45d7-96d2-e5f08b3ffff1", "flowName": "flow_display_name", + "description": "test flow description", "tags": {"owner": "sdk-test"}, "flowType": + "Default", "experimentId": "00000000-0000-0000-0000-000000000000", "createdDate": + "2023-12-05T10:56:45.191911Z", "lastModifiedDate": "2023-12-05T10:56:45.1919113Z", + "owner": {"userObjectId": "00000000-0000-0000-0000-000000000000", "userTenantId": + "00000000-0000-0000-0000-000000000000", "userName": "Honglin Du"}, "flowResourceId": + "azureml://locations/eastus/workspaces/00000/flows/8d1dba7e-b1a9-45d7-96d2-e5f08b3ffff1", "isArchived": false, "flowDefinitionFilePath": "Users/unknown_user/promptflow/flow_display_name/flow.dag.yaml"}' headers: connection: - keep-alive content-length: - - '801' + - '1038' content-type: - application/json; charset=utf-8 strict-transport-security: @@ -835,7 +836,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.880' + - '0.350' status: code: 200 message: OK @@ -845,13 +846,13 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - azsdk-python-storage-file-share/12.14.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-file-share/12.14.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:18 GMT + - Tue, 05 Dec 2023 10:56:51 GMT x-ms-version: - '2023-08-03' method: HEAD @@ -865,21 +866,21 @@ interactions: content-type: - application/octet-stream last-modified: - - Thu, 30 Nov 2023 03:23:12 GMT + - Tue, 05 Dec 2023 10:56:42 GMT server: - Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0 x-ms-file-attributes: - Archive x-ms-file-change-time: - - '2023-11-30T03:23:12.5752717Z' + - '2023-12-05T10:56:42.5859852Z' x-ms-file-creation-time: - - '2023-11-30T03:23:11.5109482Z' + - '2023-12-05T10:56:42.3848686Z' x-ms-file-id: - - '13835185555681312768' + - '10376433651884752896' x-ms-file-last-write-time: - - '2023-11-30T03:23:12.5752717Z' + - '2023-12-05T10:56:42.5859852Z' x-ms-file-parent-id: - - '13835150371309223936' + - '11529355156491599872' x-ms-type: - File x-ms-version: @@ -893,12 +894,12 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.1 azsdk-python-mgmt-machinelearningservices/0.1.0 - Python/3.10.13 (Windows-10-10.0.22631-SP0) + - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.0 azsdk-python-mgmt-machinelearningservices/0.1.0 + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/datastores/workspaceblobstore response: @@ -935,7 +936,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.075' + - '0.171' status: code: 200 message: OK @@ -945,14 +946,14 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - '0' User-Agent: - - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.1 azsdk-python-mgmt-machinelearningservices/0.1.0 - Python/3.10.13 (Windows-10-10.0.22631-SP0) + - promptflow-sdk/0.0.1 promptflow/0.0.1 azure-ai-ml/1.12.0 azsdk-python-mgmt-machinelearningservices/0.1.0 + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: POST uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/datastores/workspaceblobstore/listSecrets response: @@ -976,7 +977,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.160' + - '0.148' status: code: 200 message: OK @@ -986,15 +987,15 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - azsdk-python-storage-blob/12.19.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-blob/12.18.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:21 GMT + - Tue, 05 Dec 2023 10:56:53 GMT x-ms-version: - - '2023-11-03' + - '2023-08-03' method: HEAD uri: https://fake_account_name.blob.core.windows.net/fake-container-name/LocalUpload/000000000000000000000000000000000000/simple_hello_world.jsonl response: @@ -1026,7 +1027,7 @@ interactions: x-ms-meta-version: - 2266d840-3ecd-4a91-9e63-8d57e7b0a62e x-ms-version: - - '2023-11-03' + - '2023-08-03' status: code: 200 message: OK @@ -1036,15 +1037,15 @@ interactions: Accept: - application/xml Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive User-Agent: - - azsdk-python-storage-blob/12.19.0 Python/3.10.13 (Windows-10-10.0.22631-SP0) + - azsdk-python-storage-blob/12.18.1 Python/3.9.18 (Windows-10-10.0.22631-SP0) x-ms-date: - - Thu, 30 Nov 2023 03:23:22 GMT + - Tue, 05 Dec 2023 10:56:54 GMT x-ms-version: - - '2023-11-03' + - '2023-08-03' method: HEAD uri: https://fake_account_name.blob.core.windows.net/fake-container-name/az-ml-artifacts/000000000000000000000000000000000000/simple_hello_world.jsonl response: @@ -1060,14 +1061,13 @@ interactions: x-ms-error-code: - BlobNotFound x-ms-version: - - '2023-11-03' + - '2023-08-03' status: code: 404 message: The specified blob does not exist. - request: body: '{"flowDefinitionResourceId": "azureml://locations/fake-region/workspaces/00000/flows/00000000-0000-0000-0000-000000000000/", - "runId": "name", "runDisplayName": "name", "runExperimentName": "", "batchDataInput": - {"dataUri": "azureml://datastores/workspaceblobstore/paths/LocalUpload/000000000000000000000000000000000000/simple_hello_world.jsonl"}, + "runId": "name", "runDisplayName": "name", "batchDataInput": {"dataUri": "azureml://datastores/workspaceblobstore/paths/LocalUpload/000000000000000000000000000000000000/simple_hello_world.jsonl"}, "inputsMapping": {"name": "${data.name}"}, "connections": {}, "environmentVariables": {}, "runtimeName": "fake-runtime-name", "sessionId": "000000000000000000000000000000000000000000000000", "flowLineageId": "0000000000000000000000000000000000000000000000000000000000000000", @@ -1076,16 +1076,16 @@ interactions: Accept: - application/json Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: - - '747' + - '684' Content-Type: - application/json User-Agent: - promptflow-sdk/0.0.1 promptflow/0.0.1 azsdk-python-azuremachinelearningdesignerserviceclient/unknown - Python/3.10.13 (Windows-10-10.0.22631-SP0) + Python/3.9.18 (Windows-10-10.0.22631-SP0) method: POST uri: https://eastus.api.azureml.ms/flow/api/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/BulkRuns/submit response: @@ -1103,7 +1103,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '26.366' + - '9.608' status: code: 200 message: OK @@ -1114,7 +1114,7 @@ interactions: Accept: - '*/*' Accept-Encoding: - - gzip, deflate + - gzip, deflate, br Connection: - keep-alive Content-Length: @@ -1127,35 +1127,36 @@ interactions: uri: https://eastus.api.azureml.ms/history/v1.0/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/00000/providers/Microsoft.MachineLearningServices/workspaces/00000/rundata response: body: - string: '{"runMetadata": {"runNumber": 1701314627, "rootRunId": "name", "createdUtc": - "2023-11-30T03:23:47.9737418+00:00", "createdBy": {"userObjectId": "4e60fbf3-0338-41a8-bed5-fc341be556f8", - "userPuId": null, "userIdp": "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", - "userAltSecId": null, "userIss": "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", - "userTenantId": "00000000-0000-0000-0000-000000000000", "userName": "4cbd0e2e-aae4-4099-b4ba-94d3a4910587", - "upn": null}, "userId": "4e60fbf3-0338-41a8-bed5-fc341be556f8", "token": null, - "tokenExpiryTimeUtc": null, "error": null, "warnings": null, "revision": 2, - "statusRevision": 1, "runUuid": "46fa0b12-31c4-4a6c-b667-9716be172bfd", "parentRunUuid": - null, "rootRunUuid": "46fa0b12-31c4-4a6c-b667-9716be172bfd", "lastStartTimeUtc": + string: '{"runMetadata": {"runNumber": 1701773875, "rootRunId": "name", "createdUtc": + "2023-12-05T10:57:55.2244808+00:00", "createdBy": {"userObjectId": "00000000-0000-0000-0000-000000000000", + "userPuId": "10032000324F7449", "userIdp": null, "userAltSecId": null, "userIss": + "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", "userTenantId": + "00000000-0000-0000-0000-000000000000", "userName": "Honglin Du", "upn": null}, + "userId": "00000000-0000-0000-0000-000000000000", "token": null, "tokenExpiryTimeUtc": + null, "error": null, "warnings": null, "revision": 3, "statusRevision": 1, + "runUuid": "9ac9ce4d-552f-43f5-a8d3-4bc76d4c3ddc", "parentRunUuid": null, + "rootRunUuid": "9ac9ce4d-552f-43f5-a8d3-4bc76d4c3ddc", "lastStartTimeUtc": null, "currentComputeTime": "00:00:00", "computeDuration": null, "effectiveStartTimeUtc": - null, "lastModifiedBy": {"userObjectId": "4e60fbf3-0338-41a8-bed5-fc341be556f8", - "userPuId": null, "userIdp": "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", - "userAltSecId": null, "userIss": "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", - "userTenantId": "00000000-0000-0000-0000-000000000000", "userName": "4cbd0e2e-aae4-4099-b4ba-94d3a4910587", - "upn": null}, "lastModifiedUtc": "2023-11-30T03:23:47.9737418+00:00", "duration": - null, "cancelationReason": null, "currentAttemptId": 1, "runId": "name", "parentRunId": - null, "experimentId": "1f302029-d5c6-48eb-a94f-6f2d9579b05d", "status": "Preparing", + null, "lastModifiedBy": {"userObjectId": "00000000-0000-0000-0000-000000000000", + "userPuId": "10032000324F7449", "userIdp": null, "userAltSecId": null, "userIss": + "https://sts.windows.net/00000000-0000-0000-0000-000000000000/", "userTenantId": + "00000000-0000-0000-0000-000000000000", "userName": "Honglin Du", "upn": null}, + "lastModifiedUtc": "2023-12-05T10:57:59.8558899+00:00", "duration": null, + "cancelationReason": null, "currentAttemptId": 1, "runId": "name", "parentRunId": + null, "experimentId": "61e4542b-defc-42f6-a6dd-5e2b8579cddb", "status": "Preparing", "startTimeUtc": null, "endTimeUtc": null, "scheduleId": null, "displayName": "name", "name": null, "dataContainerId": "dcid.name", "description": null, "hidden": false, "runType": "azureml.promptflow.FlowRun", "runTypeV2": {"orchestrator": - null, "traits": [], "attribution": "PromptFlow", "computeType": "MIR_v2"}, - "properties": {"azureml.promptflow.runtime_name": "demo-mir", "azureml.promptflow.runtime_version": - "20231011.v2", "azureml.promptflow.definition_file_name": "flow.dag.yaml", - "azureml.promptflow.session_id": "c3dee562-21a4-424d-9964-9c00b3cf913b", "azureml.promptflow.flow_lineage_id": - "c3dee562-21a4-424d-9964-9c00b3cf913b", "azureml.promptflow.flow_definition_resource_id": - "azureml://locations/eastus/workspaces/00000/flows/c3dee562-21a4-424d-9964-9c00b3cf913b", - "azureml.promptflow.input_data": "azureml://datastores/workspaceblobstore/paths/LocalUpload/79f088fae0e502653c43146c9682f425/simple_hello_world.jsonl", - "azureml.promptflow.inputs_mapping": "{\"name\":\"${data.name}\"}", "azureml.promptflow.snapshot_id": - "1ba3ca26-8da5-4f0a-a9ff-cfb2f99bcbc8", "_azureml.evaluation_run": "promptflow.BatchRun"}, + null, "traits": [], "attribution": "PromptFlow", "computeType": "AmlcDsi"}, + "properties": {"azureml.promptflow.runtime_name": "hod-ci", "azureml.promptflow.runtime_version": + "20231114.v2", "azureml.promptflow.definition_file_name": "flow.dag.yaml", + "azureml.promptflow.session_id": "8d1dba7e-b1a9-45d7-96d2-e5f08b3ffff1", "azureml.promptflow.flow_lineage_id": + "8d1dba7e-b1a9-45d7-96d2-e5f08b3ffff1", "azureml.promptflow.flow_definition_resource_id": + "azureml://locations/eastus/workspaces/00000/flows/8d1dba7e-b1a9-45d7-96d2-e5f08b3ffff1", + "azureml.promptflow.flow_id": "8d1dba7e-b1a9-45d7-96d2-e5f08b3ffff1", "azureml.promptflow.input_data": + "azureml://datastores/workspaceblobstore/paths/LocalUpload/79f088fae0e502653c43146c9682f425/simple_hello_world.jsonl", + "azureml.promptflow.inputs_mapping": "{\"name\":\"${data.name}\"}", "_azureml.evaluation_run": + "promptflow.BatchRun", "azureml.promptflow.snapshot_id": "a394648a-17bc-4350-a92e-6800eb42548f"}, "parameters": {}, "actionUris": {}, "scriptName": null, "target": null, "uniqueChildRunComputeTargets": [], "tags": {}, "settings": {}, "services": {}, "inputDatasets": [], "outputDatasets": [], "runDefinition": null, "jobSpecification": null, "primaryMetricName": @@ -1164,241 +1165,283 @@ interactions: false, "queueingInfo": null, "inputs": null, "outputs": null}, "runDefinition": {"Nodes": [{"Name": "hello_world", "Type": "python", "Source": {"Type": "code", "Tool": null, "Path": "hello_world.py"}, "Inputs": {"name": "${inputs.name}"}, - "Tool": "hello_world.py", "Reduce": false, "Comment": null, "Activate": null, + "Tool": "hello_world.py", "Reduce": false, "Activate": null, "Comment": null, "Api": null, "Provider": null, "Connection": null, "Module": null}], "Tools": [{"Name": "Content Safety (Text Analyze)", "Type": "python", "Inputs": {"connection": {"Name": null, "Type": ["AzureContentSafetyConnection"], "Default": null, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, - "generated_by": null, "input_type": "default"}, "hate_category": {"Name": - null, "Type": ["string"], "Default": "medium_sensitivity", "Description": - null, "Enum": ["disable", "low_sensitivity", "medium_sensitivity", "high_sensitivity"], - "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": - null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, - "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "self_harm_category": {"Name": null, "Type": ["string"], "Default": "medium_sensitivity", - "Description": null, "Enum": ["disable", "low_sensitivity", "medium_sensitivity", - "high_sensitivity"], "enabled_by": null, "enabled_by_type": null, "enabled_by_value": - null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "sexual_category": {"Name": null, "Type": ["string"], "Default": "medium_sensitivity", + "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "hate_category": {"Name": null, "Type": ["string"], "Default": "medium_sensitivity", "Description": null, "Enum": ["disable", "low_sensitivity", "medium_sensitivity", "high_sensitivity"], "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "text": {"Name": null, "Type": ["string"], "Default": null, "Description": + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}, "self_harm_category": {"Name": null, + "Type": ["string"], "Default": "medium_sensitivity", "Description": null, + "Enum": ["disable", "low_sensitivity", "medium_sensitivity", "high_sensitivity"], + "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": + null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, + "is_multi_select": false, "generated_by": null, "input_type": "default", "advanced": + null, "ui_hints": null}, "sexual_category": {"Name": null, "Type": ["string"], + "Default": "medium_sensitivity", "Description": null, "Enum": ["disable", + "low_sensitivity", "medium_sensitivity", "high_sensitivity"], "enabled_by": + null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, + "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": + false, "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "text": {"Name": null, "Type": ["string"], "Default": null, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "violence_category": {"Name": null, "Type": ["string"], "Default": "medium_sensitivity", - "Description": null, "Enum": ["disable", "low_sensitivity", "medium_sensitivity", - "high_sensitivity"], "enabled_by": null, "enabled_by_type": null, "enabled_by_value": - null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}}, - "Outputs": null, "Description": "Use Azure Content Safety to detect harmful - content.", "connection_type": null, "Module": "content_safety_text.tools.content_safety_text_tool", + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}, "violence_category": {"Name": null, "Type": + ["string"], "Default": "medium_sensitivity", "Description": null, "Enum": + ["disable", "low_sensitivity", "medium_sensitivity", "high_sensitivity"], + "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": + null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, + "is_multi_select": false, "generated_by": null, "input_type": "default", "advanced": + null, "ui_hints": null}}, "Outputs": null, "Description": "Use Azure Content + Safety to detect harmful content.", "connection_type": null, "Module": "content_safety_text.tools.content_safety_text_tool", "class_name": null, "Source": null, "LkgCode": null, "Code": null, "Function": "analyze_text", "action_type": null, "provider_config": null, "function_config": null, "Icon": null, "Category": null, "Tags": null, "is_builtin": true, "package": - "promptflow-contentsafety", "package_version": "0.0.5", "default_prompt": - null, "enable_kwargs": false}, {"Name": "Embedding", "Type": "python", "Inputs": - {"connection": {"Name": null, "Type": ["AzureOpenAIConnection", "OpenAIConnection"], - "Default": null, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": + "promptflow-contentsafety", "package_version": "0.0.9", "default_prompt": + null, "enable_kwargs": false, "deprecated_tools": null, "tool_state": "stable"}, + {"Name": "Embedding", "Type": "python", "Inputs": {"connection": {"Name": + null, "Type": ["AzureOpenAIConnection", "OpenAIConnection"], "Default": null, + "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, - "generated_by": null, "input_type": "default"}, "deployment_name": {"Name": + "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "deployment_name": {"Name": null, "Type": ["string"], "Default": null, + "Description": null, "Enum": null, "enabled_by": "connection", "enabled_by_type": + ["AzureOpenAIConnection"], "enabled_by_value": null, "model_list": ["text-embedding-ada-002", + "text-search-ada-doc-001", "text-search-ada-query-001"], "Capabilities": {"completion": + false, "chat_completion": false, "embeddings": true}, "dynamic_list": null, + "allow_manual_entry": false, "is_multi_select": false, "generated_by": null, + "input_type": "default", "advanced": null, "ui_hints": null}, "input": {"Name": null, "Type": ["string"], "Default": null, "Description": null, "Enum": null, - "enabled_by": "connection", "enabled_by_type": ["AzureOpenAIConnection"], - "enabled_by_value": null, "model_list": ["text-embedding-ada-002", "text-search-ada-doc-001", - "text-search-ada-query-001"], "Capabilities": {"completion": false, "chat_completion": - false, "embeddings": true}, "dynamic_list": null, "allow_manual_entry": false, - "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "input": {"Name": null, "Type": ["string"], "Default": null, "Description": - null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": - null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "model": {"Name": null, "Type": ["string"], "Default": null, "Description": - null, "Enum": ["text-embedding-ada-002", "text-search-ada-doc-001", "text-search-ada-query-001"], - "enabled_by": "connection", "enabled_by_type": ["OpenAIConnection"], "enabled_by_value": - null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}}, - "Outputs": null, "Description": "Use Open AI''s embedding model to create - an embedding vector representing the input text.", "connection_type": null, - "Module": "promptflow.tools.embedding", "class_name": null, "Source": null, - "LkgCode": null, "Code": null, "Function": "embedding", "action_type": null, - "provider_config": null, "function_config": null, "Icon": null, "Category": - null, "Tags": null, "is_builtin": true, "package": "promptflow-tools", "package_version": - "0.1.0b8", "default_prompt": null, "enable_kwargs": false}, {"Name": "Open - Source LLM", "Type": "custom_llm", "Inputs": {"api": {"Name": null, "Type": - ["string"], "Default": null, "Description": null, "Enum": ["chat", "completion"], "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, - "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "connection": {"Name": null, "Type": ["CustomConnection"], "Default": null, - "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": + "is_multi_select": false, "generated_by": null, "input_type": "default", "advanced": + null, "ui_hints": null}, "model": {"Name": null, "Type": ["string"], "Default": + null, "Description": null, "Enum": ["text-embedding-ada-002", "text-search-ada-doc-001", + "text-search-ada-query-001"], "enabled_by": "connection", "enabled_by_type": + ["OpenAIConnection"], "enabled_by_value": null, "model_list": null, "Capabilities": + null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": + false, "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}}, "Outputs": null, "Description": "Use Open AI''s embedding model to + create an embedding vector representing the input text.", "connection_type": + null, "Module": "promptflow.tools.embedding", "class_name": null, "Source": + null, "LkgCode": null, "Code": null, "Function": "embedding", "action_type": + null, "provider_config": null, "function_config": null, "Icon": null, "Category": + null, "Tags": null, "is_builtin": true, "package": "promptflow-tools", "package_version": + "0.1.0b10", "default_prompt": null, "enable_kwargs": false, "deprecated_tools": + null, "tool_state": "stable"}, {"Name": "Open Source LLM", "Type": "custom_llm", + "Inputs": {"api": {"Name": null, "Type": ["string"], "Default": null, "Description": + null, "Enum": ["chat", "completion"], "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, - "generated_by": null, "input_type": "default"}, "deployment_name": {"Name": - null, "Type": ["string"], "Default": null, "Description": null, "Enum": null, - "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": - null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, - "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "model_kwargs": {"Name": null, "Type": ["object"], "Default": "{}", "Description": - null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": - null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}}, - "Outputs": null, "Description": "Use an Open Source model from the Azure Model - catalog, deployed to an AzureML Online Endpoint for LLM Chat or Completion - API calls.", "connection_type": null, "Module": "promptflow.tools.open_source_llm", - "class_name": "OpenSourceLLM", "Source": null, "LkgCode": null, "Code": null, - "Function": "call", "action_type": null, "provider_config": null, "function_config": - null, "Icon": null, "Category": null, "Tags": null, "is_builtin": true, "package": - "promptflow-tools", "package_version": "0.1.0b8", "default_prompt": null, - "enable_kwargs": false}, {"Name": "Serp API", "Type": "python", "Inputs": - {"connection": {"Name": null, "Type": ["SerpConnection"], "Default": null, + "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "connection": {"Name": null, "Type": ["CustomConnection"], "Default": + null, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": + null, "enabled_by_value": null, "model_list": null, "Capabilities": null, + "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, + "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "deployment_name": {"Name": null, "Type": ["string"], "Default": null, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, - "generated_by": null, "input_type": "default"}, "engine": {"Name": null, "Type": - ["string"], "Default": "google", "Description": null, "Enum": ["google", "bing"], - "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": - null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, - "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "location": {"Name": null, "Type": ["string"], "Default": "", "Description": + "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "endpoint_name": {"Name": null, "Type": ["string"], "Default": "-- + please enter an endpoint name --", "Description": null, "Enum": null, "enabled_by": + null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, + "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": + false, "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "max_new_tokens": {"Name": null, "Type": ["int"], "Default": 500, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "num": {"Name": null, "Type": ["int"], "Default": "10", "Description": null, - "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": - null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "query": {"Name": null, "Type": ["string"], "Default": null, "Description": + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}, "model_kwargs": {"Name": null, "Type": + ["object"], "Default": "{}", "Description": null, "Enum": null, "enabled_by": + null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, + "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": + false, "generated_by": null, "input_type": "default", "advanced": true, "ui_hints": + null}, "temperature": {"Name": null, "Type": ["double"], "Default": 1.0, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "safe": {"Name": null, "Type": ["string"], "Default": "off", "Description": - null, "Enum": ["active", "off"], "enabled_by": null, "enabled_by_type": null, + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}, "top_p": {"Name": null, "Type": ["double"], + "Default": 1.0, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": + null, "enabled_by_value": null, "model_list": null, "Capabilities": null, + "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, + "generated_by": null, "input_type": "default", "advanced": true, "ui_hints": + null}}, "Outputs": null, "Description": "Use an Open Source model from the + Azure Model catalog, deployed to an AzureML Online Endpoint for LLM Chat or + Completion API calls.", "connection_type": null, "Module": "promptflow.tools.open_source_llm", + "class_name": "OpenSourceLLM", "Source": null, "LkgCode": null, "Code": null, + "Function": "call", "action_type": null, "provider_config": null, "function_config": + null, "Icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAABYUlEQVR4nIWRsUtbcRRGz70v5BmHiLSh7pJu0oJDHUrf1kVwlCIRHMTN/yDasd0imCkgZGibFlrd5DmFNDSiksADsdAhk3TIZmj6kCa/65BERCie6Rsu93LPByPeajUxztWEKXcxzwTg/VQz18y9mwYwMQ9AxkNHLzI5nfvT9lwqa1H3c9AAwRATob7qLw8mLTz/tHEJxZnnK/4i/+Ivr8oGUNtqho1gdCz5yx+mRtAK63kAooPSAhwVTor7TwE+Zs+K4Q6UFqIDSIDG02nTb7tTa7N7xxFMPuvVrsumX9MaQwJM+wNxtNne9Fc/iJZfF2KAysAUbv81rzqxe939cfW9EFcnhi8CKIjz1BSjjyQfJR8j9DFTT8UNN6Q6XXFIRo3eRe/CyCgirtN1KQDq+VZ4GnCPRtAKa3nuiEq5w5+V9d+w82T+TXJJR6Luqf7b9pyftahXeXk8VP1gWbf8r+4bvICY0FkMumIAAAAASUVORK5CYII=", + "Category": null, "Tags": null, "is_builtin": true, "package": "promptflow-tools", + "package_version": "0.1.0b10", "default_prompt": null, "enable_kwargs": false, + "deprecated_tools": null, "tool_state": "stable"}, {"Name": "Serp API", "Type": + "python", "Inputs": {"connection": {"Name": null, "Type": ["SerpConnection"], + "Default": null, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": + null, "enabled_by_value": null, "model_list": null, "Capabilities": null, + "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, + "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "engine": {"Name": null, "Type": ["string"], "Default": "google", "Description": + null, "Enum": ["google", "bing"], "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, "generated_by": - null, "input_type": "default"}}, "Outputs": null, "Description": "Use Serp - API to obtain search results from a specific search engine.", "connection_type": - null, "Module": "promptflow.tools.serpapi", "class_name": "SerpAPI", "Source": - null, "LkgCode": null, "Code": null, "Function": "search", "action_type": - null, "provider_config": null, "function_config": null, "Icon": null, "Category": - null, "Tags": null, "is_builtin": true, "package": "promptflow-tools", "package_version": - "0.1.0b8", "default_prompt": null, "enable_kwargs": false}, {"Name": "Faiss - Index Lookup", "Type": "python", "Inputs": {"path": {"Name": null, "Type": - ["string"], "Default": null, "Description": null, "Enum": null, "enabled_by": - null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, - "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": - false, "generated_by": null, "input_type": "default"}, "top_k": {"Name": null, - "Type": ["int"], "Default": "3", "Description": null, "Enum": null, "enabled_by": + null, "input_type": "default", "advanced": null, "ui_hints": null}, "location": + {"Name": null, "Type": ["string"], "Default": "", "Description": null, "Enum": + null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, + "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}, "num": {"Name": null, "Type": ["int"], + "Default": "10", "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": + null, "enabled_by_value": null, "model_list": null, "Capabilities": null, + "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, + "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "query": {"Name": null, "Type": ["string"], "Default": null, "Description": + null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": + null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}, "safe": {"Name": null, "Type": ["string"], + "Default": "off", "Description": null, "Enum": ["active", "off"], "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": - false, "generated_by": null, "input_type": "default"}, "vector": {"Name": - null, "Type": ["list"], "Default": null, "Description": null, "Enum": null, + false, "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}}, "Outputs": null, "Description": "Use Serp API to obtain search results + from a specific search engine.", "connection_type": null, "Module": "promptflow.tools.serpapi", + "class_name": "SerpAPI", "Source": null, "LkgCode": null, "Code": null, "Function": + "search", "action_type": null, "provider_config": null, "function_config": + null, "Icon": null, "Category": null, "Tags": null, "is_builtin": true, "package": + "promptflow-tools", "package_version": "0.1.0b10", "default_prompt": null, + "enable_kwargs": false, "deprecated_tools": null, "tool_state": "stable"}, + {"Name": "Faiss Index Lookup", "Type": "python", "Inputs": {"path": {"Name": + null, "Type": ["string"], "Default": null, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, - "is_multi_select": false, "generated_by": null, "input_type": "default"}}, - "Outputs": null, "Description": "Search vector based query from the FAISS - index file.", "connection_type": null, "Module": "promptflow_vectordb.tool.faiss_index_lookup", - "class_name": "FaissIndexLookup", "Source": null, "LkgCode": null, "Code": - null, "Function": "search", "action_type": null, "provider_config": null, - "function_config": null, "Icon": null, "Category": null, "Tags": null, "is_builtin": - true, "package": "promptflow-vectordb", "package_version": "0.0.1", "default_prompt": - null, "enable_kwargs": false}, {"Name": "Vector DB Lookup", "Type": "python", - "Inputs": {"class_name": {"Name": null, "Type": ["string"], "Default": null, - "Description": null, "Enum": null, "enabled_by": "connection", "enabled_by_type": - ["WeaviateConnection"], "enabled_by_value": null, "model_list": null, "Capabilities": - null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": - false, "generated_by": null, "input_type": "default"}, "collection_name": - {"Name": null, "Type": ["string"], "Default": null, "Description": null, "Enum": - null, "enabled_by": "connection", "enabled_by_type": ["QdrantConnection"], - "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": - null, "allow_manual_entry": false, "is_multi_select": false, "generated_by": - null, "input_type": "default"}, "connection": {"Name": null, "Type": ["CognitiveSearchConnection", + "is_multi_select": false, "generated_by": null, "input_type": "default", "advanced": + null, "ui_hints": null}, "top_k": {"Name": null, "Type": ["int"], "Default": + "3", "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": + null, "enabled_by_value": null, "model_list": null, "Capabilities": null, + "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, + "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "vector": {"Name": null, "Type": ["list"], "Default": null, "Description": + null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": + null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}}, "Outputs": null, "Description": "Search + vector based query from the FAISS index file.", "connection_type": null, "Module": + "promptflow_vectordb.tool.faiss_index_lookup", "class_name": "FaissIndexLookup", + "Source": null, "LkgCode": null, "Code": null, "Function": "search", "action_type": + null, "provider_config": null, "function_config": null, "Icon": null, "Category": + null, "Tags": null, "is_builtin": true, "package": "promptflow-vectordb", + "package_version": "0.0.1", "default_prompt": null, "enable_kwargs": false, + "deprecated_tools": null, "tool_state": "stable"}, {"Name": "Vector DB Lookup", + "Type": "python", "Inputs": {"class_name": {"Name": null, "Type": ["string"], + "Default": null, "Description": null, "Enum": null, "enabled_by": "connection", + "enabled_by_type": ["WeaviateConnection"], "enabled_by_value": null, "model_list": + null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, + "is_multi_select": false, "generated_by": null, "input_type": "default", "advanced": + null, "ui_hints": null}, "collection_name": {"Name": null, "Type": ["string"], + "Default": null, "Description": null, "Enum": null, "enabled_by": "connection", + "enabled_by_type": ["QdrantConnection"], "enabled_by_value": null, "model_list": + null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, + "is_multi_select": false, "generated_by": null, "input_type": "default", "advanced": + null, "ui_hints": null}, "connection": {"Name": null, "Type": ["CognitiveSearchConnection", "QdrantConnection", "WeaviateConnection"], "Default": null, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "index_name": {"Name": null, "Type": ["string"], "Default": null, "Description": - null, "Enum": null, "enabled_by": "connection", "enabled_by_type": ["CognitiveSearchConnection"], + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}, "index_name": {"Name": null, "Type": + ["string"], "Default": null, "Description": null, "Enum": null, "enabled_by": + "connection", "enabled_by_type": ["CognitiveSearchConnection"], "enabled_by_value": + null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}, "search_filters": {"Name": null, "Type": + ["object"], "Default": null, "Description": null, "Enum": null, "enabled_by": + "connection", "enabled_by_type": ["CognitiveSearchConnection", "QdrantConnection"], "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, "generated_by": - null, "input_type": "default"}, "search_filters": {"Name": null, "Type": ["object"], - "Default": null, "Description": null, "Enum": null, "enabled_by": "connection", - "enabled_by_type": ["CognitiveSearchConnection", "QdrantConnection"], "enabled_by_value": - null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "search_params": {"Name": null, "Type": ["object"], "Default": null, "Description": - null, "Enum": null, "enabled_by": "connection", "enabled_by_type": ["CognitiveSearchConnection", + null, "input_type": "default", "advanced": null, "ui_hints": null}, "search_params": + {"Name": null, "Type": ["object"], "Default": null, "Description": null, "Enum": + null, "enabled_by": "connection", "enabled_by_type": ["CognitiveSearchConnection", "QdrantConnection"], "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": - false, "generated_by": null, "input_type": "default"}, "text_field": {"Name": - null, "Type": ["string"], "Default": null, "Description": null, "Enum": null, - "enabled_by": "connection", "enabled_by_type": ["CognitiveSearchConnection", + false, "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "text_field": {"Name": null, "Type": ["string"], "Default": null, "Description": + null, "Enum": null, "enabled_by": "connection", "enabled_by_type": ["CognitiveSearchConnection", "QdrantConnection", "WeaviateConnection"], "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, - "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "top_k": {"Name": null, "Type": ["int"], "Default": "3", "Description": null, - "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": - null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "vector": {"Name": null, "Type": ["list"], "Default": null, "Description": + "is_multi_select": false, "generated_by": null, "input_type": "default", "advanced": + null, "ui_hints": null}, "top_k": {"Name": null, "Type": ["int"], "Default": + "3", "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": + null, "enabled_by_value": null, "model_list": null, "Capabilities": null, + "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, + "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "vector": {"Name": null, "Type": ["list"], "Default": null, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "vector_field": {"Name": null, "Type": ["string"], "Default": null, "Description": - null, "Enum": null, "enabled_by": "connection", "enabled_by_type": ["CognitiveSearchConnection"], - "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": - null, "allow_manual_entry": false, "is_multi_select": false, "generated_by": - null, "input_type": "default"}}, "Outputs": null, "Description": "Search vector - based query from existing Vector Database.", "connection_type": null, "Module": - "promptflow_vectordb.tool.vector_db_lookup", "class_name": "VectorDBLookup", + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}, "vector_field": {"Name": null, "Type": + ["string"], "Default": null, "Description": null, "Enum": null, "enabled_by": + "connection", "enabled_by_type": ["CognitiveSearchConnection"], "enabled_by_value": + null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}}, "Outputs": null, "Description": "Search + vector based query from existing Vector Database.", "connection_type": null, + "Module": "promptflow_vectordb.tool.vector_db_lookup", "class_name": "VectorDBLookup", "Source": null, "LkgCode": null, "Code": null, "Function": "search", "action_type": null, "provider_config": null, "function_config": null, "Icon": null, "Category": null, "Tags": null, "is_builtin": true, "package": "promptflow-vectordb", - "package_version": "0.0.1", "default_prompt": null, "enable_kwargs": false}, - {"Name": "Vector Index Lookup", "Type": "python", "Inputs": {"path": {"Name": - null, "Type": ["string"], "Default": null, "Description": null, "Enum": null, - "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": - null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, - "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "query": {"Name": null, "Type": ["object"], "Default": null, "Description": + "package_version": "0.0.1", "default_prompt": null, "enable_kwargs": false, + "deprecated_tools": null, "tool_state": "stable"}, {"Name": "Vector Index + Lookup", "Type": "python", "Inputs": {"path": {"Name": null, "Type": ["string"], + "Default": null, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": + null, "enabled_by_value": null, "model_list": null, "Capabilities": null, + "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, + "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}, "query": {"Name": null, "Type": ["object"], "Default": null, "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}, - "top_k": {"Name": null, "Type": ["int"], "Default": "3", "Description": null, - "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": - null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}}, - "Outputs": null, "Description": "Search text or vector based query from AzureML - Vector Index.", "connection_type": null, "Module": "promptflow_vectordb.tool.vector_index_lookup", + false, "is_multi_select": false, "generated_by": null, "input_type": "default", + "advanced": null, "ui_hints": null}, "top_k": {"Name": null, "Type": ["int"], + "Default": "3", "Description": null, "Enum": null, "enabled_by": null, "enabled_by_type": + null, "enabled_by_value": null, "model_list": null, "Capabilities": null, + "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": false, + "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}}, "Outputs": null, "Description": "Search text or vector based query + from AzureML Vector Index.", "connection_type": null, "Module": "promptflow_vectordb.tool.vector_index_lookup", "class_name": "VectorIndexLookup", "Source": null, "LkgCode": null, "Code": null, "Function": "search", "action_type": null, "provider_config": null, "function_config": null, "Icon": null, "Category": null, "Tags": null, "is_builtin": true, "package": "promptflow-vectordb", "package_version": "0.0.1", "default_prompt": - null, "enable_kwargs": false}, {"Name": "hello_world.py", "Type": "python", - "Inputs": {"name": {"Name": null, "Type": ["string"], "Default": null, "Description": - null, "Enum": null, "enabled_by": null, "enabled_by_type": null, "enabled_by_value": - null, "model_list": null, "Capabilities": null, "dynamic_list": null, "allow_manual_entry": - false, "is_multi_select": false, "generated_by": null, "input_type": "default"}}, - "Outputs": null, "Description": null, "connection_type": null, "Module": null, - "class_name": null, "Source": "hello_world.py", "LkgCode": null, "Code": null, - "Function": "hello_world", "action_type": null, "provider_config": null, "function_config": - null, "Icon": null, "Category": null, "Tags": null, "is_builtin": false, "package": - null, "package_version": null, "default_prompt": null, "enable_kwargs": false}], - "Codes": null, "Inputs": {"name": {"Name": null, "Type": "string", "Default": - "hod", "Description": null, "is_chat_input": false, "is_chat_history": null}}, - "Outputs": {"result": {"Name": null, "Type": "string", "Description": null, - "Reference": "${hello_world.output}", "evaluation_only": false, "is_chat_output": - false}}}, "jobSpecification": null, "systemSettings": null}' + null, "enable_kwargs": false, "deprecated_tools": null, "tool_state": "stable"}, + {"Name": "hello_world.py", "Type": "python", "Inputs": {"name": {"Name": null, + "Type": ["string"], "Default": null, "Description": null, "Enum": null, "enabled_by": + null, "enabled_by_type": null, "enabled_by_value": null, "model_list": null, + "Capabilities": null, "dynamic_list": null, "allow_manual_entry": false, "is_multi_select": + false, "generated_by": null, "input_type": "default", "advanced": null, "ui_hints": + null}}, "Outputs": null, "Description": null, "connection_type": null, "Module": + null, "class_name": null, "Source": "hello_world.py", "LkgCode": null, "Code": + null, "Function": "hello_world", "action_type": null, "provider_config": null, + "function_config": null, "Icon": null, "Category": null, "Tags": null, "is_builtin": + false, "package": null, "package_version": null, "default_prompt": null, "enable_kwargs": + false, "deprecated_tools": null, "tool_state": "stable"}], "Codes": null, + "Inputs": {"name": {"name": null, "type": "string", "default": "hod", "description": + null, "is_chat_input": false, "is_chat_history": null}}, "Outputs": {"result": + {"name": null, "type": "string", "description": null, "reference": "${hello_world.output}", + "evaluation_only": false, "is_chat_output": false}}}, "jobSpecification": + null, "systemSettings": null}' headers: connection: - keep-alive content-length: - - '34097' + - '39895' content-type: - application/json; charset=utf-8 strict-transport-security: @@ -1410,7 +1453,7 @@ interactions: x-content-type-options: - nosniff x-request-time: - - '0.048' + - '0.045' status: code: 200 message: OK From 8115017c7c8f50b27491611c3a4f3f3f2fd88176 Mon Sep 17 00:00:00 2001 From: Zhengfei Wang <38847871+zhengfeiwang@users.noreply.github.com> Date: Wed, 6 Dec 2023 16:14:33 +0800 Subject: [PATCH 2/8] [Fundamental] Introduce stale for issue/PR status monitor (#1329) # Description This PR targets to leverage [actions/stale](https://github.com/actions/stale) to add label for stale issue/PR. In short, issue will be tagged label `no-recent-activity` after 30 days, and stale PR will be tagged after 7 days. Issues with label `long-term` will be excluded. **References** - Azure SDK stale issue: - Azure SDK stale pull request: # All Promptflow Contribution checklist: - [x] **The pull request does not introduce [breaking changes].** - [ ] **CHANGELOG is updated for new features, bug fixes or other significant changes.** - [x] **I have read the [contribution guidelines](../CONTRIBUTING.md).** - [ ] **Create an issue and link to the pull request to get dedicated review from promptflow team. Learn more: [suggested workflow](../CONTRIBUTING.md#suggested-workflow).** ## General Guidelines and Best Practices - [x] Title of the pull request is clear and informative. - [x] There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, [see this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md). ### Testing Guidelines - [ ] Pull request includes test coverage for the included changes. --- .github/workflows/stale.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000000..69d218babec --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,27 @@ +name: 'Close stale issues and pull requests' +on: + schedule: + - cron: '30 21 * * *' # 5:30 Beijing Time (GMT+8) + workflow_dispatch: + +jobs: + stale: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@v8 + with: + exempt-issue-labels: 'long-term' # syntax: , + # stale issue/pull request + stale-issue-message: "Hi, we're sending this friendly reminder because we haven't heard back from you in 30 days. We need more information about this issue to help address it. Please be sure to give us your input." + stale-issue-label: 'no-recent-activity' + stale-pr-message: "Hi, thank you for your interest in helping to improve the prompt flow experience and for your contribution. We've noticed that there hasn't been recent engagement on this pull request. If this is still an active work stream, please let us know by pushing some changes or leaving a comment." + stale-pr-label: 'no-recent-activity' + days-before-issue-stale: 30 + days-before-pr-stale: 14 + # # close issue/pull request + # close-pr-message: 'Hi, thank you for your contribution. Since there hasn't been recent engagement, we're going to close this out.' + # days-before-issue-close: 7 + # days-before-pr-close: 7 From fa6dc4a9ae02d3f14c34125baf3a02130baf2bab Mon Sep 17 00:00:00 2001 From: Honglin Date: Wed, 6 Dec 2023 18:29:04 +0800 Subject: [PATCH 3/8] [SDK/CLI] Add pfazure download run feature. (#1378) # Description ![image](https://github.com/microsoft/promptflow/assets/2572521/1f1f2cdf-6b2f-4706-aa42-114a0249afdd) ![image](https://github.com/microsoft/promptflow/assets/2572521/b016e614-b8c9-4404-ae4f-fbc8659c0a2c) # All Promptflow Contribution checklist: - [ ] **The pull request does not introduce [breaking changes].** - [ ] **CHANGELOG is updated for new features, bug fixes or other significant changes.** - [ ] **I have read the [contribution guidelines](../CONTRIBUTING.md).** - [ ] **Create an issue and link to the pull request to get dedicated review from promptflow team. Learn more: [suggested workflow](../CONTRIBUTING.md#suggested-workflow).** ## General Guidelines and Best Practices - [ ] Title of the pull request is clear and informative. - [ ] There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, [see this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md). ### Testing Guidelines - [ ] Pull request includes test coverage for the included changes. --- src/promptflow/CHANGELOG.md | 3 + src/promptflow/promptflow/_cli/_params.py | 64 +---- .../promptflow/_cli/_pf_azure/_run.py | 39 ++- src/promptflow/promptflow/_sdk/_constants.py | 1 + src/promptflow/promptflow/_sdk/_errors.py | 6 + .../azure/operations/_async_run_downloader.py | 252 ++++++++++++++++++ .../azure/operations/_run_operations.py | 60 ++++- .../e2etests/test_run_operations.py | 17 ++ .../sdk_cli_azure_test/unittests/test_cli.py | 17 ++ 9 files changed, 405 insertions(+), 54 deletions(-) create mode 100644 src/promptflow/promptflow/azure/operations/_async_run_downloader.py diff --git a/src/promptflow/CHANGELOG.md b/src/promptflow/CHANGELOG.md index cd49623225d..38dfa0a6d1d 100644 --- a/src/promptflow/CHANGELOG.md +++ b/src/promptflow/CHANGELOG.md @@ -2,6 +2,9 @@ ## 1.2.0 (upcoming) +### Features Added +- [SDK/CLI] Support `pfazure run download` to download run data from Azure AI. + ### Bugs Fixed - [SDK/CLI] Removing telemetry warning when running commands. diff --git a/src/promptflow/promptflow/_cli/_params.py b/src/promptflow/promptflow/_cli/_params.py index df17434c5fe..3aea229b36b 100644 --- a/src/promptflow/promptflow/_cli/_params.py +++ b/src/promptflow/promptflow/_cli/_params.py @@ -56,20 +56,20 @@ def add_param_ua(parser): def add_param_flow_display_name(parser): - parser.add_argument("--flow", type=str, required=True, help="the flow name to create.") + parser.add_argument("--flow", type=str, required=True, help="The flow name to create.") def add_param_entry(parser): - parser.add_argument("--entry", type=str, help="the entry file.") + parser.add_argument("--entry", type=str, help="The entry file.") def add_param_function(parser): - parser.add_argument("--function", type=str, help="the function name in entry file.") + parser.add_argument("--function", type=str, help="The function name in entry file.") def add_param_prompt_template(parser): parser.add_argument( - "--prompt-template", action=AppendToDictAction, help="the prompt template parameter and assignment.", nargs="+" + "--prompt-template", action=AppendToDictAction, help="The prompt template parameter and assignment.", nargs="+" ) @@ -146,58 +146,30 @@ def add_param_inputs(parser): ) -def add_param_input(parser): - parser.add_argument( - "--input", type=str, required=True, help="the input file path. Note that we accept jsonl file only for now." - ) - - def add_param_env(parser): parser.add_argument( "--env", type=str, default=None, - help="the dotenv file path containing the environment variables to be used in the flow.", + help="The dotenv file path containing the environment variables to be used in the flow.", ) def add_param_output(parser): - parser.add_argument("--output", type=str, default="outputs", help="the output directory to store the results.") - - -def add_param_flow(parser): - parser.add_argument("--flow", type=str, required=True, help="the evaluation flow to be used.") - - -def add_param_source(parser): - parser.add_argument("--source", type=str, required=True, help="The flow or run source to be used.") - - -def add_param_bulk_run_output(parser): - parser.add_argument("--bulk-run-output", type=str, help="the output directory of the bulk run.") - - -def add_param_eval_output(parser): - parser.add_argument("--eval-output", type=str, help="the output file path of the evaluation result.") - - -def add_param_column_mapping(parser): parser.add_argument( - "--column-mapping", type=str, required=True, help="the column mapping to be used in the evaluation." + "-o", + "--output", + type=str, + help="The output directory to store the results. Default to be current working directory if not specified.", ) -def add_param_runtime(parser): - parser.add_argument( - "--runtime", - type=str, - default="local", - help="Name of your runtime in Azure ML workspace, will run in cloud when runtime is not none.", - ) +def add_param_overwrite(parser): + parser.add_argument("--overwrite", action="store_true", help="Overwrite the existing results.") -def add_param_connection(parser): - parser.add_argument("--connection", type=str, help="Name of your connection in Azure ML workspace.") +def add_param_source(parser): + parser.add_argument("--source", type=str, required=True, help="The flow or run source to be used.") def add_param_run_name(parser): @@ -208,16 +180,6 @@ def add_param_connection_name(parser): parser.add_argument("-n", "--name", type=str, help="Name of the connection to create.") -def add_param_variants(parser): - parser.add_argument( - "--variants", - type=str, - nargs="+", - help="the variant run ids to be used in the evaluation. Note that we only support one variant for now.", - default=[], - ) - - def add_param_max_results(parser): parser.add_argument( # noqa: E731 "-r", diff --git a/src/promptflow/promptflow/_cli/_pf_azure/_run.py b/src/promptflow/promptflow/_cli/_pf_azure/_run.py index ff2a7c701e4..6eb10af7be9 100644 --- a/src/promptflow/promptflow/_cli/_pf_azure/_run.py +++ b/src/promptflow/promptflow/_cli/_pf_azure/_run.py @@ -13,7 +13,9 @@ add_param_debug, add_param_include_archived, add_param_max_results, + add_param_output, add_param_output_format, + add_param_overwrite, add_param_run_name, add_param_set, add_param_verbose, @@ -52,6 +54,7 @@ def add_parser_run(subparsers): add_parser_run_archive(subparsers) add_parser_run_restore(subparsers) add_parser_run_update(subparsers) + add_parser_run_download(subparsers) run_parser.set_defaults(action="run") @@ -334,7 +337,7 @@ def add_parser_run_update(subparsers): Example: # Update a run metadata: -pf run update --name --set display_name="" description="" tags.key="" +pfazure run update --name --set display_name="" description="" tags.key="" """ add_params = [ _set_workspace_argument_for_subparsers, @@ -353,6 +356,32 @@ def add_parser_run_update(subparsers): ) +def add_parser_run_download(subparsers): + """Add run download parser to the pfazure subparsers.""" + epilog = """ +Example: + +# Download a run data to local: +pfazure run download --name --output +""" + add_params = [ + add_param_run_name, + add_param_output, + add_param_overwrite, + _set_workspace_argument_for_subparsers, + ] + base_params + + activate_action( + name="download", + description="A CLI tool to download a run.", + epilog=epilog, + add_params=add_params, + subparsers=subparsers, + help_message="Download a run.", + action_param_name="sub_action", + ) + + def dispatch_run_commands(args: argparse.Namespace): if args.sub_action == "create": pf = _get_azure_pf_client(args.subscription, args.resource_group, args.workspace_name, debug=args.debug) @@ -403,6 +432,8 @@ def dispatch_run_commands(args: argparse.Namespace): restore_run(args.subscription, args.resource_group, args.workspace_name, args.name) elif args.sub_action == "update": update_run(args.subscription, args.resource_group, args.workspace_name, args.name, params=args.params_override) + elif args.sub_action == "download": + download_run(args) @exception_handler("List runs") @@ -530,3 +561,9 @@ def update_run( pf = _get_azure_pf_client(subscription_id, resource_group, workspace_name) run = pf.runs.update(run=run_name, display_name=display_name, description=description, tags=tags) print(json.dumps(run._to_dict(), indent=4)) + + +@exception_handler("Download run") +def download_run(args: argparse.Namespace): + pf = _get_azure_pf_client(args.subscription, args.resource_group, args.workspace_name, debug=args.debug) + pf.runs.download(run=args.name, output=args.output, overwrite=args.overwrite) diff --git a/src/promptflow/promptflow/_sdk/_constants.py b/src/promptflow/promptflow/_sdk/_constants.py index 2ef182e6d43..399251669ec 100644 --- a/src/promptflow/promptflow/_sdk/_constants.py +++ b/src/promptflow/promptflow/_sdk/_constants.py @@ -18,6 +18,7 @@ FLOW_TOOLS_JSON = "flow.tools.json" FLOW_TOOLS_JSON_GEN_TIMEOUT = 60 PROMPT_FLOW_DIR_NAME = ".promptflow" +PROMPT_FLOW_RUNS_DIR_NAME = ".runs" HOME_PROMPT_FLOW_DIR = (Path.home() / PROMPT_FLOW_DIR_NAME).resolve() SERVICE_CONFIG_FILE = "pf.yaml" PF_SERVICE_PORT_FILE = "pfs.port" diff --git a/src/promptflow/promptflow/_sdk/_errors.py b/src/promptflow/promptflow/_sdk/_errors.py index c850b567f77..9e3e686c2eb 100644 --- a/src/promptflow/promptflow/_sdk/_errors.py +++ b/src/promptflow/promptflow/_sdk/_errors.py @@ -92,6 +92,12 @@ class RunOperationParameterError(PromptflowException): pass +class RunOperationError(PromptflowException): + """Exception raised when run operation failed.""" + + pass + + class FlowOperationError(PromptflowException): """Exception raised when flow operation failed.""" diff --git a/src/promptflow/promptflow/azure/operations/_async_run_downloader.py b/src/promptflow/promptflow/azure/operations/_async_run_downloader.py new file mode 100644 index 00000000000..75176e109e1 --- /dev/null +++ b/src/promptflow/promptflow/azure/operations/_async_run_downloader.py @@ -0,0 +1,252 @@ +import asyncio +import json +import logging +from pathlib import Path +from typing import Optional, Union + +import httpx +from azure.storage.blob.aio import BlobServiceClient + +from promptflow._sdk._constants import DEFAULT_ENCODING, LOGGER_NAME +from promptflow._sdk._errors import RunNotFoundError, RunOperationError +from promptflow._utils.logger_utils import LoggerFactory +from promptflow.exceptions import UserErrorException + +logger = LoggerFactory.get_logger(name=LOGGER_NAME, verbosity=logging.WARNING) + + +class AsyncRunDownloader: + """Download run results from the service asynchronously. + + :param run: The run id. + :type run: str + :param run_ops: The run operations. + :type run_ops: ~promptflow.azure.operations.RunOperations + :param output_folder: The output folder to save the run results. + :type output_folder: Union[Path, str] + """ + + LOCAL_SNAPSHOT_FOLDER = "snapshot" + LOCAL_METRICS_FILE_NAME = "metrics.json" + LOCAL_LOGS_FILE_NAME = "logs.txt" + + IGNORED_PATTERN = ["__pycache__"] + + def __init__(self, run: str, run_ops: "RunOperations", output_folder: Union[str, Path]) -> None: + self.run = run + self.run_ops = run_ops + self.datastore = run_ops._workspace_default_datastore + self.output_folder = Path(output_folder) + self.blob_service_client = self._init_blob_service_client() + self._use_flow_outputs = False # old runtime does not write debug_info output asset, use flow_outputs instead + + def _init_blob_service_client(self): + logger.debug("Initializing blob service client.") + account_url = f"{self.datastore.account_name}.blob.{self.datastore.endpoint}" + return BlobServiceClient(account_url=account_url, credential=self.run_ops._credential) + + async def download(self) -> str: + """Download the run results asynchronously.""" + try: + # pass verify=False to client to disable SSL verification. + # Source: https://github.com/encode/httpx/issues/1331 + async with httpx.AsyncClient(verify=False) as client: + + async_tasks = [ + # put async functions in tasks to run in coroutines + self._download_artifacts_and_snapshot(client), + ] + sync_tasks = [ + # below functions are actually synchronous functions in order to reuse code, + # the execution time of these functions should be shorter than the above async functions + # so it won't increase the total execution time. + # the reason we still put them in the tasks is, on one hand the code is more consistent and + # we can use asyncio.gather() to wait for all tasks to finish, on the other hand, we can + # also evaluate below functions to be shorter than the async functions with the help of logs + self._download_run_metrics(), + self._download_run_logs(), + ] + tasks = async_tasks + sync_tasks + await asyncio.gather(*tasks) + except Exception as e: + raise RunOperationError(f"Failed to download run {self.run!r}. Error: {e}") from e + + return self.output_folder.resolve().as_posix() + + async def _download_artifacts_and_snapshot(self, httpx_client: httpx.AsyncClient): + run_data = await self._get_run_data_from_run_history(httpx_client) + + logger.debug("Parsing run data from run history to get necessary information.") + # extract necessary information from run data + snapshot_id = run_data["runMetadata"]["properties"]["azureml.promptflow.snapshot_id"] + output_data = run_data["runMetadata"]["outputs"].get("debug_info", None) + if output_data is None: + logger.warning( + "Downloading run '%s' but the 'debug_info' output assets is not available, " + "maybe because the job ran on old version runtime, trying to get `flow_outputs` output asset instead.", + self.run, + ) + self._use_flow_outputs = True + output_data = run_data["runMetadata"]["outputs"].get("flow_outputs", None) + output_asset_id = output_data["assetId"] + + async with self.blob_service_client: + container_name = self.datastore.container_name + logger.debug("Getting container client (%s) from workspace default datastore.", container_name) + container_client = self.blob_service_client.get_container_client(container_name) + + async with container_client: + tasks = [ + self._download_flow_artifacts(httpx_client, container_client, output_asset_id), + self._download_snapshot(httpx_client, container_client, snapshot_id), + ] + await asyncio.gather(*tasks) + + async def _get_run_data_from_run_history(self, client: httpx.AsyncClient): + """Get the run data from the run history.""" + logger.debug("Getting run data from run history.") + headers = self.run_ops._get_headers() + url = self.run_ops._run_history_endpoint_url + "/rundata" + + payload = { + "runId": self.run, + "selectRunMetadata": True, + "selectRunDefinition": True, + "selectJobSpecification": True, + } + + response = await client.post(url, headers=headers, json=payload) + if response.status_code == 200: + return response.json() + elif response.status_code == 404: + raise RunNotFoundError(f"Run {self.run!r} not found.") + else: + raise RunOperationError( + f"Failed to get run from service. Code: {response.status_code}, text: {response.text}" + ) + + async def _download_run_metrics( + self, + ): + """Download the run metrics.""" + logger.debug("Downloading run metrics.") + metrics = self.run_ops.get_metrics(self.run) + with open(self.output_folder / self.LOCAL_METRICS_FILE_NAME, "w", encoding=DEFAULT_ENCODING) as f: + json.dump(metrics, f, ensure_ascii=False) + logger.debug("Downloaded run metrics.") + + async def _download_flow_artifacts(self, httpx_client: httpx.AsyncClient, container_client, output_data): + """Download the output data.""" + asset_path = await self._get_asset_path(httpx_client, output_data) + await self._download_blob_folder_from_asset_path(container_client, asset_path) + + async def _download_blob_folder_from_asset_path( + self, container_client, asset_path: str, local_folder: Optional[Path] = None + ): + """Download the blob data from the data path.""" + logger.debug("Downloading all blobs from data path prefix '%s'", asset_path) + if local_folder is None: + local_folder = self.output_folder + + tasks = [] + async for blob in container_client.list_blobs(name_starts_with=asset_path): + blob_client = container_client.get_blob_client(blob.name) + relative_path = Path(blob.name).relative_to(asset_path) + local_path = local_folder / relative_path + tasks.append(self._download_single_blob(blob_client, local_path)) + await asyncio.gather(*tasks) + + async def _download_single_blob(self, blob_client, local_path: Optional[Path] = None): + """Download a single blob.""" + if local_path is None: + local_path = Path(self.output_folder / blob_client.blob_name) + elif local_path.exists(): + raise UserErrorException(f"Local file {local_path.resolve().as_posix()!r} already exists.") + + # ignore some files + for item in self.IGNORED_PATTERN: + if item in blob_client.blob_name: + logger.warning( + "Ignoring file '%s' because it matches the ignored pattern '%s'", local_path.as_posix(), item + ) + return None + + logger.debug("Downloading blob '%s' to local path '%s'", blob_client.blob_name, local_path.resolve().as_posix()) + local_path.parent.mkdir(parents=True, exist_ok=True) + async with blob_client: + with open(local_path, "wb") as f: + stream = await blob_client.download_blob() + data = await stream.readall() + # TODO: File IO may block the event loop, consider using thread pool. e.g. to_thread() method + f.write(data) + return local_path + + async def _download_snapshot(self, httpx_client: httpx.AsyncClient, container_client, snapshot_id): + """Download the flow snapshot.""" + snapshot_urls = await self._get_flow_snapshot_urls(httpx_client, snapshot_id) + + logger.debug("Downloading all snapshot blobs from snapshot urls.") + tasks = [] + for url in snapshot_urls: + blob_name = url.split(self.datastore.container_name)[-1].lstrip("/") + blob_client = container_client.get_blob_client(blob_name) + relative_path = url.split(self.run)[-1].lstrip("/") + local_path = Path(self.output_folder / self.LOCAL_SNAPSHOT_FOLDER / relative_path) + tasks.append(self._download_single_blob(blob_client, local_path)) + await asyncio.gather(*tasks) + + async def _get_flow_snapshot_urls(self, httpx_client: httpx.AsyncClient, snapshot_id): + logger.debug("Getting flow snapshot blob urls from snapshot id with calling to content service.") + headers = self.run_ops._get_headers() + endpoint = self.run_ops._run_history_endpoint_url.replace("/history/v1.0", "/content/v2.0") + url = endpoint + "/snapshots/sas" + payload = { + "snapshotOrAssetId": snapshot_id, + } + + response = await httpx_client.post(url, headers=headers, json=payload) + if response.status_code == 200: + return self._parse_snapshot_response(response.json()) + elif response.status_code == 404: + raise UserErrorException(f"Snapshot {snapshot_id!r} not found.") + else: + raise RunOperationError( + f"Failed to get snapshot {snapshot_id!r} from content service. " + f"Code: {response.status_code}, text: {response.text}" + ) + + async def _get_asset_path(self, client: httpx.AsyncClient, asset_id): + """Get the asset path from asset id.""" + logger.debug("Getting asset path from asset id with calling to data service.") + headers = self.run_ops._get_headers() + endpoint = self.run_ops._run_history_endpoint_url.replace("/history", "/data") + url = endpoint + "/dataversion/getByAssetId" + payload = { + "value": asset_id, + } + + response = await client.post(url, headers=headers, json=payload) + response_data = response.json() + data_path = response_data["dataVersion"]["dataUri"].split("/paths/")[-1] + if self._use_flow_outputs: + data_path = data_path.replace("flow_outputs", "flow_artifacts") + return data_path + + def _parse_snapshot_response(self, response: dict): + """Parse the snapshot response.""" + urls = [] + if response["absoluteUrl"]: + urls.append(response["absoluteUrl"]) + for value in response["children"].values(): + urls += self._parse_snapshot_response(value) + + return urls + + async def _download_run_logs(self): + """Download the run logs.""" + logger.debug("Downloading run logs.") + logs = self.run_ops._get_log(self.run) + + with open(self.output_folder / self.LOCAL_LOGS_FILE_NAME, "w", encoding=DEFAULT_ENCODING) as f: + f.write(logs) + logger.debug("Downloaded run logs.") diff --git a/src/promptflow/promptflow/azure/operations/_run_operations.py b/src/promptflow/promptflow/azure/operations/_run_operations.py index fe64c3c845d..d7d56f8b03a 100644 --- a/src/promptflow/promptflow/azure/operations/_run_operations.py +++ b/src/promptflow/promptflow/azure/operations/_run_operations.py @@ -1,6 +1,7 @@ # --------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # --------------------------------------------------------- +import asyncio import concurrent import copy import hashlib @@ -8,10 +9,12 @@ import logging import os import re +import shutil import sys import time from concurrent.futures import ThreadPoolExecutor from functools import cached_property +from pathlib import Path from typing import Any, Dict, List, Optional, Union import requests @@ -33,6 +36,8 @@ LOGGER_NAME, MAX_RUN_LIST_RESULTS, MAX_SHOW_DETAILS_RESULTS, + PROMPT_FLOW_DIR_NAME, + PROMPT_FLOW_RUNS_DIR_NAME, REGISTRY_URI_PREFIX, VIS_PORTAL_URL_TMPL, AzureRunTypes, @@ -45,6 +50,7 @@ from promptflow._sdk._telemetry import ActivityType, WorkspaceTelemetryMixin, monitor_operation from promptflow._sdk._utils import in_jupyter_notebook, incremental_print, is_remote_uri, print_red_error from promptflow._sdk.entities import Run +from promptflow._utils.async_utils import async_run_allowing_running_loop from promptflow._utils.flow_utils import get_flow_lineage_id from promptflow._utils.logger_utils import LoggerFactory from promptflow.azure._constants._flow import ( @@ -59,6 +65,7 @@ from promptflow.azure._restclient.flow_service_caller import FlowServiceCaller from promptflow.azure._utils.gerneral import get_user_alias_from_credential from promptflow.azure.operations._flow_operations import FlowOperations +from promptflow.exceptions import UserErrorException RUNNING_STATUSES = RunStatus.get_running_statuses() @@ -109,7 +116,7 @@ def __init__( self._credential = credential self._flow_operations = flow_operations self._orchestrators = OperationOrchestrator(self._all_operations, self._operation_scope, self._operation_config) - self._workspace_default_datastore = self._datastore_operations.get_default().name + self._workspace_default_datastore = self._datastore_operations.get_default() @property def _data_operations(self): @@ -761,7 +768,7 @@ def _get_data_type(_data): self._operation_scope, self._datastore_operations, test_data, - datastore_name=self._workspace_default_datastore, + datastore_name=self._workspace_default_datastore.name, show_progress=self._show_progress, ) if data_type == AssetTypes.URI_FOLDER and test_data and not test_data.endswith("/"): @@ -994,3 +1001,52 @@ def _resolve_flow_definition_resource_id(self, run: Run): workspace_id = self._workspace._workspace_id location = self._workspace.location return f"azureml://locations/{location}/workspaces/{workspace_id}/flows/{run._flow_name}" + + @monitor_operation(activity_name="pfazure.runs.download", activity_type=ActivityType.PUBLICAPI) + def download( + self, run: Union[str, Run], output: Optional[Union[str, Path]] = None, overwrite: Optional[bool] = False + ) -> str: + """Download the data of a run, including input, output, snapshot and other run information. + + :param run: The run name or run object + :type run: Union[str, ~promptflow.entities.Run] + :param output: The output directory. Default to be default to be "~/.promptflow/.runs" folder. + :type output: Optional[str] + :param overwrite: Whether to overwrite the existing run folder. Default to be False. + :type overwrite: Optional[bool] + :return: The run directory path + :rtype: str + """ + import platform + + from promptflow.azure.operations._async_run_downloader import AsyncRunDownloader + + run = Run._validate_and_return_run_name(run) + if output is None: + # default to be "~/.promptflow/.runs" folder + output_directory = Path.home() / PROMPT_FLOW_DIR_NAME / PROMPT_FLOW_RUNS_DIR_NAME + else: + output_directory = Path(output) + + run_folder = output_directory / run + if run_folder.exists(): + if overwrite is True: + logger.warning("Removing existing run folder %r.", run_folder.resolve().as_posix()) + shutil.rmtree(run_folder) + else: + raise UserErrorException( + f"Run folder {run_folder.resolve().as_posix()!r} already exists, please specify a new output path " + f"or set the overwrite flag to be true." + ) + run_folder.mkdir(parents=True) + + run_downloader = AsyncRunDownloader(run=run, run_ops=self, output_folder=run_folder) + if platform.system().lower() == "windows": + # Reference: https://stackoverflow.com/questions/45600579/asyncio-event-loop-is-closed-when-getting-loop + # On Windows seems to be a problem with EventLoopPolicy, use this snippet to work around it + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) + + async_run_allowing_running_loop(run_downloader.download) + result_path = run_folder.resolve().as_posix() + logger.info(f"Successfully downloaded run {run!r} to {result_path!r}.") + return result_path diff --git a/src/promptflow/tests/sdk_cli_azure_test/e2etests/test_run_operations.py b/src/promptflow/tests/sdk_cli_azure_test/e2etests/test_run_operations.py index 63f55fa5098..9f2e7c92326 100644 --- a/src/promptflow/tests/sdk_cli_azure_test/e2etests/test_run_operations.py +++ b/src/promptflow/tests/sdk_cli_azure_test/e2etests/test_run_operations.py @@ -796,6 +796,23 @@ def test_vnext_workspace_base_url(self): ) assert service_caller.caller._client._base_url == "https://promptflow.azure-api.net/" + @pytest.mark.skipif(condition=not is_live(), reason="need to fix recording") + def test_download_run(self, pf): + from promptflow.azure.operations._async_run_downloader import AsyncRunDownloader + + run = "c619f648-c809-4545-9f94-f67b0a680706" + + expected_files = [ + AsyncRunDownloader.LOCAL_LOGS_FILE_NAME, + AsyncRunDownloader.LOCAL_METRICS_FILE_NAME, + f"{AsyncRunDownloader.LOCAL_SNAPSHOT_FOLDER}/flow.dag.yaml", + ] + + with TemporaryDirectory() as tmp_dir: + pf.runs.download(run=run, output=tmp_dir) + for file in expected_files: + assert Path(tmp_dir, run, file).exists() + def test_request_id_when_making_http_requests(self, pf, runtime: str, randstr: Callable[[str], str]): from azure.core.exceptions import HttpResponseError diff --git a/src/promptflow/tests/sdk_cli_azure_test/unittests/test_cli.py b/src/promptflow/tests/sdk_cli_azure_test/unittests/test_cli.py index 7a496d8fb0a..dcf8761c62e 100644 --- a/src/promptflow/tests/sdk_cli_azure_test/unittests/test_cli.py +++ b/src/promptflow/tests/sdk_cli_azure_test/unittests/test_cli.py @@ -320,3 +320,20 @@ def check_workspace_info(*args, **kwargs): "--include-archived", *operation_scope_args, ) + + def test_run_download(self, mocker: MockFixture, operation_scope_args): + from promptflow.azure.operations._run_operations import RunOperations + + mocked = mocker.patch.object(RunOperations, "download") + mocked.return_value = "fake_output_run_dir" + run_pf_command( + "run", + "download", + "--name", + "test_run", + "--output", + "fake_output_dir", + "--overwrite", + *operation_scope_args, + ) + mocked.assert_called_once() From 429c6312d3e229989ba03264cd7c24a72f5e5d1b Mon Sep 17 00:00:00 2001 From: Philip Gao Date: Wed, 6 Dec 2023 19:20:25 +0800 Subject: [PATCH 4/8] Enable more on new matrix. (#1376) # Description 1step, enable python 311 # All Promptflow Contribution checklist: - [x] **The pull request does not introduce [breaking changes].** - [ ] **CHANGELOG is updated for new features, bug fixes or other significant changes.** - [ ] **I have read the [contribution guidelines](../CONTRIBUTING.md).** - [ ] **Create an issue and link to the pull request to get dedicated review from promptflow team. Learn more: [suggested workflow](../CONTRIBUTING.md#suggested-workflow).** ## General Guidelines and Best Practices - [ ] Title of the pull request is clear and informative. - [ ] There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, [see this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md). ### Testing Guidelines - [ ] Pull request includes test coverage for the included changes. --- ...romptflow-release-testing-matrix-alter.yml | 266 ------------------ .../promptflow-release-testing-matrix.yml | 225 ++++++++++++--- scripts/building/run_coverage_tests.py | 2 +- .../unittests/test_azure_cli_activity_name.py | 54 ++-- .../sdk_cli_test/e2etests/test_executable.py | 5 +- src/promptflow/tests/sdk_pfs_test/conftest.py | 3 +- 6 files changed, 221 insertions(+), 334 deletions(-) delete mode 100644 .github/workflows/promptflow-release-testing-matrix-alter.yml diff --git a/.github/workflows/promptflow-release-testing-matrix-alter.yml b/.github/workflows/promptflow-release-testing-matrix-alter.yml deleted file mode 100644 index a74e4545060..00000000000 --- a/.github/workflows/promptflow-release-testing-matrix-alter.yml +++ /dev/null @@ -1,266 +0,0 @@ -name: promptflow-release-testing-matrix -on: - workflow_call: - workflow_dispatch: - inputs: - # can leave empty when trigger manually - # GitHub Actions API for trigger does not return workflow run id - # there we reference below Stack Overflow solution: - # https://stackoverflow.com/a/69500478 - # which adds an identifier in workflow run jobs and can be used for filter - id: - description: Identifier for the workflow run - required: false - type: string -env: - testWorkingDirectory: src/promptflow - PYTHONPATH: ${{ github.workspace }}/src/promptflow - IS_IN_CI_PIPELINE: "true" -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: workflow run id - ${{ inputs.id }} - run: | - echo "workflow run id: ${{ inputs.id }}" - - name: checkout - uses: actions/checkout@v4 - - name: Python Setup - 3.9 - uses: "./.github/actions/step_create_python_environment" - with: - pythonVersion: 3.9 - - name: Build wheel - uses: "./.github/actions/step_sdk_setup" - with: - setupType: promptflow_with_extra - scriptPath: ${{ env.testWorkingDirectory }} - - name: Upload Wheel - uses: actions/upload-artifact@v3 - with: - name: wheel - path: | - ${{ github.workspace }}/src/promptflow/dist/*.whl - ${{ github.workspace }}/src/promptflow-tools/dist/*.whl - promptflow_sdk_cli_tests: - if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call' || github.event_name == 'pull_request' }} - needs: build - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - pythonVersion: ['3.8', '3.9', '3.10'] - runs-on: ${{ matrix.os }} - steps: - - name: set test mode - shell: pwsh - run: | - # Windows support of multiprocessing is different from other platforms, mock injections is not working properly in replay mode. - if ("${{ github.event_name }}" -eq "pull_request" -and (-not "${{ matrix.os }}" -eq "windows-latest")) { - echo "PROMPT_FLOW_TEST_MODE=replay" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append - } else { - echo "PROMPT_FLOW_TEST_MODE=live" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append - } - - name: checkout - uses: actions/checkout@v3 - - name: Display and Set Environment Variables - run: - env | sort >> $GITHUB_OUTPUT - shell: bash -el {0} - - name: Python Env Setup - ${{ matrix.os }} - Python Version ${{ matrix.pythonVersion }} - uses: "./.github/actions/step_create_python_environment" - with: - pythonVersion: ${{ matrix.pythonVersion }} - - name: Download Artifacts - uses: actions/download-artifact@v3 - with: - name: wheel - path: artifacts - - name: Azure Login - uses: azure/login@v1 - with: - creds: ${{ secrets.AZURE_CREDENTIALS }} - - name: Generate Configs - uses: "./.github/actions/step_generate_configs" - with: - targetFolder: ${{ env.testWorkingDirectory }} - - name: Install pf - shell: pwsh - working-directory: artifacts - run: | - pip install -r ${{ github.workspace }}/src/promptflow/dev_requirements.txt - gci ./promptflow -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install "$($_.FullName)"}} - gci ./promptflow-tools -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install $_.FullName}} - pip freeze - - name: Run SDK CLI Test - shell: pwsh - working-directory: ${{ env.testWorkingDirectory }} - run: | - python "../../scripts/building/run_coverage_tests.py" ` - -p promptflow ` - -t ${{ github.workspace }}/src/promptflow/tests/sdk_cli_test ` - -l eastus ` - -m "unittest or e2etest" ` - -o "${{ github.workspace }}/test-results-sdk-cli.xml" ` - --ignore-glob ${{ github.workspace }}/src/promptflow/tests/sdk_cli_test/e2etests/test_executable.py - - name: Install pf executable - shell: pwsh - working-directory: artifacts - run: | - Set-PSDebug -Trace 1 - gci ./promptflow -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install "$($_.FullName)[executable]"}} - pip freeze - - name: Run SDK CLI Executable Test - shell: pwsh - working-directory: ${{ env.testWorkingDirectory }} - run: | - python "../../scripts/building/run_coverage_tests.py" ` - -p promptflow ` - -t ${{ github.workspace }}/src/promptflow/tests/sdk_cli_test/e2etests/test_executable.py ` - -l eastus ` - -m "unittest or e2etest" ` - -o "${{ github.workspace }}/test-results-sdk-cli-executable.xml" - - name: Upload pytest test results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) - if: ${{ always() }} - uses: actions/upload-artifact@v3 - with: - name: Test Results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) - path: ${{ github.workspace }}/*.xml - promptflow_sdk_cli_azure_tests: - needs: build - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - pythonVersion: ['3.8', '3.9', '3.10'] - runs-on: ${{ matrix.os }} - steps: - - name: checkout - uses: actions/checkout@v3 - - name: Display and Set Environment Variables - run: - env | sort >> $GITHUB_OUTPUT - shell: bash -el {0} - - name: Python Env Setup - ${{ matrix.os }} - Python Version ${{ matrix.pythonVersion }} - uses: "./.github/actions/step_create_python_environment" - with: - pythonVersion: ${{ matrix.pythonVersion }} - - name: Download Artifacts - uses: actions/download-artifact@v3 - with: - name: wheel - path: artifacts - - name: Azure Login - uses: azure/login@v1 - with: - creds: ${{ secrets.AZURE_CREDENTIALS }} - - name: Generate Configs - uses: "./.github/actions/step_generate_configs" - with: - targetFolder: ${{ env.testWorkingDirectory }} - - name: Install pf azure - shell: pwsh - working-directory: artifacts - run: | - pip install -r ${{ github.workspace }}/src/promptflow/dev_requirements.txt - gci ./promptflow -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install "$($_.FullName)[azure]"}} - gci ./promptflow-tools -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install "$($_.FullName)"}} - pip freeze - - name: Run SDK CLI Azure Test - shell: pwsh - working-directory: ${{ env.testWorkingDirectory }} - env: - PROMPT_FLOW_TEST_MODE: "live" - run: | - python "../../scripts/building/run_coverage_tests.py" ` - -p promptflow ` - -t ${{ github.workspace }}/src/promptflow/tests/sdk_cli_azure_test ` - -l eastus ` - -m "unittest or e2etest" ` - -o "${{ github.workspace }}/test-results-sdk-cli-azure.xml" - - name: Upload pytest test results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) - if: ${{ always() }} - uses: actions/upload-artifact@v3 - with: - name: Test Results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) - path: ${{ github.workspace }}/*.xml - promptflow_executor_tests: - if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call' || github.event_name == 'pull_request' }} - needs: build - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - pythonVersion: ['3.8', '3.9', '3.10'] - runs-on: ${{ matrix.os }} - steps: - - name: checkout - uses: actions/checkout@v3 - - name: Display and Set Environment Variables - run: - env | sort >> $GITHUB_OUTPUT - shell: bash -el {0} - - name: Python Env Setup - ${{ matrix.os }} - Python Version ${{ matrix.pythonVersion }} - uses: "./.github/actions/step_create_python_environment" - with: - pythonVersion: ${{ matrix.pythonVersion }} - - name: Download Artifacts - uses: actions/download-artifact@v3 - with: - name: wheel - path: artifacts - - name: Azure Login - uses: azure/login@v1 - with: - creds: ${{ secrets.AZURE_CREDENTIALS }} - - name: Generate Configs - uses: "./.github/actions/step_generate_configs" - with: - targetFolder: ${{ env.testWorkingDirectory }} - - name: Install pf - shell: pwsh - working-directory: artifacts - run: | - pip install -r ${{ github.workspace }}/src/promptflow/dev_requirements.txt - gci ./promptflow -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install "$($_.FullName)[azure]"}} - gci ./promptflow-tools -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install $_.FullName}} - pip freeze - - name: Run Executor Test - shell: pwsh - working-directory: ${{ github.workspace }} - run: | - gci env:* | sort-object name - az account show - pip install langchain - pip install numexpr - python scripts/building/run_coverage_tests.py ` - -p ${{ github.workspace }}/src/promptflow/promptflow ` - -t ${{ github.workspace }}/src/promptflow/tests/executor/e2etests ${{ github.workspace }}/src/promptflow/tests/executor/unittests ` - -l eastus ` - -m "all" ` - -o "${{ github.workspace }}/test-results-executor.xml" - - name: Upload pytest test results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) - if: ${{ always() }} - uses: actions/upload-artifact@v3 - with: - name: Test Results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) - path: ${{ github.workspace }}/*.xml - publish-test-results: - name: "Publish Tests Results" - needs: [ promptflow_sdk_cli_tests, promptflow_sdk_cli_azure_tests, promptflow_executor_tests ] - runs-on: ubuntu-latest - permissions: - checks: write - pull-requests: write - contents: read - issues: read - if: always() - - steps: - - name: Download Artifacts - uses: actions/download-artifact@v3 - with: - path: artifacts - - name: Publish Test Results - uses: EnricoMi/publish-unit-test-result-action@v2 - with: - files: "artifacts/**/test-*.xml" diff --git a/.github/workflows/promptflow-release-testing-matrix.yml b/.github/workflows/promptflow-release-testing-matrix.yml index 945a3caf525..9d63907fdca 100644 --- a/.github/workflows/promptflow-release-testing-matrix.yml +++ b/.github/workflows/promptflow-release-testing-matrix.yml @@ -13,7 +13,6 @@ on: required: false type: string env: - packageSetupType: promptflow_with_extra testWorkingDirectory: src/promptflow PYTHONPATH: ${{ github.workspace }}/src/promptflow IS_IN_CI_PIPELINE: "true" @@ -24,12 +23,36 @@ jobs: - name: workflow run id - ${{ inputs.id }} run: | echo "workflow run id: ${{ inputs.id }}" - all_tests: + build: + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@v4 + - name: Python Setup - 3.9 + uses: "./.github/actions/step_create_python_environment" + with: + pythonVersion: 3.9 + - name: Build wheel + uses: "./.github/actions/step_sdk_setup" + with: + setupType: promptflow_with_extra + scriptPath: ${{ env.testWorkingDirectory }} + - name: Upload Wheel + uses: actions/upload-artifact@v3 + with: + name: wheel + path: | + ${{ github.workspace }}/src/promptflow/dist/*.whl + ${{ github.workspace }}/src/promptflow-tools/dist/*.whl + promptflow_sdk_cli_tests: + if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call' || github.event_name == 'pull_request' }} + needs: build + env: + PROMPT_FLOW_TEST_MODE: "live" strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - testType: [sdk-cli, executor] + os: [ubuntu-latest, windows-latest, macos-latest] pythonVersion: ['3.8', '3.9', '3.10', '3.11'] runs-on: ${{ matrix.os }} steps: @@ -43,43 +66,174 @@ jobs: uses: "./.github/actions/step_create_python_environment" with: pythonVersion: ${{ matrix.pythonVersion }} - - name: Build wheel - uses: "./.github/actions/step_sdk_setup" + - name: Download Artifacts + uses: actions/download-artifact@v3 with: - setupType: promptflow_with_extra - scriptPath: ${{ env.testWorkingDirectory }} + name: wheel + path: artifacts - name: Azure Login uses: azure/login@v1 + if: env.PROMPT_FLOW_TEST_MODE == 'live' with: creds: ${{ secrets.AZURE_CREDENTIALS }} - name: Generate Configs uses: "./.github/actions/step_generate_configs" + if: env.PROMPT_FLOW_TEST_MODE == 'live' with: targetFolder: ${{ env.testWorkingDirectory }} - - name: Get number of CPU cores - uses: SimenB/github-actions-cpu-cores@v1 - id: cpu-cores + - name: generate test resources placeholder + if: env.PROMPT_FLOW_TEST_MODE != 'live' + shell: pwsh + working-directory: ${{ env.testWorkingDirectory }} + run: | + cp ${{ github.workspace }}/src/promptflow/dev-connections.json.example ${{ github.workspace }}/src/promptflow/connections.json + - name: Install pf + shell: pwsh + working-directory: artifacts + run: | + pip install -r ${{ github.workspace }}/src/promptflow/dev_requirements.txt + gci ./promptflow -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install "$($_.FullName)"}} + gci ./promptflow-tools -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install $_.FullName}} + pip freeze - name: Run SDK CLI Test - if : ${{ matrix.testType == 'sdk-cli' }} shell: pwsh working-directory: ${{ env.testWorkingDirectory }} run: | - gci env:* | sort-object name - az account show python "../../scripts/building/run_coverage_tests.py" ` -p promptflow ` - -t ${{ github.workspace }}/src/promptflow/tests/sdk_cli_azure_test ${{ github.workspace }}/src/promptflow/tests/sdk_cli_test ` + -t ${{ github.workspace }}/src/promptflow/tests/sdk_cli_test ` -l eastus ` -m "unittest or e2etest" ` - -n ${{ steps.cpu-cores.outputs.count }} - mv ${{ github.workspace }}/${{ env.testWorkingDirectory }}/test-results.xml ${{ github.workspace }}/test-results-sdk-cli.xml + -o "${{ github.workspace }}/test-results-sdk-cli.xml" ` + --ignore-glob ${{ github.workspace }}/src/promptflow/tests/sdk_cli_test/e2etests/test_executable.py + - name: Install pf executable + shell: pwsh + working-directory: artifacts + run: | + Set-PSDebug -Trace 1 + gci ./promptflow -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install "$($_.FullName)[executable]"}} + pip freeze + - name: Run SDK CLI Executable Test + shell: pwsh + working-directory: ${{ env.testWorkingDirectory }} + run: | + python "../../scripts/building/run_coverage_tests.py" ` + -p promptflow ` + -t ${{ github.workspace }}/src/promptflow/tests/sdk_cli_test/e2etests/test_executable.py ` + -l eastus ` + -m "unittest or e2etest" ` + -o "${{ github.workspace }}/test-results-sdk-cli-executable.xml" + - name: Upload pytest test results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) + if: ${{ always() }} + uses: actions/upload-artifact@v3 + with: + name: promptflow_sdk_cli_tests Test Results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) + path: ${{ github.workspace }}/*.xml + promptflow_sdk_cli_azure_tests: + needs: build + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + pythonVersion: ['3.8', '3.9', '3.10', '3.11'] + env: + PROMPT_FLOW_TEST_MODE: "live" + runs-on: ${{ matrix.os }} + steps: + - name: checkout + uses: actions/checkout@v4 + - name: Display and Set Environment Variables + run: + env | sort >> $GITHUB_OUTPUT + shell: bash -el {0} + - name: Python Env Setup - ${{ matrix.os }} - Python Version ${{ matrix.pythonVersion }} + uses: "./.github/actions/step_create_python_environment" + with: + pythonVersion: ${{ matrix.pythonVersion }} + - name: Download Artifacts + uses: actions/download-artifact@v3 + with: + name: wheel + path: artifacts + - name: Azure Login + uses: azure/login@v1 + if: env.PROMPT_FLOW_TEST_MODE == 'live' + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + - name: Generate Configs + uses: "./.github/actions/step_generate_configs" + if: env.PROMPT_FLOW_TEST_MODE == 'live' + with: + targetFolder: ${{ env.testWorkingDirectory }} + - name: Install pf azure + shell: pwsh + working-directory: artifacts + run: | + pip install -r ${{ github.workspace }}/src/promptflow/dev_requirements.txt + gci ./promptflow -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install "$($_.FullName)[azure]"}} + gci ./promptflow-tools -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install "$($_.FullName)"}} + pip freeze + - name: Run SDK CLI Azure Test + shell: pwsh + working-directory: ${{ env.testWorkingDirectory }} + run: | + python "../../scripts/building/run_coverage_tests.py" ` + -p promptflow ` + -t ${{ github.workspace }}/src/promptflow/tests/sdk_cli_azure_test ` + -l eastus ` + -m "unittest or e2etest" ` + -o "${{ github.workspace }}/test-results-sdk-cli-azure.xml" + - name: Upload pytest test results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) + if: ${{ always() }} + uses: actions/upload-artifact@v3 + with: + name: promptflow_sdk_cli_azure_tests Test Results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) + path: ${{ github.workspace }}/*.xml + promptflow_executor_tests: + if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call' || github.event_name == 'pull_request' }} + needs: build + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + pythonVersion: ['3.8', '3.9', '3.10', '3.11'] + runs-on: ${{ matrix.os }} + steps: + - name: checkout + uses: actions/checkout@v4 + - name: Display and Set Environment Variables + run: + env | sort >> $GITHUB_OUTPUT + shell: bash -el {0} + - name: Python Env Setup - ${{ matrix.os }} - Python Version ${{ matrix.pythonVersion }} + uses: "./.github/actions/step_create_python_environment" + with: + pythonVersion: ${{ matrix.pythonVersion }} + - name: Download Artifacts + uses: actions/download-artifact@v3 + with: + name: wheel + path: artifacts + - name: Azure Login + uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + - name: Generate Configs + uses: "./.github/actions/step_generate_configs" + with: + targetFolder: ${{ env.testWorkingDirectory }} + - name: Install pf + shell: pwsh + working-directory: artifacts + run: | + pip install -r ${{ github.workspace }}/src/promptflow/dev_requirements.txt + gci ./promptflow -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install "$($_.FullName)[azure]"}} + gci ./promptflow-tools -Recurse | % {if ($_.Name.Contains('.whl')) {python -m pip install $_.FullName}} + pip freeze - name: Run Executor Test - if : ${{ matrix.testType == 'executor' }} shell: pwsh working-directory: ${{ github.workspace }} run: | - gci env:* | sort-object name - az account show pip install langchain pip install numexpr python scripts/building/run_coverage_tests.py ` @@ -87,29 +241,30 @@ jobs: -t ${{ github.workspace }}/src/promptflow/tests/executor/e2etests ${{ github.workspace }}/src/promptflow/tests/executor/unittests ` -l eastus ` -m "all" ` - -n ${{ steps.cpu-cores.outputs.count }} - mv ./test-results.xml ./test-results-executor.xml + -o "${{ github.workspace }}/test-results-executor.xml" - name: Upload pytest test results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) if: ${{ always() }} uses: actions/upload-artifact@v3 with: - name: Test Results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) + name: promptflow_executor_tests Test Results (Python ${{ matrix.pythonVersion }}) (OS ${{ matrix.os }}) path: ${{ github.workspace }}/*.xml publish-test-results: name: "Publish Tests Results" - needs: - - all_tests + needs: [ promptflow_sdk_cli_tests, promptflow_sdk_cli_azure_tests, promptflow_executor_tests ] runs-on: ubuntu-latest - permissions: write-all + permissions: + checks: write + pull-requests: write + contents: read + issues: read if: always() steps: - - name: checkout - uses: actions/checkout@v4 - - name: Publish Test Results - uses: "./.github/actions/step_publish_test_results" - with: - testActionFileName: promptflow-release-testing-matrix.yml - testResultTitle: Release Test Matrix - token: ${{ secrets.GITHUB_TOKEN }} - coverageThreshold: 0 + - name: Download Artifacts + uses: actions/download-artifact@v3 + with: + path: artifacts + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + with: + files: "artifacts/**/test-*.xml" diff --git a/scripts/building/run_coverage_tests.py b/scripts/building/run_coverage_tests.py index 15ec2f98483..96781561fd1 100644 --- a/scripts/building/run_coverage_tests.py +++ b/scripts/building/run_coverage_tests.py @@ -69,7 +69,7 @@ run_command(["pip", "list"]) run_command(["pip", "show", "promptflow", "promptflow-sdk"]) - pytest_command = ["pytest", "--junitxml=test-results.xml"] + pytest_command = ["pytest", f"--junitxml={args.o}"] pytest_command += test_paths_list if args.coverage_config: if args.p: diff --git a/src/promptflow/tests/sdk_cli_azure_test/unittests/test_azure_cli_activity_name.py b/src/promptflow/tests/sdk_cli_azure_test/unittests/test_azure_cli_activity_name.py index 7fc2752afb3..9b9a7eb731f 100644 --- a/src/promptflow/tests/sdk_cli_azure_test/unittests/test_azure_cli_activity_name.py +++ b/src/promptflow/tests/sdk_cli_azure_test/unittests/test_azure_cli_activity_name.py @@ -1,4 +1,5 @@ import pytest + from promptflow._cli._pf_azure.entry import get_parser_args from promptflow._cli._utils import _get_cli_activity_name @@ -11,37 +12,30 @@ def get_cli_activity_name(cmd): @pytest.mark.unittest class TestAzureCliTimeConsume: def test_pfazure_run_create(self, activity_name="pfazure.run.create"): - assert get_cli_activity_name( - cmd=( - "pfazure", - "run", - "create", - "--flow", - "print_input_flow", - "--data", - "print_input_flow.jsonl" - )) == activity_name + assert ( + get_cli_activity_name( + cmd=("pfazure", "run", "create", "--flow", "print_input_flow", "--data", "print_input_flow.jsonl") + ) + == activity_name + ) def test_pfazure_run_update(self, activity_name="pfazure.run.update"): - assert get_cli_activity_name( - cmd=( - "pfazure", - "run", - "update", - "--name", - "test_run", - "--set", - "display_name=test_run", - "description='test_description'", - "tags.key1=value1" - )) == activity_name + assert ( + get_cli_activity_name( + cmd=( + "pfazure", + "run", + "update", + "--name", + "test_run", + "--set", + "display_name=test_run", + "description='test_description'", + "tags.key1=value1", + ) + ) + == activity_name + ) def test_run_restore(self, activity_name="pfazure.run.restore"): - assert get_cli_activity_name( - cmd=( - "pfazure", - "run", - "restore", - "--name", - "test_run" - )) == activity_name + assert get_cli_activity_name(cmd=("pfazure", "run", "restore", "--name", "test_run")) == activity_name diff --git a/src/promptflow/tests/sdk_cli_test/e2etests/test_executable.py b/src/promptflow/tests/sdk_cli_test/e2etests/test_executable.py index 5d0b28a6140..e10597382e7 100644 --- a/src/promptflow/tests/sdk_cli_test/e2etests/test_executable.py +++ b/src/promptflow/tests/sdk_cli_test/e2etests/test_executable.py @@ -18,7 +18,10 @@ @pytest.mark.cli_test @pytest.mark.e2etest class TestExecutable: - @pytest.mark.skipif(sys.platform == "win32", reason="Raise Exception: Process terminated with exit code 4294967295") + @pytest.mark.skipif( + sys.platform == "win32" or sys.platform == "darwin", + reason="Raise Exception: Process terminated with exit code 4294967295", + ) def test_flow_build_executable(self): source = f"{FLOWS_DIR}/web_classification/flow.dag.yaml" target = "promptflow._sdk.operations._flow_operations.FlowOperations._run_pyinstaller" diff --git a/src/promptflow/tests/sdk_pfs_test/conftest.py b/src/promptflow/tests/sdk_pfs_test/conftest.py index 17147455d9e..30dc613db4f 100644 --- a/src/promptflow/tests/sdk_pfs_test/conftest.py +++ b/src/promptflow/tests/sdk_pfs_test/conftest.py @@ -6,13 +6,14 @@ from flask.app import Flask from promptflow import PFClient -from promptflow._sdk._service.app import create_app from .utils import PFSOperations @pytest.fixture def app() -> Flask: + from promptflow._sdk._service.app import create_app + app, _ = create_app() app.config.update({"TESTING": True}) yield app From eb489336fd695438146a3d32b846dab39005e1a8 Mon Sep 17 00:00:00 2001 From: Han Wang Date: Thu, 7 Dec 2023 10:57:33 +0800 Subject: [PATCH 5/8] [SDK] Fix test in matrix (#1400) # Description This pull request includes a modification to the `log_event` function in `test_telemetry.py` to assert the value of the `ai.cloud.role` tag in the `envelope` dictionary. The change ensures that the `ai.cloud.role` tag is either equal to the base name of the current script or the string "***". This modification was made to either scrub the role name or keep it in a whitelist. Main change: * `src/promptflow/tests/sdk_cli_azure_test/e2etests/test_telemetry.py`: Modified the `log_event` function to assert the value of the `ai.cloud.role` tag in the `envelope` dictionary. Please add an informative description that covers that changes made by the pull request and link all relevant issues. # All Promptflow Contribution checklist: - [ ] **The pull request does not introduce [breaking changes].** - [ ] **CHANGELOG is updated for new features, bug fixes or other significant changes.** - [ ] **I have read the [contribution guidelines](../CONTRIBUTING.md).** - [ ] **Create an issue and link to the pull request to get dedicated review from promptflow team. Learn more: [suggested workflow](../CONTRIBUTING.md#suggested-workflow).** ## General Guidelines and Best Practices - [ ] Title of the pull request is clear and informative. - [ ] There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, [see this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md). ### Testing Guidelines - [ ] Pull request includes test coverage for the included changes. --- .../tests/sdk_cli_azure_test/e2etests/test_telemetry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/promptflow/tests/sdk_cli_azure_test/e2etests/test_telemetry.py b/src/promptflow/tests/sdk_cli_azure_test/e2etests/test_telemetry.py index ea9d415be53..22dc741e422 100644 --- a/src/promptflow/tests/sdk_cli_azure_test/e2etests/test_telemetry.py +++ b/src/promptflow/tests/sdk_cli_azure_test/e2etests/test_telemetry.py @@ -304,8 +304,8 @@ def log_event(*args, **kwargs): # device name removed assert "ai.cloud.roleInstance" not in envelope.tags assert "ai.device.id" not in envelope.tags - # role not scrubbed for test scenario - assert envelope.tags["ai.cloud.role"] == os.path.basename(sys.argv[0]) + # role name should be scrubbed or kept in whitelist + assert envelope.tags["ai.cloud.role"] in [os.path.basename(sys.argv[0]), "***"] with patch.object(PromptFlowSDKLogHandler, "emit") as mock_logger: mock_logger.side_effect = log_event From 1c7e7727008055c1c43c5e5a78803742af90ce85 Mon Sep 17 00:00:00 2001 From: Peiwen Gao <111329184+PeiwenGaoMS@users.noreply.github.com> Date: Thu, 7 Dec 2023 11:07:49 +0800 Subject: [PATCH 6/8] [Internal][Executor] Print a warning log when a node does not give a default value to its bypassed father node (#1406) # Description Print a warning log when a node does not give a default value to its bypassed father node # All Promptflow Contribution checklist: - [x] **The pull request does not introduce [breaking changes].** - [ ] **CHANGELOG is updated for new features, bug fixes or other significant changes.** - [x] **I have read the [contribution guidelines](../CONTRIBUTING.md).** - [x] **Create an issue and link to the pull request to get dedicated review from promptflow team. Learn more: [suggested workflow](../CONTRIBUTING.md#suggested-workflow).** ## General Guidelines and Best Practices - [x] Title of the pull request is clear and informative. - [x] There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, [see this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md). ### Testing Guidelines - [ ] Pull request includes test coverage for the included changes. --- src/promptflow/promptflow/executor/_dag_manager.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/promptflow/promptflow/executor/_dag_manager.py b/src/promptflow/promptflow/executor/_dag_manager.py index a6d8aca3fd8..e28ed8212ab 100644 --- a/src/promptflow/promptflow/executor/_dag_manager.py +++ b/src/promptflow/promptflow/executor/_dag_manager.py @@ -1,6 +1,7 @@ import inspect from typing import Any, Callable, Dict, List, Mapping +from promptflow._utils.logger_utils import logger from promptflow.contracts.flow import InputAssignment, InputValueType, Node from promptflow.executor import _input_assignment_parser @@ -67,6 +68,10 @@ def get_node_valid_inputs(self, node: Node, f: Callable) -> Mapping[str, Any]: continue # If the parameter has no default value, the input will be set to None so that function will not fail. else: + logger.warning( + f"The node '{i.value}' referenced by the input '{name}' of the current node '{node.name}' " + "has been bypassed, and no default value is set. Will use 'None' as the value for this input." + ) results[name] = None else: results[name] = self._get_node_dependency_value(i) From f2245daca1cfa2e78bb30943a7282cb94a413c5b Mon Sep 17 00:00:00 2001 From: Philip Gao Date: Thu, 7 Dec 2023 11:37:33 +0800 Subject: [PATCH 7/8] Change executor pipeline coverage following code owners. (#1413) # Description Change executor pipeline coverage following code owners. # All Promptflow Contribution checklist: - [x] **The pull request does not introduce [breaking changes].** - [ ] **CHANGELOG is updated for new features, bug fixes or other significant changes.** - [ ] **I have read the [contribution guidelines](../CONTRIBUTING.md).** - [ ] **Create an issue and link to the pull request to get dedicated review from promptflow team. Learn more: [suggested workflow](../CONTRIBUTING.md#suggested-workflow).** ## General Guidelines and Best Practices - [ ] Title of the pull request is clear and informative. - [ ] There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, [see this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md). ### Testing Guidelines - [ ] Pull request includes test coverage for the included changes. --- .github/workflows/promptflow-executor-e2e-test.yml | 14 +++++++++++++- .../workflows/promptflow-executor-unit-test.yml | 14 +++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/promptflow-executor-e2e-test.yml b/.github/workflows/promptflow-executor-e2e-test.yml index 617fe9fd850..059bd54fb27 100644 --- a/.github/workflows/promptflow-executor-e2e-test.yml +++ b/.github/workflows/promptflow-executor-e2e-test.yml @@ -4,7 +4,19 @@ on: - cron: "40 20 * * *" # Every day starting at 4:40 BJT pull_request_target: paths: - - src/promptflow/** + - src/promptflow/* + - src/promptflow/promptflow/* + - src/promptflow/promptflow/_core/** + - src/promptflow/promptflow/_internal/** + - src/promptflow/promptflow/_utils/** + - src/promptflow/promptflow/batch/** + - src/promptflow/promptflow/contracts/** + - src/promptflow/promptflow/entities/** + - src/promptflow/promptflow/executor/** + - src/promptflow/promptflow/integrations/** + - src/promptflow/promptflow/storage/** + - src/promptflow/tests/* + - src/promptflow/tests/executor/** - scripts/building/** - .github/workflows/promptflow-executor-e2e-test.yml workflow_dispatch: diff --git a/.github/workflows/promptflow-executor-unit-test.yml b/.github/workflows/promptflow-executor-unit-test.yml index 2a532b3cf5e..896994c595e 100644 --- a/.github/workflows/promptflow-executor-unit-test.yml +++ b/.github/workflows/promptflow-executor-unit-test.yml @@ -4,7 +4,19 @@ on: - cron: "40 19 * * *" # Every day starting at 3:40 BJT pull_request_target: paths: - - src/promptflow/** + - src/promptflow/* + - src/promptflow/promptflow/* + - src/promptflow/promptflow/_core/** + - src/promptflow/promptflow/_internal/** + - src/promptflow/promptflow/_utils/** + - src/promptflow/promptflow/batch/** + - src/promptflow/promptflow/contracts/** + - src/promptflow/promptflow/entities/** + - src/promptflow/promptflow/executor/** + - src/promptflow/promptflow/integrations/** + - src/promptflow/promptflow/storage/** + - src/promptflow/tests/* + - src/promptflow/tests/executor/** - scripts/building/** - .github/workflows/promptflow-executor-unit-test.yml workflow_dispatch: From e381b87a97911f795c16c60e0bb58fe286cd210e Mon Sep 17 00:00:00 2001 From: Peiwen Gao <111329184+PeiwenGaoMS@users.noreply.github.com> Date: Thu, 7 Dec 2023 12:06:02 +0800 Subject: [PATCH 8/8] [Internal][Executor] Fix executor ci tests (#1416) # Description Fix executor ci tests # All Promptflow Contribution checklist: - [ ] **The pull request does not introduce [breaking changes].** - [ ] **CHANGELOG is updated for new features, bug fixes or other significant changes.** - [ ] **I have read the [contribution guidelines](../CONTRIBUTING.md).** - [ ] **Create an issue and link to the pull request to get dedicated review from promptflow team. Learn more: [suggested workflow](../CONTRIBUTING.md#suggested-workflow).** ## General Guidelines and Best Practices - [ ] Title of the pull request is clear and informative. - [ ] There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, [see this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md). ### Testing Guidelines - [ ] Pull request includes test coverage for the included changes. --- .../tests/executor/e2etests/test_csharp_executor_proxy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/promptflow/tests/executor/e2etests/test_csharp_executor_proxy.py b/src/promptflow/tests/executor/e2etests/test_csharp_executor_proxy.py index 086dd1d6d8c..f8e1b34abcd 100644 --- a/src/promptflow/tests/executor/e2etests/test_csharp_executor_proxy.py +++ b/src/promptflow/tests/executor/e2etests/test_csharp_executor_proxy.py @@ -82,7 +82,7 @@ def create( ) -> "MockCSharpExecutorProxy": """Create a new executor""" port = cls.find_available_port() - process = multiprocessing.Process(target=run_executor_server, args=(port,)) + process = multiprocessing.Process(target=run_executor_server, args=(int(port),)) process.start() return cls(process, port)