Skip to content

Commit

Permalink
feat: enable multi container based on environment variable (#2313)
Browse files Browse the repository at this point in the history
# Description

This pull request primarily introduces the ability to enable
multi-container functionality and expands the capabilities of the Azure
Machine Learning Designer Service Client. The most significant changes
include the addition of a new constant, the creation of a function to
check if multi-container functionality is enabled, and the extension of
the Azure Machine Learning Designer Service Client's operations.

**Addition of Multi-Container Functionality:**

*
[`src/promptflow/promptflow/_constants.py`](diffhunk://#diff-0d3cf5f31883ff073bf1e11cb2e17db5cc8fe6e5e38cbb4af7b99f37ac31d41aR14):
Added a new constant `ENABLE_MULTI_CONTAINER_KEY` to enable
multi-container functionality.
*
[`src/promptflow/promptflow/_sdk/_utils.py`](diffhunk://#diff-47208ac35b30920275fcd5e55d662647ef360129359bdc77fddd2a2157b6f47eL35-R41):
Imported the new constant and added a new function
`is_multi_container_enabled()` to check if multi-container functionality
is enabled.
[[1]](diffhunk://#diff-47208ac35b30920275fcd5e55d662647ef360129359bdc77fddd2a2157b6f47eL35-R41)
[[2]](diffhunk://#diff-47208ac35b30920275fcd5e55d662647ef360129359bdc77fddd2a2157b6f47eR983-R988)
*
[`src/promptflow/promptflow/_sdk/entities/_run.py`](diffhunk://#diff-14f4d7a1d9b077c7b749230a92628782f990e1fc7cb741b20ff894f868327020R43):
Imported the new function and used it in the `_to_rest_object()` method.
[[1]](diffhunk://#diff-14f4d7a1d9b077c7b749230a92628782f990e1fc7cb741b20ff894f868327020R43)
[[2]](diffhunk://#diff-14f4d7a1d9b077c7b749230a92628782f990e1fc7cb741b20ff894f868327020R593)

**Expansion of Azure Machine Learning Designer Service Client
Operations:**

*
`src/promptflow/promptflow/azure/_restclient/flow/_azure_machine_learning_designer_service_client.py`,
`src/promptflow/promptflow/azure/_restclient/flow/aio/_azure_machine_learning_designer_service_client.py`:
Added `ExperimentsOperations` and `ExperimentTemplatesOperations` to the
Azure Machine Learning Designer Service Client's operations.
[[1]](diffhunk://#diff-0d897b1801e67d281d2e78b96e4735815629d7341c4ba5bb328326bd917719d9L15-R15)
[[2]](diffhunk://#diff-0d897b1801e67d281d2e78b96e4735815629d7341c4ba5bb328326bd917719d9R32-R35)
[[3]](diffhunk://#diff-0d897b1801e67d281d2e78b96e4735815629d7341c4ba5bb328326bd917719d9R75-R76)
[[4]](diffhunk://#diff-b86b4b5a24655b993946a74b33780deb5eeab5452feb269e74456ba3871de495L16-R16)
[[5]](diffhunk://#diff-b86b4b5a24655b993946a74b33780deb5eeab5452feb269e74456ba3871de495R27-R30)
[[6]](diffhunk://#diff-b86b4b5a24655b993946a74b33780deb5eeab5452feb269e74456ba3871de495R69-R70)
*
[`src/promptflow/promptflow/azure/_restclient/flow/aio/operations/__init__.py`](diffhunk://#diff-f5d068b386d3698c8836998d281dbf65844be98620f017683ab25632bd7f4e29R10-R11):
Imported the new operations.
[[1]](diffhunk://#diff-f5d068b386d3698c8836998d281dbf65844be98620f017683ab25632bd7f4e29R10-R11)
[[2]](diffhunk://#diff-f5d068b386d3698c8836998d281dbf65844be98620f017683ab25632bd7f4e29R24-R25)
*
[`src/promptflow/promptflow/azure/_restclient/flow/aio/operations/_experiment_templates_operations.py`](diffhunk://#diff-ac47ed666715906825cc330909c705299ad504c397818b964e5313c12e84fb8fR1-R171):
Added a new file to implement the `ExperimentTemplatesOperations`.

# All Promptflow Contribution checklist:
- [x] **The pull request does not introduce [breaking changes].**
- [x] **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.
- [ ] 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.
  • Loading branch information
elliotzh authored Mar 14, 2024
1 parent e7bceaa commit cb2b5d2
Show file tree
Hide file tree
Showing 20 changed files with 33,271 additions and 30,904 deletions.
1 change: 1 addition & 0 deletions src/promptflow/promptflow/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
PROMPTFLOW_SECRETS_FILE = "PROMPTFLOW_SECRETS_FILE"
PF_NO_INTERACTIVE_LOGIN = "PF_NO_INTERACTIVE_LOGIN"
PF_RUN_AS_BUILT_BINARY = "PF_RUN_AS_BUILT_BINARY"
ENABLE_MULTI_CONTAINER_KEY = "PF_ENABLE_MULTI_CONTAINER"
PF_LOGGING_LEVEL = "PF_LOGGING_LEVEL"
OPENAI_API_KEY = "openai-api-key"
BING_API_KEY = "bing-api-key"
Expand Down
14 changes: 13 additions & 1 deletion src/promptflow/promptflow/_sdk/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@
from marshmallow import ValidationError

import promptflow
from promptflow._constants import EXTENSION_UA, PF_NO_INTERACTIVE_LOGIN, PF_USER_AGENT, USER_AGENT
from promptflow._constants import (
ENABLE_MULTI_CONTAINER_KEY,
EXTENSION_UA,
PF_NO_INTERACTIVE_LOGIN,
PF_USER_AGENT,
USER_AGENT,
)
from promptflow._sdk._constants import (
AZURE_WORKSPACE_REGEX_FORMAT,
DAG_FILE_NAME,
Expand Down Expand Up @@ -971,6 +977,12 @@ def is_from_cli():
return CLI_UA in ClientUserAgentUtil.get_user_agent()


def is_multi_container_enabled():
if ENABLE_MULTI_CONTAINER_KEY in os.environ:
return os.environ[ENABLE_MULTI_CONTAINER_KEY].lower() == "true"
return None


def is_url(value: Union[PathLike, str]) -> bool:
try:
result = urlparse(str(value))
Expand Down
2 changes: 2 additions & 0 deletions src/promptflow/promptflow/_sdk/entities/_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from promptflow._sdk._orm import RunInfo as ORMRun
from promptflow._sdk._utils import (
_sanitize_python_variable_name,
is_multi_container_enabled,
is_remote_uri,
parse_remote_flow_pattern,
parse_variant,
Expand Down Expand Up @@ -589,6 +590,7 @@ def _to_rest_object(self):
session_setup_mode=SessionSetupModeEnum.SYSTEM_WAIT,
compute_name=compute_name,
identity=identity_resource_id,
enable_multi_container=is_multi_container_enabled(),
)

if str(self.flow).startswith(REMOTE_URI_PREFIX):
Expand Down
1 change: 1 addition & 0 deletions src/promptflow/promptflow/azure/_restclient/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Download swagger.json from [here](https://int.api.azureml-test.ms/flow/swagger/v
- 2024.2.2 - [Support specify compute instance as session compute](https://github.com/microsoft/promptflow/pull/1925)
- 2024.2.5 - [Support retrieve Cosmos token](https://github.com/microsoft/promptflow/pull/1972)
- 2024.2.19 - [Update SDK restclient](https://github.com/microsoft/promptflow/pull/2165)
- 2024.3.14 - [Add enable_multi_container](https://github.com/microsoft/promptflow/pull/2313)

## Troubleshooting

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from . import models
from ._configuration import AzureMachineLearningDesignerServiceClientConfiguration
from .operations import BulkRunsOperations, ConnectionOperations, ConnectionsOperations, FlowRuntimesOperations, FlowRuntimesWorkspaceIndependentOperations, FlowSessionsOperations, FlowsOperations, FlowsProviderOperations, ToolsOperations, TraceSessionsOperations
from .operations import BulkRunsOperations, ConnectionOperations, ConnectionsOperations, ExperimentTemplatesOperations, ExperimentsOperations, FlowRuntimesOperations, FlowRuntimesWorkspaceIndependentOperations, FlowSessionsOperations, FlowsOperations, FlowsProviderOperations, ToolsOperations, TraceSessionsOperations

if TYPE_CHECKING:
# pylint: disable=unused-import,ungrouped-imports
Expand All @@ -29,6 +29,10 @@ class AzureMachineLearningDesignerServiceClient(object):
:vartype connection: flow.operations.ConnectionOperations
:ivar connections: ConnectionsOperations operations
:vartype connections: flow.operations.ConnectionsOperations
:ivar experiments: ExperimentsOperations operations
:vartype experiments: flow.operations.ExperimentsOperations
:ivar experiment_templates: ExperimentTemplatesOperations operations
:vartype experiment_templates: flow.operations.ExperimentTemplatesOperations
:ivar flow_runtimes: FlowRuntimesOperations operations
:vartype flow_runtimes: flow.operations.FlowRuntimesOperations
:ivar flow_runtimes_workspace_independent: FlowRuntimesWorkspaceIndependentOperations
Expand Down Expand Up @@ -68,6 +72,8 @@ def __init__(
self.bulk_runs = BulkRunsOperations(self._client, self._config, self._serialize, self._deserialize)
self.connection = ConnectionOperations(self._client, self._config, self._serialize, self._deserialize)
self.connections = ConnectionsOperations(self._client, self._config, self._serialize, self._deserialize)
self.experiments = ExperimentsOperations(self._client, self._config, self._serialize, self._deserialize)
self.experiment_templates = ExperimentTemplatesOperations(self._client, self._config, self._serialize, self._deserialize)
self.flow_runtimes = FlowRuntimesOperations(self._client, self._config, self._serialize, self._deserialize)
self.flow_runtimes_workspace_independent = FlowRuntimesWorkspaceIndependentOperations(self._client, self._config, self._serialize, self._deserialize)
self.flows = FlowsOperations(self._client, self._config, self._serialize, self._deserialize)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from .. import models
from ._configuration import AzureMachineLearningDesignerServiceClientConfiguration
from .operations import BulkRunsOperations, ConnectionOperations, ConnectionsOperations, FlowRuntimesOperations, FlowRuntimesWorkspaceIndependentOperations, FlowSessionsOperations, FlowsOperations, FlowsProviderOperations, ToolsOperations, TraceSessionsOperations
from .operations import BulkRunsOperations, ConnectionOperations, ConnectionsOperations, ExperimentTemplatesOperations, ExperimentsOperations, FlowRuntimesOperations, FlowRuntimesWorkspaceIndependentOperations, FlowSessionsOperations, FlowsOperations, FlowsProviderOperations, ToolsOperations, TraceSessionsOperations

class AzureMachineLearningDesignerServiceClient:
"""AzureMachineLearningDesignerServiceClient.
Expand All @@ -24,6 +24,10 @@ class AzureMachineLearningDesignerServiceClient:
:vartype connection: flow.aio.operations.ConnectionOperations
:ivar connections: ConnectionsOperations operations
:vartype connections: flow.aio.operations.ConnectionsOperations
:ivar experiments: ExperimentsOperations operations
:vartype experiments: flow.aio.operations.ExperimentsOperations
:ivar experiment_templates: ExperimentTemplatesOperations operations
:vartype experiment_templates: flow.aio.operations.ExperimentTemplatesOperations
:ivar flow_runtimes: FlowRuntimesOperations operations
:vartype flow_runtimes: flow.aio.operations.FlowRuntimesOperations
:ivar flow_runtimes_workspace_independent: FlowRuntimesWorkspaceIndependentOperations
Expand Down Expand Up @@ -62,6 +66,8 @@ def __init__(
self.bulk_runs = BulkRunsOperations(self._client, self._config, self._serialize, self._deserialize)
self.connection = ConnectionOperations(self._client, self._config, self._serialize, self._deserialize)
self.connections = ConnectionsOperations(self._client, self._config, self._serialize, self._deserialize)
self.experiments = ExperimentsOperations(self._client, self._config, self._serialize, self._deserialize)
self.experiment_templates = ExperimentTemplatesOperations(self._client, self._config, self._serialize, self._deserialize)
self.flow_runtimes = FlowRuntimesOperations(self._client, self._config, self._serialize, self._deserialize)
self.flow_runtimes_workspace_independent = FlowRuntimesWorkspaceIndependentOperations(self._client, self._config, self._serialize, self._deserialize)
self.flows = FlowsOperations(self._client, self._config, self._serialize, self._deserialize)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from ._bulk_runs_operations import BulkRunsOperations
from ._connection_operations import ConnectionOperations
from ._connections_operations import ConnectionsOperations
from ._experiments_operations import ExperimentsOperations
from ._experiment_templates_operations import ExperimentTemplatesOperations
from ._flow_runtimes_operations import FlowRuntimesOperations
from ._flow_runtimes_workspace_independent_operations import FlowRuntimesWorkspaceIndependentOperations
from ._flows_operations import FlowsOperations
Expand All @@ -19,6 +21,8 @@
'BulkRunsOperations',
'ConnectionOperations',
'ConnectionsOperations',
'ExperimentsOperations',
'ExperimentTemplatesOperations',
'FlowRuntimesOperations',
'FlowRuntimesWorkspaceIndependentOperations',
'FlowsOperations',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# coding=utf-8
# --------------------------------------------------------------------------
# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.8.0, generator: @autorest/[email protected])
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------
import functools
from typing import Any, Callable, Dict, Generic, Optional, TypeVar
import warnings

from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error
from azure.core.pipeline import PipelineResponse
from azure.core.pipeline.transport import AsyncHttpResponse
from azure.core.rest import HttpRequest
from azure.core.tracing.decorator_async import distributed_trace_async

from ... import models as _models
from ..._vendor import _convert_request
from ...operations._experiment_templates_operations import build_create_experiment_template_request, build_get_experiment_template_request
T = TypeVar('T')
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]

class ExperimentTemplatesOperations:
"""ExperimentTemplatesOperations async operations.
You should not instantiate this class directly. Instead, you should create a Client instance that
instantiates it for you and attaches it as an attribute.
:ivar models: Alias to model classes used in this operation group.
:type models: ~flow.models
:param client: Client for service requests.
:param config: Configuration of service client.
:param serializer: An object model serializer.
:param deserializer: An object model deserializer.
"""

models = _models

def __init__(self, client, config, serializer, deserializer) -> None:
self._client = client
self._serialize = serializer
self._deserialize = deserializer
self._config = config

@distributed_trace_async
async def create_experiment_template(
self,
subscription_id: str,
resource_group_name: str,
workspace_name: str,
experiment_template_id: str,
body: Optional["_models.CreateExperimentTemplateRequest"] = None,
**kwargs: Any
) -> "_models.ExperimentTemplateDto":
"""create_experiment_template.
:param subscription_id: The Azure Subscription ID.
:type subscription_id: str
:param resource_group_name: The Name of the resource group in which the workspace is located.
:type resource_group_name: str
:param workspace_name: The name of the workspace.
:type workspace_name: str
:param experiment_template_id:
:type experiment_template_id: str
:param body:
:type body: ~flow.models.CreateExperimentTemplateRequest
:keyword callable cls: A custom type or function that will be passed the direct response
:return: ExperimentTemplateDto, or the result of cls(response)
:rtype: ~flow.models.ExperimentTemplateDto
:raises: ~azure.core.exceptions.HttpResponseError
"""
cls = kwargs.pop('cls', None) # type: ClsType["_models.ExperimentTemplateDto"]
error_map = {
401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
}
error_map.update(kwargs.pop('error_map', {}))

content_type = kwargs.pop('content_type', "application/json") # type: Optional[str]

if body is not None:
_json = self._serialize.body(body, 'CreateExperimentTemplateRequest')
else:
_json = None

request = build_create_experiment_template_request(
subscription_id=subscription_id,
resource_group_name=resource_group_name,
workspace_name=workspace_name,
experiment_template_id=experiment_template_id,
content_type=content_type,
json=_json,
template_url=self.create_experiment_template.metadata['url'],
)
request = _convert_request(request)
request.url = self._client.format_url(request.url)

pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
response = pipeline_response.http_response

if response.status_code not in [200]:
map_error(status_code=response.status_code, response=response, error_map=error_map)
error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
raise HttpResponseError(response=response, model=error)

deserialized = self._deserialize('ExperimentTemplateDto', pipeline_response)

if cls:
return cls(pipeline_response, deserialized, {})

return deserialized

create_experiment_template.metadata = {'url': '/flow/api/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.MachineLearningServices/workspaces/{workspaceName}/ExperimentTemplates/{experimentTemplateId}'} # type: ignore


@distributed_trace_async
async def get_experiment_template(
self,
subscription_id: str,
resource_group_name: str,
workspace_name: str,
experiment_template_id: str,
**kwargs: Any
) -> "_models.ExperimentTemplateDto":
"""get_experiment_template.
:param subscription_id: The Azure Subscription ID.
:type subscription_id: str
:param resource_group_name: The Name of the resource group in which the workspace is located.
:type resource_group_name: str
:param workspace_name: The name of the workspace.
:type workspace_name: str
:param experiment_template_id:
:type experiment_template_id: str
:keyword callable cls: A custom type or function that will be passed the direct response
:return: ExperimentTemplateDto, or the result of cls(response)
:rtype: ~flow.models.ExperimentTemplateDto
:raises: ~azure.core.exceptions.HttpResponseError
"""
cls = kwargs.pop('cls', None) # type: ClsType["_models.ExperimentTemplateDto"]
error_map = {
401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
}
error_map.update(kwargs.pop('error_map', {}))


request = build_get_experiment_template_request(
subscription_id=subscription_id,
resource_group_name=resource_group_name,
workspace_name=workspace_name,
experiment_template_id=experiment_template_id,
template_url=self.get_experiment_template.metadata['url'],
)
request = _convert_request(request)
request.url = self._client.format_url(request.url)

pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
response = pipeline_response.http_response

if response.status_code not in [200]:
map_error(status_code=response.status_code, response=response, error_map=error_map)
error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
raise HttpResponseError(response=response, model=error)

deserialized = self._deserialize('ExperimentTemplateDto', pipeline_response)

if cls:
return cls(pipeline_response, deserialized, {})

return deserialized

get_experiment_template.metadata = {'url': '/flow/api/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.MachineLearningServices/workspaces/{workspaceName}/ExperimentTemplates/{experimentTemplateId}'} # type: ignore

Loading

0 comments on commit cb2b5d2

Please sign in to comment.