Skip to content

Commit

Permalink
[Serving] Support default env var override behavior for connection (#713
Browse files Browse the repository at this point in the history
)

# Description

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.

---------

Co-authored-by: Ying Chen <[email protected]>
  • Loading branch information
YingChen1996 and Ying Chen authored Oct 12, 2023
1 parent 8f04d2e commit 5ed0e82
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 0 deletions.
7 changes: 7 additions & 0 deletions docs/how-to-guides/deploy-a-flow/deploy-using-dev-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ an example to show how to deploy a flow.
Please ensure you have [create the connection](../manage-connections.md#create-a-connection) required by flow, if not, you could
refer to [Setup connection for web-classification](https://github.com/microsoft/promptflow/tree/main/examples/flows/standard/web-classification).

Note: We will use relevant environment variable ({connection_name}_{key_name}) to override connection configurations in
serving mode, white space in connection name will be removed directly from environment variable name. For instance,
if there is a custom connection named 'custom_connection' with a configuration key called 'chat_deployment_name,' the
function will attempt to retrieve 'chat_deployment_name' from the environment variable
'CUSTOM_CONNECTION_CHAT_DEPLOYMENT_NAME' by default. If the environment variable is not set, it will use the original
value as a fallback.


The following CLI commands allows you serve a flow folder as an endpoint. By running this command, a [flask](https://flask.palletsprojects.com/en/) app will start in the environment where command is executed, please ensure all prerequisites required by flow have been installed.
```bash
Expand Down
2 changes: 2 additions & 0 deletions src/promptflow/promptflow/_sdk/_serving/flow_invoker.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
get_local_connections_from_executable,
resolve_connections_environment_variable_reference,
update_environment_variables_with_connections,
override_connection_config_with_environment_variable,
)
from promptflow._sdk.entities._connection import _Connection
from promptflow.executor import FlowExecutor
Expand Down Expand Up @@ -61,6 +62,7 @@ def _init_connections(self, connection_provider):
else:
raise UnsupportedConnectionProvider(connection_provider)

override_connection_config_with_environment_variable(self.connections)
resolve_connections_environment_variable_reference(self.connections)
update_environment_variables_with_connections(self.connections)
logger.info(f"Promptflow get connections successfully. keys: {self.connections.keys()}")
Expand Down
23 changes: 23 additions & 0 deletions src/promptflow/promptflow/_sdk/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,29 @@ def _match_env_reference(val: str):
return name


def override_connection_config_with_environment_variable(connections: Dict[str, dict]):
"""
The function will use relevant environment variable to override connection configurations. For instance, if there
is a custom connection named 'custom_connection' with a configuration key called 'chat_deployment_name,' the
function will attempt to retrieve 'chat_deployment_name' from the environment variable
'CUSTOM_CONNECTION_CHAT_DEPLOYMENT_NAME' by default. If the environment variable is not set, it will use the
original value as a fallback.
"""
logger = logging.getLogger(LOGGER_NAME)
for connection_name, connection in connections.items():
values = connection.get("value", {})
for key, val in values.items():
connection_name = connection_name.replace(" ", "_")
env_name = f"{connection_name}_{key}".upper()
if env_name not in os.environ:
continue
values[key] = os.environ[env_name]
logger.info(
f"Connection {connection_name}'s {key} is overridden with environment variable {env_name}"
)
return connections


def resolve_connections_environment_variable_reference(connections: Dict[str, dict]):
"""The function will resolve connection secrets env var reference like api_key: ${env:KEY}"""
for connection in connections.values():
Expand Down
24 changes: 24 additions & 0 deletions src/promptflow/tests/sdk_cli_test/unittests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
generate_flow_tools_json,
refresh_connections_dir,
resolve_connections_environment_variable_reference,
override_connection_config_with_environment_variable,
snake_to_camel,
)

Expand Down Expand Up @@ -87,6 +88,29 @@ def test_resolve_connections_environment_variable_reference(self):
assert connections["test_connection"]["value"]["api_base"] == "BASE"
assert connections["test_custom_connection"]["value"]["key"] == "CUSTOM_VALUE"

def test_override_connection_config_with_environment_variable(self):
connections = {
"test_connection": {
"type": "AzureOpenAIConnection",
"value": {
"api_key": "KEY",
"api_base": "https://gpt-test-eus.openai.azure.com/",
},
},
"test_custom_connection": {
"type": "CustomConnection",
"value": {"key": "value1", "key2": "value2"},
},
}
with mock.patch.dict(
os.environ, {"TEST_CONNECTION_API_BASE": "BASE", "TEST_CUSTOM_CONNECTION_KEY": "CUSTOM_VALUE"}
):
override_connection_config_with_environment_variable(connections)
assert connections["test_connection"]["value"]["api_key"] == "KEY"
assert connections["test_connection"]["value"]["api_base"] == "BASE"
assert connections["test_custom_connection"]["value"]["key"] == "CUSTOM_VALUE"
assert connections["test_custom_connection"]["value"]["key2"] == "value2"

def test_generate_flow_tools_json(self) -> None:
# call twice to ensure system path won't be affected during generation
for _ in range(2):
Expand Down

0 comments on commit 5ed0e82

Please sign in to comment.