開始使用 Azure OpenAI 安全性建置組塊
本文說明如何建立及使用 Azure OpenAI 安全性建置組塊範例。 其目的是要示範使用角色型訪問控制 (RBAC) 布建 Azure OpenAI 帳戶,以對 Azure OpenAI 進行無密鑰(Microsoft Entra ID)驗證。 此聊天應用程式範例也包含布建 Azure OpenAI 資源所需的所有基礎結構和設定,以及使用 Azure 開發人員 CLI 將應用程式部署至 Azure Container Apps。
遵循本文中的指示,您將會:
- 部署安全的 Azure 容器聊天應用程式。
- 使用受控識別進行 Azure OpenAI 存取。
- 使用 OpenAI 連結庫與 Azure OpenAI 大型語言模型 (LLM) 聊天。
完成本文之後,您可以使用自定義程式代碼和數據開始修改新專案。
注意
本文使用一或多個 AI 應用程式範本 作為本文範例和指引的基礎。 AI 應用程式範本提供您妥善維護且易於部署的參考實作,以協助確保 AI 應用程式的高品質起點。
架構概觀
聊天應用程式會以 Azure 容器應用程式的形式執行。 應用程式會透過 Microsoft Entra ID 使用受控識別,向 Azure OpenAI 進行驗證,而不是 API 金鑰。 聊天應用程式會使用 Azure OpenAI 來產生使用者訊息的回應。
應用程式架構依賴下列服務和元件:
- Azure OpenAI 代表我們傳送用戶查詢的 AI 提供者。
- Azure Container Apps 是裝載應用程式的容器環境。
- 受控識別 可協助我們確保頂級安全性,並免除身為開發人員安全地管理秘密的需求。
- 布建 Azure 資源的 Bicep 檔案 ,包括 Azure OpenAI、Azure Container Apps、Azure Container Registry、Azure Log Analytics 和 RBAC 角色。
- Microsoft AI 聊天通訊協定 提供跨 AI 解決方案和語言的標準化 API 合約。 聊天應用程式符合Microsoft AI 聊天通訊協定,可讓評估應用程式針對符合通訊協定的任何聊天應用程式執行。
- 使用套件來產生使用者訊息回應的 Python
openai
。 - 基本 HTML/JavaScript 前端,可透過 ReadableStream 使用 JSON Line 串流來自後端的回應。
- Blazor Web 應用程式,使用 Azure.AI.OpenAI NuGet 套件來產生使用者訊息的回應。
- 使用 openai npm 套件來產生使用者訊息回應的 TypeScript Web 應用程式。
成本
嘗試讓此範例中的定價盡可能低,大部分的資源都會使用基本或耗用量定價層。 根據您的預期使用量,視需要改變階層層級。 若要停止產生費用,請在完成本文時刪除資源。
深入瞭解 範例存放庫中的成本。
深入瞭解 範例存放庫中的成本。
深入瞭解 範例存放庫中的成本。
必要條件
開發容器環境可提供完成本文所需的所有相依性。 您可以在 GitHub Codespaces (瀏覽器中) 或使用 Visual Studio Code 在本機執行開發容器。
若要使用本文,您必須滿足下列必要條件:
Azure 訂用帳戶 - 免費建立一個訂用帳戶
Azure 帳戶許可權 - 您的 Azure 帳戶必須具有
Microsoft.Authorization/roleAssignments/write
許可權,例如 使用者存取系統管理員 或 擁有者。GitHub 帳戶
開啟開發環境
使用下列指示來部署預先設定的開發環境,其中包含完成本文所需的所有相依性。
GitHub Codespaces 會使用網頁版 Visual Studio Code 作爲使用者介面,執行由 GitHub 管理的開發容器。 如需最直接的開發環境,請使用 GitHub Codespaces,使得您有已預先安裝的正確開發人員工具和相依性,以便完成本文。
重要
所有 GitHub 帳戶每個月最多可以使用 Codespaces 60 小時,且有 2 個核心執行個體。 如需詳細資訊,請參閱 GitHub Codespaces 每月包含的儲存體和核心時數。
使用下列步驟,在 GitHub 存放庫的main
分支上Azure-Samples/openai-chat-app-quickstart
建立新的 GitHub Codespace。
以滑鼠右鍵按下列按鈕,然後選取新視窗中的 [開啟連結]。 此動作可讓您擁有開發環境和可供檢閱的檔。
在 [ 建立代碼空間] 頁面上,檢閱然後選取 [ 建立新的程式代碼空間]
等候 Codespace 開始。 此啟動程序可能需要幾分鐘的時間。
使用畫面底部終端機中的 Azure 開發人員 CLI 登入 Azure。
azd auth login
從終端機複製程式碼,然後將它貼到瀏覽器中。 遵循指示使用 Azure 帳戶進行驗證。
本文中的其餘工作會在此開發容器的內容中進行。
使用下列步驟,在 GitHub 存放庫的main
分支上Azure-Samples/openai-chat-app-quickstart-dotnet
建立新的 GitHub Codespace。
以滑鼠右鍵按下列按鈕,然後選取新視窗中的 [開啟連結]。 此動作可讓您擁有開發環境和可供檢閱的檔。
在 [ 建立代碼空間] 頁面上,檢閱然後選取 [ 建立程式代碼空間]
等候 Codespace 開始。 此啟動程序可能需要幾分鐘的時間。
使用畫面底部終端機中的 Azure 開發人員 CLI 登入 Azure。
azd auth login
從終端機複製程式碼,然後將它貼到瀏覽器中。 遵循指示使用 Azure 帳戶進行驗證。
本文中的其餘工作會在此開發容器的內容中進行。
使用下列步驟,在 GitHub 存放庫的main
分支上Azure-Samples/openai-chat-app-quickstart-javascript
建立新的 GitHub Codespace。
- 以滑鼠右鍵按下列按鈕,然後選取新視窗中的 [開啟連結]。 此動作可讓您擁有開發環境和可供檢閱的檔。
在 [ 建立代碼空間] 頁面上,檢閱然後選取 [ 建立新的程式代碼空間]
等候 Codespace 開始。 此啟動程序可能需要幾分鐘的時間。
使用畫面底部終端機中的 Azure 開發人員 CLI 登入 Azure。
azd auth login
從終端機複製程式碼,然後將它貼到瀏覽器中。 遵循指示使用 Azure 帳戶進行驗證。
本文中的其餘工作會在此開發容器的內容中進行。
部署和執行
範例存放庫包含聊天應用程式 Azure 部署的所有程式代碼和組態檔。 下列步驟會逐步引導您完成範例聊天應用程式 Azure 部署程式。
部署聊天應用程式至 Azure
重要
本節中建立的 Azure 資源會產生立即成本。 即使您在命令完整執行之前中斷命令,這些資源仍可能會產生成本。
針對 Azure 資源布建和原始程式碼部署執行下列 Azure 開發人員 CLI 命令:
azd up
使用下表回答提示:
提示 回答 環境名稱 保持簡短和小寫。 新增您的名稱或別名。 例如: secure-chat
。 它用來作為資源組名的一部分。訂用帳戶 選取要在其中建立資源的訂用帳戶。 位置 (用於載入) 從清單中選取您附近的位置。 OpenAI 模型的位置 從清單中選取您附近的位置。 如果有與您的第一個位置相同的位置,請選取該位置。 等候應用程式部署。 部署通常需要 5 到 10 分鐘才能完成。
使用聊天應用程式向大型語言模型詢問問題
終端機會在應用程式部署成功之後顯示 URL。
選取標示為
Deploying service web
的 URL,以在瀏覽器中開啟聊天應用程式。在瀏覽器中,輸入「為什麼受控識別比密鑰更好?」之類的問題。
答案來自 Azure OpenAI,結果隨即顯示。
探索範例程序代碼
雖然 OpenAI 和 Azure OpenAI 服務依賴一般 Python 用戶端連結庫,但使用 Azure OpenAI 端點時需要小型程式代碼變更。 讓我們看看此範例如何使用 Microsoft Entra ID 設定無密鑰驗證,並與 Azure OpenAI 通訊。
使用受控識別設定驗證
在此範例中,檔案 src\quartapp\chat.py
會從設定無密鑰驗證開始。
下列代碼段會使用 azure.identity.aio 模組來建立異步Microsoft Entra 驗證流程。
下列代碼段會AZURE_CLIENT_ID
azd
使用環境變數來建立可透過使用者指派的受控識別進行驗證的ManagedIdentityCredential 實例。
user_assigned_managed_identity_credential = ManagedIdentityCredential(client_id=os.getenv("AZURE_CLIENT_ID"))
注意
資源 azd
環境變數會在應用程式部署期間 azd
布建。
下列代碼段會使用AZURE_TENANT_ID
azd
資源環境變數來建立能夠向目前Microsoft Entra 租用戶進行驗證的 AzureDeveloperCliCredential 實例。
azure_dev_cli_credential = AzureDeveloperCliCredential(tenant_id=os.getenv("AZURE_TENANT_ID"), process_timeout=60)
Azure 身分識別客戶端連結庫提供 認證-公用類別,可實作 Azure Core 連結庫的 TokenCredential 通訊 協定。 認證代表從 Microsoft Entra ID 取得存取權杖的不同驗證流程。 這些認證可以鏈結在一起,形成一個經過排序的驗證機制以進行嘗試。
下列代碼段會 ChainedTokenCredential
使用 ManagedIdentityCredential
和 AzureDeveloperCliCredential
建立 :
-
ManagedIdentityCredential
用於 Azure Functions 和 Azure App 服務。 將 傳遞client_id
至ManagedIdentityCredential
,支援使用者指派的受控識別。 -
AzureDeveloperCliCredential
用於本機開發。 先前已根據要使用的 Microsoft Entra 租用戶來設定。
azure_credential = ChainedTokenCredential(
user_assigned_managed_identity_credential,
azure_dev_cli_credential
)
提示
認證的順序很重要,因為會使用第一個有效的Microsoft Entra 存取令牌。 如需詳細資訊,請參閱 ChainedTokenCredential 概觀 一文。
下列代碼段會根據選取的 Azure 認證取得 Azure OpenAI 令牌提供者。 使用兩個自變數呼叫 azure.identity.aio.get_bearer_token_provider 來取得此值:
azure_credential
ChainedTokenCredential
:稍早建立以驗證要求的實例。https://cognitiveservices.azure.com/.default
:需要一或多個持有人令牌範圍。 在此情況下, Azure 認知服務 端點。
token_provider = get_bearer_token_provider(
azure_credential, "https://cognitiveservices.azure.com/.default"
)
下列幾行會檢查在應用程式部署期間AZURE_OPENAI_ENDPOINT
布建的必要AZURE_OPENAI_CHATGPT_DEPLOYMENT
和資源azd
azd
環境變數。 如果值不存在,則會擲回錯誤。
if not os.getenv("AZURE_OPENAI_ENDPOINT"):
raise ValueError("AZURE_OPENAI_ENDPOINT is required for Azure OpenAI")
if not os.getenv("AZURE_OPENAI_CHATGPT_DEPLOYMENT"):
raise ValueError("AZURE_OPENAI_CHATGPT_DEPLOYMENT is required for Azure OpenAI")
此代碼段會初始化 Azure OpenAI 用戶端,並設定 api_version
、 azure_endpoint
和 azure_ad_token_provider
(client_args
) 參數:
bp.openai_client = AsyncAzureOpenAI(
api_version=os.getenv("AZURE_OPENAI_API_VERSION") or "2024-02-15-preview",
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
azure_ad_token_provider=token_provider,
)
下列這一行會設定 Azure OpenAI 模型部署名稱,以用於 API 呼叫:
bp.openai_model = os.getenv("AZURE_OPENAI_CHATGPT_DEPLOYMENT")
注意
OpenAI 會使用 model
關鍵字引數來指定要使用的模型。 Azure OpenAI 具有唯一模型部署的概念。 當您使用 Azure OpenAI 時, model
應該參考 在 Azure OpenAI 模型部署期間選擇的基礎部署名稱 。
此函式完成後,用戶端就會正確設定,並準備好與 Azure OpenAI 服務互動。
使用 OpenAI 用戶端和模型的響應數據流
會 response_stream
處理路由中的聊天完成呼叫。 下列代碼段示範如何使用 openai_client
和 model
。
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
chat_coroutine = bp.openai_client.chat.completions.create(
# Azure OpenAI takes the deployment name as the model name
model=bp.openai_model,
messages=all_messages,
stream=True,
)
探討範例程式碼
.NET 應用程式依賴 Azure.AI.OpenAI 用戶端連結庫來與 Azure OpenAI 服務通訊,這會相依於 OpenAI 連結庫。 此範例應用程式會使用 Microsoft Entra ID 來設定無密鑰驗證,以與 Azure OpenAI 通訊。
設定驗證和服務註冊
在此範例中,會在檔案中 program.cs
設定無密鑰驗證。 下列代碼段會使用 所設定的AZURE_CLIENT_ID
環境變數來建立azd
實例。
var userAssignedIdentityCredential =
new ManagedIdentityCredential(builder.Configuration.GetValue<string>("AZURE_CLIENT_ID"));
注意
資源 azd
環境變數會在應用程式部署期間 azd
布建。
下列代碼段會使用 所設定的AZURE_TENANT_ID
環境變數來建立可使用登入帳戶azd
在本機進行驗證的 AzureDeveloperCliCredentialazd
實例。
var azureDevCliCredential = new AzureDeveloperCliCredential(
new AzureDeveloperCliCredentialOptions()
{
TenantId = builder.Configuration.GetValue<string>("AZURE_TENANT_ID")
});
Azure 身分識別客戶端連結庫提供實作 Azure Core 連結庫 TokenCredential 通訊協定的認證類別。 認證代表從 Microsoft Entra ID 取得存取權杖的不同驗證流程。 這些認證可以使用鏈結在一起 ChainedTokenCredential
,以形成要嘗試的已排序驗證機制序列。
下列代碼段會AzureOpenAIClient
註冊 以進行相依性插入,並使用 和 ChainedTokenCredential
建立 ManagedIdentityCredential
AzureDeveloperCliCredential
:
-
ManagedIdentityCredential
用於 Azure Functions 和 Azure App 服務。 使用AZURE_CLIENT_ID
提供給ManagedIdentityCredential
的 ,支援使用者指派的受控識別。 -
AzureDeveloperCliCredential
用於本機開發。 先前已根據要使用的 Microsoft Entra 租用戶來設定。
builder.Services.AddAzureClients(
clientBuilder => {
clientBuilder.AddClient<AzureOpenAIClient, AzureOpenAIClientOptions>((options, _, _)
=> new AzureOpenAIClient(
new Uri(endpoint),
new ChainedTokenCredential(
userAssignedIdentityCredential, azureDevCliCredential), options));
});
提示
認證的順序很重要,因為會使用第一個有效的Microsoft Entra 存取令牌。 如需詳細資訊,請參閱 ChainedTokenCredential 概觀 一文。
使用 Azure OpenAI 用戶端取得聊天完成
Blazor Web 應用程式會在元件頂端插入已註冊 AzureOpenAIClient
的 Home.Razor
:
@inject AzureOpenAIClient azureOpenAIClient
當使用者提交表單時,會將 AzureOpenAIClient
提示傳送至 OpenAI 模型以產生完成:
ChatClient chatClient = azureOpenAIClient.GetChatClient("gpt-4o-mini");
messages.Add(new UserChatMessage(model.UserMessage));
ChatCompletion completion = await chatClient.CompleteChatAsync(messages);
messages.Add(new SystemChatMessage(completion.Content[0].Text));
探討範例程式碼
雖然 OpenAI 和 Azure OpenAI 服務依賴 openai (常見的 JavaScript 用戶端連結庫),但使用 Azure OpenAI 端點時需要小型程式代碼變更。 讓我們看看此範例如何使用 Microsoft Entra ID 設定無密鑰驗證,並與 Azure OpenAI 通訊。
每個環境的無金鑰驗證
Azure 身分識別客戶端連結庫提供實作 Azure Core 連結庫 TokenCredential 通訊協定的認證類別。 認證代表從 Microsoft Entra ID 取得存取權杖的不同驗證流程。 這些認證可以使用鏈結在一起 ChainedTokenCredential
,以形成要嘗試的已排序驗證機制序列。 這可讓您在生產環境與本機開發環境中部署相同的程序代碼。
使用受控識別設定驗證
在此範例中 ./src/azure-authentication.ts
,提供數個函式來提供 Azure OpenAI 的無密鑰驗證。
第一個函式 getChainedCredential()
會傳回鏈結中找到的第一個有效 Azure 認證。
function getChainedCredential() {
return new ChainedTokenCredential(
new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID!),
new AzureDeveloperCliCredential({
tenantId: process.env.AZURE_TENANT_ID! ? process.env.AZURE_TENANT_ID! : undefined
})
);
}
- 先嘗試ManagedIdentityCredential 。 其會使用生產運行時間中的AZURE_CLIENT_ID環境變數進行設定,而且能夠透過使用者指派的受控識別進行驗證。
-
嘗試第二個 AzureDeveloperCliCredential 。 當開發使用 Azure CLI
az login
登入時,就會設定它。
提示
認證的順序很重要,因為會使用第一個有效的Microsoft Entra 存取令牌。 如需詳細資訊,請參閱 ChainedTokenCredential 概觀 一文。
取得 OpenAI 的持有人令牌
中的./src/azure-authentication.ts
第二個函式是 getTokenProvider()
,它會傳回,提供範圍限定於 Azure 認知服務端點的持有人令牌。
function getTokenProvider(): () => Promise<string> {
const credential = getChainedCredential();
const scope = "https://cognitiveservices.azure.com/.default";
return getBearerTokenProvider(credential, scope);
}
上述代碼段會使用 getBearerTokenProvider
來取得認證和範圍,然後傳回提供持有人令牌的回呼。
建立已驗證的 Azure OpenAI 用戶端
中的 ./src/azure-authentication.ts
第三個函式是 getOpenAiClient()
,它會傳回 Azure OpenAI 用戶端。
export function getOpenAiClient(): AzureOpenAI | undefined{
try {
if (!process.env.AZURE_OPENAI_ENDPOINT) {
throw new Error("AZURE_OPENAI_ENDPOINT is required for Azure OpenAI");
}
if (!process.env.AZURE_OPENAI_CHAT_DEPLOYMENT) {
throw new Error("AZURE_OPENAI_CHAT_DEPLOYMENT is required for Azure OpenAI");
}
const options = {
azureADTokenProvider: getTokenProvider(),
deployment: process.env.AZURE_OPENAI_CHAT_DEPLOYMENT!,
apiVersion: process.env.AZURE_OPENAI_API_VERSION! || "2024-02-15-preview",
endpoint: process.env.AZURE_OPENAI_ENDPOINT!
}
// Create the Asynchronous Azure OpenAI client
return new AzureOpenAI (options);
} catch (error) {
console.error('Error getting Azure OpenAI client: ', error);
}
}
此程式代碼會採用選項,包括正確的範圍令牌,並建立 AzureOpenAI
用戶端
使用 Azure OpenAI 串流聊天答案
使用中的 ./src/openai-chat-api.ts
下列 Fastify 路由處理程式,將訊息傳送至 Azure OpenAI 並串流回應。
import { FastifyReply, FastifyRequest } from 'fastify';
import { AzureOpenAI } from "openai";
import { getOpenAiClient } from './azure-authentication.js';
import { ChatCompletionChunk, ChatCompletionMessageParam } from 'openai/resources/chat/completions';
interface ChatRequestBody {
messages: ChatCompletionMessageParam [];
}
export async function chatRoute (request: FastifyRequest<{ Body: ChatRequestBody }>, reply: FastifyReply) {
const requestMessages: ChatCompletionMessageParam[] = request?.body?.messages;
const openaiClient: AzureOpenAI | undefined = getOpenAiClient();
if (!openaiClient) {
throw new Error("Azure OpenAI client is not configured");
}
const allMessages = [
{ role: "system", content: "You are a helpful assistant."},
...requestMessages
] as ChatCompletionMessageParam [];
const chatCompletionChunks = await openaiClient.chat.completions.create({
// Azure Open AI takes the deployment name as the model name
model: process.env.AZURE_OPENAI_CHAT_DEPLOYMENT_MODEL || "gpt-4o-mini",
messages: allMessages,
stream: true
})
reply.raw.setHeader('Content-Type', 'text/html; charset=utf-8');
reply.raw.setHeader('Cache-Control', 'no-cache');
reply.raw.setHeader('Connection', 'keep-alive');
reply.raw.flushHeaders();
for await (const chunk of chatCompletionChunks as AsyncIterable<ChatCompletionChunk>) {
for (const choice of chunk.choices) {
reply.raw.write(JSON.stringify(choice) + "\n")
}
}
reply.raw.end()
}
函式會取得聊天交談,包括任何先前的訊息,並將其傳送至 Azure OpenAI。 從 Azure OpenAI 傳回數據流區塊時,會將 傳送至用戶端。
其他安全性考量
本文示範範例 ChainedTokenCredential
如何使用 驗證 Azure OpenAI 服務。
此範例也有 GitHub Action ,可掃描基礎結構即程式代碼檔案,並產生包含任何偵測到問題的報表。 為了確保您自己的存放庫中持續最佳做法,我們建議任何人根據我們的範本建立解決方案,確保 已啟用 GitHub 秘密掃描設定 。
請考慮其他安全性措施,例如:
使用 Microsoft Entra 限制對適當應用程式使用者的存取。
清除資源
清除 Azure 資源
在本文中建立的 Azure 資源會向您的 Azure 訂用帳戶計費。 如果您預計未來不需要這些資源,請將其刪除,以避免產生更多費用。
若要刪除 Azure 資源並移除原始程式碼,請執行下列 Azure 開發人員 CLI 命令:
azd down --purge
清除 GitHub Codespaces
刪除 GitHub Codespaces 環境,可確保您可將您為帳戶取得的每個核心免費時數權利數量最大化。
重要
如需 GitHub 帳戶權利的詳細資訊,請參閱 GitHub Codespaces 每月包含的儲存體和核心時數。
登入 GitHub Codespaces 儀表板 (https://github.com/codespaces)。
找出您目前執行中的 Codespaces,而其來源為
Azure-Samples/openai-chat-app-quickstart
GitHub 存放庫。開啟 Codespace 的快顯功能表,然後選取 [刪除]。
登入 GitHub Codespaces 儀表板 (https://github.com/codespaces)。
找出您目前執行中的 Codespaces,而其來源為
Azure-Samples/openai-chat-app-quickstart-dotnet
GitHub 存放庫。開啟 Codespace 的快顯功能表,然後選取 [刪除]。
登入 GitHub Codespaces 儀表板 (https://github.com/codespaces)。
找出您目前執行中的 Codespaces,而其來源為
Azure-Samples/openai-chat-app-quickstart-javascript
GitHub 存放庫。開啟 Codespace 的快顯功能表,然後選取 [刪除]。