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

以 Azure 函数的形式发布 QIO 作业

了解如何将 QIO 模型作为 Web 服务进行部署。 你将使用可通过 Web API 调用的 Azure 函数来完成此任务。 函数通过请求 URL 或请求正文接收模型输入。 然后调用 Azure Quantum 求解器,并以 JSON 字符串的形式返回结果。

你可以将 QIO 模型及其功能提供给其他开发人员,他们可以将其集成到自己的传统代码中。 无需进一步了解量子概念或 QDK 库,即可实现这种集成。 为此目的公开 QIO 功能的一种方法是通过 Azure 函数,Azure 函数可通过 Web API 调用。

Azure Functions 是一种无服务器解决方案,可让你在 Azure 中托管功能,而无需担心底层基础结构。

将作为 Azure 函数发布的 QIO 作业实现了所谓的数字分区问题。 它将给定的整数集拆分为两个子集,子集的元素之和相等(或相似)。 请查看以下 MS Learn 模块,了解有关此问题及其实现的详细信息:使用量子衍生优化解决优化问题

先决条件

若要完成本文中的步骤,需要符合以下先决条件。

创建新的 Azure Functions 项目

首先,通过 Visual Studio Code 用 Python 创建一个本地 Azure Functions 项目。 稍后,你会将函数代码发布到 Azure。

  1. 在活动栏中选择“Azure”图标,然后在“Azure:函数”区域中选择“创建新项目...”图标。 这些图标可能仅在将鼠标指针移到 Azure Functions 字段时出现。

    创建新项目

  2. 为项目工作区选择目录位置,然后选择“选择” 。

  3. 根据提示提供以下信息:

    • 选择函数项目的语言:选择 Python
    • 选择 Python 解释器以创建虚拟环境:选择提供的解释器之一(例如 python 3.9.6
    • 为项目的第一个函数选择模板:选择HTTP trigger
    • 提供函数名称:键入 SplitWeights
    • 授权级别:选择 Anonymous,这使任何人都可以调用你的函数终结点。 若要了解授权级别(以及限制对函数的访问的方法),请参阅授权密钥
    • 选择打开项目的方式:选择Open in current window
  4. Visual Studio Code 根据这些信息生成一个包含 HTTP 触发器的 Azure Functions 项目,这意味着可以通过 http-RESTful API 调用函数。 可以在资源管理器中查看本地项目文件。 若要详细了解所创建的文件,请参阅生成的项目文件

在本地环境中测试 Azure 函数

尽管该函数尚未提供任何有用的功能,但现在是在本地测试函数的最佳时机。

提示

最好在执行接下来的每个步骤之后重复此步骤,以确保所做的更改不会造成任何中断。 继续操作时,应相应地更改请求参数。

  1. 若要调用函数,请按 F5 启动函数应用项目。 来自 Core Tools 的输出会显示在“终端” 面板中。 应用将在“终端”面板中启动。 可以看到 HTTP 触发函数的 URL 终结点在本地运行。

    在本地运行 Azure 函数

    如果在 Windows 上运行时遇到问题,请确保用于 Visual Studio Code 的默认终端未设置为“WSL Bash”。

  2. 运行 Core Tools 后,转到“Azure: Functions”区域。 在“函数”下,展开“本地项目”>“函数”。 右键单击 (Windows) 或按住 Ctrl 并选择 (macOS) SplitWeights 函数,然后选择“立即执行函数...”。

    调用函数

  3. 在“输入请求正文”中,你将看到请求消息正文值 { "name": "Azure" }。 按 Enter 将此请求消息发送给函数。

  4. 当函数在本地执行并返回响应时,Visual Studio Code 中将引发通知。 函数执行的相关信息将显示在“终端”面板中。

  5. 按 Ctrl + C 停止 Core Tools 并断开调试器的连接

引用 Azure Quantum 库

默认情况下,生成的 Azure Functions 项目仅引用标准 Python 库。 必须显式引用特定函数所需的所有其他库。 这些引用告诉 Azure Functions 运行时在调用函数时加载哪些库。 你可以添加对 Azure Quantum Python 库的引用。

  1. 为该库选择文件 requirements.txt

  2. azure-functions 后面添加对 Azure Quantum Python 库的引用,方法是在文件末尾添加 azure-quantum。 完整的文件应如下所示:

    # DO NOT include azure-functions-worker in this file
    # The Python Worker is managed by Azure Functions platform
    # Manually managing azure-functions-worker may cause unexpected issues
    
    azure-functions
    azure-quantum
    
  3. 保存该文件。

添加对 Azure Quantum 工作区的引用

你现在拥有一个函数,当通过 http 调用进行调用时,该函数可以访问必要的 Azure Quantum 库。 但到目前为止,该函数还没有执行任何操作。 若要改变现状,请添加对 Azure Quantum 工作区的引用。

  1. 打开文件夹 SplitWeights 中的文件 __init__.py。 此文件包含收到 http 请求时执行的代码。

  2. 添加对 Azure Quantum 工作区的引用。 在最后一个 import 语句后面添加以下代码。

    from azure.quantum import Workspace
    
    workspace = Workspace (
        subscription_id = "",  # Add your subscription_id
        resource_group = "",   # Add your resource_group
        name = "",             # Add your workspace name
        location = ""          # Add your workspace location (for example, "eastus")
        )
    
  3. 保存该文件。

添加 QIO 算法代码

到目前为止,我们仅为函数加载必要的 Python 库以及与 Azure Quantum 工作区建立连接进行了准备。 现在是时候添加一些有用的优化代码了。

  1. 在开头添加必要的 import 语句。 在第一个 import 语句后面添加以下行。

    import json
    
  2. Workspace import 后面添加以下语句。

    from typing import List
    from azure.quantum.optimization import Problem, ProblemType, Term
    from azure.quantum.optimization import QuantumMonteCarlo
    
  3. 将现有 main 函数替换为以下代码。

    def main(req: func.HttpRequest) -> func.HttpResponse:
        mineralWeights = []
    
        # Try to read the mineralWeights from the URL-string.
        mwStr = req.params.get('mineralWeights')
        if mwStr:
            list = mwStr.split (",")
            for i in list:
                mineralWeights.append(int(i))
        else:
            # If not passed via URL, try to extract the mineral Weights from the request body.
            try:
                req_body = req.get_json()
            except ValueError:
                pass
            else:
                mineralWeights = req_body.get('mineralWeights')
    
        if mineralWeights:
            # Create a problem for the given list of minerals:
            problem = createProblemForMineralWeights(mineralWeights)
    
            # Instantiate a solver to solve the problem.
            solver = QuantumMonteCarlo(workspace, sweeps = 2, trotter_number = 10, restarts = 72, seed = 22, beta_start = 0.1, transverse_field_start = 10, transverse_field_stop = 0.1)
    
            # Optimize the problem
            result = solver.optimize(problem)
    
            return func.HttpResponse(
                 json.dumps(result['configuration']),
                 status_code=200
            )
        else:
            return func.HttpResponse(
                 "The function couldn't be executed successfully. Pass a mineralWeights param in the query string or in the request body for a personalized response.",
                 status_code=400
            )
    
    def createProblemForMineralWeights(mineralWeights: List[int]) -> Problem:
        terms: List[Term] = []
    
        # Expand the squared summation
        for i in range(len(mineralWeights)):
            for j in range(len(mineralWeights)):
                if i == j:
                    # Skip the terms where i == j as they form constant terms in an Ising problem and can be disregarded.
                    continue
    
                terms.append(
                    Term(
                        c = mineralWeights[i] * mineralWeights[j],
                        indices = [i, j]
                    )
                )
    
        # Return an Ising-type problem
        return Problem(name="Freight Balancing Problem", problem_type=ProblemType.ising, terms=terms)
    

该函数现在包含两个函数:main 函数在收到 http 请求时执行。 它会分析请求并查看请求 URL。 如果在 URL 中找到 mineralWeights 参数,则会处理这些重量。 如果 URL 不包含此参数,则会分析请求正文。 如果在正文中找到 mineralWeights 参数,则会处理这些重量。 重量将传递到创建 Problem 对象的 createProblemForMineralWeights 函数。 main 函数将此 Problem 对象传递给 Azure Quantum 求解器并返回结果。

准备云环境

现在可以准备目标环境来​托管函数。 准备工作包括创建一个空的 Azure Functions 应用并授予对 Azure Quantum 工作区的访问权限。

  1. 转到 Azure 门户并登录 Azure 帐户。

  2. 创建函数应用。 在门户左上角选择“创建资源”。

    创建资源

  3. 搜索“函数应用”,然后选择“创建” 。

  4. 提供以下信息:

    • 订阅:选择要使用的订阅。 使用同时包含 Azure Quantum 工作区的订阅。
    • 资源组:选择同时包含 Azure Quantum 工作区的资源组。
    • 函数应用名称:输入函数应用的全局唯一名称。 键入在 URL 路径中有效的名称。 将对你键入的名称进行验证,以确保其在 Azure Functions 中是唯一的。
    • 发布:选择 Code
    • 运行时堆栈:选择 Python
    • 版本:选择你一直在本地运行的 Python 版本。 可以使用 python --version 命令来检查你的版本。
    • 区域:选择同时包含 Azure Quantum 工作区的区域。

    选择“查看 + 创建”以确认输入。

  5. 验证输入并选择“创建”。 部署将需要几秒钟的时间。 等待显示确认信息。

  6. 选择“转到资源”以导航到函数应用。

  7. 为函数应用配置托管标识。 托管标识允许该应用访问其他 Azure 资源(如 Azure Quantum 工作区)。

    为函数应用创建托管标识

    选择“保存”以保留配置,并在打开的对话框中单击“是”进行确认。

  8. 允许 Functions 应用访问 Azure Quantum 工作区。 导航到 Azure Quantum 工作区并从左侧菜单中选择“访问控制(IAM)”。 依次选择“添加”、“添加角色分配”。 在 Azure Quantum 工作区上创建新的角色分配

  9. 角色分配对话框打开。 提供以下信息:

    • 角色:选择 Contributor
    • 将访问权限分配到:选择 Function App
    • 订阅:选择订阅。
    • 选择:输入函数应用名称。

    将函数应用作为参与者添加到 Azure Quantum 工作区

  10. 选择函数应用,并单击“保存”确认选择。

将 Azure 函数部署到云

将函数代码部署到上一步中准备的环境。

  1. 在 Visual Studio Code 中,在活动栏中选择“Azure”图标,然后在“Azure: Functions”区域中,选择“部署到函数应用...”按钮 。

    部署函数

  2. 在提示“选择 Azure 中的函数应用”时,选择之前创建的函数应用。

  3. 部署函数应用后,会显示一条通知。 选择“查看输出”以显示状态信息和可以调用函数的 URL。

部署成功后的通知

通过 Azure 函数调用 QIO 算法

现在可以在云中测试函数。

  1. 通过在浏览器中调用函数 URL 来调用函数。 调用以下 URL:

    https://<your_function_app_name>.azurewebsites.net/api/splitweights
    

    此调用应生成以下输出:

    The function couldn't be executed successfully. Pass a mineralWeights param in the query string or in the request body for a personalized response.
    
  2. 通过在浏览器中使用所需参数调用函数 URL 来调用函数。 调用以下 URL:

    https://<your_function_app_name>.azurewebsites.net/api/splitweights?mineralWeights=5,11,8,7,1,1
    

    此调用应生成以下输出:

    {"0": -1, "1": 1, "2": -1, "3": 1, "4": -1, "5": -1}
    
  3. 使用请求正文中传递的矿物重量调用函数。 返回 Visual Studio Code,在侧栏的“Azure: Functions”区域中,展开订阅、新函数应用和 Functions。 右键单击 (Windows) 或按住 Ctrl 并选择 (macOS) SplitWeights 函数,然后选择“立即执行函数...”。

    通过 Visual Studio Code 执行函数

  4. 在输入字段“输入请求正文”中,你将看到请求消息正文。 输入值 { "mineralWeights": [5,11,8,7,1,1] }。 按 Enter 将此请求消息发送给函数。

  5. 几秒钟后应出现以下确认消息:

    函数调用后的结果

提示

刚部署的函数实现了数字分区问题。 它允许你将给定的一组数字拆分为两个子集,子集的元素之和相等(或相似)。 若要详细了解此问题及其实现,请查看 MS Learn 模块:使用量子衍生优化解决优化问题

后续步骤

  • 你已经知道如何以 Azure 函数的形式发布作业,现在可以尝试从我们提供的示例集合中发布其他作业,或尝试发布你自己的作业。
  • 若要详细了解数字分区问题及其实现,请参阅以下 MS Learn 模块:使用量子衍生优化解决优化问题