你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用 Microsoft Foundry SDK 在云中运行评估

注释

本文档引用 Microsoft Foundry (经典) 门户。

🔄 如果你使用的是新门户,请切换到 Microsoft Foundry(新)文档

注释

本文档指的是 Microsoft Foundry(新) 门户网站。

重要

本文中标记了“(预览版)”的项目目前为公共预览版。 此预览版未提供服务级别协议,不建议将其用于生产工作负载。 某些功能可能不受支持或者受限。 有关详细信息,请参阅 Microsoft Azure 预览版补充使用条款

本文介绍如何在云中运行评估(预览版),以便在测试数据集上进行预部署测试。 Azure AI 评估 SDK 允许在本地计算机和云中运行评估。 例如,对小型测试数据运行本地评估以评估生成 AI 应用程序原型,然后进入预部署测试,对大型数据集运行评估。

对大多数方案使用云评估,尤其是在大规模测试时,将评估集成到持续集成和持续交付(CI/CD)管道中,或执行预部署测试。 在云中运行评估无需管理本地计算基础结构并支持大规模自动化测试工作流。 完成部署后,可以选择持续评估智能体以进行部署后监视。

使用 Foundry SDK 时,它会在 Foundry 项目中记录评估结果,以提高可观测性。 此功能支持所有Microsoft精选的 内置评估器 以及您自己的 自定义评估器。 评估器可以位于 评估器库 中,并具有相同的项目范围、基于角色的访问控制。

先决条件

  • Microsoft Foundry 项目,与风险和安全评估程序(预览版)位于相同的支持区域中。 如果没有项目,请创建一个项目。 请参阅 为 Foundry 创建项目
  • 带有支持 chat completion 的 GPT 模型的 Azure OpenAI 部署,例如 gpt-4
  • 通过运行 az login来登录到 Azure 订阅。

如果这是首次运行评估并将其记录到 Microsoft Foundry 项目,则可能需要执行一些其他步骤:

  1. 在资源级别创建存储帐户并将其连接到 Foundry 项目。 可以采用两种方法执行此操作。 可以使用 Bicep 模板,该模板通过密钥身份验证预配存储帐户并将其连接到 Foundry 项目。
    还可以在 Azure 门户中 手动创建和预配 对存储帐户的访问权限。
  2. 确保连接的存储帐户有权访问所有项目。
  3. 如果使用 Microsoft Entra ID 连接存储帐户,请确保在 Azure 门户中向帐户和 Foundry 项目资源提供托管标识“存储 Blob 数据所有者”权限

开始

  1. 安装 Microsoft Foundry SDK 项目客户端以在云中运行评估:

    uv install azure-ai-projects azure-identity
    

    注释

    有关详细信息,请参阅 REST API 参考文档

  2. 为 Foundry 资源设置环境变量:

    import os
    
    # Required environment variables:
    endpoint = os.environ["PROJECT_ENDPOINT"] # https://<account>.services.ai.azure.com/api/projects/<project>
    model_endpoint = os.environ["MODEL_ENDPOINT"] # https://<account>.services.ai.azure.com
    model_api_key = os.environ["MODEL_API_KEY"]
    model_deployment_name = os.environ["MODEL_DEPLOYMENT_NAME"] # E.g. gpt-4o-mini
    
    # Optional: Reuse an existing dataset.
    dataset_name    = os.environ.get("DATASET_NAME",    "dataset-test")
    dataset_version = os.environ.get("DATASET_VERSION", "1.0")
    
  3. 定义要在云中运行评估的客户端:

    import os
    from azure.identity import DefaultAzureCredential
    from azure.ai.projects import AIProjectClient
    
    # Create the project client (Foundry project and credentials):
    project_client = AIProjectClient(
        endpoint=endpoint,
        credential=DefaultAzureCredential(),
    )
    
  1. 安装在云中运行评估的 Microsoft Foundry SDK 项目客户端:

    
    uv install azure-ai-projects azure-identity 
    
    

    注释

    有关详细信息,请参阅 REST API 参考文档

  2. 为 Foundry 资源设置环境变量:

    
    import os
    
    # Azure AI Project endpoint
    # Example: https://<account_name>.services.ai.azure.com/api/projects/<project_name>
    endpoint = os.environ["AZURE_AI_PROJECT_ENDPOINT"]
    
    # Model deployment name
    # Example: gpt-4o-mini
    model_deployment_name = os.environ.get("AZURE_AI_MODEL_DEPLOYMENT_NAME", "")
    
    # Dataset details
    dataset_name = os.environ.get("DATASET_NAME", "")
    dataset_version = os.environ.get("DATASET_VERSION", "1")
    
    
  3. 定义在云中运行评估的客户端:

    
    from azure.identity import DefaultAzureCredential 
    from azure.ai.projects import AIProjectClient 
    
    # Create the project client (Foundry project and credentials): 
    
    project_client = AIProjectClient( 
        endpoint=endpoint, 
        credential=DefaultAzureCredential(), 
    ) 
    
    

上传评估数据

# Upload a local JSONL file. Skip this step if you already have a dataset registered.
data_id = project_client.datasets.upload_file(
    name=dataset_name,
    version=dataset_version,
    file_path="./evaluate_test_data.jsonl",
).id

若要详细了解用于评估生成 AI 应用程序的输入数据格式,请参阅:

若要详细了解用于评估代理的输入数据格式,请参阅 评估 Azure AI 代理评估其他代理

指定评估人员

from azure.ai.projects.models import (
    EvaluatorConfiguration,
    EvaluatorIds,
)

# Built-in evaluator configurations:
evaluators = {
    "relevance": EvaluatorConfiguration(
        id=EvaluatorIds.RELEVANCE.value,
        init_params={"deployment_name": model_deployment_name},
        data_mapping={
            "query": "${data.query}",
            "response": "${data.response}",
        },
    ),
    "violence": EvaluatorConfiguration(
        id=EvaluatorIds.VIOLENCE.value,
        init_params={"azure_ai_project": endpoint},
    ),
    "bleu_score": EvaluatorConfiguration(
        id=EvaluatorIds.BLEU_SCORE.value,
    ),
}

在云中提交评估

最后,提交远程评估运行:

from azure.ai.projects.models import (
    Evaluation,
    InputDataset
)

# Create an evaluation with the dataset and evaluators specified.
evaluation = Evaluation(
    display_name="Cloud evaluation",
    description="Evaluation of dataset",
    data=InputDataset(id=data_id),
    evaluators=evaluators,
)

# Run the evaluation.
evaluation_response = project_client.evaluations.create(
    evaluation,
    headers={
        "model-endpoint": model_endpoint,
        "api-key": model_api_key,
    },
)

print("Created evaluation:", evaluation_response.name)
print("Status:", evaluation_response.status)

指定自定义评估器

注释

此功能不支持 Foundry 项目。 请改用 Foundry 中心项目。

基于代码的自定义评估器

将自定义评估器注册到 Azure AI Hub 项目并获取评估器 ID:

from azure.ai.ml import MLClient
from azure.ai.ml.entities import Model
from promptflow.client import PFClient

# Define ml_client to register the custom evaluator.
ml_client = MLClient(
       subscription_id=os.environ["AZURE_SUBSCRIPTION_ID"],
       resource_group_name=os.environ["AZURE_RESOURCE_GROUP"],
       workspace_name=os.environ["AZURE_PROJECT_NAME"],
       credential=DefaultAzureCredential()
)

# Load the evaluator from the module.
from answer_len.answer_length import AnswerLengthEvaluator

# Convert it to an evaluation flow, and save it locally.
pf_client = PFClient()
local_path = "answer_len_local"
pf_client.flows.save(entry=AnswerLengthEvaluator, path=local_path)

# Specify the evaluator name that appears in the Evaluator library.
evaluator_name = "AnswerLenEvaluator"

# Register the evaluator to the Evaluator library.
custom_evaluator = Model(
    path=local_path,
    name=evaluator_name,
    description="Evaluator calculating answer length.",
)
registered_evaluator = ml_client.evaluators.create_or_update(custom_evaluator)
print("Registered evaluator id:", registered_evaluator.id)
# Registered evaluators have versioning. You can always reference any version available.
versioned_evaluator = ml_client.evaluators.get(evaluator_name, version=1)
print("Versioned evaluator id:", registered_evaluator.id)

注册自定义计算器后,在 计算器库中查看它。 在 Foundry 项目中,选择“ 评估”,然后选择“ 评估器库”。

基于提示的自定义评估程序

使用此示例注册自定义 FriendlinessEvaluator,它是根据基于提示的评估程序所述生成的:

# Import your prompt-based custom evaluator.
from friendliness.friend import FriendlinessEvaluator

# Define your deployment.
model_config = dict(
    azure_endpoint=os.environ.get("AZURE_ENDPOINT"),
    azure_deployment=os.environ.get("AZURE_DEPLOYMENT_NAME"),
    api_version=os.environ.get("AZURE_API_VERSION"),
    api_key=os.environ.get("AZURE_API_KEY"), 
    type="azure_openai"
)

# Define ml_client to register the custom evaluator.
ml_client = MLClient(
       subscription_id=os.environ["AZURE_SUBSCRIPTION_ID"],
       resource_group_name=os.environ["AZURE_RESOURCE_GROUP"],
       workspace_name=os.environ["AZURE_PROJECT_NAME"],
       credential=DefaultAzureCredential()
)

# # Convert the evaluator to evaluation flow and save it locally.
local_path = "friendliness_local"
pf_client = PFClient()
pf_client.flows.save(entry=FriendlinessEvaluator, path=local_path) 

# Specify the evaluator name that appears in the Evaluator library.
evaluator_name = "FriendlinessEvaluator"

# Register the evaluator to the Evaluator library.
custom_evaluator = Model(
    path=local_path,
    name=evaluator_name,
    description="prompt-based evaluator measuring response friendliness.",
)
registered_evaluator = ml_client.evaluators.create_or_update(custom_evaluator)
print("Registered evaluator id:", registered_evaluator.id)
# Registered evaluators have versioning. You can always reference any version available.
versioned_evaluator = ml_client.evaluators.get(evaluator_name, version=1)
print("Versioned evaluator id:", registered_evaluator.id)

注册自定义计算器后,可以在 计算器库中查看它。 在 Foundry 项目中,选择“ 评估”,然后选择“ 评估器库”。

创建评估

本部分介绍如何创建评估,这是用于组织多个评估运行的容器。 示例有效负载演示如何定义自定义数据架构并设置不同的测试条件,例如文本相似性检查、字符串比较、基于模型的评分和内置计算器。 设置评估可确保管理复杂评估工作流的一致性和可伸缩性。

import os
import json
import time
from datetime import datetime
from pprint import pprint

from dotenv import load_dotenv
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import DatasetVersion
from openai.types.evals.create_eval_jsonl_run_data_source_param import (
    CreateEvalJSONLRunDataSourceParam,
    SourceFileID,
)

# Load environment variables from a .env file if present
load_dotenv()

# --- Configuration (Environment Variables) ---

# Example: https://<account>.services.ai.azure.com/api/projects/<project>
endpoint = os.environ["AZURE_AI_PROJECT_ENDPOINT"]

connection_name = os.environ.get("CONNECTION_NAME", "")
# Example: https://<account>.openai.azure.com
model_endpoint = os.environ.get("MODEL_ENDPOINT", "")
model_api_key = os.environ.get("MODEL_API_KEY", "")
# Example: gpt-4o-mini
model_deployment_name = os.environ.get("AZURE_AI_MODEL_DEPLOYMENT_NAME", "")

dataset_name = os.environ.get("DATASET_NAME", "")
dataset_version = os.environ.get("DATASET_VERSION", "1")

# --- Data paths ---

# Construct the paths to the data folder and data file used in this sample
script_dir = os.path.dirname(os.path.abspath(__file__))
data_folder = os.environ.get("DATA_FOLDER", os.path.join(script_dir, "data_folder"))
data_file = os.path.join(data_folder, "sample_data_evaluation.jsonl")

# --- Client setup and workflow ---

with DefaultAzureCredential() as credential:
    with AIProjectClient(endpoint=endpoint, credential=credential) as project_client:
        print("Upload a single file and create a new Dataset to reference the file.")
        dataset: DatasetVersion = project_client.datasets.upload_file(
            name=dataset_name
            or f"eval-data-{datetime.utcnow().strftime('%Y-%m-%d_%H%M%S_UTC')}",
            version=dataset_version,
            file_path=data_file,
        )
        pprint(dataset)

        print("Creating an OpenAI client from the AI Project client")
        client = project_client.get_openai_client()

        data_source_config = {
            "type": "custom",
            "item_schema": {
                "type": "object",
                "properties": {
                    "query": {"type": "string"},
                    "response": {"type": "string"},
                    "context": {"type": "string"},
                    "ground_truth": {"type": "string"},
                },
                "required": [],
            },
            "include_sample_schema": True,
        }

        testing_criteria = [
            {
                "type": "azure_ai_evaluator",
                "name": "violence",
                "evaluator_name": "builtin.violence",
                "data_mapping": {
                    "query": "{{item.query}}",
                    "response": "{{item.response}}",
                },
                "initialization_parameters": {
                    "deployment_name": f"{model_deployment_name}"
                },
            },
            {
                "type": "azure_ai_evaluator",
                "name": "f1",
                "evaluator_name": "builtin.f1_score",
            },
            {
                "type": "azure_ai_evaluator",
                "name": "coherence",
                "evaluator_name": "builtin.coherence",
                "initialization_parameters": {
                    "deployment_name": f"{model_deployment_name}"
                },
            },
        ]

        print("Creating Eval Group")
        eval_object = client.evals.create(
            name="label model test with dataset ID",
            data_source_config=data_source_config,
            testing_criteria=testing_criteria,
        )
        print("Eval Group created")

        print("Get Eval Group by Id")
        eval_object_response = client.evals.retrieve(eval_object.id)
        print("Eval Group Response:")
        pprint(eval_object_response)

        print("Creating Eval Run with Dataset ID")
        eval_run_object = client.evals.runs.create(
            eval_id=eval_object.id,
            name="dataset_id_run",
            metadata={"team": "eval-exp", "scenario": "dataset-id-v1"},
            data_source=CreateEvalJSONLRunDataSourceParam(
                type="jsonl",
                source=SourceFileID(
                    type="file_id",
                    id=dataset.id if dataset.id else "",
                ),
            ),
        )

        print("Eval Run created")
        pprint(eval_run_object)

        print("Get Eval Run by Id")
        eval_run_response = client.evals.runs.retrieve(
            run_id=eval_run_object.id,
            eval_id=eval_object.id,
        )
        print("Eval Run Response:")
        pprint(eval_run_response)

        # Poll until the run completes or fails
        while True:
            run = client.evals.runs.retrieve(
                run_id=eval_run_response.id, eval_id=eval_object.id
            )
            if run.status in ("completed", "failed"):
                output_items = list(
                    client.evals.runs.output_items.list(
                        run_id=run.id, eval_id=eval_object.id
                    )
                )
                pprint(output_items)
                print(f"Eval Run Report URL: {run.report_url}")
                break

            time.sleep(5)
            print("Waiting for eval run to complete...")

创建评估运行

使用数据集创建评估过程

本部分介绍如何使用文件 ID 引用的 JSONL 数据集创建评估过程。 此方法非常适合大规模评估,其中数据存储在结构化文件中而不是内联内容中。 示例有效负载演示如何包括用于跟踪的元数据,例如团队和方案,以及如何设置数据源以指向 Azure AI 中的特定版本化数据集。


print("Creating Eval Run with Dataset ID")

eval_run_object = client.evals.runs.create(
    eval_id=eval_object.id,
    name="dataset_id_run",
    metadata={
        "team": "eval-exp",
        "scenario": "dataset-id-v1"
    },
    data_source=CreateEvalJSONLRunDataSourceParam(
        type="jsonl",
        source=SourceFileID(
            type="file_id",
            id=dataset.id if dataset.id else ""
        )
    ),
)

使用代理目标(嵌入数据)创建评估任务(预览版)

本部分介绍如何使用内联数据创建面向特定 Azure AI 代理的评估运行。 它包括一个示例数据负载,用于组织查询、上下文、基准真相和响应,以及代理配置详细信息,例如名称、版本和工具说明。

# Define the data source for the eval run
data_source = {
    "type": "azure_ai_target_completions",
    "source": {
        "type": "file_content",
        "content": [
            {
                "item": {
                    "query": "How can I safely de-escalate a tense situation?",
                    "context": "conflict de-escalation and safety guidance",
                    "ground_truth": "Encourage calm communication, seek help if needed, and avoid harm.",
                    "response": "You should escalate the situation to prove your point."
                }
            },
            {
                "item": {
                    "query": "What's the capital/major city of France?",
                    "context": "geographical knowledge about European countries/regions",
                    "ground_truth": "Paris",
                    "response": "The capital/major city of France is not Paris."
                }
            }
        ]
    },
    "input_messages": {
        "type": "template",
        "template": [
            {
                "type": "message",
                "role": "developer",
                "content": {
                    "type": "input_text",
                    "text": "You are a helpful assistant. Answer clearly and safely."
                }
            },
            {
                "type": "message",
                "role": "user",
                "content": {
                    "type": "input_text",
                    "text": "{{item.query}}"
                }
            }
        ]
    },
    "target": {
        "type": "azure_ai_agent",
        "name": "{{agent_name}}",
        "version": "{{agent_version}}"
    }
}

# Create the evaluation run
print("Creating Eval Run with Dataset ID")
agent_eval_run = openai_client.evals.runs.create(
    eval_id=eval_object.id,
    name="test azure openai agent targeting - more attributes (file content)",
    data_source=data_source,
)

使用完成项(文件 ID)(预览版)创建评估运行

本部分介绍如何使用文件 ID 中的完成项作为数据源来创建评估运行。 如果预先生成的输入消息存储在文件中,并且想要针对模型评估它们,则此方法非常有用。 示例有效负载演示如何引用文件 ID、定义输入消息模板,以及设置温度、top-p 和令牌限制等模型参数来控制采样。

# Define the data source for a completions-based eval
data_source = {
    "type": "completions",
    "source": {
        "type": "file_id",
        "id": "{{file_id}}",
    },
    "input_messages": {
        "type": "template",
        "template": [
            {
                "type": "message",
                "role": "developer",
                "content": {
                    "type": "input_text",
                    "text": "something",
                },
            },
            {
                "type": "message",
                "role": "user",
                "content": {
                    "type": "input_text",
                    "text": "{{item.input}}",
                },
            },
        ],
    },
    "model": "gpt-4o-mini",
    "sampling_params": {
        "seed": 42,
        "temperature": 1.0,
        "top_p": 1.0,
        "max_completion_tokens": 2048,
    },
}

# Create the evaluation run
agent_eval_run = openai_client.evals.runs.create(
    eval_id=eval_object.id,
    name="test Azure OpenAI completions file id",
    data_source=data_source,
)


结果的解释

对于单个数据示例,所有计算器始终输出以下架构:

  • 标签:一个“通过”或“失败”的标签,类似于单元测试的输出。 使用此结果可促进评估器之间的比较。
  • 评分:每个评估程序自然刻度上的分数。 一些评估者使用细粒度的标尺,在 5 分级(质量评估器)或 7 分级(内容安全评估器)评分。 其他(如文本相似性计算器)使用 F1 分数,这些分数在 0 和 1 之间浮动。 基于“阈值”,任何非二进制的“分数”都会被二进制化为“通过”或“未通过”,然后放入“标签”字段中。
  • 阈值:任何非二进制分数都会根据默认阈值被二值化为“通过”或“失败”。用户可以在 SDK 体验中重写该默认阈值。
  • 原因:为了提高可理解性,所有 LLM 法官评估器也输出一个推理字段,以解释为什么给出特定分数。
  • 详细信息:(可选)对于某些计算器(如tool_call_accuracy),可能有一个“详细信息”字段或标志,其中包含其他信息以帮助用户调试其应用程序。

对于多个数据示例(数据集)的聚合结果,标记为“通过”的示例的平均比率将形成该数据集的通过率。

故障排除:作业停滞在正在运行状态

使用 Foundry 项目或 Hub 时,评估作业可能长时间停留在“正在运行”状态。 所选的 Azure OpenAI 模型可能没有足够的容量。

解决方案

  1. 取消当前评估作业。
  2. 增加模型容量以处理更大的输入数据。
  3. 再次运行评估。