【Tutorial】Azure OpenAI — 在 Teams 中提供 ChatGPT Bot 服務(Power Virtual Agents)

Get started using GPT-35-Turbo and GPT-4 with Azure OpenAI Service on Microsoft Teams(Creating Conversational Chatbots)

Kellen
22 min readMay 4, 2024

背景說明與設計想法

對於想在 Teams 有效引入 OpenAI 進一步作為組織內部使用或是與 M365 進一步達成 AI-RPA (智慧流程自動化),Teams 簡易來說可以分成以下的設計模式。

除此之外,技術可行性 Option 4 也可以這樣使用 Teams PowerAutomate Azure Open AI

在這篇文章中,我記錄了將 Power Virtual Agents(PVA 目前改名為 Copilot Studio)結合 Azure OpenAI 服務的使用(#Option 2),簡單的透過 PVA 在 Teams 中部署機器人,而不是使用 Azure Bot SDK Framework 的機器人服務進行後端的開發(#Option 3)。

  • 如果您想探索 #Option 1,閱讀文檔後我發現已開始棄用,不建議使用此選項 Use the text generation model in Power Automate (deprecated)
  • 如果您想探索 #Option 3,推薦 【GitHub】freistli/rootbot 這邊有許多 Bot App 與 OpenAI 和 Azure OpenAI 的多個 LLM 服務(ChatGPT、GPT-3、DALL-E )整合,至於如何上手 Bot Framework 與 Azure Function 可參考前幾篇的記錄,輔以 API 的方式呼叫 OpenAI API,可行性就差不多完成,至於 serverless workload 可以搭配使用 API management 來進行管理

TL; DR
📙
【How-to Guides】Azure Apps — Build Your First EchoBot with Python
📙
【Tutorial】Azure 新手村 — Azure Function init() | for Develpoer

完整 Teams 引入 Bot 的機制,亦可以使用 Bot Service + Bot Framework SDK 來將 Bot 以 Skill 擴充型式加入至 Power Virtual Agents(透過提供清單 url 新增技能:設定 -> 技能,然後點擊「新增技能 」)。

Azure OpenAI 跟 OpenAI 的關係

OpenAI 是一家人工智慧研究機構,而 Azure OpenAI 是微軟雲計算平台中 Azure 提供的 OpenAI 人工智慧服務,兩者合作推出了 Azure OpenAI。你可以從 Azure OpenAI 系列的服務和工具,使用和部署 OpenAI 的人工智慧模型和算法。而本次實作,是希望促成 AI-RPA (智慧流程自動化)的可能性的基礎,我們可將 GPT 模型與所有微軟平台的 Service 互相結合,成為完全自動化的流程。

https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models
微軟從 2019 就投資在 OpenAI 強大的人工智慧模式,打的戰略希望可以更廣泛地使用並整合在 Azure 上,以下是迄今為止一些主要里程碑的簡要總結
「ada」、「babbage」、「curie」、「davinci」

儘管「davinci」是最強大的,但其他模型的推理時間更快,因此價格較低。 Microsoft 建議在嘗試時從達文西開始,因為它將產生最佳結果。一旦有了工作原型,就可以優化模型選擇以滿足應用程式的延遲/效能要求。要了解有關 Azure OpenAI 的更多訊息,參閱下面提供的資源聯結

技術要求

  • Azure OpenAI 服務:您需要 Azure 訂閱及授予模型 gpt-35-turbogpt-4 的存取權,若是要作為提供組織使用,可以的話設計好你的資源管理或分離測試、營運環境之用途
  • Azure OpenAI 服務需要以訂閱 ID 進行申請制並檢附公司組織或 mail,模型目前在美國區域可用,目前審核還滿快的,大概是一天就可以通過了
  • 對於 Power Virtual Agents 與 Power Automate 有一定的操作水準
  • AI Builder for Power Automate 此選項為 Power Automate 提供了一個內建連接器,用於在 Azure OpenAI 服務上查詢 ChatGPT

部署並設定 Azure OpenAI 服務

I Integrate Teams request message to virtual agent, communicate with Power Automate flow, communicate with Azure OpenAI using secret key

請檢查您是否符合所有技術要求,並需要 Endpoint, API Key, Deployment Name 的資訊

圖來自 TAYGAN

👣 Step 1. 建立 Azure OpenAI Service

  • 輸入 Azure OpenAI > 點選搜尋結果

Create 畫面並命名

👣 Step 02. 建立部署模型

  • 模型部署Model deployments > 管理部署Manage Deployments
  • 接著進入到 Azure AI Studio 點選 部署 後再點選上方的 + 建立新部署

輸入相關資訊畫面如下

  • 選取模型 欄位請選擇 gpt-35-turbo
  • 部署名稱 欄位請輸入唯一且可識別的名稱
Deployment 為 assistant-sre

👣 Step 03. 至「金鑰與端點」取得資訊

點選 Keys and Endpoint 取得 KEY 1Endpoint

👣 Step 04. 機器人調教(Fine-tune)

Fine-tune 指的是讓類神經網路基於預訓練模型(pre-trained model)的權重上再作微調,目的是讓模型能在特定場景表現的更好,不是真的重新訓練而是去影響模型預測下一個字的權重,影響他回答的方式或是答案,而像是 OpenAI LLM 大型語言模型中的幾個常調的參數:頻率懲罰(Frequency Penalty)和存在懲罰(Presence Penalty)、Tempature。

  • 頻率懲罰(Frequency Penalty):它的作用是懲罰原始文本中已經出現過的單字或片語,從而鼓勵產生無重複的輸出。白話就是不要讓你的機器人不要有特定的口頭禪或語助詞。
  • 狀態懲罰(Presence Penalty):這個參數的作用減少總體上使用頻率較高的單字或短語的機率,增加使用頻率較低的單字或短語的可能性。這個參數是適合特定主題回覆的平衡點,以確保文本既豐富又具有連貫性。
  • temperature: OpenAI 的 API 有效 payload 中,temperature越高模型越活潑,此選項是一個控制語言模型輸出的隨機性或創造性的參數。假設我們有一個語言模型可以預測句子「The mouse ate the _____」中的最後一個單字。考慮到句子中前面的單字及其先前的訓練,我們的語言模型將嘗試用合理的標記來填充空白。而增加輸出的隨機性,即 temperature 參數提高,可以幫助模型創建更具創意和有趣的輸出,例如以下是 🐭 最喜歡吃什麼食物。但是在特定的領域要儘量避免 temperature越高,例如講究製程的製造業與金融流程或顧客權益解釋性上。
What is Temperature in NLP?🐭

Token

OpenAI 在計價上是以 Token 數來計價,他會將文字細分成 Token 來處理,Token 的計算會根據不同模型會有所差異。

👣 Step 05. 機器人調教(Prompt Stuffing)

良好的 Prompt Stuffing 可以指導模型生成什麼或是不生成什麼!由於本次範例是制作一個 SRE 助理機器人,未來可以 on 在服務 Channel 上偵測異常的 log,並希望只服務與 IT 相關的知識,因此不是與 IT 相關的會請 OpenAI 直接忽略並強調所服務的範圍!

未加調教語詞或限定服務範圍前

Section1.
As an AI assistant specialized in system (such as Linux) and cloud-related topics, if I encounter questions outside of these domains, I will respond with “I’m sorry, I am a system assistant AI and that question is beyond my service scope.” Thank you for clarifying, and please let me know if you have any system or cloud-related queries!

Section2.
Can You give me PS5 prices
“I’m sorry, I am a system assistant AI and that question is beyond my service scope.” Thank you for clarifying, and please let me know if you have any system or cloud-related queries!

Playground
加入調教語詞或限定服務範圍後,這邊可以檢視程式碼,選擇「JSON, CURL, …」拿取現成的程式

👣 Step 06. 使用 KeyVault 進行 API Key 管理

TL;DR
KeyVault 分兩種權限設定,推薦使用 RBAC 方式,才不會造成後續 KeyVault 權限管理散落四處
📙【How-to Guides】Azure Security — Azure KeyVault 金鑰管理

若在組織權限設計分責,給予來自一般使用者 Power Automate 可以 Read Secret 即可!

👣 Step 07. (Optional)註冊服務專用的應用程式以進行合宜的權限管控

前面已經設定了 Azure KeyVault,由於我們是透過 PVA 來制作機器人,預設在制作的時候已經幫你直接註冊了一個 App Registration 了,如果希望 Power Automate 在呼叫 Azure 能多納管在應用程式當中的話,或是在 Teams 的權限中希望取得較多的權限,建議可以建立一組專用的 Application,未來在管理或是合規性會比較嚴謹,若只是測試或是 PoC 可以跳過此步驟,

若是在 Azure Cloud 中使用,建議應用程式都應該透過 managed identity 的方式來處理,以便在連線至支援 Azure AD 驗證的資源時候可以使用 managed identity 的身份,應用程式就可以享受直接使用受控身份識別來取得 Azure AD 的權杖,過程中不需要管理任何認證(密碼、API Key…等)。

以下,我們將使用 Azure 應用程式註冊來建立一個應用程序,該應用程式亦能夠透過 API 呼叫與這個新的 Azure Key Vault 進行互動。

現在應用程式已創建,讓我們繼續配置 Key Vaults 服務的權限。導航至“ API 權限”並點擊“新增權限”。

將彈出一個新的 Blade,點擊 Azure Key Vault 服務。

現在,在完成整個 Key Vault 操作之前,我們需要進行最後幾個設定…儲存客戶端金鑰值。

轉到概觀 Overview 選項卡並保存 AppID

導航至 Key Vault 頁面並為我們的應用程式建立新的存取策略。轉到你本身 對 KeyVault 的權限管理方式,若是 KeyVault 保管庫就選「存取原則」;因為我使用的是存取控制IAM 方式,並新增「角色指派」,使其權限給予 Secret Reader 即可。

成員這邊選擇「使用者、群組或服務主體」選擇你的 App Registration 註冊的名稱,我的是 Teams-Assistant-SRE

指派成功

現在已成功設定!

👣 Step 08. 使用 Power Automate 將 Power Virtual Agents 連接到 Azure OpenAI

  1. 前往 https://copilotstudio.microsoft.com/
  2. Topics 選擇 System 項下的 Fallback,在大多數情況下,這是預設路由,目的是如果機器人無法確定使用者的意圖,則會觸發該主題,並將開啟 Fallback 主題的對話流程 ,
  3. 刪除此流程中所有現有的步驟並新增新步驟,只留下 On Unknown Intent 的觸發器
刪除 Fallback 項下的流程

接續著新增「Power Automate」的流程進來,點選「呼叫動作」中的「建立流程」

最終會產出此新的 flow,在階段中會來實作 Power Automate 的 flow

👣 Step 09. Power Automate 引入 OpenAI 作法

✅01. 流程一覽說明

✅02. 前置作業

  • 從 Power Automate 中,將 “文字” 輸入新增至觸發器(執行來自 Copilot 流程),將參數命名 request
  • 新增 JSON 類型的操作 “Initialize Variable”,並貼上在👣 Step 05. 中從 Azure OpenAI 聊天平台儲存的 JSON
  • (選項)temperature, frequency_penalty, presence_penalty 等參數可以使用 Adaptive Cards 作為使用者的選項
{
"messages": [
{
"role": "system",
"content": "As an AI assistant specialized in system (such as Linux) and cloud-related topics, if I encounter questions outside of these domains, I will respond with \"I'm sorry, I am a system assistant AI and that question is beyond my service scope. And please let me know if you have any system or cloud-related queries!\""
},
{
"role": "user",
"content": "Can You give me the price of PS5."
},
{
"role": "assistant",
"content": "I'm sorry, I am a system assistant AI and that question is beyond my service scope. And please let me know if you have any system or cloud-related queries!"
},
{
"role": "user",
"content": ""
},
{
"role": "assistant",
"content": ""
}
],
"temperature": 0.5,
"top_p": 0.95,
"frequency_penalty": 0,
"presence_penalty": 0,
"max_tokens": 800,
"stop": null
}

更新 JSON 定義以包含來自 Power Virtual Agent 的使用者請求,注意 一下 JSON 中的結構和位置

✅03. HTTP Query AI services

在觸發器後新增 HTTP 操作以查詢 Azure OpenAI 服務終端點,在 HTTP 連接器中使用下列參數:

  • Method: POST
  • Headers: Contype-Typeapplication/json
  • KeyVault 拿取 API_Key 金鑰
find your OAI_ENDPOINT, OAI_DEPLOYMENT_NAME
  • [OAI_ENDPOINT] 可在 👣 Step 03. 找到,即你的 Azure OpenAI Service 的 endpoint
  • [OAI_DEPLOYMENT_NAME] 為 OpenAI model 可在 👣 Step 04.,我的範例為 assistant-sre

✅04. Initialize OpenAI Assistant response

  • 新增 OAI_ResponseString 初始化變數,這邊目的是初始化變數「OAI_Response」來儲存來自 Azure OpenAI 和內容篩選器的文字回應

✅05. 條件

總會有天災人禍或其他 Bug,這邊簡易用一個 Condition 去處理

然後,我們檢查 ChatGPT 回應是否正常(http status 200),如果沒有,請在 OAI_Response 中設定錯誤訊息。測試針對先前的 HTTP 操作的狀態碼值是否等於 200;若否則回覆 “Sorry, I couldn't generate an answer from your prompt. Can you rephrase your request?”

✅05. Parse JSON & Set Variable — OAI R

先掌握 OpenAI 的 Response 結構長相

Quickstart: Get started using GPT-35-Turbo and GPT-4 with Azure OpenAI Service

如果條件為真,我們配置以下操作:

  • 根據以下架構解析 HTTP 回應正文的 JSON
  • 使用來自 Azure OpenAI 服務的文字回應設定 OAI_Response 的值。使用以下表達式: body('Parse_JSON')['choices'][0]['message']['content']注意:本次僅擷取 Azure OpenAI 產生的第一個答案,不支援多個回應,因為作法會需要在 PVA 另外處理 Global Variable,篇幅關係有空再寫

解析 JSON 操作的架構定義

{
"type": "object",
"properties": {
"choices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"finish_reason": {},
"message": {
"type": "object",
"properties": {
"content": {
"type": "string"
}
}
}
},
"required": [
"finish_reason",
"message"
]
}
}
}
}

註:若以 Python 這邊的處理則是會呈現如下,而 return 的值則是 response.json()['choices'][0]['message']['content']

✅06. Response to Copilot

將回應傳送回 Power Virtual Agents,將輸出新增至現有操作並將值設為變數 OAI_Response,將 Power Virtual Agents 變數對應到 Power Automate inputs/outputs

  • Power Automate inputs “request” = PVA system variable Activity.Text
  • Power Automate outputs “response” = PVA Topic variable response(建立新變數)
  • 最後新增訊息上去 {Topic.response},或是你可以使用 Adaptive Cards 來包裝你的訊息
  • 進行 Deploy 到 Microsoft Teams 中使用,在「頻道 > Microsoft Teams」下,按一下「開啟機器人」以在 Teams 中安裝機器人。若是有 Teams 組織管理員的話,會需要與管理員進行合作,相關的上架指引,先前有寫過一篇如下

📙【Reference】Azure PVA — Power Virtual Agents 上架至 Teams 程序

在 Power Virtual Agent 中運行測試的機器人

也可以用 Adaptive Cards 來加強美觀性

Summary

以上是直接使用大型語言模型(LLM)並透過 PVA 發佈至 Teams,過程中使用 App Registration, KeyVault 及使用 RBAC 進行管理的實作 Demo。不過,當我們使用大型語言模型(LLM)時,雖然它在回答問題和生成文本方面表現出色,但存在幾個挑戰。第一個會產生「幻覺」(hallucinations),即給予人們貌似合理的錯誤訊息,實則會誤導並墜入陷阱;其次 LLM 可能會產生不準確、過時或虛假嘴炮的回應,而這可能損害使用者的信任。

為了解決這些問題,若我們希望它回答的是有所本的,我們可以使用 Grounding 的概念,讓生成模型以「真實資料」為基礎來產生答案,一般會使用資訊檢索(information retrieval techniques, e.g., search and queries)與 generative AI models 的方式來產生真實的答案,常見的架構是使用檢索增強生成(Retrieval-Augmented Generation, RAG)技術,流程如下:

  • Retriever:對大規模的資料或企業知識庫進行檢索,找到語意最相關的文件或段落
  • Generator:參考上述所找到的資料進行摘要或揉合,產生新的文本

通過從預先確定的權威知識來源中擷取資訊來指導 LLM 的輸出,以確保輸出更相關、準確和可信,其次是 Security AI 還是最重要,本次實作方式亦會用 zero trust 及走 backbone 的方式來完成。

--

--

Kellen

Backend(Python)/Kubernetes and Container eco-system/Technical&Product Manager/host of Developer Experience/早期投入資料創新與 ETL 工作,近期研究 GCP/Azure/AWS,於此記錄實作過程