-
Notifications
You must be signed in to change notification settings - Fork 924
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into dev/runtime-compatibility-hot-fix
- Loading branch information
Showing
48 changed files
with
797 additions
and
327 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -195,6 +195,7 @@ | |
"autogen", | ||
"spawnve", | ||
"addrs", | ||
"pycache", | ||
"pywin", | ||
"STARTF", | ||
"mltable", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
{"question": "What is Prompt flow?", "statements": {"correctness": "should explain what's 'Prompt flow'"}} | ||
{"question": "What is ChatGPT? Please explain with consise statement", "statements": { "correctness": "should explain what's ChatGPT", "consise": "It is a consise statement."}} | ||
{"question": "What is Prompt flow?", "chat_history": [], "statements": { "correctness": "result should be 1", "consise": "It is a consise statement."}} | ||
{"question": "What is ChatGPT? Please explain with consise statement", "chat_history": [], "statements": { "correctness": "result should be 1", "consise": "It is a consise statement."}} | ||
{"question": "How many questions did user ask?", "chat_history": [{"role": "user","content": "where is the nearest coffee shop?"},{"role": "system","content": "I'm sorry, I don't know that. Would you like me to look it up for you?"}], "statements": { "correctness": "result should be 1", "consise": "It is a consise statement."}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import os | ||
import subprocess | ||
import multiprocessing | ||
import importlib | ||
|
||
git_base = subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).decode().strip() | ||
|
||
|
||
def walk_and_ignore_pycache(directory): | ||
list = [] | ||
for root, dirnames, files in os.walk(directory, topdown=True): | ||
# This line removes any __pycache__ directories from the list | ||
dirnames[:] = [d for d in dirnames if d != '__pycache__' and d != 'tests' and d != 'data'] | ||
filenames = [f for f in files if f.endswith('.py') and not f.startswith('__init__')] | ||
for filename in filenames: | ||
# Process files as you would like | ||
list.append(os.path.join(root, filename)) | ||
return list | ||
|
||
|
||
def file_to_import(file): | ||
push_file = [] | ||
head_tail = os.path.split(file) | ||
while head_tail[1] != "promptflow" and head_tail[0] != "": | ||
if head_tail[1].endswith(".py"): | ||
push_file.insert(0, head_tail[1][:-3]) | ||
else: | ||
push_file.insert(0, head_tail[1]) | ||
file = head_tail[0] | ||
head_tail = os.path.split(file) | ||
push_file.insert(0, "promptflow") | ||
return ".".join(push_file) | ||
|
||
|
||
# If there is an import error, the process will exit with a non-zero exit code | ||
# Find this importlib.import_module as the keyword to search for the error | ||
# The error below this is the import error / circular import error. | ||
def subprocess_check_python_import(file): | ||
print(f'Checking import of {file} on process ID: {os.getpid()}') | ||
importlib.import_module(file) | ||
|
||
|
||
def process_file(file): | ||
import_name = file_to_import(file) | ||
subprocess_check_python_import(import_name) | ||
|
||
|
||
if __name__ == '__main__': | ||
pool = multiprocessing.Pool() | ||
list = walk_and_ignore_pycache(git_base + "/src/promptflow-tracing/") | ||
list.extend(walk_and_ignore_pycache(git_base + "/src/promptflow-core/")) | ||
list.extend(walk_and_ignore_pycache(git_base + "/src/promptflow-devkit/")) | ||
list.extend(walk_and_ignore_pycache(git_base + "/src/promptflow-azure/")) | ||
pool.map(process_file, list) | ||
pool.close() | ||
pool.join() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
src/promptflow-azure/promptflow/azure/operations/_metrics_client.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# --------------------------------------------------------- | ||
# Copyright (c) Microsoft Corporation. All rights reserved. | ||
# --------------------------------------------------------- | ||
from typing import Dict | ||
|
||
import httpx | ||
|
||
from promptflow._sdk._errors import MetricInternalError, SDKError, UserAuthenticationError | ||
from promptflow._sdk._utilities.general_utils import get_promptflow_sdk_version | ||
from promptflow._utils.logger_utils import get_cli_sdk_logger | ||
from promptflow.azure._utils.general import get_authorization | ||
|
||
logger = get_cli_sdk_logger() | ||
|
||
POST_METRICS_URL = ( | ||
"{endpoint}/metric/v2.0/subscriptions/{sub}/resourceGroups/{rg}/" | ||
"providers/Microsoft.MachineLearningServices/workspaces/{ws}/runs/{runId}/batchsync" | ||
) | ||
|
||
|
||
class AsyncMetricClient: | ||
def __init__( | ||
self, | ||
subscription_id, | ||
resource_group, | ||
workspace_name, | ||
service_endpoint, | ||
credential, | ||
): | ||
self.subscription_id = subscription_id | ||
self.resource_group = resource_group | ||
self.workspace_name = workspace_name | ||
self.service_endpoint = service_endpoint | ||
self.credential = credential | ||
|
||
async def log_metric(self, run_id, metric_key: str, metric_value: float): | ||
"""Write metric for a run.""" | ||
url = POST_METRICS_URL.format( | ||
sub=self.subscription_id, | ||
rg=self.resource_group, | ||
ws=self.workspace_name, | ||
endpoint=self.service_endpoint, | ||
runId=run_id, | ||
) | ||
|
||
logger.debug(f"Writing metrics for Run {run_id}...") | ||
|
||
payload = { | ||
"values": [ | ||
{ | ||
"name": metric_key, | ||
"columns": {metric_key: "Double"}, | ||
"properties": {"uxMetricType": "azureml.v1.scalar"}, | ||
"value": [{"data": {metric_key: metric_value}, "step": 0}], | ||
} | ||
] | ||
} | ||
|
||
error_msg_prefix = f"Failed to write metrics for Run {run_id!r}" | ||
try: | ||
async with httpx.AsyncClient(verify=False) as client: | ||
response = await client.post(url, headers=self._get_header(), json=payload) | ||
if response.status_code == 401 or response.status_code == 403: | ||
# if it's auth issue, return auth_error_message | ||
raise UserAuthenticationError(response.text) | ||
elif response.status_code != 200: | ||
error_message = f"{error_msg_prefix}. Code={response.status_code}. Message={response.text}" | ||
logger.error(error_message) | ||
raise MetricInternalError(error_message) | ||
except Exception as e: | ||
error_message = f"{error_msg_prefix}: {str(e)}" | ||
logger.error(error_message) | ||
raise MetricInternalError(error_message) from e | ||
|
||
def _get_header(self) -> Dict[str, str]: | ||
headers = { | ||
"Authorization": get_authorization(credential=self.credential), | ||
"Content-Type": "application/json", | ||
"User-Agent": "promptflow/%s" % get_promptflow_sdk_version(), | ||
} | ||
return headers | ||
|
||
@classmethod | ||
def from_run_operations(cls, run_ops): | ||
from promptflow.azure.operations import RunOperations | ||
|
||
if not isinstance(run_ops, RunOperations): | ||
raise SDKError(f"run_ops should be an instance of azure RunOperations, got {type(run_ops)!r} instead.") | ||
|
||
return cls( | ||
subscription_id=run_ops._operation_scope.subscription_id, | ||
resource_group=run_ops._operation_scope.resource_group_name, | ||
workspace_name=run_ops._operation_scope.workspace_name, | ||
service_endpoint=run_ops._service_caller._service_endpoint[0:-1], # remove trailing slash | ||
credential=run_ops._credential, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.