通过 Azure OpenAI 开始使用多模式视觉聊天应用

本文介绍如何使用 Azure OpenAI 多模式模型在聊天应用中生成对用户消息和上传图像的响应。 此聊天应用示例还包括预配 Azure OpenAI 资源以及使用 Azure 开发人员 CLI 将应用部署到 Azure 容器应用所需的所有基础结构和配置。

按照本文中的说明操作,你将:

  • 部署使用托管标识进行身份验证的 Azure 容器聊天应用。
  • 上传要用作聊天流的一部分的图像。
  • 使用 OpenAI 库与 Azure OpenAI 多模式大型语言模型(LLM)聊天。

完成此文章后,可以使用自定义代码开始修改新项目。

注意

本文使用一个或多个 AI 应用模板作为本文中的示例和指南的基础。 AI 应用模板为你提供了维护良好、易于部署的参考实现,可帮助确保 AI 应用有一个高质量的起点。

体系结构概述

下图显示了聊天应用的简单体系结构: 显示从客户端到后端应用的体系结构的示意图。

聊天应用作为 Azure 容器应用运行。 应用通过 Microsoft Entra ID 使用托管标识通过 Azure OpenAI 进行身份验证,而不是 API 密钥。 聊天应用使用 Azure OpenAI 生成对用户消息的响应。

应用程序体系结构依赖于以下服务和组件:

  • Azure OpenAI 表示我们向其发送用户查询的 AI 提供程序。
  • Azure 容器应用是托管应用程序的容器环境。
  • 托管标识 可帮助我们确保一流的安全性,并消除了开发人员安全管理机密的要求。
  • 用于预配 Azure 资源的 Bicep 文件,包括 Azure OpenAI、Azure 容器应用、Azure 容器注册表、Azure Log Analytics 和基于角色的访问控制(RBAC)角色。
  • Microsoft AI 聊天协议提供了跨 AI 解决方案和语言的标准化 API 协定。 聊天应用符合 Microsoft AI 聊天协议。
  • 一个 Python Quart ,它 openai 使用包生成对包含上传图像文件的用户消息的响应。
  • 基本 HTML/JavaScript 前端,它使用 JSON 行通过 ReadableStream 从后端流式传输响应。

成本

为了尽量降低此示例中的定价,大多数资源都使用基本定价层或消耗定价层。 根据需要根据预期使用情况更改层级别。 若要停止产生费用,在完成本文后删除资源。

在示例存储库中了解有关成本的详细信息

先决条件

开发容器 环境提供了完成本文所需的所有依赖项。 可以在 GitHub Codespaces(在浏览器中)或在本地使用 Visual Studio Code 运行开发容器。

若要使用本文,需要满足以下先决条件:

打开开发环境

按照以下说明部署预配置开发环境,其中包含完成本文所需的所有依赖项。

GitHub Codespaces 运行由 GitHub 托管的开发容器,将 Visual Studio Code 网页版作为用户界面。 对于最简单的开发环境,请使用 GitHub Codespaces,以便预先安装完成本文所需的合适的开发人员工具和依赖项。

重要

所有 GitHub 帐户每月可以使用 Codespaces 最多 60 小时,其中包含 2 个核心实例。 有关详细信息,请参阅 GitHub Codespaces 每月包含的存储和核心小时数

使用以下步骤在 GitHub 存储库的Azure-Samples/openai-chat-vision-quickstart分支上main创建新的 GitHub Codespace。

  1. 右键单击以下按钮,然后在新窗口中选择“打开”链接。 此操作允许你拥有可供查看的开发环境和文档。

    在 GitHub Codespaces 中打开

  2. “创建代码空间”页上,查看并选择“创建新代码空间”

  3. 等待 Codespace 启动。 此启动过程会花费几分钟时间。

  4. 使用屏幕底部终端中的 Azure 开发人员 CLI 登录到 Azure。

    azd auth login
    
  5. 从终端复制代码,然后将其粘贴到浏览器中。 按照说明使用 Azure 帐户进行身份验证。

本文中的剩余任务需要在此开发容器的上下文中完成。

部署和运行

示例存储库包含聊天应用 Azure 部署的所有代码和配置文件。 以下步骤将引导你完成示例聊天应用 Azure 部署过程。

将聊天应用部署到 Azure

重要

在本部分中创建的 Azure 资源会产生即时成本。 即使在完全执行命令之前中断命令,这些资源也会产生费用。

  1. 针对 Azure 资源预配和源代码部署运行以下 Azure 开发人员 CLI 命令:

    azd up
    
  2. 使用下表回答提示:

    提示 Answer
    环境名称 保持简短和小写。 添加名称或别名。 例如,chat-vision。 它用作资源组名称的一部分。
    订阅 选择要在其中创建资源的订阅。
    位置(用于托管) 从列表中选择附近的位置。
    Azure OpenAI 模型的位置 从列表中选择附近的位置。 如果可以使用与第一个位置相同的位置,请选择该位置。
  3. 等待应用部署完成。 部署通常需要 5 到 10 分钟才能完成。

使用聊天应用向大型语言模型提问

  1. 终端在成功部署应用程序后显示 URL。

  2. 选择标记为 Deploying service web 的 URL 在浏览器中打开聊天应用程序。

    浏览器中聊天应用的屏幕截图,其中包含有关聊天中上传图像的问题以及响应和聊天文本框以输入问题。

  3. 在浏览器中,通过单击 “选择文件 ”并选择图像来上传图像。

  4. 询问有关上传的图像的问题,例如“图像是什么?”

  5. 答案来自 Azure OpenAI 并显示结果。

浏览示例代码

虽然 OpenAI 和 Azure OpenAI 服务依赖于 常见的 Python 客户端库,但使用 Azure OpenAI 终结点时需要进行少量代码更改。 此示例使用 Azure OpenAI 多模式模型生成对用户消息和上传图像的响应。

Base64 对前端中上传的图像进行编码

上传的图像需要经过 Base64 编码,以便可以直接用作数据 URI 作为消息的一部分。

在示例中,文件标记src/quartapp/templates/index.html中的script以下前端代码片段处理该功能。 toBase64箭头函数使用readAsDataURL上传的图像文件中异步读取的方法FileReader作为 base64 编码字符串。

    const toBase64 = file => new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = reject;
    });

函数 toBase64 由窗体 submit 事件的侦听器调用。 submit当事件触发时,侦听器会检查图像文件,并使用函数对图像进行 toBase64 Base64 编码时进行处理。 然后,新图像数据 URL fileData将追加到消息中。

    form.addEventListener("submit", async function(e) {
        e.preventDefault();

        const file = document.getElementById("file").files[0];
        const fileData = file ? await toBase64(file) : null;

        const message = messageInput.value;

        const userTemplateClone = userTemplate.content.cloneNode(true);
        userTemplateClone.querySelector(".message-content").innerText = message;
        if (file) {
            const img = document.createElement("img");
            img.src = fileData;
            userTemplateClone.querySelector(".message-file").appendChild(img);
        }
        targetContainer.appendChild(userTemplateClone);

使用后端处理映像

src\quartapp\chat.py 文件中,用于映像处理的后端代码在配置无密钥身份验证后开始。

注意

有关如何使用无密钥连接进行身份验证和授权到 Azure OpenAI 的详细信息,请参阅 Azure OpenAI 安全构建基块 入门Microsoft Learn 一文。

聊天处理程序函数

chat_handler() 函数等待来自终结点的 chat/stream 传入请求 JSON 数据,然后处理它。 然后,将从 JSON 数据中提取消息。 最后,从 JSON 数据检索 base64 编码图像。

@bp.post("/chat/stream")
async def chat_handler():
    request_json = await request.get_json()
    request_messages = request_json["messages"]
    # get the base64 encoded image from the request
    image = request_json["context"]["file"]

使用 OpenAI 客户端和模型的响应流

函数 response_stream 内部 chat_handler 处理路由中的聊天完成调用。 以下代码片段首先处理用户内容消息。 如果存在图像,则图像 URL 将追加到用户内容,并带有

    @stream_with_context
    async def response_stream():
        # This sends all messages, so API request may exceed token limits
        all_messages = [
            {"role": "system", "content": "You are a helpful assistant."},
        ] + request_messages[0:-1]
        all_messages = request_messages[0:-1]
        if image:
            user_content = []
            user_content.append({"text": request_messages[-1]["content"], "type": "text"})
            user_content.append({"image_url": {"url": image, "detail": "auto"}, "type": "image_url"})
            all_messages.append({"role": "user", "content": user_content})
        else:
            all_messages.append(request_messages[-1])

注意

有关图像 detail 参数和相关设置的详细信息,请查看 图像处理中的详细信息参数设置:“将 GPT-4 Turbo 与视觉配合使用”中的“低、高、自动 ”部分,Microsoft Learn 文章。

接下来, bp.openai_client.chat.completions 通过 Azure OpenAI API 调用获取聊天完成并流式传输响应。

        chat_coroutine = bp.openai_client.chat.completions.create(
            # Azure OpenAI takes the deployment name as the model name
            model=os.environ["OPENAI_MODEL"],
            messages=all_messages,
            stream=True,
            temperature=request_json.get("temperature", 0.5),
        )

最后,响应将流式传输到客户端,并针对任何异常进行错误处理。

        try:
            async for event in await chat_coroutine:
                event_dict = event.model_dump()
                if event_dict["choices"]:
                    yield json.dumps(event_dict["choices"][0], ensure_ascii=False) + "\n"
        except Exception as e:
            current_app.logger.error(e)
            yield json.dumps({"error": str(e)}, ensure_ascii=False) + "\n"

    return Response(response_stream())

要浏览的其他示例资源

除了聊天应用示例,存储库中还有其他资源可供进一步学习。 查看目录中的以下笔记本 notebooks

笔记本 说明
chat_pdf_images.ipynb 此笔记本演示如何将 PDF 页面转换为图像,并将其发送到视觉模型进行推理。
chat_vision.ipynb 此笔记本用于手动试验应用中使用的视觉模型。

清理资源

清理 Azure 资源

本文中创建的 Azure 资源的费用将计入你的 Azure 订阅。 如果你预计将来不需要这些资源,请将其删除,以避免产生更多费用。

要删除 Azure 资源并移除源代码,请运行以下 Azure Developer CLI 命令:

azd down --purge

清理 GitHub Codespaces

删除 GitHub Codespaces 环境可确保可以最大程度地提高帐户获得的每核心免费小时数权利。

重要

有关 GitHub 帐户权利的详细信息,请参阅 GitHub Codespaces 每月包含的存储和核心小时数

  1. 登录到 GitHub Codespaces 仪表板 (https://github.com/codespaces)。

  2. 找到当前正在运行的、源自 Azure-Samples//openai-chat-vision-quickstart GitHub 存储库的 Codespaces。

  3. 打开 codespace 的上下文菜单,然后选择“删除”。

获取帮助

将问题记录到存储库 的问题

后续步骤