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

教程:在 Visual Studio Code 中向函数添加 Azure OpenAI 文本完成提示

本文介绍如何使用 Visual Studio Code 将 HTTP 终结点添加到上一快速入门文章中创建的函数应用。 触发时,这个新的 HTTP 终结点使用 Azure OpenAI 文本完成输入绑定从数据模型获取文本完成提示。

本教程介绍如何完成以下任务:

  • 在 Azure OpenAI 中创建资源。
  • 在 OpenAI 中部署资源模型。
  • 设置模型资源的访问权限。
  • 使函数应用能够连接到 OpenAI。
  • 将 OpenAI 绑定添加到 HTTP 触发的函数。

1.检查先决条件

  • 在 Azure 订阅中获取对 Azure OpenAI 的访问权限。 如果尚未授予访问权限,请完成此表单以请求访问权限。
  • Azurite 存储模拟器。 虽然也可以使用实际的 Azure 存储帐户,但本文假定你使用的是此模拟器。

2.创建 Azure OpenAI 资源

以下步骤演示如何在 Azure 门户中创建 Azure OpenAI 数据模型。

  1. Azure 门户中使用 Azure 订阅登录。

  2. 选择“创建资源”并搜索“Azure OpenAI”。 找到该服务后,选择“创建”。

  3. 在“创建 Azure OpenAI”页面上,为“基础知识”选项卡上的字段提供以下信息:

    字段 说明
    订阅 你的订阅已载入,可以使用 Azure OpenAI。
    资源组 在上一篇文章中为函数应用创建的资源组。 可以在 Azure 资源浏览器中右键单击函数应用,选择属性,然后在返回的 JSON 资源文件中搜索 resourceGroup 设置来查找此资源组名称。
    区域 理想情况下,与函数应用相同的位置。
    Name Azure OpenAI 服务资源的描述性名称,例如 mySampleOpenAI
    定价层 资源的定价层。 目前,Azure OpenAI 服务仅提供标准层。 有关定价的详细信息,请访问 Azure OpenAI 定价页

    显示如何在 Azure 门户中配置 Azure OpenAI 资源的屏幕截图。

  4. 选择“下一步”两次以接受“网络”和“标记”选项卡的默认值。 创建的服务没有任何网络限制,包括来自 Internet 的限制。

  5. 选择“下一步”,最后一次转到流程的最后阶段:审阅 + 提交

  6. 确认你的配置设置,然后选择“创建”。

    当新资源可用时,Azure 门户会显示通知。 选择通知中的“转到资源”,或按名称搜索新的 Azure OpenAI 资源。

  7. 在新资源的 Azure OpenAI 资源页面中,选择“Essentials”>“终结点”下的“单击此处以查看终结点”。 复制终结点 URL 和密钥。 保存这些值,稍后需要它们。

在 Azure OpenAI 中拥有连接到模型的凭据后,需要在应用程序设置中设置这些访问凭据。

3.部署模型

现在可以部署模型。 可以从 Azure OpenAI Studio 中的多个可用模型中进行选择。

若要部署模型,请执行以下步骤:

  1. 登录到 Azure OpenAI Studio

  2. 选择订阅和创建的 Azure OpenAI 资源,然后选择“使用资源”。

  3. 在“管理”下,选择“部署”。

  4. 选择“创建新部署”并配置以下字段:

    字段 说明
    部署名称 请谨慎选择名称。 部署名称用于代码中,以使用客户端库和 REST API 调用模型,因此必须保存供以后使用。
    选择模型 模型可用性因区域而异。 有关每个区域的可用模型的列表,请参阅模型摘要表和区域可用性

    重要

    通过 API 访问模型时,需要在 API 调用中引用部署名称而不是基础模型名称,这是 OpenAI 和 Azure OpenAI 之间的主要区别之一。 OpenAI 只需要模型名称。 即使使用了模型参数,Azure OpenAI 也始终需要部署名称。 在我们的文档中,经常有一些示例,其中部署名称表示为与模型名称相同的名称,这样有助于指示哪个模型适用于特定 API 终结点。 最终,部署名称可以遵循最适合你的用例的任何命名约定。

  5. 接受其余设置的默认值,然后选择“创建”。

    部署表会显示与新建模型相对应的新条目。

现在,只需将基于 Azure OpenAI 的文本完成添加到函数应用。

4.更新应用程序设置

  1. 在 Visual Studio Code 中,打开在完成上一篇文章时创建的本地代码项目。

  2. 在项目根文件夹中的 local.settings.json 文件中,将 AzureWebJobsStorage 设置更新为 UseDevelopmentStorage=true。 如果 local.settings.json 中的 AzureWebJobsStorage 设置设置为现有 Azure 存储帐户的连接字符串,而不是 UseDevelopmentStorage=true,则可以跳过此步骤。

  3. 在 local.settings.json 文件中,添加以下设置值:

    • AZURE_OPENAI_ENDPOINT:绑定扩展所必需的。 将此值设置为之前创建的 Azure OpenAI 资源的终结点。
    • AZURE_OPENAI_KEY:绑定扩展所必需的。 将此值设置为 Azure OpenAI 资源的密钥。
    • CHAT_MODEL_DEPLOYMENT_NAME:用于定义输入绑定。 将此值设置为你为模型部署选择的名称。
  4. 保存文件。 部署到 Azure 时,还必须将这些设置添加到函数应用。

5.注册绑定扩展

由于你使用 Azure OpenAI 输出绑定,因此在运行项目之前,必须安装对应的绑定扩展。

绑定(HTTP 和计时器触发器除外)将实现为扩展包。 若要将 Azure OpenAI 扩展包添加到项目,请在“终端”窗口中运行此 dotnet add package 命令:

dotnet add package Microsoft.Azure.Functions.Worker.Extensions.OpenAI --prerelease

5.更新扩展捆绑包

若要访问预览版 Azure OpenAI 绑定,必须使用包含此扩展的扩展捆绑包的预览版本。

将当前 host.json 文件中的 extensionBundle 设置替换为以下 JSON:

 "extensionBundle": {
   "id": "Microsoft.Azure.Functions.ExtensionBundle.Preview",
   "version": "[4.*, 5.0.0)"
 }

现在,可以在项目中使用 Azure OpenAI 输出绑定。

6.从模型返回文本完成

添加的代码会在现有项目中创建 whois HTTP 函数终结点。 在此函数中,GET 请求的 URL 中的 name 参数中传递的数据用于动态创建完成提示。 这个动态提示被绑定到一个文本完成输入绑定上,该绑定根据提示从模型中返回响应。 模型的完成在 HTTP 响应中返回。

  1. 在现有 HttpExample 类文件中,添加以下 using 语句:

    using Microsoft.Azure.Functions.Worker.Extensions.OpenAI.TextCompletion;
    
  2. 在同一文件中,添加此代码以定义名为 whois 的新 HTTP 触发器终结点:

    [Function(nameof(WhoIs))]
    public IActionResult WhoIs([HttpTrigger(AuthorizationLevel.Function, Route = "whois/{name}")] HttpRequest req,
    [TextCompletionInput("Who is {name}?", Model = "%CHAT_MODEL_DEPLOYMENT_NAME%")] TextCompletionResponse response)
    {
        if(!String.IsNullOrEmpty(response.Content))
        {
            return new OkObjectResult(response.Content);
        }
        else
        {
            return new NotFoundObjectResult("Something went wrong.");
        }
    }
    
  1. 更新 pom.xml 项目文件以将此引用添加到 properties 集合:

    <azure-functions-java-library-openai>0.4.0-preview</azure-functions-java-library-openai>
    
  2. 在同一文件中,将此依赖项添加到 dependencies 集合:

    <dependency>
        <groupId>com.microsoft.azure.functions</groupId>
        <artifactId>azure-functions-java-library-openai</artifactId>
        <version>${azure-functions-java-library-openai}</version>
    </dependency>
    
  3. 在现有 Function.java 项目文件中,添加以下 import 语句:

    import com.microsoft.azure.functions.openai.annotation.textcompletion.TextCompletion;
    import com.microsoft.azure.functions.openai.annotation.textcompletion.TextCompletionResponse;
    
  4. 在同一文件中,添加此代码以定义名为 whois 的新 HTTP 触发器终结点:

    @FunctionName("WhoIs")
    public HttpResponseMessage whoIs(
        @HttpTrigger(
            name = "req", 
            methods = {HttpMethod.GET},
            authLevel = AuthorizationLevel.ANONYMOUS, 
            route = "whois/{name}") 
            HttpRequestMessage<Optional<String>> request,
        @BindingName("name") String name,
        @TextCompletion(prompt = "Who is {name}?", model = "%CHAT_MODEL_DEPLOYMENT_NAME%", name = "response") TextCompletionResponse response,
        final ExecutionContext context) {
        return request.createResponseBuilder(HttpStatus.OK)
            .header("Content-Type", "application/json")
            .body(response.getContent())
            .build();
    }
    
  1. 在 Visual Studio Code 中,按 F1,在命令面板类型 Azure Functions: Create Function...中,选择 HTTP 触发器,键入函数名称 whois,然后按 Enter。

  2. 在新的 whois.js 代码文件中,将文件的内容替换为以下代码:

    const { app, input } = require("@azure/functions");
    
    // This OpenAI completion input requires a {name} binding value.
    const openAICompletionInput = input.generic({
        prompt: 'Who is {name}?',
        maxTokens: '100',
        type: 'textCompletion',
        model: '%CHAT_MODEL_DEPLOYMENT_NAME%'
    })
    
    app.http('whois', {
        methods: ['GET'],
        route: 'whois/{name}',
        authLevel: 'function',
        extraInputs: [openAICompletionInput],
        handler: async (_request, context) => {
            var response = context.extraInputs.get(openAICompletionInput)
            return { body: response.content.trim() }
        }
    });
    
  1. 在 Visual Studio Code 中,按 F1,在命令面板类型 Azure Functions: Create Function...中,选择 HTTP 触发器,键入函数名称 whois,然后按 Enter。

  2. 在新的 whois.ts 代码文件中,将文件的内容替换为以下代码:

    import { app, input } from "@azure/functions";
    
    // This OpenAI completion input requires a {name} binding value.
    const openAICompletionInput = input.generic({
        prompt: 'Who is {name}?',
        maxTokens: '100',
        type: 'textCompletion',
        model: '%CHAT_MODEL_DEPLOYMENT_NAME%'
    })
    
    app.http('whois', {
        methods: ['GET'],
        route: 'whois/{name}',
        authLevel: 'function',
        extraInputs: [openAICompletionInput],
        handler: async (_request, context) => {
            var response: any = context.extraInputs.get(openAICompletionInput)
            return { body: response.content.trim() }
        }
    });
    
  1. 在现有 function_app.py 项目文件中,添加以下 import 语句:

    import json
    
  2. 在同一文件中,添加此代码以定义名为 whois 的新 HTTP 触发器终结点:

    @app.route(route="whois/{name}", methods=["GET"])
    @app.text_completion_input(arg_name="response", prompt="Who is {name}?", max_tokens="100", model = "%CHAT_MODEL_DEPLOYMENT_NAME%")
    def whois(req: func.HttpRequest, response: str) -> func.HttpResponse:
        response_json = json.loads(response)
        return func.HttpResponse(response_json["content"], status_code=200)
    
    
    @app.route(route="genericcompletion", methods=["POST"])
    @app.text_completion_input(arg_name="response", prompt="{Prompt}", model = "%CHAT_MODEL_DEPLOYMENT_NAME%")
    def genericcompletion(req: func.HttpRequest, response: str) -> func.HttpResponse:
        response_json = json.loads(response)
        return func.HttpResponse(response_json["content"], status_code=200)
    
  1. 在 Visual Studio Code 中,按 F1,在命令面板类型 Azure Functions: Create Function... 中,选择“HTTP 触发器”,键入函数名称 whois,选择“匿名”,然后按 Enter。

  2. 打开新的 whois/function.json 代码文件并将其内容替换为此代码,这将为 TextCompletionResponse 输入绑定添加定义:

    {
      "bindings": [
        {
          "authLevel": "function",
          "type": "httpTrigger",
          "direction": "in",
          "name": "Request",
          "route": "whois/{name}",
          "methods": [
            "get"
          ]
        },
        {
          "type": "http",
          "direction": "out",
          "name": "Response"
        },
        {
          "type": "textCompletion",
          "direction": "in",
          "name": "TextCompletionResponse",
          "prompt": "Who is {name}?",
          "maxTokens": "100",
          "model": "%CHAT_MODEL_DEPLOYMENT_NAME%"
        }
      ]
    }
    
  3. whois/run.ps1 代码文件的内容替换为此代码,这将返回输入绑定响应:

    using namespace System.Net
    
    param($Request, $TriggerMetadata, $TextCompletionResponse)
    
    Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
            StatusCode = [HttpStatusCode]::OK
            Body       = $TextCompletionResponse.Content
        })
    

7.运行函数

  1. 在 Visual Studio Code 中,按 F1,在命令面板类型 Azurite: Start 中,按 Enter 启动 Azurite 存储模拟器。

  2. F5 在调试模式下启动函数应用项目和 Core Tools。

  3. 运行 Core Tools 后,向 whois 终结点函数发送 GET 请求,路径中具有名称,如下所示:

    http://localhost:7071/api/whois/<NAME>

    <NAME> 字符串替换为要传递给 "Who is {name}?" 提示的值。 <NAME> 必须是公共图形的 URL 编码名称,如 Abraham%20Lincoln

    你看到的响应是 Azure OpenAI 模型中的文本完成响应。

  4. 返回响应后,按 Ctrl + C 停用 Core Tools。

8.清理资源

在 Azure 中,“资源”是指函数应用、函数、存储帐户等。 这些资源可以组合到资源组中,删除该组即可删除组中的所有内容。

已创建完成这些快速入门所需的资源。 这些资源可能需要付费,具体取决于帐户状态服务定价。 如果不再需要这些资源,请参阅下面介绍的资源删除方法:

  1. 在 Visual Studio Code 中,按 F1 打开命令面板。 在命令面板中,搜索并选择 Azure: Open in portal

  2. 选择你的函数应用,然后按 Enter。 随即将在 Azure 门户中打开函数应用页面。

  3. 在“概览”选项卡中,选择“资源组”旁边的命名链接。

    从函数应用页选择要删除的资源组的屏幕截图。

  4. 在“资源组”页上查看所包括的资源的列表,然后验证这些资源是否是要删除的。

  5. 选择“删除资源组”,然后按说明操作。

    可能需要数分钟才能删除完毕。 完成后会显示一个通知,持续数秒。 也可以选择页面顶部的钟形图标来查看通知。