將 OpenAI、通訊和組織資料功能整合到企業營運應用程式中
層級:中繼
本教學課程示範如何將 Azure OpenAI、Azure 通訊服務 和 Microsoft Graph/Microsoft Graph 工具組整合到企業營運 (LOB) 應用程式中,以提升用戶生產力、提高用戶體驗,並將 LOB 應用程式提升到下一個層級。
- AI:讓使用者以自然語言詢問問題,並將其答案轉換成 SQL,以用來查詢資料庫、允許使用者定義可用來自動產生電子郵件和簡訊的規則,以及瞭解如何使用自然語言從您自己的自定義數據源擷取數據。 Azure OpenAI 用於這些功能。
- 通訊:使用 Azure 通訊服務,對客戶啟用應用程式內電話通話和 Email/SMS 功能。
- 組織數據:提取使用者可能需要 (檔、聊天、電子郵件、行事曆活動) 的相關組織數據,以避免內容切換。 提供這種組織數據的存取權,可減少使用者切換至 Outlook、Teams、OneDrive、其他自定義應用程式、其手機等的需求,因為直接在應用程式中提供所需的特定數據和功能。 Microsoft Graph 和 Microsoft Graph 工具組會用於這項功能。
應用程式是簡單的客戶管理應用程式,可讓使用者管理其客戶和相關數據。 它包含使用 TypeScript 建置的前端,其會呼叫後端 API 來擷取數據、與 AI 功能互動、傳送電子郵件/SMS 訊息,以及提取組織數據。 以下是您將在本教學課程中逐步解說的應用程式解決方案概觀:
本教學課程將逐步引導您完成設定必要 Azure 和 Microsoft 365 資源的程式。 它也會逐步引導您完成用來實作 AI、通訊和組織數據功能的程式碼。 雖然您不需要複製和貼上程序代碼,但有些練習會讓您修改程式代碼來嘗試不同的案例。
您將在本教學課程中建置的內容
選擇您自己的 Adventure
您可以從頭到尾完成整個教學課程,或完成您感興趣的特定主題。 本教學課程分成下列主題領域:
- 複製項目練習 (必要的練習) 。
- AI 練習:建立 Azure OpenAI 資源 ,並將其用來將自然語言轉換成 SQL、產生電子郵件/簡訊,以及使用您自己的數據和檔。
- 通訊練習:建立 Azure 通訊服務 資源,並使用它來從應用程式撥打電話,並傳送電子郵件/簡訊。
- 組織數據練習:建立 Microsoft Entra ID 應用程式註冊,讓 Microsoft Graph 和 Microsoft Graph 工具組可用來驗證組織數據,並將組織數據提取到應用程式中。
必要條件
- 節點 - 節點 16+ 和 npm 7+ 將用於此專案
- git
- 雖然建議使用 Visual Studio Code Visual Studio Code (,但可以使用任何編輯器)
- Azure 訂用帳戶
- Microsoft 365 開發人員租使用者
- Docker Desktop 或其他 OCI (Open Container Initiative) 相容的容器運行時間,例如 Podman 或能夠執行容器 的 nerdctl 。
本教學課程中使用的 Microsoft 雲端技術
- Microsoft Entra 識別碼
- Azure 通訊服務
- Azure OpenAI 服務
- Microsoft Graph
- Microsoft Graph 工具組
複製專案
本教學課程中使用的程式碼項目位於 https://github.com/microsoft/MicrosoftCloud。 專案的存放庫包含執行專案所需的用戶端和伺服器端程序代碼,可讓您探索與人工智慧相關的整合功能, (AI) 、通訊和組織數據。 此外,專案可作為資源,引導您將類似的功能併入您自己的應用程式中。
在此練習中,您將會:
- 複製 GitHub 存放庫。
- 將 .env 檔案新增至專案並加以更新。
繼續之前,請確定您已安裝並設定所有必要條件,如本教學 課程的必要條件 一節中所述。
複製 GitHub 存放庫並建立 .env
檔案
執行下列命令,將 Microsoft Cloud GitHub 存放庫 複製到您的電腦。
git clone https://github.com/microsoft/MicrosoftCloud
在 Visual Studio Code 中開啟 MicrosoftCloud/samples/openai-acs-msgraph 資料夾。
注意
雖然我們將在本教學課程中使用 Visual Studio Code,但任何程式代碼編輯器都可以用來處理範例專案。
請注意下列資料夾與檔案:
- 用戶端:用戶端應用程式程序代碼。
- 伺服器:伺服器端 API 程式代碼。
- docker-compose.yml:用來執行本機 PostgreSQL 資料庫。
將專案根目錄中的 .env.example 重新命名為 .env。
開啟 .env 檔案,並花一點時間查看包含的金鑰:
ENTRAID_CLIENT_ID= TEAM_ID= CHANNEL_ID= OPENAI_API_KEY= OPENAI_ENDPOINT= OPENAI_API_VERSION=2023-06-01-preview OPENAI_MODEL=gpt-35-turbo POSTGRES_USER= POSTGRES_PASSWORD= ACS_CONNECTION_STRING= ACS_PHONE_NUMBER= ACS_EMAIL_ADDRESS= CUSTOMER_EMAIL_ADDRESS= CUSTOMER_PHONE_NUMBER= API_PORT=3000 AZURE_COGNITIVE_SEARCH_ENDPOINT= AZURE_COGNITIVE_SEARCH_KEY= AZURE_COGNITIVE_SEARCH_INDEX=
更新 .env 中的下列值。 API 伺服器會使用這些值來連線到本機 PostgreSQL 資料庫。
POSTGRES_USER=web POSTGRES_PASSWORD=web-password
現在您已備妥專案,讓我們試用一些應用程式功能,並瞭解其建置方式。 選取下方的 [ 下一步] 按鈕,以使用目錄繼續或跳至特定練習。
AI:建立 Azure OpenAI 資源並部署模型
若要開始在應用程式中使用 Azure OpenAI,您需要建立 Azure OpenAI 服務並部署模型,以用來執行工作,例如將自然語言轉換成 SQL、產生電子郵件/簡訊內容等等。
在此練習中,您將會:
- 建立 Azure OpenAI 服務資源。
- 部署模型。
- 使用來自 Azure OpenAI 服務資源的值來更新 .env 檔案。
建立 Azure OpenAI 服務資源
瀏覽瀏覽器中的 Azure 入口網站 並登入。
在入口網站頁面頂端的搜尋列中輸入 openai,然後從出現的選項中選取 [Azure OpenAI]。
選取工具列中的 [ 建立 ]。
注意
如果您在訂用帳戶上看到有關完成應用程式表單以啟用 Azure OpenAI 的訊息,請選取 [按兩下這裡以要求存取 Azure OpenAI 服務 ] 連結並完成表單。 完成表單之後,您必須等候 Azure OpenAI 小組核准您的要求。 收到核准通知之後,您可以返回此練習並建立資源。
雖然本教學課程著重於 Azure OpenAI,但如果您有 OpenAI API 金鑰,而且想要在等候存取 Azure OpenAI 時使用該金鑰,您可以略過本節並直接移至下方 的更新專案的 .env 檔案 一節。 將 OpenAI API 金鑰指派給
OPENAI_API_KEY
.env 檔案 (您可以忽略與 OpenAI) 相關的任何其他.env
指示。 一旦您能夠存取 Azure OpenAI,請重新瀏覽此練習、建立資源和模型,並使用來自 Azure OpenAI 資源的值來更新 .env 檔案。執行下列工作:
- 選取 Azure 訂閱。
- 選取資源群組, (視需要建立新的資源群組) 。
- 選取您想要使用的區域。
- 輸入資源名稱。 它必須是唯一值。
- 選取 標準 S0 定價層。
選取 [下一步 ],直到您進入 [ 檢閱 + 提交 ] 畫面為止。 選取 [建立]。
建立 Azure OpenAI 資源之後,請流覽至該資源,然後在 [資源管理] 區段中選取 [密鑰和端點]。
找出 KEY 1 和 端點 值。 您將在下一節中使用這兩個值,以便將它們複製到本機檔案。
在 [資源管理] 區段中選取 [模型部署]。
選取 [ 管理部署] 按鈕以移至 Azure OpenAI Studio。
選取工具列中的 [建立新部署 ]。
輸入下列值:
- 模型: gpt-35-turbo。
- 模型版本: 自動更新為預設值。
- 部署名稱: gpt-35-turbo。
注意
Azure OpenAI 支援 數種不同類型的模型。 每個模型都可以用來處理不同的案例。
選取 [建立]。
部署模型之後,請選取 [遊樂場] 區段中的 [完成]。
從 [部署] 下拉式清單中選取 gpt-35-turbo 模型。 從 [範例] 下拉式清單中選取 [產生電子郵件]。
請花點時間閱讀所提供的提示文字。 選取 [產生 ] 以查看模型產生的文字。
警告
如果您收到有關模型尚未就緒的錯誤訊息,請稍候幾分鐘后再試一次。 模型可能需要幾分鐘的時間才能完整部署且可供使用。
如果您收到錯誤,指出「完成作業不適用於指定的模型。」,這通常表示您選取了較新的模型版本,而不是預設版本。 選取 [部署 ],然後刪除您稍早建立的模型。 建立新的 gpt-35-turbo 模型部署、確定您選取 [自動更新為模型版本預設值]、為它命名 gpt-35-turbo,並等候模型完全部署。 部署之後,請返回 遊樂場 ,然後再試一次完成。
選取 [ 重新產生 多次]。 請注意,每次文字都不同。
在畫面右側,您會看到列出如 Temperature 等屬性。 將 [溫度] 值變更為 0 ,然後再次選取 [ 重新產生 ]。 閱讀產生的電子郵件文字。
選取 [ 重新產生 最後一次],並注意電子郵件文字與先前產生的文字相同。
注意
降低溫度表示模型會產生更重複且具決定性的回應。 增加溫度會導致更多非預期或創意的回應。
更新項目的 .env
檔案
返回 以 Visual Studio Code,並在專案的根目錄開啟
.env
檔案。從您的 Azure OpenAI 資源複製 KEY 1 值,並將它指派給
OPENAI_API_KEY
位於 openai-acs-msgraph 資料夾根目錄的 .env 檔案中:OPENAI_API_KEY=<KEY_1_VALUE>
複製 *Endpoint 值,並將它指派給
OPENAI_ENDPOINT
.env 檔案中。/
如果值存在,請從值的結尾移除字元。OPENAI_ENDPOINT=<ENDPOINT_VALUE>
注意
您會看到 和
OPENAI_API_VERSION
的值OPENAI_MODEL
已在 .env 檔案中設定。 模型值設定為 gpt-35-turbo ,其應該符合您稍早在本練習中建立的模型名稱。 API 版本會設定為 Azure OpenAI 參考文件中定義的支援值。儲存 .env 檔案。
啟動應用程式服務
是時候啟動您的應用程式服務,包括資料庫、API 伺服器和 Web 伺服器。
在下列步驟中,您將在 Visual Studio Code 中建立三個終端機視窗。
以滑鼠右鍵按兩下 Visual Studio Code 檔案清單中的 .env 檔案,然後選取 [在整合式終端機中開啟]。 在繼續之前,請確定您的終端機位於專案的根目錄 - openai-acs-msgraph 。
從下列 其中一 個選項中選擇,以啟動 PostgreSQL 資料庫:
如果您已安裝並執行 Docker Desktop ,請在終端機視窗中執行
docker-compose up
,然後按 Enter。如果您已安裝 並執行 Podman-compose 的 Podman ,請在終端機視窗中執行
podman-compose up
,然後按 Enter。若要直接使用 Docker Desktop、Podman、nerdctl 或您已安裝的另一個容器運行時間來執行 PostgreSQL 容器,請在終端機視窗中執行下列命令:
Mac、Linux 或 Windows 子系統 Linux 版 (WSL) :
[docker | podman | nerdctl] run --name postgresDb -e POSTGRES_USER=web -e POSTGRES_PASSWORD=web-password -e POSTGRES_DB=CustomersDB -v $(pwd)/data:/var/lib/postgresql/data -p 5432:5432 postgres
使用 PowerShell 的 Windows:
[docker | podman] run --name postgresDb -e POSTGRES_USER=web -e POSTGRES_PASSWORD=web-password -e POSTGRES_DB=CustomersDB -v ${PWD}/data:/var/lib/postgresql/data -p 5432:5432 postgres
資料庫容器啟動之後,請按 + [Visual Studio Code 終端機] 工具列中的圖示,以建立第二個終端機視窗。
cd
進入 伺服器/typescript 資料夾,然後執行下列命令來安裝相依性並啟動 API 伺服器。npm install
npm start
在 + [Visual Studio Code 終端機] 工具列中再次按下圖示,以建立第三個終端機視窗。
cd
進入 客戶端 資料夾,然後執行下列命令來安裝相依性並啟動 Web 伺服器。npm install
npm start
瀏覽器將會啟動,並帶您前往 http://localhost:4200。
AI:自然語言到 SQL
在考慮 AI 功能時,「只是因為您無法表示您應該」是有用的指南。 例如,Azure OpenAI 對 SQL 的自然語言功能可讓使用者以純英文進行資料庫查詢,這可以是增強其生產力的強大工具。 不過, 功能強大的 不一定表示 適當 或 安全。 此練習將示範如何使用此 AI 功能,同時討論在決定實作之前要記住的重要考慮。
以下是可用來從資料庫擷取數據的自然語言查詢範例:
Get the the total revenue for all companies in London.
使用適當的提示時,Azure OpenAI 會將此查詢轉換成 SQL,以用來從資料庫傳回結果。 因此,包括商務分析師、營銷人員和主管的非技術使用者,可以更輕鬆地從資料庫擷取寶貴的資訊,而不需要處理複雜的 SQL 語法或依賴受限制的數據格和篩選條件。 這種簡化的方法可以藉由免除使用者向技術專家尋求協助的需求,來提升生產力。
本練習提供一個起點,可協助您瞭解 SQL 的自然語言運作方式、介紹一些重要的考慮、讓您思考優缺點,以及示範程式代碼以開始使用。
在本練習中,您將會:
- 使用 GPT 提示將自然語言轉換成 SQL。
- 試驗不同的 GPT 提示。
- 使用產生的 SQL 查詢稍早啟動的 PostgreSQL 資料庫。
- 從 PostgreSQL 傳回查詢結果,並將其顯示在瀏覽器中。
讓我們從試驗可用來將自然語言轉換成 SQL 的不同 GPT 提示開始。
使用自然語言到 SQL 功能
在 上一個練習 中,您已啟動資料庫、API 和應用程式。 您也會更新檔案
.env
。 如果您未完成這些步驟,請先遵循練習結尾的指示,再繼續進行。返回 瀏覽器 (http://localhost:4200) ,然後找出 datagrid 下方頁面的 [自定義查詢] 區段。 請注意,範例查詢值已包含: 取得所有訂單的總營收。依公司分組,並包含城市。
選取 [ 執行查詢] 按鈕。 這會將使用者的自然語言查詢傳遞至 Azure OpenAI,以將其轉換成 SQL。 SQL 查詢接著會用來查詢資料庫,並傳回任何可能的結果。
執行下列 自訂查詢:
Get the total revenue for Adventure Works Cycles. Include the contact information as well.
檢視在 Visual Studio Code 中執行 API 伺服器的終端機視窗,並注意到它會顯示從 Azure OpenAI 傳回的 SQL 查詢。 伺服器端 API 會使用 JSON 數據來查詢 PostgreSQL 資料庫。 查詢中包含的任何字串值會新增為參數值,以防止 SQL 插入式攻擊:
{ "sql": "SELECT c.company, c.city, c.email, SUM(o.total) AS revenue FROM customers c INNER JOIN orders o ON c.id = o.customer_id WHERE c.company = $1 GROUP BY c.company, c.city, c.email", "paramValues": ["Adventure Works Cycles"] }
返回 瀏覽器,然後選取 [重設數據] 以在 datagrid 中再次檢視所有客戶。
探索自然語言至 SQL 程式代碼
提示
如果您使用 Visual Studio Code,您可以選取下列專案來直接開啟檔案:
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
然後輸入您要開啟的檔案名。
注意
本練習的目標是要示範 SQL 功能的自然語言可能,並示範如何開始使用。 如先前所述,在繼續進行任何實作之前,請務必討論此類型的 AI 是否適合您的組織。 也 請務必規劃適當的提示規則和資料庫安全性措施 ,以防止未經授權的存取和保護敏感數據。
既然您已瞭解 SQL 功能的自然語言運作方式,讓我們來檢查其實作方式。
開啟 伺服器/apiRoutes.ts 檔案,並找出
generateSql
路由。 此 API 路由是由在瀏覽器中執行的用戶端應用程式呼叫,並用來從自然語言查詢產生 SQL。 擷取 SQL 查詢之後,它會用來查詢資料庫並傳回結果。router.post('/generateSql', async (req, res) => { const userPrompt = req.body.prompt; if (!userPrompt) { return res.status(400).json({ error: 'Missing parameter "prompt".' }); } try { // Call Azure OpenAI to convert the user prompt into a SQL query const sqlCommandObject = await getSQLFromNLP(userPrompt); let result: any[] = []; // Execute the SQL query if (sqlCommandObject && !sqlCommandObject.error) { result = await queryDb(sqlCommandObject) as any[]; } else { result = [ { query_error : sqlCommandObject.error } ]; } res.json(result); } catch (e) { console.error(e); res.status(500).json({ error: 'Error generating or running SQL query.' }); } });
請注意路由中的
generateSql
下列功能:- 它會從
req.body.query
擷取用戶查詢值,並將它指派給名為的userQuery
變數。 此值將用於 GPT 提示字元中。 - 它會呼叫函
getSQLFromNLP()
式,將自然語言轉換成 SQL。 - 它會將產生的 SQL 傳遞至名為
queryDb
的函式,該函式會執行 SQL 查詢,並從資料庫傳回結果。
- 它會從
在編輯器中開啟 伺服器/openAI.ts 檔案,並找出 函
getSQLFromNLP()
式。 路由會呼叫此函式,generatesql
並用來將自然語言轉換為 SQL。async function getSQLFromNLP(userPrompt: string): Promise<QueryData> { // Get the high-level database schema summary to be used in the prompt. // The db.schema file could be generated by a background process or the // schema could be dynamically retrieved. const dbSchema = await fs.promises.readFile('db.schema', 'utf8'); const systemPrompt = ` Assistant is a natural language to SQL bot that returns only a JSON object with the SQL query and the parameter values in it. The SQL will query a PostgreSQL database. PostgreSQL tables, with their columns: ${dbSchema} Rules: - Convert any strings to a PostgreSQL parameterized query value to avoid SQL injection attacks. - Always return a JSON object with the SQL query and the parameter values in it. - Return a JSON object. Do NOT include any text outside of the JSON object. - Example JSON object to return: { "sql": "", "paramValues": [] } User: "Display all company reviews. Group by company." Assistant: { "sql": "SELECT * FROM reviews", "paramValues": [] } User: "Display all reviews for companies located in cities that start with 'L'." Assistant: { "sql": "SELECT r.* FROM reviews r INNER JOIN customers c ON r.customer_id = c.id WHERE c.city LIKE 'L%'", "paramValues": [] } User: "Display revenue for companies located in London. Include the company name and city." Assistant: { "sql": "SELECT c.company, c.city, SUM(o.total) AS revenue FROM customers c INNER JOIN orders o ON c.id = o.customer_id WHERE c.city = $1 GROUP BY c.company, c.city", "paramValues": ["London"] } User: "Get the total revenue for Adventure Works Cycles. Include the contact information as well." Assistant: { "sql": "SELECT c.company, c.city, c.email, SUM(o.total) AS revenue FROM customers c INNER JOIN orders o ON c.id = o.customer_id WHERE c.company = $1 GROUP BY c.company, c.city, c.email", "paramValues": ["Adventure Works Cycles"] } - Convert any strings to a PostgreSQL parameterized query value to avoid SQL injection attacks. - Do NOT include any text outside of the JSON object. Do not provide any additional explanations or context. Just the JSON object is needed. `; let queryData: QueryData = { sql: '', paramValues: [], error: '' }; let results = ''; try { results = await callOpenAI(systemPrompt, userPrompt); if (results) { console.log('results', results); const parsedResults = JSON.parse(results); queryData = { ...queryData, ...parsedResults }; if (isProhibitedQuery(queryData.sql)) { queryData.sql = ''; queryData.error = 'Prohibited query.'; } } } catch (error) { console.log(error); if (isProhibitedQuery(results)) { queryData.sql = ''; queryData.error = 'Prohibited query.'; } else { queryData.error = results; } } return queryData; }
-
userPrompt
參數會傳遞至函式。 此值userPrompt
是使用者在瀏覽器中輸入的自然語言查詢。 - 定義
systemPrompt
要使用的 AI 助理 類型,以及應該遵循的規則。 這有助於 Azure OpenAI 了解資料庫結構、要套用的規則,以及如何傳回產生的 SQL 查詢和參數。 - 名為
callOpenAI()
的函式會呼叫,systemPrompt
並將 和userPrompt
值傳遞給它。 - 系統會檢查結果,以確保產生的 SQL 查詢中未包含禁止的值。 如果找到禁止的值,SQL 查詢會設定為空字串。
-
讓我們更詳細地逐步解說系統提示:
const systemPrompt = ` Assistant is a natural language to SQL bot that returns only a JSON object with the SQL query and the parameter values in it. The SQL will query a PostgreSQL database. PostgreSQL tables, with their columns: ${dbSchema} Rules: - Convert any strings to a PostgreSQL parameterized query value to avoid SQL injection attacks. - Always return a JSON object with the SQL query and the parameter values in it. - Return a JSON object. Do NOT include any text outside of the JSON object. - Example JSON object to return: { "sql": "", "paramValues": [] } User: "Display all company reviews. Group by company." Assistant: { "sql": "SELECT * FROM reviews", "paramValues": [] } User: "Display all reviews for companies located in cities that start with 'L'." Assistant: { "sql": "SELECT r.* FROM reviews r INNER JOIN customers c ON r.customer_id = c.id WHERE c.city LIKE 'L%'", "paramValues": [] } User: "Display revenue for companies located in London. Include the company name and city." Assistant: { "sql": "SELECT c.company, c.city, SUM(o.total) AS revenue FROM customers c INNER JOIN orders o ON c.id = o.customer_id WHERE c.city = $1 GROUP BY c.company, c.city", "paramValues": ["London"] } User: "Get the total revenue for Adventure Works Cycles. Include the contact information as well." Assistant: { "sql": "SELECT c.company, c.city, c.email, SUM(o.total) AS revenue FROM customers c INNER JOIN orders o ON c.id = o.customer_id WHERE c.company = $1 GROUP BY c.company, c.city, c.email", "paramValues": ["Adventure Works Cycles"] } - Convert any strings to a PostgreSQL parameterized query value to avoid SQL injection attacks. - Do NOT include any text outside of the JSON object. Do not provide any additional explanations or context. Just the JSON object is needed. `;
定義要使用的 AI 助理 類型。 在此情況下,「SQL Bot 的自然語言」。
定義資料庫中的數據表名稱和數據行。 提示中包含的高階架構可以在 server/db.schema 檔案中找到,如下所示。
- customers (id, company, city, email) - orders (id, customer_id, date, total) - order_items (id, order_id, product_id, quantity, price) - reviews (id, customer_id, review, date, comment)
提示
您可以考慮建立僅包含數據使用者的只讀檢視,以使用自然語言查詢 SQL。
規則的定義是將任何字串值轉換成參數化查詢值,以避免發生 SQL 插入式攻擊。
規則會定義為一律傳回 JSON 物件 (,而且不會使用 SQL 查詢和其中的參數值) 其他任何專案。
針對要傳回的 JSON 物件類型,提供了一個範例。
會提供範例使用者提示和預期的 SQL 查詢和參數值。 這稱為 「少數」學習。 雖然 LLM 是針對大量數據進行定型,但只能使用一些範例來調整為新的工作。 替代方法是「零次」學習,其中沒有提供範例,而且模型預期會產生正確的 SQL 查詢和參數值。
系統提示字元底部會再次重複兩個重大規則,以避免「直方偏差」。
提示
函
getSQLFromNLP()
式會將系統和使用者提示傳送至名為callOpenAI()
的函式,該函式也位於 伺服器/openAI.ts 檔案中。 函callOpenAI()
式會藉由檢查環境變數來判斷是否應該呼叫 Azure OpenAI 服務或 OpenAI 服務。 如果環境變數中有密鑰、端點和模型可供使用,則會呼叫 Azure OpenAI,否則會呼叫 OpenAI。function callOpenAI(systemPrompt: string, userPrompt: string, temperature = 0, useBYOD = false) { const isAzureOpenAI = OPENAI_API_KEY && OPENAI_ENDPOINT && OPENAI_MODEL; if (isAzureOpenAI && useBYOD) { return getAzureOpenAIBYODCompletion(systemPrompt, userPrompt, temperature); } if (isAzureOpenAI) { return getAzureOpenAICompletion(systemPrompt, userPrompt, temperature); } return getOpenAICompletion(systemPrompt, userPrompt, temperature); }
注意
雖然我們會在整個教學課程中專注於 Azure OpenAI,但如果您只提供
OPENAI_API_KEY
.env 檔案中的值,應用程式將會改用 OpenAI。 如果您選擇使用 OpenAI 而不是 Azure OpenAI,在某些情況下可能會看到不同的結果。找出函式
getAzureOpenAICompletion()
。async function getAzureOpenAICompletion(systemPrompt: string, userPrompt: string, temperature: number): Promise<string> { checkRequiredEnvVars(['OPENAI_API_KEY', 'OPENAI_ENDPOINT', 'OPENAI_MODEL']); const fetchUrl = `${OPENAI_ENDPOINT}/openai/deployments/${OPENAI_MODEL}/chat/completions?api-version=${OPENAI_API_VERSION}`; const messageData: ChatGPTData = { max_tokens: 1024, temperature, messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt } ] }; const headersBody: OpenAIHeadersBody = { method: 'POST', headers: { 'Content-Type': 'application/json', 'api-key': OPENAI_API_KEY }, body: JSON.stringify(messageData), }; const completion = await fetchAndParse(fetchUrl, headersBody); console.log(completion); let content = (completion.choices[0]?.message?.content?.trim() ?? '') as string; console.log('Azure OpenAI Output: \n', content); if (content && content.includes('{') && content.includes('}')) { content = extractJson(content); } console.log('After parse: \n', content); return content; } function checkRequiredEnvVars(requiredEnvVars: string[]) { for (const envVar of requiredEnvVars) { if (!process.env[envVar]) { throw new Error(`Missing ${envVar} in environment variables.`); } } } async function fetchAndParse(url: string, headersBody: Record<string, any>): Promise<any> { try { const response = await fetch(url, headersBody); return await response.json(); } catch (error) { console.error(`Error fetching data from ${url}:`, error); throw error; } }
此函式會執行下列動作:
接受
systemPrompt
、userPrompt
和temperature
參數。-
systemPrompt
:讓 Azure OpenAI 模型知道它應該扮演的角色,以及要遵循的規則。 -
userPrompt
:輸入應用程式的使用者資訊,例如模型將用來產生輸出的自然語言或規則。 -
temperature
:決定產生回應時模型應該如何有創意。 較高的值表示模型會承擔更多風險。
-
藉由呼叫
checkRequiredEnvVars()
,確保有有效的 Azure OpenAI API 金鑰、端點和模型可供使用。fetchUrl
建立值,用來呼叫 Azure OpenAI 的 REST API,並將環境變數中的端點、模型和 API 版本值內嵌至 URL。建立
messageData
包含max_token
、temperature
和messages
的物件,以傳送至 Azure OpenAI。-
max_tokens
:完成時要產生的令牌數目上限。 提示的權杖計數加上 max_tokens 不能超過模型的內容長度。 較舊的 模型 具有 2,048 個令牌的內容長度,而較新的模型則支援 4,096、8、192 或甚至 32,768 令牌,視所使用的模型而定。 -
temperature
:要使用的取樣溫度。 較高的值表示模型會承擔更多風險。 嘗試 0.9 以取得更多創意應用程式,而 0 則用於定義完善的答案。 -
messages
:表示以聊天格式產生聊天完成的訊息。 在此範例中,會傳入兩個訊息:一個用於系統,另一個用於使用者。 系統訊息會定義將使用的整體行為和規則,而使用者訊息則會定義使用者所提供的提示文字。
-
呼叫
fetchAndParse()
,將fetchUrl
和headersBody
值傳送至 Azure OpenAI。藉由擷
completion.choices[0].message.content
取 值來處理回應。 如果回應包含預期的結果,程式代碼會從回應中擷取 JSON 物件,並傳回它。注意
您可以在 Azure OpenAI 參考檔中深入瞭解這些參數和其他參數。
註函式
getSQLFromNLP()
中的下列幾行:// if (isProhibitedQuery(queryData.sql)) { // queryData.sql = ''; // }
儲存 openAI.ts。 API 伺服器會自動重建 TypeScript 程式代碼,並重新啟動伺服器。
返回 瀏覽器,然後輸入 從資料庫選取所有數據表名稱到自定義查詢輸入。 選取 [執行查詢]。 是否顯示資料表名稱?
返回 伺服器
getSQLFromNLP()
/openAI.ts中的函式,並將下列規則新增至Rules:
系統提示字元的 區段中,然後儲存盤案。- Do not allow the SELECT query to return table names, function names, or procedure names.
返回 至瀏覽器,然後執行下列工作:
- 輸入 從資料庫選取所有數據表名稱 到 自定義查詢 輸入。 選取 [執行查詢]。 是否顯示資料表名稱?
- 輸入 選取資料庫中的所有函式名稱。 在 [自定義查詢] 輸入中,然後再次選取 [ 執行查詢 ]。 是否顯示函式名稱?
問題:新增規則之後,為什麼這仍然正常運作,指出不允許數據表名稱、函式名稱和程式名稱?
答案:這是因為只有 JSON 規則。 如果規則更具彈性,而且不需要傳回 JSON 物件,您可能會看到有關 Azure OpenAI 無法執行工作的訊息。
注意
請務必注意,OpenAI 模型可能會在有時傳回不符合您所定義規則的非預期結果。 請務必在程式代碼中規劃。
從中移除下列規則
systemPrompt
並儲存盤案。- Only return a JSON object. Do NOT include any text outside of the JSON object. Do not provide any additional explanations or context. Just the JSON object is needed.
再次 執行 從資料庫查詢選取所有數據表名稱 。
請注意,訊息現在會顯示在瀏覽器中。 Azure OpenAI 因為下列規則而無法執行工作。 由於我們移除了「僅限 JSON」規則,因此回應可以提供無法執行工作原因的其他詳細數據。
- Do not allow the SELECT query to return table names, function names, or procedure names.
您可以看到,即使您已有特定規則,AI 仍可能會產生非預期的結果。 這就是為什麼您需要仔細規劃提示文字和規則,但也計劃將後置處理步驟新增至您的程序代碼,以處理您收到非預期結果的情況。
返回 至伺服器/openAI.ts並找出函
isProhibitedQuery()
式。 這是可在 Azure OpenAI 傳回結果之後執行的後置處理程式碼範例。 請注意,如果產生的 SQL 查詢中傳回禁止的關鍵詞,它會將sql
屬性設定為空字串。 這可確保如果 Azure OpenAI 傳回非預期的結果,SQL 查詢將不會對資料庫執行。function isProhibitedQuery(query: string): boolean { if (!query) return false; const prohibitedKeywords = [ 'insert', 'update', 'delete', 'drop', 'truncate', 'alter', 'create', 'replace', 'information_schema', 'pg_catalog', 'pg_tables', 'pg_namespace', 'pg_class', 'table_schema', 'table_name', 'column_name', 'column_default', 'is_nullable', 'data_type', 'udt_name', 'character_maximum_length', 'numeric_precision', 'numeric_scale', 'datetime_precision', 'interval_type', 'collation_name', 'grant', 'revoke', 'rollback', 'commit', 'savepoint', 'vacuum', 'analyze' ]; const queryLower = query.toLowerCase(); return prohibitedKeywords.some(keyword => queryLower.includes(keyword)); }
注意
請務必注意,這隻是示範程序代碼。 如果您選擇將自然語言轉換成 SQL,可能需要其他禁止的關鍵詞來涵蓋您的特定使用案例。 這是您必須謹慎規劃並使用的功能,以確保只會傳回有效的 SQL 查詢,並針對資料庫執行。 除了禁止的關鍵詞之外,您也需要考慮安全性。
返回 至伺服器/openAI.ts,並取消批注函式中的
getSQLFromNLP()
下列程序代碼。 儲存檔案。if (isProhibitedQuery(queryData.sql)) { queryData.sql = ''; }
請從
systemPrompt
中移除下列規則,並儲存盤案。- Do not allow the SELECT query to return table names, function names, or procedure names.
返回 瀏覽器,再次在 [自定義查詢] 輸入中,輸入 [從資料庫選取所有數據表名稱],然後選取 [執行查詢] 按鈕。
是否有任何數據表結果顯示? 即使沒有規則,
isProhibitedQuery()
後續處理程式碼仍禁止對資料庫執行該類型的查詢。如先前所述,將自然語言整合到企業營運應用程式中的 SQL 對使用者很有説明,但它確實隨附自己的一組考慮。
優點:
用戶易記性:這項功能可讓使用者更容易存取資料庫互動,而不需要技術專業知識,進而減少 SQL 知識的需求,並可能加速作業。
提高生產力:商務分析師、營銷人員、主管和其他非技術使用者可以從資料庫擷取寶貴的資訊,而不需要依賴技術專家,進而提升效率。
廣泛應用程式:藉由使用進階語言模型,應用程式可以設計為符合各種使用者和使用案例。
考量因素:
安全性:其中一個最大的考慮是安全性。 如果使用者可以使用自然語言與資料庫互動,則必須備妥健全的安全性措施,以防止未經授權的存取或惡意查詢。 您可以考慮實作唯讀模式,以防止使用者修改數據。
數據隱私權:某些數據可能很機密,且不應輕易存取,因此您必須確保已具備適當的保護和用戶許可權。
正確性:雖然自然語言處理已大幅改善,但並不完美。 使用者查詢的誤判可能會導致不正確的結果或非預期的行為。 您必須規劃如何處理非預期的結果。
效率:不保證從自然語言查詢傳回的 SQL 會有效率。 在某些情況下,如果後續處理規則偵測到 SQL 查詢的問題,可能需要對 Azure OpenAI 進行其他呼叫。
訓練和用戶適應:用戶必須經過訓練,才能正確制定其查詢。 雖然比學習 SQL 更容易,但仍可能會有相關的學習曲線。
繼續進行下一個練習之前,請先考慮幾個最後幾點:
- 請記住,「因為您不表示應該」適用於此處。 在將自然語言與 SQL 整合至應用程式之前,請先謹慎謹慎且謹慎地規劃。 請務必瞭解潛在風險,並規劃這些風險。
- 使用這種類型的技術之前,請與您的小組、資料庫管理員、安全性小組、項目關係人和其他任何相關方討論潛在案例,以確保它適合您的組織。 請務必討論 SQL 的自然語言是否符合安全性、隱私權,以及貴組織可能具備的任何其他需求。
- 安全性應該是主要考慮,並內建於規劃、開發和部署程式內。
- 雖然 SQL 的自然語言非常強大,但仔細規劃必須進入,以確保提示具有必要的規則,且包含後續處理功能。 規劃額外的時間來實作及測試這種類型的功能,並考慮傳回非預期結果的案例。
- 透過 Azure OpenAI,客戶可享有 Microsoft Azure 的安全性功能,同時執行與 OpenAI 相同的模型。 Azure OpenAI 提供私人網路、區域可用性,以及負責任 AI 內容篩選。 深入瞭解 Azure OpenAI 服務的數據、隱私權和安全性。
您現在已瞭解如何使用 Azure OpenAI 將自然語言轉換成 SQL,並了解實作這種類型的功能的優點和缺點。 在下一個練習中,您將瞭解如何使用 Azure OpenAI 產生電子郵件和簡訊。
AI:產生完成
除了 SQL 的自然語言功能之外,您也可以使用 Azure OpenAI 服務來產生電子郵件和簡訊,以增強用戶生產力並簡化通訊工作流程。 藉由利用 Azure OpenAI 的語言產生功能,使用者可以定義特定規則,例如「訂單延遲 5 天」,系統會自動根據這些規則產生適當的電子郵件和 SMS 訊息。
這項功能可做為使用者的「快速啟動」,為使用者提供一個經過仔細製作的郵件範本,讓他們可以輕鬆地在傳送之前加以自定義。 結果是撰寫訊息所需的時間和精力大幅減少,讓使用者專注於其他重要工作。 此外,Azure OpenAI 的語言產生技術可以整合到自動化工作流程中,讓系統能夠自發產生和傳送訊息,以響應預先定義的觸發程式。 這種自動化層級不僅可加速通訊程式,還能確保各種案例的一致且精確的傳訊。
在本練習中,您將會:
- 使用不同的 GPT 提示進行實驗。
- 使用 GPT 提示來產生電子郵件和簡訊的完成。
- 探索啟用 GPT 完成的程式代碼。
- 瞭解提示工程的重要性,並在提示中包含規則。
讓我們開始試驗可用來產生電子郵件和簡訊的不同規則。
使用 GPT 完成功能
在 先前的練習 中,您已啟動資料庫、API 和應用程式。 您也會更新檔案
.env
。 如果您未完成這些步驟,請先遵循練習結尾的指示,再繼續進行。返回 至瀏覽器 (http://localhost:4200) ,然後選取 datagrid 中任何數據列的 [連絡客戶],然後選取 [Email/SMS 客戶] 以前往 [訊息產生器] 畫面。
這會使用 Azure OpenAI 將您定義的訊息規則轉換成 Email/SMS 訊息。 執行下列工作:
輸入 [訂單] 之類的規則會在輸入中延遲 5 天,然後選取 [產生 Email/SMS 訊息] 按鈕。
您會看到針對電子郵件產生的主旨和本文,以及針對SMS產生的簡短訊息。
注意
因為尚未啟用 Azure 通訊服務,所以您將無法傳送電子郵件或簡訊。
關閉瀏覽器中的電子郵件/SMS 對話框視窗。 現在您已瞭解這項功能的運作方式,讓我們來看看其實作方式。
探索 GPT 完成程式碼
提示
如果您使用 Visual Studio Code,您可以選取下列專案來直接開啟檔案:
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
然後輸入您要開啟的檔案名。
開啟 伺服器/apiRoutes.ts 檔案,並找出
completeEmailSmsMessages
路由。 選取 [產生 Email/SMS 訊息] 按鈕時,應用程式前端部分會呼叫此 API。 它會從本文擷取使用者提示、公司及聯繫人名稱值,並將其傳遞至completeEmailSMSMessages()
伺服器/openAI.ts檔案中的函式。 結果接著會傳回給用戶端。router.post('/completeEmailSmsMessages', async (req, res) => { const { prompt, company, contactName } = req.body; if (!prompt || !company || !contactName) { return res.status(400).json({ status: false, error: 'The prompt, company, and contactName parameters must be provided.' }); } let result; try { // Call OpenAI to get the email and SMS message completions result = await completeEmailSMSMessages(prompt, company, contactName); } catch (e: unknown) { console.error('Error parsing JSON:', e); } res.json(result); });
開啟 伺服器/openAI.ts 檔案,並找出 函
completeEmailSMSMessages()
式。async function completeEmailSMSMessages(prompt: string, company: string, contactName: string) { console.log('Inputs:', prompt, company, contactName); const systemPrompt = ` Assistant is a bot designed to help users create email and SMS messages from data and return a JSON object with the email and SMS message information in it. Rules: - Generate a subject line for the email message. - Use the User Rules to generate the messages. - All messages should have a friendly tone and never use inappropriate language. - SMS messages should be in plain text format and NO MORE than 160 characters. - Start the message with "Hi <Contact Name>,\n\n". Contact Name can be found in the user prompt. - Add carriage returns to the email message to make it easier to read. - End with a signature line that says "Sincerely,\nCustomer Service". - Return a valid JSON object with the emailSubject, emailBody, and SMS message values in it: { "emailSubject": "", "emailBody": "", "sms": "" } - The sms property value should be in plain text format and NO MORE than 160 characters. - Only return a valid JSON object. Do NOT include any text outside of the JSON object. Do not provide any additional explanations or context. Just the JSON object is needed. `; const userPrompt = ` User Rules: ${prompt} Contact Name: ${contactName} `; let content: EmailSmsResponse = { status: true, email: '', sms: '', error: '' }; let results = ''; try { results = await callOpenAI(systemPrompt, userPrompt, 0.5); if (results) { const parsedResults = JSON.parse(results); content = { ...content, ...parsedResults, status: true }; } } catch (e) { console.log(e); content.status = false; content.error = results; } return content; }
此函式具有下列功能:
-
systemPrompt
用來定義 AI 助理 能夠產生電子郵件和 SMS 訊息。systemPrompt
也包括:- 要遵循 助理 的規則,以控制訊息的音調、開始和結束格式、SMS 訊息的最大長度等等。
- 回應中應包含的數據相關信息 - 在此案例中為 JSON 物件,而且只有 JSON 物件。
- 系統提示字元底部會再次重複兩個重大規則,以避免 「直方偏差」。
-
userPrompt
用來定義使用者想要在產生電子郵件和簡訊時包含的規則和聯繫人名稱。 您稍早輸入 的訂單延遲 5 天 規則包含在 中userPrompt
。 - 函式會呼叫
callOpenAI()
您稍早探索的函式,以產生電子郵件和SMS完成。
-
返回 至瀏覽器,重新整理頁面,然後選取 [連絡客戶],然後在任何數據列上選取 [連絡客戶],然後選取 [Email/SMS 客戶],再次前往 [訊息產生器] 畫面。
在 訊息產生器 輸入中輸入下列規則:
- 訂單會事先排程。
- 告訴客戶永遠不會再次訂購,我們不希望他們的業務。
選取 [產生 Email/SMS 訊息],並記下訊息。
All messages should have a friendly tone and never use inappropriate language.
系統提示字元中的規則會覆寫使用者提示中的負規則。返回 至編輯器中的伺服器/openAI.ts*,並從函式中的
completeEmailSMSMessages()
提示中移除All messages should have a friendly tone and never use inappropriate language.
規則。 儲存檔案。返回 至瀏覽器中的電子郵件/SMS 訊息產生器,然後再次執行相同的規則:
- 訂單會事先排程。
- 告訴客戶永遠不會再次訂購,我們不希望他們的業務。
選取 [產生 Email/SMS 訊息],並注意傳回的訊息。
這些案例中會發生什麼情況? 使用 Azure OpenAI 時,會套用 內容篩選 ,以確保一律使用適當的語言。 如果您使用 OpenAI,系統會使用系統提示中定義的規則,以確保傳回的訊息適當。
注意
這說明使用正確的資訊和規則來設計提示的重要性,以確保傳回適當的結果。 如需此程式的詳細資訊,請參閱 提示工程文件的簡介 。
復原您在 中
completeEmailSMSMessages()
所做的systemPrompt
變更,儲存盤案並重新執行,但只使用Order is ahead of schedule.
規則 (不包含負規則) 。 這次您應該會看到如預期傳回的電子郵件和簡訊。繼續進行下一個練習之前,請先考慮幾個最後幾點:
- 請務必讓迴圈中的人類檢閱產生的訊息。 在此範例中,Azure OpenAI 完成會傳回建議的電子郵件和簡訊,但用戶可以在傳送之前覆寫這些訊息。 如果您打算將電子郵件自動化,請執行某種類型的人工檢閱程式,以確保已核准的郵件已送出非常重要。 將 AI 視為 copilot,而不是 autopilot。
- 完成只會和您在提示中新增的規則一樣好。 花點時間測試您的提示和傳回的完成時間。 邀請其他項目項目關係人檢閱完成專案。
- 您可能需要包含後置處理程序代碼,以確保正確處理非預期的結果。
- 使用系統提示來定義 AI 助理 應遵循的規則和資訊。 使用使用者提示來定義終端使用者想要包含在完成中的規則和資訊。
AI:攜帶您自己的數據
Azure OpenAI 自然語言處理 (NLP) 和完成功能整合,可大幅提升用戶生產力。 利用適當的提示和規則,AI 助理 可以有效率地產生各種形式的通訊,例如電子郵件訊息、SMS 訊息等等。 這項功能可提升使用者效率並簡化工作流程。
雖然此功能本身相當強大,但在某些情況下,使用者可能需要根據貴公司的自定義數據產生完成。 例如,您可能有一組產品手冊,讓使用者在協助客戶遇到安裝問題時流覽可能很困難。 或者,您可以維護一組完整的常見問題 (常見問題) ,這些常見問題與醫療保健權益相關,可讓使用者閱讀並取得所需的解答。 在這些案例和許多其他情況下,Azure OpenAI 服務可讓您利用自己的數據來產生完成,確保更量身訂做且內容正確的用戶問題回應。
以下是 Azure OpenAI 檔中「攜帶您自己的數據」功能運作方式的快速概觀。
注意
以自有資料為基礎的 Azure OpenAI 的主要功能之一,就是能夠以增強模型輸出的方式擷取及利用資料。 以自有資料為基礎的 Azure OpenAI 會與 Azure 認知搜尋一起根據使用者輸入和提供的交談記錄,決定要從指定資料來源擷取哪些資料。 然後,此資料會擴增並重新提交為 OpenAI 模型的提示,並將擷取的資訊附加至原始提示。 雖然擷取的資料會附加至提示,但模型仍會處理產生的輸入,就像任何其他提示一樣。 擷取資料並將提示提交至模型之後,模型會使用這項資訊來提供完成。
在本練習中,您將會:
- 使用 Azure AI Studio 建立自定義數據來源。
- 使用 Azure AI Studio 部署內嵌模型。
- 上傳自定義檔。
- 在聊天遊樂場中啟動聊天會話,以根據您自己的數據來實驗產生完成。
- 探索使用 Azure 認知搜尋 和 Azure OpenAI 來根據您自己的數據產生完成的程式代碼。
讓我們開始部署內嵌模型,並在 Azure AI Studio 中新增自定義數據源。
將自訂數據源新增至 Azure AI Studio
流覽至 Azure OpenAI Studio ,並使用可存取 Azure OpenAI 資源的認證登入。
從導覽功能表中選取 [ 部署 ]。
選取 [建立新的部署 ],然後輸入下列值:
- 模型: text-embedding-ada-002。
- 模型版本: 預設值。
- 部署名稱: text-embedding-ada-002。
建立模型之後,請從導覽功能表中選取 [Azure OpenAI ],以移至歡迎畫面。
在歡迎畫面上找出 [攜帶您自己的數據 ] 圖格,然後選取 [ 立即試用]。
從 [選取數據源] 下拉式清單中選取 [上傳檔案]。
在 [ 選取 Azure Blob 記憶體資源 ] 下拉式清單中,選取 [建立新的 Azure Blob 記憶體資源]。
這會帶您前往 Azure 入口網站,您可以在其中執行下列工作:
- 輸入記憶體帳戶的唯一名稱,例如 byodstorage[您的姓氏]。
- 選取靠近您位置的區域。
- 選取 [檢閱 ],後面接著 [ 建立]。
建立 Blob 記憶體資源之後,請回到 [Azure AI Studio] 對話框,然後從 [選取 Azure Blob 記憶體資源] 下拉式清單中選取您新建立的 Blob 記憶體資源。 如果您沒有看到列出,請選取下拉式清單旁的重新整理圖示。
必須開啟跨原始來源資源分享 (CORS) ,才能存取記憶體帳戶。 在 [Azure AI Studio] 對話框中選取 [開啟 CORS]。
在 [選取 Azure 認知搜尋 資源] 下拉式清單中,選取 [建立新的 Azure 認知搜尋 資源]。
這會將您帶回 Azure 入口網站,您可以在其中執行下列工作:
- 輸入認知搜尋資源的唯一名稱,例如 byodsearch[您的姓氏]。
- 選取靠近您位置的區域。
- 在 [ 定價層 ] 區段中,選取 [變更定價層 ],然後選取 [ 基本 ],然後選取 [ 選取]。 不支持免費層,因此您將在本教學課程結束時清除認知搜尋資源。
- 選取 [檢閱 ],後面接著 [ 建立]。
建立認知搜尋資源之後,請移至資源 [概 觀 ] 頁面,並將 Url 值複製到本機檔案。
選取左側導覽功能表中的 [金鑰 ],然後將 [主要管理員密鑰 ] 值複製到本機檔案。 您稍後會在練習中需要這些值。
選取左側導覽功能表中的 [語意排名器 ],並確定已選取 [ 免費 ]。
注意
若要檢查特定區域中是否有語意排名器,請檢查 Azure 網站上的 [ 依區域提供的產品 ] 頁面,以查看您的區域是否已列出。
返回 至 [Azure AI Studio 新增數據] 對話框,然後從 [選取 Azure 認知搜尋 資源] 下拉式清單中選取新建立的搜尋資源。 如果您沒有看到列出,請選取下拉式清單旁的重新整理圖示。
針對 Enter 索引名稱值輸入 byod-search-index 的值。
選取 [ 新增向量搜尋至此搜尋資源 ] 複選框。
在 [ 選取內嵌模型 ] 下拉式清單中,選取您稍早建立的 text-embedding-ada-002 模型。
選取複選框,後面接著 [下一步]。
在 [ 上傳檔案] 對話框中,選取 [瀏覽檔案]。
瀏覽至專案 的客戶檔案 資料夾 (位於專案根目錄) ,然後選取下列檔案:
- 時鐘 A102 安裝 Instructions.docx
- 公司 FAQs.docx
注意
這項功能目前支援下列檔格式來建立本機索引:.txt、.md、.html、.pdf、.docx 和 .pptx。
選取 [上傳檔案]。 檔案會上傳至您稍早建立之 Blob 記憶體資源的 fileupload-byod-search-index 容器。
選取 [下一步 ] 以移至 [資料管理] 對話框。
在 [ 搜尋類型 ] 下拉式清單中,選取 [混合式 + 語意]。
注意
此選項提供關鍵詞和向量搜尋的支援。 傳回結果之後,系統會使用深度學習模型將次要排名程式套用至結果集,以改善使用者的搜尋相關性。 若要深入瞭解語意搜尋,請在 Azure 認知搜尋 檔中檢視語意搜尋。
選取複選框,以確認使用語意搜尋和向量內嵌相關聯的成本。
選取 [下一步],檢閱詳細數據,然後選取 [ 儲存並關閉]。
現在已上傳您的自定義數據,數據將會編製索引,並可供在 聊天遊樂場中使用。 此流程可能需要幾分鐘的時間。 完成後,請繼續進行下一節。
在聊天遊樂場中使用自定義數據源
在 Azure AI Studio 中找到頁面的 [聊天會話] 區段,然後輸入下列 [使用者] 訊息:
What safety rules are required to install a clock?
您應該會看到類似下列顯示的結果:
展開聊天回應中的 1個參考 區段,並注意 時鐘A102安裝 Instructions.docx 檔案已列出,而且您可以選取它來檢視檔。
輸入下列 使用者訊息:
What should I do to mount the clock on the wall?
您應該會看到類似以下顯示的結果:
現在讓我們試驗公司常見問題檔。 在 [ 使用者訊息 ] 欄位中輸入下列文字:
What is the company's policy on vacation time?
您應該會看到找不到該要求的資訊。
在 [ 使用者訊息 ] 欄位中輸入下列文字:
How should I handle refund requests?
您應該會看到類似以下顯示的結果:
展開聊天回應中的 1 個參考 區段,並注意 公司 FAQs.docx 檔案已列出,而且您可以選取該檔案來檢視檔。
選取 [聊天會話] 區段頂端的 [檢視程序代碼]。
請注意,您可以在不同語言之間切換、檢視端點,以及存取端點的密鑰。 關閉 [ 範例程式代碼 ] 對話框視窗。
在 *聊天會話中開啟 [顯示原始 JSON] 切換。 請注意,聊天會話會以類似下列的訊息開始:
{ "role": "system", "content": "You are an AI assistant that helps people find information." }
既然您已建立自定義數據源並在 Chat 遊樂場中實驗過,讓我們看看如何在專案的應用程式中使用它。
在應用程式中使用自備數據功能
返回 Visual Studio Code 中的項目,然後開啟 .env 檔案。 使用認知服務端點、金鑰和索引名稱更新下列值。 您稍早在本練習中將端點和金鑰複製到本機檔案。
AZURE_COGNITIVE_SEARCH_ENDPOINT=<COGNITIVE_SERVICES_ENDPOINT_VALUE> AZURE_COGNITIVE_SEARCH_KEY=<COGNITIVE_SERVICES_KEY_VALUE> AZURE_COGNITIVE_SEARCH_INDEX=byod-search-index
在 先前的練習 中,您已啟動資料庫、API 和應用程式。 您也會更新檔案
.env
。 如果您未完成這些步驟,請先遵循先前練習結尾的指示,再繼續進行。在瀏覽器中載入應用程式之後,請選取應用程式右上角的 [聊天說明 ] 圖示。
下列文字應該會出現在聊天對話框中:
How should I handle refund requests?
選取 [ 取得說明] 按鈕。 您應該會看到您稍早在 Azure AI Studio 中上傳的公司 FAQs.docx 檔傳回的結果。 如果您想要閱讀檔,您可以在專案根目錄的客戶 檔案 資料夾中找到它。
將文字變更為下列內容,然後選取 [ 取得說明 ] 按鈕:
What safety rules are required to install a clock?
您應該會看到您稍早在 Azure AI Studio 中上傳的 Clock A102 安裝 Instructions.docx 檔傳回的結果。 此檔也可在專案根目錄的客戶 檔案 資料夾中取得。
探索程式碼
提示
如果您使用 Visual Studio Code,您可以選取下列專案來直接開啟檔案:
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
然後輸入您要開啟的檔案名。
返回 Visual Studio Code中的項目原始程式碼。
開啟 伺服器/apiRoutes.ts 檔案,並找出
completeBYOD
路由。 在 [聊天說明] 對話框中選取 [ 取得說明 ] 按鈕時,會呼叫此 API。 它會從要求本文擷取使用者提示,並將它completeBYOD()
傳遞給 伺服器/openAI.ts 檔案中的 函式。 結果接著會傳回給用戶端。router.post('/completeBYOD', async (req, res) => { const { prompt } = req.body; if (!prompt) { return res.status(400).json({ status: false, error: 'The prompt parameter must be provided.' }); } let result; try { // Call OpenAI to get custom "bring your own data" completion result = await completeBYOD(prompt); } catch (e: unknown) { console.error('Error parsing JSON:', e); } res.json(result); });
開啟 server/openAI.ts 檔案,然後找出 函式
completeBYOD()
。async function completeBYOD(userPrompt: string): Promise<string> { const systemPrompt = 'You are an AI assistant that helps people find information.'; // Pass that we're using Cognitive Search along with Azure OpenAI. return await callOpenAI(systemPrompt, userPrompt, 0, true); }
此函式具有下列功能:
- 參數
userPrompt
包含使用者輸入至聊天說明對話框的資訊。 - 變數
systemPrompt
會定義 AI 助理 設計來協助人員尋找資訊。 -
callOpenAI()
用來呼叫 Azure OpenAI API 並傳回結果。 它會傳遞systemPrompt
和userPrompt
值以及下列參數:-
temperature
- 要包含在回應中的創意量。 在此情況下,使用者需要一致的 (較不具創意的) 答案,因此此值會設定為 0。 -
useBYOD
- 布爾值,指出是否搭配 Azure OpenAI 使用認知搜尋。 在此情況下,它會設定為true
,以便使用認知搜尋功能。
-
- 參數
函
callOpenAI()
式會接受用來判斷要呼叫哪一個useBYOD
OpenAI 函式的參數。 在此情況下,它會將 設定useBYOD
為true
,以便呼叫 函getAzureOpenAIBYODCompletion()
式。function callOpenAI(systemPrompt: string, userPrompt: string, temperature = 0, useBYOD = false) { const isAzureOpenAI = OPENAI_API_KEY && OPENAI_ENDPOINT && OPENAI_MODEL; if (isAzureOpenAI && useBYOD) { // Azure OpenAI + Cognitive Search: Bring Your Own Data return getAzureOpenAIBYODCompletion(systemPrompt, userPrompt, temperature); } if (isAzureOpenAI) { // Azure OpenAI return getAzureOpenAICompletion(systemPrompt, userPrompt, temperature); } // OpenAI return getOpenAICompletion(systemPrompt, userPrompt, temperature); }
在 server/openAI.ts 中找到函
getAzureOpenAIBYODCompletion()
式。 這與您稍早檢查的getAzureOpenAICompletion()
函式相當類似,但會顯示為個別的函式,以醒目提示 Azure OpenAI 中提供「攜帶您自己的數據」案例特有的幾個主要差異。此值
fetchUrl
在 URL 中包含區extensions
段,而標準 Azure OpenAI API 的 URL 則不會。const fetchUrl = `${OPENAI_ENDPOINT}/openai/deployments/${OPENAI_MODEL}/extensions/chat/completions?api-version=${OPENAI_API_VERSION}`;
屬性
dataSources
會新增至messageData
傳送至 Azure OpenAI 的物件。 屬性dataSources
包含稍早在本練習中新增至.env
檔案的認知搜尋資源的endpoint
、key
和indexName
值。const messageData: ChatGPTData = { max_tokens: 1024, temperature, messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt } ], // Adding BYOD data source so that Cognitive Search is used with Azure OpenAI dataSources: [ { type: 'AzureCognitiveSearch', parameters: { endpoint: AZURE_COGNITIVE_SEARCH_ENDPOINT, key: AZURE_COGNITIVE_SEARCH_KEY, indexName: AZURE_COGNITIVE_SEARCH_INDEX } } ] };
物件
headersBody
包含chatpgpt_url
和chatgpt_key
屬性,這些屬性會在取得認知搜尋結果之後用來呼叫 Azure OpenAI。const headersBody: OpenAIHeadersBody = { method: 'POST', headers: { 'Content-Type': 'application/json', 'api-key': OPENAI_API_KEY, chatgpt_url: fetchUrl.replace('extensions/', ''), chatgpt_key: OPENAI_API_KEY }, body: JSON.stringify(messageData), };
Azure OpenAI 所傳回的回應包含和 角色
tool
assistant
的兩個雜亂。 範例應用程式會使用 的第二則訊息搭配 的role
assistant
,為使用者提供他們所要求的資訊。 如果您想要提供用來建立回應 (檔的其他資訊,如稍早在 Azure AI Studio 遊樂場) 中所見,您可以使用包含url
檔 () 的第一則訊息。{ "id": "12345678-1a2b-3c4e5f-a123-12345678abcd", "model": "", "created": 1684304924, "object": "chat.completion", "choices": [ { "index": 0, "messages": [ { "role": "tool", "content": "{\"citations\": [{\"content\": \"\\nCognitive Services are cloud-based artificial intelligence (AI) services...\", \"id\": null, \"title\": \"What is Cognitive Services\", \"filepath\": null, \"url\": null, \"metadata\": {\"chunking\": \"orignal document size=250. Scores=0.4314117431640625 and 1.72564697265625.Org Highlight count=4.\"}, \"chunk_id\": \"0\"}], \"intent\": \"[\\\"Learn about Azure Cognitive Services.\\\"]\"}", "end_turn": false }, { "role": "assistant", "content": " \nAzure Cognitive Services are cloud-based artificial intelligence (AI) services that help developers build cognitive intelligence into applications without having direct AI or data science skills or knowledge. [doc1]. Azure Machine Learning is a cloud service for accelerating and managing the machine learning project lifecycle. [doc1].", "end_turn": true } ] } ] }
在中使用
getAzureOpenAIBYODCompletion()
下列程式代碼來存取訊息。 雖然此範例中並未使用引文,但會記錄到主控台,因此您可以看到傳回的數據類型。const completion = await fetchAndParse(fetchUrl, headersBody); console.log(completion); if (completion.error) { console.error('Azure OpenAI BYOD Error: \n', completion.error); return completion.error.message; } const citations = (completion.choices[0]?.messages[0]?.content?.trim() ?? '') as string; console.log('Azure OpenAI BYOD Citations: \n', citations); let content = (completion.choices[0]?.messages[1]?.content?.trim() ?? '') as string; console.log('Azure OpenAI BYOD Output: \n', content); return content;
繼續進行下一個練習之前,要考慮的最後幾點:
- Azure OpenAI 的「攜帶您自己的數據」功能目前為預覽狀態。 目前不建議在生產應用程式中使用它。
- 範例應用程式會在 Azure 認知搜尋 中使用單一索引。 您可以搭配 Azure OpenAI 使用多個索引和數據源。
dataSources
函式中的getAzureOpenAIBYODCompletion()
屬性可以更新為視需要包含多個數據源。 - 安全性必須使用這種類型的案例仔細評估。 使用者應該無法詢問問題,並從無法存取的檔取得結果。
既然您已瞭解 Azure OpenAI、提示、完成,以及如何使用自己的數據,讓我們繼續進行下一個練習,以瞭解如何使用通訊功能來增強應用程式。 如果您想要深入瞭解 Azure OpenAI,請檢視 開始使用 Azure OpenAI 服務 訓練內容。 如需搭配 Azure OpenAI 使用您自己的數據的其他資訊,請參閱 數據檔中的 Azure OpenAI 。
通訊:建立 Azure 通訊服務 資源
有效的通訊對於成功的自定義商務應用程式而言非常重要。 您可以使用 Azure 通訊服務 (ACS) ,將通話、即時聊天、音訊/視訊通話和電子郵件和簡訊等功能新增至您的應用程式。 稍早,您已瞭解 Azure OpenAI 如何為電子郵件和簡訊產生完成。 現在,您將瞭解如何傳送訊息。 ACS 和 OpenAI 可以藉由簡化通訊、改善互動,以及提升商務生產力,來增強您的應用程式。
在本練習中,您將會:
- 建立 Azure 通訊服務 (ACS) 資源。
- 新增具有通話和SMS功能的免付費電話號碼。
- 線上電子郵件網域。
- 使用 ACS 資源的值來更新專案的 .env 檔案。
建立 Azure 通訊服務 資源
如果您尚未登入,請瀏覽瀏覽器中的 Azure 入口網站 並登入。
在頁面頂端的搜尋列中輸入通訊服務,然後從出現的選項中選取 [通訊服務]。
選取工具列中的 [ 建立 ]。
執行下列工作:
- 選取 Azure 訂閱。
- 如果資源群組) 不存在,請選取資源群組, (建立新的資源群組。
- 輸入 ACS 資源名稱。 它必須是唯一值。
- 選取數據位置。
選取 [檢閱 + 建立 ],後面接著 [ 建立]。
您已成功建立新的 Azure 通訊服務 資源! 接下來,您將啟用通話和簡訊功能。 您也會將電子郵件網域連線到資源。
啟用通話和簡訊功能
新增電話號碼,並確定電話號碼已啟用通話功能。 您將使用此電話號碼從應用程式撥打電話。
從 [資源] 選單中選取
Phone numbers
。選取
+ Get
工具列 (,或選取 [ 取得數位 ] 按鈕) ,然後輸入下列資訊:-
國家或地區:
United States
-
使用案例:選取
An application will be making calls or sending SMS mesages
- 號碼類型:免付費電話
注意
Azure 訂用帳戶上需要信用卡才能建立免付費電話號碼。 如果您沒有檔案上的卡片,您可以略過新增電話號碼,並跳至聯機電子郵件網域的練習下一節。 您仍然可以使用應用程式,但無法撥打電話號碼。
-
通話:
Make calls
-
SMS:
Send and receive SMS
-
國家或地區:
選取 [下一步:數位]。
選取前置 詞 (, 例如
877
) ,並將 Quantity 保留為 1。 選取 [搜尋]。一旦顯示免付費電話號碼,請選取 [ 下一步:摘要]。
檢閱詳細數據,然後選取 [下單] 以將電話號碼新增至 ACS 資源。
建立電話號碼之後,請選取它以移至 [功能] 面板。 請確定已設定下列值:
- 在 [ 呼叫] 區段中,選取
Make calls
。 - 在 [SMS] 區段中,選取
Send and receive SMS
。 - 選取 [儲存]。
- 在 [ 呼叫] 區段中,選取
將電話號碼值複製到檔案中,以供稍後使用。
線上 Email 網域
執行下列工作,為您的 ACS 資源建立連線的電子郵件網域,以便傳送電子郵件。 這會用來從應用程式傳送電子郵件。
- 從 [資源] 功能選取 [ 網域 ]。
- 從工具列中選取 [連線網域 ]。
- 選取您的 訂 用帳戶和資源 群組。
- 在 [Email 服務] 下拉式清單中,選取
Add an email service
。 - 提供電子郵件服務的名稱,例如
acs-demo-email-service
。 - 選取
Review + create
後面Create
接著 。 - 部署完成後,請選取
Go to resource
,然後選取1-click add
以新增免費的 Azure 子域。 - 新增子域之後 (需要一些時間才能部署) ,請加以選取。
- 一旦您在 AzureManagedDomain 畫面上,請從 [資源] 功能表中選取 [ MailFrom 位址 ]。
- 將 MailFrom 值複製到檔案。 您稍後會在更新 .env 檔案時使用它。
- 返回 至您的 Azure 通訊服務 資源,然後從 [資源] 選單中選取
Domains
。 - 選取
Add domain
並輸入MailFrom
上一個步驟中的值, (確保您選取正確的訂用帳戶、資源群組和電子郵件服務) 。 選取Connect
按鈕。
.env
更新檔案
現在您的 ACS 電話號碼已 (已啟用通話和 SMS) 和電子郵件網域,請更新專案中 .env 檔案中的下列機碼/值:
ACS_CONNECTION_STRING=<ACS_CONNECTION_STRING> ACS_PHONE_NUMBER=<ACS_PHONE_NUMBER> ACS_EMAIL_ADDRESS=<ACS_EMAIL_ADDRESS> CUSTOMER_EMAIL_ADDRESS=<EMAIL_ADDRESS_TO_SEND_EMAIL_TO> CUSTOMER_PHONE_NUMBER=<UNITED_STATES_BASED_NUMBER_TO_SEND_SMS_TO>
ACS_CONNECTION_STRING
connection string
:ACS 資源的 [金鑰] 區段的值。ACS_PHONE_NUMBER
:將您的免付費號碼指派給ACS_PHONE_NUMBER
值。ACS_EMAIL_ADDRESS
:指派電子郵件 “MailTo” 位址值。CUSTOMER_EMAIL_ADDRESS
:指派您想要從應用程式 (傳送電子郵件的電子郵件地址,因為應用程式資料庫中的客戶數據只是範例數據) 。 您可以使用個人電子郵件位址。CUSTOMER_PHONE_NUMBER
:您必須在目前) 提供 美國 型電話號碼 (,因為其他國家/地區需要額外的驗證才能傳送簡訊。 如果您沒有以美國為基礎的數位,您可以將它保留空白。
啟動/重新啟動應用程式和 API 伺服器
根據您完成到此時間點的練習,執行下列步驟 之一 :
如果您在先前的練習中啟動資料庫、API 伺服器和網頁伺服器,您必須停止 API 伺服器和網頁伺服器,然後重新啟動它們以挑選 .env 檔案變更。 您可以讓資料庫保持執行狀態。
找出執行 API 伺服器和網頁伺服器的終端機視窗,然後按 CTRL + C 來停止它們。 在每一個終端機視窗中輸入
npm start
,然後按 Enter 鍵,以再次啟動它們。 繼續進行下一個練習。如果您尚未啟動資料庫、API 伺服器和 Web 伺服器,請完成下列步驟:
在下列步驟中,您將在 Visual Studio Code 中建立三個終端機視窗。
以滑鼠右鍵按兩下 Visual Studio Code 檔案清單中的 .env 檔案,然後選取 [在整合式終端機中開啟]。 在繼續之前,請確定您的終端機位於專案的根目錄 - openai-acs-msgraph 。
從下列 其中一 個選項中選擇,以啟動 PostgreSQL 資料庫:
如果您已安裝並執行 Docker Desktop ,請在終端機視窗中執行
docker-compose up
,然後按 Enter。如果您已安裝 並執行 Podman-compose 的 Podman ,請在終端機視窗中執行
podman-compose up
,然後按 Enter。若要直接使用 Docker Desktop、Podman、nerdctl 或您已安裝的另一個容器運行時間來執行 PostgreSQL 容器,請在終端機視窗中執行下列命令:
Mac、Linux 或 Windows 子系統 Linux 版 (WSL) :
[docker | podman | nerdctl] run --name postgresDb -e POSTGRES_USER=web -e POSTGRES_PASSWORD=web-password -e POSTGRES_DB=CustomersDB -v $(pwd)/data:/var/lib/postgresql/data -p 5432:5432 postgres
使用 PowerShell 的 Windows:
[docker | podman] run --name postgresDb -e POSTGRES_USER=web -e POSTGRES_PASSWORD=web-password -e POSTGRES_DB=CustomersDB -v ${PWD}/data:/var/lib/postgresql/data -p 5432:5432 postgres
資料庫容器啟動之後,請按 + [Visual Studio Code 終端機] 工具列中的圖示,以建立第二個終端機視窗。
cd
進入 伺服器/typescript 資料夾,然後執行下列命令來安裝相依性並啟動 API 伺服器。npm install
npm start
在 + [Visual Studio Code 終端機] 工具列中再次按下圖示,以建立第三個終端機視窗。
cd
進入 客戶端 資料夾,然後執行下列命令來安裝相依性並啟動 Web 伺服器。npm install
npm start
瀏覽器將會啟動,並帶您前往 http://localhost:4200。
通訊:撥打電話
將 Azure 通訊服務 的電話通話功能整合到自定義企業營運 (LOB) 應用程式,可為企業及其使用者提供數個主要優點:
- 直接從 LOB 應用程式內,讓員工、客戶和合作夥伴之間能夠順暢且實時的通訊,而不需要在多個平臺或裝置之間切換。
- 增強用戶體驗,並改善整體作業效率。
- 協助快速解決問題,因為使用者可以快速且輕鬆地與相關的支援小組或主題專家聯繫。
在本練習中,您將會:
- 探索應用程式中的通話功能。
- 逐步解說程序代碼,以瞭解如何建置通話功能。
使用通話功能
在上一個練習中,您已建立 Azure 通訊服務 (ACS) 資源,並啟動資料庫、Web 伺服器和 API 伺服器。 您也會更新 .env 檔案中的下列值。
ACS_CONNECTION_STRING=<ACS_CONNECTION_STRING> ACS_PHONE_NUMBER=<ACS_PHONE_NUMBER> ACS_EMAIL_ADDRESS=<ACS_EMAIL_ADDRESS> CUSTOMER_EMAIL_ADDRESS=<EMAIL_ADDRESS_TO_SEND_EMAIL_TO> CUSTOMER_PHONE_NUMBER=<UNITED_STATES_BASED_NUMBER_TO_SEND_SMS_TO>
繼續之前,請確定您已完成 上一個練習 。
返回 瀏覽器 () http://localhost:4200 ,找出 datagrid,然後選取 [連絡客戶],然後在第一個數據列中選取 [連絡客戶]。
通話元件將會新增至標頭。 輸入您的電話號碼 (確定以 + 開頭,並包含國家/地區代碼) ,然後選取 [ 通話]。 系統會提示您允許存取麥克風。
選取 [停止回應 ] 結束通話。 選取 [關閉 ] 以關閉通話元件。
探索通話碼
提示
如果您使用 Visual Studio Code,您可以直接選取下列項目來開啟檔案:
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
然後輸入您要開啟的檔案名。
開啟 customers-list.component.ts 檔案。 檔案的完整路徑是 client/src/app/customers-list/customers-list.component.ts。
請注意,
openCallDialog()
使用事件總線傳送CustomerCall
訊息和客戶電話號碼。openCallDialog(data: Phone) { this.eventBus.emit({ name: Events.CustomerCall, value: data }); }
注意
如果您想要深入瞭解,可以在 eventbus.service.ts 檔案中找到事件總線程序代碼。 檔案的完整路徑是 client/src/app/core/eventbus.service.ts。
標頭元件的函
ngOnInit()
式會訂閱事件總線所傳送的事件,CustomerCall
並顯示通話元件。 您可以在 header.component.ts 中找到此程式碼。ngOnInit() { this.subscription.add( this.eventBus.on(Events.CustomerCall, (data: Phone) => { this.callVisible = true; // Show phone call component this.callData = data; // Set phone number to call }) ); }
開啟 phone-call.component.ts。 花點時間來指數程序代碼。 檔案的完整路徑是 client/src/app/phone-call/phone-call.component.ts。 請注意下列主要功能:
- 在 中
ngOnInit()
呼叫acsService.getAcsToken()
函式,以擷取 Azure 通訊服務 存取令牌。 - 將「電話撥號程式」新增至頁面。 您可以按下標頭中的電話號碼輸入來查看撥號程式。
- 分別使用和函式來
startCall()
啟動和endCall()
結束呼叫。
- 在 中
在查看撥打電話的程序代碼之前,讓我們先檢查如何擷取 ACS 存取令牌,以及如何建立通話物件。 在 phone-call.component.ts 中找到 函
ngOnInit()
式。async ngOnInit() { if (ACS_CONNECTION_STRING) { this.subscription.add( this.acsService.getAcsToken().subscribe(async (user: AcsUser) => { const callClient = new CallClient(); const tokenCredential = new AzureCommunicationTokenCredential(user.token); this.callAgent = await callClient.createCallAgent(tokenCredential); }) ); } }
此函式會執行下列動作:
- 藉由呼叫
acsService.getAcsToken()
函式來擷取 ACS userId 和存取令牌。 - 擷取存取令牌之後,程式代碼會執行下列動作:
- 建立的新實例
CallClient
,並使用AzureCommunicationTokenCredential
存取令牌。 - 使用
CallClient
和AzureCommunicationTokenCredential
物件建立 的新實例CallAgent
。 稍後您會看到CallAgent
用來開始和結束通話。
- 建立的新實例
- 藉由呼叫
開啟 acs.services.ts 並找出函式
getAcsToken()
。 檔案的完整路徑是 client/src/app/core/acs.service.ts。 函式會對 API 伺服器所公開的路由提出 HTTP GET 要求/acstoken
。getAcsToken(): Observable<AcsUser> { return this.http.get<AcsUser>(this.apiUrl + 'acstoken') .pipe( catchError(this.handleError) ); }
名為的
createACSToken()
API 伺服器函式會擷取 userId 和存取令牌,並將它傳回給用戶端。 您可以在 伺服器/typescript/acs.ts 檔案中找到。import { CommunicationIdentityClient } from '@azure/communication-identity'; const connectionString = process.env.ACS_CONNECTION_STRING as string; async function createACSToken() { if (!connectionString) return { userId: '', token: '' }; const tokenClient = new CommunicationIdentityClient(connectionString); const user = await tokenClient.createUser(); const userToken = await tokenClient.getToken(user, ["voip"]); return { userId: user.communicationUserId, ...userToken }; }
此函式會執行下列動作:
- 檢查 ACS
connectionString
值是否可用。 如果沒有,則傳回具有空白userId
和token
的物件。 - 建立 的新實例
CommunicationIdentityClient
,並將值傳遞給connectionString
它。 - 使用
tokenClient.createUser()
建立新的使用者。 - 使用取得具有 「voip」 範圍
tokenClient.getToken()
之新使用者的令牌。 - 傳回包含
userId
和token
值的物件。
- 檢查 ACS
既然您已瞭解如何擷取 userId 和令牌,請返回
phone-call.component.ts
並找出函startCall()
式。在通話元件中選取 [通話 ] 時,會呼叫此函式。 它會使用
CallAgent
稍早所述的 對象來啟動呼叫。 函式callAgent.startCall()
會接受 物件,此物件表示要呼叫的號碼,以及用來撥打電話的 ACS 電話號碼。startCall() { this.call = this.callAgent?.startCall( [{ phoneNumber: this.customerPhoneNumber }], { alternateCallerId: { phoneNumber: this.fromNumber } }); console.log('Calling: ', this.customerPhoneNumber); console.log('Call id: ', this.call?.id); this.inCall = true; }
stopCall()
在通話元件中選取 [停止回應] 時,會呼叫 函式。endCall() { if (this.call) { this.call.hangUp({ forEveryone: true }); this.call = undefined; this.inCall = false; } else { this.hangup.emit(); } }
如果呼叫正在進行中,則會
call.hangUp()
呼叫 函式以結束呼叫。 如果沒有進行通話,事件hangup
就會發出給標頭父元件,以隱藏通話元件。繼續進行下一個練習之前,讓我們先檢閱本練習中涵蓋的重要概念:
- ACS userId 和存取令牌是使用 函
acsService.getAcsToken()
式從 API 伺服器擷取。 - 令牌是用來建立
CallClient
和CallAgent
物件。 - 對像是
CallAgent
用來分別呼叫 和函式來啟動和callAgent.hangUp()
結束呼叫callAgent.startCall()
。
- ACS userId 和存取令牌是使用 函
既然您已瞭解如何將通話整合到應用程式中,讓我們將焦點切換為使用 Azure 通訊服務 來傳送電子郵件和簡訊。
通訊:傳送 Email 和SMS訊息
除了通話之外,Azure 通訊服務 也可以傳送電子郵件和簡訊。 當您想要直接從應用程式將訊息傳送給客戶或其他使用者時,這非常有用。
在本練習中,您將會:
- 探索如何從應用程式傳送電子郵件和簡訊。
- 逐步解說程序代碼,以瞭解如何實作電子郵件和SMS功能。
使用 Email和SMS功能
在先前的練習中,您已建立 Azure 通訊服務 (ACS) 資源,並啟動資料庫、Web 伺服器和 API 伺服器。 您也會更新 .env 檔案中的下列值。
ACS_CONNECTION_STRING=<ACS_CONNECTION_STRING> ACS_PHONE_NUMBER=<ACS_PHONE_NUMBER> ACS_EMAIL_ADDRESS=<ACS_EMAIL_ADDRESS> CUSTOMER_EMAIL_ADDRESS=<EMAIL_ADDRESS_TO_SEND_EMAIL_TO> CUSTOMER_PHONE_NUMBER=<UNITED_STATES_BASED_NUMBER_TO_SEND_SMS_TO>
請確定您已完成 練習 ,再繼續進行。
返回 瀏覽器 (http://localhost:4200) ,然後選取 [連絡客戶],然後在第一列選取 [Email/SMS 客戶]。
選取 [Email/SMS] 索引標籤,然後執行下列工作:
- 輸入 Email 主旨和本文,然後選取 [傳送 Email] 按鈕。
- 輸入SMS訊息,然後選取 [ 傳送簡訊] 按鈕。
確認您收到電子郵件和簡訊。 提醒您,電子郵件訊息會傳送至 所定義的
CUSTOMER_EMAIL_ADDRESS
值,而SMS訊息將會傳送至 .env 檔案中定義的CUSTOMER_PHONE_NUMBER
值。 如果您無法提供 美國 型電話號碼來用於SMS訊息,您可以略過該步驟。注意
如果您在收件匣中看不到您在 .env 檔案中定義的
CUSTOMER_EMAIL_ADDRESS
地址的電子郵件訊息,請檢查您的垃圾郵件資料夾。
探索 Email 程序代碼
提示
如果您使用 Visual Studio Code,您可以直接選取下列項目來開啟檔案:
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
然後輸入您要開啟的檔案名。
開啟 customers-list.component.ts 檔案。 檔案的完整路徑是 client/src/app/customers-list/customers-list.component.ts。
當您在 datagrid 中選取 [連絡客戶],後面接著 [Email/SMS 客戶] 時,
customer-list
元件會顯示對話框。 這是由openEmailSmsDialog()
customer-list.component.ts 檔案中的函式所處理。openEmailSmsDialog(data: any) { if (data.phone && data.email) { // Create the data for the dialog let dialogData: EmailSmsDialogData = { prompt: '', title: `Contact ${data.company}`, company: data.company, customerName: data.first_name + ' ' + data.last_name, customerEmailAddress: data.email, customerPhoneNumber: data.phone } // Open the dialog const dialogRef = this.dialog.open(EmailSmsDialogComponent, { data: dialogData }); // Subscribe to the dialog afterClosed observable to get the dialog result this.subscription.add( dialogRef.afterClosed().subscribe((response: EmailSmsDialogData) => { console.log('SMS dialog result:', response); if (response) { dialogData = response; } }) ); } else { alert('No phone number available.'); } }
函
openEmailSmsDialog()
式會執行下列工作:- 檢查
data
物件 (是否代表 datagrid 中的數據列) 包含phone
和email
屬性。 如果這樣做,它會建立dialogData
物件,其中包含要傳遞至對話框的資訊。 -
EmailSmsDialogComponent
開啟對話框,並將 對象傳遞dialogData
至該對話方塊。 -
afterClosed()
訂閱對話框的事件。 當對話框關閉時,就會引發此事件。 物件response
包含在對話框中輸入的資訊。
- 檢查
開啟 email-sms-dialog.component.ts 檔案。 檔案的完整路徑是 client/src/app/email-sms-dialog/email-sms-dialog.component.ts。
找出函式
sendEmail()
:sendEmail() { if (this.featureFlags.acsEmailEnabled) { // Using CUSTOMER_EMAIL_ADDRESS instead of this.data.email for testing purposes this.subscription.add( this.acsService.sendEmail(this.emailSubject, this.emailBody, this.getFirstName(this.data.customerName), CUSTOMER_EMAIL_ADDRESS /* this.data.email */) .subscribe(res => { console.log('Email sent:', res); if (res.status) { this.emailSent = true; } }) ); } else { this.emailSent = true; // Used when ACS email isn't enabled } }
函
sendEmail()
式會執行下列工作:- 檢查功能旗標是否
acsEmailEnabled
設定為true
。 此旗標會檢查環境變數是否有ACS_EMAIL_ADDRESS
指派的值。 - 如果
acsEmailEnabled
為 true,則會呼叫 函acsService.sendEmail()
式,並傳遞電子郵件主旨、本文、客戶名稱和客戶電子郵件位址。 因為資料庫包含範例數據,CUSTOMER_EMAIL_ADDRESS
所以會使用 環境變數,而不是this.data.email
。 在真實世界中,this.data.email
會使用值。 -
sendEmail()
訂閱服務中的acsService
函式。 此函式會傳回 RxJS 可觀察,其中包含來自用戶端服務的回應。 - 如果成功傳送電子郵件,屬性
emailSent
會設定為true
。
- 檢查功能旗標是否
為了提供更好的程式代碼封裝和重複使用, acs.service.ts等客戶端 服務會在整個應用程式中使用。 這可讓所有 ACS 功能合併到單一位置。
開啟 acs.service.ts 並找出 函式
sendEmail()
。 檔案的完整路徑是 client/src/app/core/acs.service.ts。sendEmail(subject: string, message: string, customerName: string, customerEmailAddress: string) : Observable<EmailSmsResponse> { return this.http.post<EmailSmsResponse>(this.apiUrl + 'sendemail', { subject, message, customerName, customerEmailAddress }) .pipe( catchError(this.handleError) ); }
中的
AcsService
函sendEmail()
式會執行下列工作:- 呼叫 函式,
http.post()
並將電子郵件主旨、訊息、客戶名稱和客戶電子郵件地址傳遞給函式。 函式會http.post()
傳回 RxJS 可觀察,其中包含來自 API 呼叫的回應。 - 使用 RxJS
catchError
運算子處理函式傳http.post()
回的任何錯誤。
- 呼叫 函式,
現在讓我們來檢查應用程式如何與 ACS 電子郵件功能互動。 開啟 acs.ts 檔案,然後找出 函
sendEmail()
式。 檔案的完整路徑是 伺服器/typescript/acs.ts。函
sendEmail()
式會執行下列工作:建立新的
EmailClient
物件,並將 ACS 連接字串 傳遞給它, (此值是從ACS_CONNECTION_STRING
環境變數擷取) 。const emailClient = new EmailClient(connectionString);
建立新的
EmailMessage
物件,並傳遞發件者、主旨、郵件和收件者資訊。const msgObject: EmailMessage = { senderAddress: process.env.ACS_EMAIL_ADDRESS as string, content: { subject: subject, plainText: message, }, recipients: { to: [ { address: customerEmailAddress, displayName: customerName, }, ], }, };
使用
emailClient.beginSend()
函式傳送電子郵件並傳回回應。 雖然函式只會在此範例中傳送給一位收件者,但beginSend()
函式也可以用來傳送給多個收件者。const poller = await emailClient.beginSend(msgObject);
等候
poller
對象發出訊號,並將回應傳送給呼叫端。
探索SMS代碼
返回 至您稍早開啟的 email-sms-dialog.component.ts 檔案。 檔案的完整路徑是 client/src/app/email-sms-dialog/email-sms-dialog.component.ts。
找出 函式
sendSms()
:sendSms() { if (this.featureFlags.acsPhoneEnabled) { // Using CUSTOMER_PHONE_NUMBER instead of this.data.customerPhoneNumber for testing purposes this.subscription.add( this.acsService.sendSms(this.smsMessage, CUSTOMER_PHONE_NUMBER /* this.data.customerPhoneNumber */).subscribe(res => { if (res.status) { this.smsSent = true; } }) ); } else { this.smsSent = true; } }
函
sendSMS()
式會執行下列工作:- 檢查功能旗標是否
acsPhoneEnabled
設定為true
。 此旗標會檢查環境變數是否有ACS_PHONE_NUMBER
指派的值。 - 如果
acsPhoneEnabled
為 true,則會呼叫 函acsService.SendSms()
式,並傳遞 SMS 訊息和客戶電話號碼。 因為資料庫包含範例數據,CUSTOMER_PHONE_NUMBER
所以會使用 環境變數,而不是this.data.customerPhoneNumber
。 在真實世界中,this.data.customerPhoneNumber
會使用值。 -
sendSms()
訂閱服務中的acsService
函式。 此函式會傳回 RxJS 可觀察,其中包含來自用戶端服務的回應。 - 如果成功傳送 SMS 訊息,它會將
smsSent
屬性設定為true
。
- 檢查功能旗標是否
開啟 acs.service.ts 並找出 函式
sendSms()
。 檔案的完整路徑是 client/src/app/core/acs.service.ts。sendSms(message: string, customerPhoneNumber: string) : Observable<EmailSmsResponse> { return this.http.post<EmailSmsResponse>(this.apiUrl + 'sendsms', { message, customerPhoneNumber }) .pipe( catchError(this.handleError) ); }
函
sendSms()
式會執行下列工作:- 呼叫 函式,
http.post()
並將訊息和客戶電話號碼傳遞給函式。 函式會http.post()
傳回 RxJS 可觀察,其中包含來自 API 呼叫的回應。 - 使用 RxJS
catchError
運算子處理函式傳http.post()
回的任何錯誤。
- 呼叫 函式,
最後,讓我們檢查應用程式如何與 ACS SMS 功能互動。 開啟 acs.ts 檔案。 檔案的完整路徑是 伺服器/typescript/acs.ts ,並找出函
sendSms()
式。函
sendSms()
式會執行下列工作:建立新的
SmsClient
物件,並將 ACS 連接字串 傳遞給它, (此值是從ACS_CONNECTION_STRING
環境變數擷取) 。const smsClient = new SmsClient(connectionString);
呼叫 函
smsClient.send()
式,並傳遞 ACS 電話號碼 (from
) 、客戶電話號碼 (to
) 和簡訊:const sendResults = await smsClient.send({ from: process.env.ACS_PHONE_NUMBER as string, to: [customerPhoneNumber], message: message }); return sendResults;
傳回呼叫端的回應。
您可以在下列文章中深入瞭解 ACS 電子郵件和 SMS 功能:
繼續進行下一個練習之前,讓我們先檢閱本練習中涵蓋的重要概念:
- acs.service.ts檔案會封裝用戶端應用程式所使用的 ACS 電子郵件和 SMS 功能。 它會處理對伺服器的 API 呼叫,並將回應傳回給呼叫端。
- 伺服器端 API 會使用 ACS
EmailClient
和SmsClient
對象來傳送電子郵件和簡訊。
既然您已瞭解如何傳送電子郵件和簡訊,讓我們將焦點切換為將組織數據整合到應用程式中。
組織數據:建立 Microsoft Entra ID 應用程式註冊
藉由將組織數據 (電子郵件、檔案、聊天和行事曆活動) 直接整合到您的自定義應用程式中,來增強用戶生產力。 藉由使用 Microsoft Graph API 和 Microsoft Entra ID,您可以順暢地擷取和顯示應用程式內的相關數據,減少使用者切換內容的需求。 無論是參考傳送給客戶的電子郵件、檢閱 Teams 訊息或存取檔案,使用者都可以快速找到所需的資訊,而不需要離開您的應用程式、簡化其決策制定程式。
在本練習中,您將會:
- 建立 Microsoft Entra ID 應用程式註冊,讓 Microsoft Graph 可以存取組織數據,並將其帶入應用程式。
- 從 Microsoft Teams 尋找
team
和channel
識別碼,以將聊天訊息傳送至特定頻道。 - 使用來自您 Microsoft Entra ID 應用程式註冊的值更新專案的 .env 檔案。
建立 Microsoft Entra ID 應用程式註冊
移至 [Azure 入口網站],然後選取 [Microsoft Entra ID]。
選取 [ 應用程式註冊] 索引 標籤,後面接著 [+ 新增註冊]。
填寫新的應用程式註冊窗體詳細數據,如下所示,然後選取 [ 註冊]:
- 名稱: microsoft-graph-app
- 支援的帳戶類型:任何組織目錄中的帳戶 (任何 Microsoft Entra ID 租使用者 - 多租使用者)
- 重新導向 URI:
- 選取[單頁應用程式 (SPA) ],然後在 [重新導向 URI] 欄位中輸入
http://localhost:4200
。
- 選取[單頁應用程式 (SPA) ],然後在 [重新導向 URI] 欄位中輸入
- 選取 [註冊] 以建立應用程式註冊。
在 [資源] 功能選取 [ 概觀 ],然後將
Application (client) ID
值複製到剪貼簿。
更新專案的 .env 檔案
在編輯器開啟 .env 檔案,並將
Application (client) ID
值指派給ENTRAID_CLIENT_ID
。ENTRAID_CLIENT_ID=<APPLICATION_CLIENT_ID_VALUE>
如果您想要啟用將訊息從應用程式傳送至 Teams 頻道的能力,請使用您的 Microsoft 365 開發租使用者帳戶登入 Microsoft Teams 。
登入之後,請展開小組,然後尋找您想要從應用程式傳送訊息的頻道。 例如,您可以選取 [公司 小組] 和 [ 一般 ] 頻道 (或任何您想要使用) 的小組/頻道。
在小組標頭中,按兩下三個點 (...) ,然後選取
Get link to team
。在彈出視窗中顯示的連結中,小組標識碼是 之後
team/
的字母和數位字串。 例如,在連結 “https://teams.microsoft.com/l/team/19%3ae9b9.../"” 中,小組標識符為 19%3ae9b9... 最多為下列/
字元。複製小組標識碼,並將它指派給
TEAM_ID
.env 檔案中。在通道標頭中,按兩下三個點 (...) ,然後選取
Get link to channel
。在彈出視窗中顯示的連結中,通道標識碼是 之後
channel/
的字母和數位字串。 例如,在連結 “https://teams.microsoft.com/l/channel/19%3aQK02.../", 信道標識符為 19%3aQK02... 最多為下列/
字元。複製通道標識碼,並將它指派給
CHANNEL_ID
.env 檔案中。繼續之前,請先儲存 env 檔案。
啟動/重新啟動應用程式和 API 伺服器
根據您完成到此時間點的練習,執行下列步驟 之一 :
如果您在先前的練習中啟動資料庫、API 伺服器和網頁伺服器,您必須停止 API 伺服器和網頁伺服器,然後重新啟動它們以挑選 .env 檔案變更。 您可以讓資料庫保持執行狀態。
找出執行 API 伺服器和網頁伺服器的終端機視窗,然後按 CTRL + C 來停止它們。 在每一個終端機視窗中輸入
npm start
,然後按 Enter 鍵,以再次啟動它們。 繼續進行下一個練習。如果您尚未啟動資料庫、API 伺服器和 Web 伺服器,請完成下列步驟:
在下列步驟中,您將在 Visual Studio Code 中建立三個終端機視窗。
以滑鼠右鍵按兩下 Visual Studio Code 檔案清單中的 .env 檔案,然後選取 [在整合式終端機中開啟]。 在繼續之前,請確定終端機位於專案的根目錄 openai-acs-msgraph 。
從下列 其中一個選項 中選擇以啟動 PostgreSQL 資料庫:
如果您已安裝並執行 Docker Desktop ,請在終端機視窗中執行
docker-compose up
,然後按 Enter。如果您已安裝 並執行 Podman-compose 的 Podman ,請在終端機視窗中執行
podman-compose up
,然後按 Enter。若要使用 Docker Desktop、Podman、nerdctl 或您已安裝的另一個容器運行時間直接執行 PostgreSQL 容器,請在終端機視窗中執行下列命令:
Mac、Linux 或 Windows 子系統 Linux 版 (WSL) :
[docker | podman | nerdctl] run --name postgresDb -e POSTGRES_USER=web -e POSTGRES_PASSWORD=web-password -e POSTGRES_DB=CustomersDB -v $(pwd)/data:/var/lib/postgresql/data -p 5432:5432 postgres
具有 PowerShell 的 Windows:
[docker | podman] run --name postgresDb -e POSTGRES_USER=web -e POSTGRES_PASSWORD=web-password -e POSTGRES_DB=CustomersDB -v ${PWD}/data:/var/lib/postgresql/data -p 5432:5432 postgres
資料庫容器啟動時,請按 + [Visual Studio Code 終端機] 工具列中的圖示來建立第二個終端機視窗。
cd
進入 伺服器/typescript 資料夾,然後執行下列命令來安裝相依性並啟動 API 伺服器。npm install
npm start
+在 [Visual Studio Code 終端機] 工具列中再次按下圖示,以建立第三個終端機視窗。
cd
進入 客戶端 資料夾,然後執行下列命令來安裝相依性並啟動網頁伺服器。npm install
npm start
瀏覽器將會啟動,而您將前往 http://localhost:4200。
組織數據:登入使用者並取得存取令牌
用戶必須向 Microsoft Entra ID 進行驗證,Microsoft Graph 才能存取組織數據。 在此練習中,您將瞭解如何使用 Microsoft Graph 工具組的 mgt-login
元件來驗證使用者並擷取存取令牌。 然後,可以使用存取令牌來呼叫 Microsoft Graph。
注意
如果您不熟悉 Microsoft Graph,您可以在 Microsoft Graph 基本概 念學習路徑中深入瞭解。
在本練習中,您將會:
- 瞭解如何將 Microsoft Entra ID 應用程式與 Microsoft Graph 工具組產生關聯,以便用來驗證使用者及擷取組織數據。
- 瞭解範圍的重要性。
- 瞭解 Microsoft Graph 工具組的 mgt-login 元件如何用來驗證使用者並擷取存取令牌。
使用登入功能
在上一個練習中,您已在 Microsoft Entra ID 中建立應用程式註冊,並啟動應用程式伺服器和 API 伺服器。 您也會更新檔案中的
.env
下列值。ENTRAID_CLIENT_ID=<APPLICATION_CLIENT_ID_VALUE> TEAM_ID=<TEAMS_TEAM_ID> CHANNEL_ID=<TEAMS_CHANNEL_ID>
請先確定您已完成 先前的練習 ,再繼續進行。
返回 瀏覽器 (http://localhost:4200) ,選取標頭中的 [登入],然後從您的 Microsoft 365 開發人員租使用者使用系統管理員用戶帳戶登入。
提示
使用您的 Microsoft 365 開發人員租用戶系統管理員帳戶登入。 您可以移至 Microsoft 365 系統管理中心,以檢視開發人員租使用者中的其他使用者。
如果您第一次登入應用程式,系統會提示您同意應用程式所要求的許可權。 您將在下一節探索程序代碼時,深入瞭解這些許可權 (也稱為「範圍」) 。 選取 [接受] 以繼續操作。
登入之後,您應該會看到標頭中顯示的用戶名稱。
探索登入程序代碼
既然您已登入,讓我們看看用來登入使用者並擷取存取令牌和使用者配置檔的程序代碼。 您將了解屬於 Microsoft Graph 工具組一部分的 mgt-login Web 元件。
提示
如果您使用 Visual Studio Code,您可以選取下列專案來直接開啟檔案:
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
然後輸入您要開啟的檔案名。
開啟 用戶端/package.json ,並注意到套件
@microsoft/mgt
包含在相依性中。 此套件包含 MSAL (Microsoft 驗證連結庫) 提供者功能,以及可用來登入使用者及擷取及顯示組織數據的 Web 元件,例如 mgt-login 和其他元件。若要使用 mgt-login 元件來登入使用者,Microsoft Entra ID 應用程式的用戶端識別碼 (儲存在 .env 檔案中,因為
ENTRAID_CLIENT_ID
必須參考並使用) 。開啟 graph.service.ts 並找出 函
init()
式。 檔案的完整路徑是 client/src/app/core/graph.service.ts。 您會看見下列程式碼:Providers.globalProvider = new Msal2Provider({ clientId: ENTRAID_CLIENT_ID, // retrieved from .env file scopes: ['User.Read', 'Presence.Read', 'Chat.ReadWrite', 'Calendars.Read', 'ChannelMessage.Read.All', 'ChannelMessage.Send', 'Files.Read.All', 'Mail.Read'] });
此程式代碼會建立新的
Msal2Provider
物件,從您的應用程式註冊傳遞 Microsoft Entra ID用戶端識別碼,以及scopes
應用程式將要求存取權的 。scopes
用來要求存取應用程式將存取的 Microsoft Graph 資源。Msal2Provider
建立對象之後,它會指派給Providers.globalProvider
Microsoft Graph 工具元件用來從 Microsoft Graph 擷取數據的物件。在編輯器中開啟 header.component.html ,然後找出 mgt-login 元件。 檔案的完整路徑是 client/src/app/header/header.component.html。
<mgt-login *ngIf="featureFlags.microsoft365Enabled" class="mgt-dark" (loginCompleted)="loginCompleted()"></mgt-login>
mgt-login 元件可讓使用者登入和存取令牌擷取,以便與 Microsoft Graph 搭配使用。 成功登入時,
loginCompleted
會觸發 事件,然後呼叫 函loginCompleted()
式。 雖然 mgt-login 用於此範例中的 Angular 元件,但它與任何 Web 應用程式相容。mgt-login 元件的顯示取決於
featureFlags.microsoft365Enabled
設定為true
的值。 此自定義旗標會檢查環境變數是否存在ENTRAID_CLIENT_ID
,以確認應用程式已正確設定,且能夠針對 Microsoft Entra ID 進行驗證。 系統會新增 旗標,以容納使用者只選擇在教學課程中完成 AI 或通訊練習的情況,而不是遵循整個順序。開啟 header.component.ts 並找出 函式
loginCompleted
。 當發出事件並使用 來擷取已登入使用者配置檔Providers.globalProvider
時loginCompleted
,會呼叫此函式。async loginCompleted() { const me = await Providers.globalProvider.graph.client.api('me').get(); this.userLoggedIn.emit(me); }
在此範例中,會呼叫 Microsoft Graph
me
API 以擷取其使用者配置檔, (me
代表目前登入的使用者) 。 程式this.userLoggedIn.emit(me)
代碼語句會從元件發出事件,以將配置檔數據傳遞至父元件。 在此案例中,父元件 是app.component.ts 檔案,這是應用程式的根元件。若要深入瞭解 mgt-login 元件,請流覽 Microsoft Graph 工具組 檔。
既然您已登入應用程式,讓我們看看如何擷取組織數據。
組織數據:擷取檔案、聊天和傳送訊息至Teams
在現今的數字環境中,使用者會使用各種組織數據,包括電子郵件、聊天、檔案、行事曆事件等等。 這可能會導致頻繁的內容轉移-在工作或應用程式之間切換,這可能會中斷焦點並減少生產力。 例如,處理項目的使用者可能需要從目前的應用程式切換至 Outlook,以在電子郵件中尋找重要詳細數據,或切換至 商務用 OneDrive 以尋找相關檔案。 這個回溯動作會中斷焦點,並浪費時間,更適合手邊的工作。
為了提升效率,您可以將組織數據直接整合到使用者每天使用的應用程式。 藉由將組織數據帶入您的應用程式,使用者可以更順暢地存取和管理資訊,將內容轉移降至最低,並提升生產力。 此外,這項整合提供寶貴的見解和內容,讓用戶能夠做出明智的決策並更有效率地運作。
在本練習中,您將會:
- 瞭解 Microsoft Graph 工具組中 的 mgt-search-results Web 元件如何用來搜尋檔案。
- 瞭解如何直接呼叫 Microsoft Graph,以從 Microsoft Teams 擷取 商務用 OneDrive 和聊天訊息的檔案。
- 瞭解如何使用 Microsoft Graph 將聊天訊息傳送至 Microsoft Teams 頻道。
注意
mgt-search-results 元件目前處於預覽狀態,而且可能會變更。 除了示範 如何使用 mgt-search-results 之外,練習也會示範如何使用 Microsoft Graph 直接執行相同的工作。
使用組織數據功能
在先前的練習中,您已在 Microsoft Entra ID 中建立應用程式註冊,並啟動應用程式伺服器和 API 伺服器。 您也會更新檔案中的
.env
下列值。ENTRAID_CLIENT_ID=<APPLICATION_CLIENT_ID_VALUE> TEAM_ID=<TEAMS_TEAM_ID> CHANNEL_ID=<TEAMS_CHANNEL_ID>
請先確定您已完成 先前的練習 ,再繼續進行。
返回 至瀏覽器 (http://localhost:4200) 。 如果您尚未登入,請選取標頭中的 [ 登入 ],然後從您的 Microsoft 365 開發人員租使用者使用使用者登入。
注意
除了驗證使用者之外, mgt-login Web 元件也會擷取 Microsoft Graph 可用來存取檔案、聊天、電子郵件、行事歷事件和其他組織數據的存取令牌。 存取權杖包含範圍 (權限) ,例如
Chat.ReadWrite
您稍早看到的、Files.Read.All
和其他專案:Providers.globalProvider = new Msal2Provider({ clientId: ENTRAID_CLIENT_ID, // retrieved from .env file scopes: ['User.Read', 'Presence.Read', 'Chat.ReadWrite', 'Calendars.Read', 'ChannelMessage.Read.All', 'ChannelMessage.Send', 'Files.Read.All', 'Mail.Read'] });
選取 datagrid 中 Adatum Corporation 數據列的 [檢視相關內容]。 這會導致使用 Microsoft Graph 擷取組織數據,例如檔案、聊天、電子郵件和行事曆事件。 數據載入之後,它會顯示在索引卷標式介面的 datagrid 下方。 請務必提及,您目前可能不會看到任何數據,因為您尚未為 Microsoft 365 開發人員租使用者中的使用者新增任何檔案、聊天、電子郵件或行事曆事件。 讓我們在下一個步驟中修正此問題。
您的 Microsoft 365 租使用者在此階段可能沒有任何 Adatum Corporation 的相關組織數據。 若要新增一些範例數據,請至少執行下列其中一個動作:
流覽 https://onedrive.com 並使用您的 Microsoft 365 開發人員租用戶認證登入來新增檔案。
- 選取左側導覽中的 [我的檔案 ]。
- 從功能表中選取 [上傳 ],然後選取 [ 資料夾 ]。
- 從您複製的項目中選取 openai-acs-msgraph/customer documents 資料夾。
流覽並使用您的 Microsoft 365 開發人員租用戶認證登入,以 https://teams.microsoft.com 新增聊天訊息和行事曆事件。
在左側導覽中選取 [Teams ]。
選取小組和頻道。
選取 [新增交談]。
輸入 為 Adatum Corporation 放置的新訂單 ,然後選取 [ 傳送 ] 按鈕。
您可以隨意新增其他聊天訊息,這些訊息提及應用程式中使用的其他公司,例如 Adventure Works Cycles、 Contoso Pharmaceuticals 和 Tailwind Traders。
選取左側導覽中的 [ 行事曆 ]。
選取 [新增會議]。
針對標題和本文輸入「與 Adatum Corporation 有關專案排程」。
選取 [儲存]。
流覽 https://outlook.com 並使用您的 Microsoft 365 開發人員租用戶認證登入來新增電子郵件。
選取 [新增郵件]。
在 [ 收 件者] 欄位中輸入您的個人電子郵件位址。
針對主旨輸入 Adatum Corporation 的新訂單 ,以及您想要用於本文的任何專案。
選取 [傳送]。
返回 至瀏覽器中的應用程式,然後重新整理頁面。 針對 Adatum Corporation 數據列再次選取 [檢視相關內容]。 您現在應該會看到索引標籤中顯示的數據,視您在上一個步驟中執行的工作而定。
讓我們探索可在應用程式中啟用組織數據功能的程序代碼。 為了擷取數據,應用程式的用戶端部分會使用您稍早查看的 mgt-login 元件所擷取的存取令牌來呼叫 Microsoft Graph API。
探索檔案搜尋程序代碼
提示
如果您使用 Visual Studio Code,您可以選取下列專案來直接開啟檔案:
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
然後輸入您要開啟的檔案名。
讓我們從查看如何從 商務用 OneDrive 擷取檔案數據開始。 開啟 files.component.html ,並花點時間查看程序代碼。 檔案的完整路徑是 client/src/app/files/files.component.html。
找出 mgt-search-results 元件,並記下下列屬性:
<mgt-search-results class="search-results" entity-types="driveItem" [queryString]="searchText" (dataChange)="dataChange($any($event))" />
mgt-search-results 元件是 Microsoft Graph 工具組的一部分,如名稱所示,它用來顯示來自 Microsoft Graph 的搜尋結果。 此元件在此範例中使用下列功能:
屬性
class
是用來指定search-results
CSS 類別應該套用至元件。屬性
entity-types
是用來指定要搜尋的數據類型。 在此情況下,值是driveItem
用來搜尋 商務用 OneDrive 中的檔案。屬性
queryString
是用來指定搜尋字詞。 在此情況下,當用戶選取 datagrid 中數據列的 [檢視相關內容] 時,此值會系結至searchText
傳遞至檔案元件的屬性。 周圍的queryString
方括弧表示屬性系結至searchText
值。當搜尋結果變更時,就會
dataChange
引發事件。 在此情況下,會在檔案元件中呼叫名為dataChange()
的客戶函式,並將事件數據傳遞至 函式。 周圍的dataChange
括號表示事件系結至 函dataChange()
式。由於未提供任何自定義範本,因此會使用內
mgt-search-results
建的預設範本來顯示搜尋結果。
使用 mgt-search-results 等元件的替代方法是使用程式代碼直接呼叫 Microsoft Graph API。 若要查看運作方式,請開啟 graph.service.ts 檔案,並找出 函
searchFiles()
式。 檔案的完整路徑是 client/src/app/core/graph.service.ts。您會注意到
query
參數會傳遞至 函式。 這是使用者選取 datagrid 中數據列的 [ 檢視相關內容 ] 時傳遞的搜尋字詞。 如果未傳遞任何搜尋字詞,則會傳回空陣列。async searchFiles(query: string) { const files: DriveItem[] = []; if (!query) return files; ... }
接著會建立篩選,以定義要執行的搜尋類型。 在此情況下,程式代碼會搜尋 商務用 OneDrive 中的檔案,因此
driveItem
就像您稍早在元件中看到一mgt-search-results
樣使用。 這與您稍早看到的 mgt-search-results 元件中傳遞driveItem
至entity-types
相同。 然後,參數query
會連同 新增至queryString
篩選ContentType:Document
。const filter = { "requests": [ { "entityTypes": [ "driveItem" ], "query": { "queryString": `${query} AND ContentType:Document` } } ] };
接著會使用
Providers.globalProvider.graph.client.api()
函式呼叫/search/query
Microsoft 圖形 API。 物件filter
會傳遞至函式,post()
以將數據傳送至 API。const searchResults = await Providers.globalProvider.graph.client.api('/search/query').post(filter);
搜尋結果接著會逐一查看,以找出
hits
。 每個hit
都包含找到之文件的相關信息。 名為resource
的屬性包含檔元數據,並新增至files
陣列。if (searchResults.value.length !== 0) { for (const hitContainer of searchResults.value[0].hitsContainers) { if (hitContainer.hits) { for (const hit of hitContainer.hits) { files.push(hit.resource); } } } }
然後,陣列
files
會傳回給呼叫端。return files;
查看此程式代碼,您可以看到您稍早探索的 mgt-search-results Web 元件會為您執行許多工作,並大幅減少您必須撰寫的程式代碼數量! 不過,在某些情況下,您可能會想要直接呼叫 Microsoft Graph,以更充分掌控傳送至 API 的數據,或處理結果的方式。
開啟 files.component.ts 檔案並找出 函
search()
式。 檔案的完整路徑是 client/src/app/files/files.component.ts。雖然此函式的主體因為正在使用 mgt-search-results 元件而批注化,但是當用戶選取 datagrid 中數據列之數據列的 [ 檢視相關內容 ] 時,可以使用函式呼叫 Microsoft Graph。 函
search()
式會在 graph.service.ts 中呼叫searchFiles()
,query
並將 參數傳遞給它, (本範例中的公司名稱) 。 搜尋的結果接著會指派給data
元件的 屬性。override async search(query: string) { this.data = await this.graphService.searchFiles(query); }
然後
data
,檔案元件可以使用 屬性來顯示搜尋結果。 您可以使用自訂 HTML 系結或使用名為mgt-file-list
的另一個 Microsoft Graph 工具組控件來處理此作業。 以下是將 屬性系結data
至其中一個元件屬性files
的範例,並在使用者與檔案互動時處理itemClick
事件。<mgt-file-list (itemClick)="itemClick($any($event))" [files]="data"></mgt-file-list>
無論您選擇使用稍早顯示的 mgt-search-results 元件,還是撰寫自定義程式碼來呼叫 Microsoft Graph,都會取決於您的特定案例。 在此範例中, mgt-search-results 元件可用來簡化程序代碼,並減少您必須執行的工作量。
探索 Teams 聊天訊息搜尋程式代碼
返回 graph.service.ts並找出函式
searchChatMessages()
。 您會看到它與您先前查看的searchFiles()
函式類似。- 它會將篩選數據張貼至 Microsoft Graph 的
/search/query
API,並將結果轉換成物件數位,這些物件具有、channelId
的相關信息teamId
,且messageId
符合搜尋字詞。 - 若要擷取 Teams 頻道訊息,系統會對
/teams/${chat.teamId}/channels/${chat.channelId}/messages/${chat.messageId}
API 進行第二次呼叫,並teamId
傳遞 、channelId
和messageId
。 這會傳回完整的訊息詳細數據。 - 系統會執行其他篩選工作,並將產生的訊息從
searchChatMessages()
傳回給呼叫端。
- 它會將篩選數據張貼至 Microsoft Graph 的
開啟 chats.component.ts 檔案,並找出 函
search()
式。 檔案的完整路徑是 client/src/app/chats/chats.component.ts。 函search()
式會在 graph.service.ts 中呼叫searchChatMessages()
,並將 參數傳遞給query
它。override async search(query: string) { this.data = await this.graphService.searchChatMessages(query); }
搜尋的結果會指派給
data
元件和數據系結的 屬性,用來逐一查看結果陣列並轉譯數據。 此範例會使用 Angular 材質卡片元件來顯示搜尋結果。<div *ngIf="data.length"> <mat-card *ngFor="let chatMessage of data"> <mat-card-header> <mat-card-title [innerHTML]="chatMessage.summary"></mat-card-title> </mat-card-header> <mat-card-actions> <a mat-stroked-button color="basic" [href]="chatMessage.webUrl" target="_blank">View Message</a> </mat-card-actions> </mat-card> </div>
將訊息傳送至 Microsoft Teams 頻道
除了搜尋 Microsoft Teams 聊天訊息之外,應用程式也允許使用者將訊息傳送至 Microsoft Teams 頻道。 您可以藉由呼叫
/teams/${teamId}/channels/${channelId}/messages
Microsoft Graph 的端點來完成此動作。在下列程序代碼中,您會看到已建立包含
teamId
和channelId
值的 URL。 在此範例中,小組標識碼和頻道標識符會使用環境變數值,但這些值也可以使用 Microsoft Graph 動態擷取。body
常數包含要傳送的訊息。 接著會提出POST要求,並將結果傳回給呼叫端。async sendTeamsChat(message: string): Promise<TeamsDialogData> { if (!message) new Error('No message to send.'); if (!TEAM_ID || !CHANNEL_ID) new Error('Team ID or Channel ID not set in environment variables. Please set TEAM_ID and CHANNEL_ID in the .env file.'); const url = `https://graph.microsoft.com/v1.0/teams/${TEAM_ID}/channels/${CHANNEL_ID}/messages`; const body = { "body": { "contentType": "html", "content": message } }; const response = await Providers.globalProvider.graph.client.api(url).post(body); return { id: response.id, teamId: response.channelIdentity.teamId, channelId: response.channelIdentity.channelId, message: response.body.content, webUrl: response.webUrl, title: 'Send Teams Chat' }; }
利用 Microsoft Graph 中的這種類型的功能,可讓使用者直接從他們正在使用的應用程式與 Microsoft Teams 互動,來增強用戶產品性。
組織數據:擷取電子郵件和行事曆事件
在上一個練習中,您已瞭解如何使用 Microsoft Graph 從 Microsoft Teams 擷取 商務用 OneDrive 和聊天中的檔案,以及 Microsoft Graph 工具組的 mgt-search-results 元件。 您也已瞭解如何將訊息傳送至 Microsoft Teams 頻道。 在此練習中,您將瞭解如何從 Microsoft Graph 擷取電子郵件訊息和行事曆事件,並將其整合到應用程式中。
在本練習中,您將會:
- 瞭解 Microsoft Graph 工具組中 的 mgt-search-results Web 元件如何用來搜尋電子郵件和行事曆活動。
- 瞭解如何自定義 mgt-search-results 元件,以自定義方式轉譯搜尋結果。
- 瞭解如何直接呼叫 Microsoft Graph 以擷取電子郵件和行事曆事件。
探索 Email 訊息搜尋程序代碼
提示
如果您使用 Visual Studio Code,您可以選取下列專案來直接開啟檔案:
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
然後輸入您要開啟的檔案名。
在先前的練習中,您已在 Microsoft Entra ID 中建立應用程式註冊,並啟動應用程式伺服器和 API 伺服器。 您也會更新檔案中的
.env
下列值。ENTRAID_CLIENT_ID=<APPLICATION_CLIENT_ID_VALUE> TEAM_ID=<TEAMS_TEAM_ID> CHANNEL_ID=<TEAMS_CHANNEL_ID>
繼續之前,請確定您已完成 上一個練習 。
開啟 emails.component.html ,並花點時間查看程序代碼。 檔案的完整路徑是 client/src/app/emails/emails.component.html。
找出 mgt-search-results 元件:
<mgt-search-results class="search-results" entity-types="message" [queryString]="searchText" (dataChange)="dataChange($any($event))"> <template data-type="result-message"></template> </mgt-search-results>
這個 mgt-search-results 元件的範例設定方式與您先前查看的元件相同。 唯一的差別在於 屬性
entity-types
設定為message
,用來搜尋電子郵件訊息,並提供空白範本。- 屬性
class
是用來指定search-results
CSS 類別應該套用至元件。 - 屬性
entity-types
是用來指定要搜尋的數據類型。 此處的值為message
。 - 屬性
queryString
是用來指定搜尋字詞。 - 當搜尋結果變更時,就會
dataChange
引發事件。 系統會呼叫電子郵件元件的dataChange()
函式、將結果傳遞至該函式,並在元件中更新名為data
的屬性。 - 已為元件定義空的範本。 這種類型的範本通常用來定義搜尋結果的轉譯方式。 不過,在此案例中,我們會告知元件不要轉譯任何訊息數據。 相反地,我們會使用標準數據系結自行轉譯數據, (Angular 在此案例中使用,但您可以使用任何您想要) 的連結庫/架構。
- 屬性
請查看 emails.component.html 中的 mgt-search-results 元件下方,尋找用來呈現電子郵件訊息的數據系結。 這個範例會逐一查看 屬性,
data
並寫出電子郵件主旨、本文預覽,以及檢視完整電子郵件訊息的連結。<div *ngIf="data.length"> <mat-card *ngFor="let email of data"> <mat-card-header> <mat-card-title>{{email.resource.subject}}</mat-card-title> <mat-card-subtitle [innerHTML]="email.resource.bodyPreview"></mat-card-subtitle> </mat-card-header> <mat-card-actions> <a mat-stroked-button color="basic" [href]="email.resource.webLink" target="_blank">View Email Message</a> </mat-card-actions> </mat-card> </div>
除了使用 mgt-search-results 元件來擷取訊息之外,Microsoft Graph 還提供數個可用來搜尋電子郵件的 API。
/search/query
您稍早看到的 API 當然可以使用,但更直接的選項是messages
API。若要查看如何呼叫此 API,請返回 graph.service.ts 並找出 函式
searchEmailMessages()
。 它會建立可用來呼叫messages
Microsoft Graph 端點的 URL,並將值指派query
給$search
參數。 然後程式代碼會提出 GET 要求,並將結果傳回給呼叫端。 運算子$search
會自動搜尋query
主旨、本文和傳送者欄位中的值。async searchEmailMessages(query:string) { if (!query) return []; // The $search operator will search the subject, body, and sender fields automatically const url = `https://graph.microsoft.com/v1.0/me/messages?$search="${query}"&$select=subject,bodyPreview,from,toRecipients,receivedDateTime,webLink`; const response = await Providers.globalProvider.graph.client.api(url).get(); return response.value; }
位於 emails.component.ts 的電子郵件 元件 會 呼叫
searchEmailMessages()
,並在 UI 中顯示結果。override async search(query: string) { this.data = await this.graphService.searchEmailMessages(query); }
探索行事曆事件搜尋程序代碼
您也可以使用 mgt-search-results 元件來完成搜尋行事歷事件。 它可以為您處理轉譯結果,但您也可以定義自己的範本,稍後會在本練習中看到。
開啟 calendar-events.component.html ,並花點時間查看程序代碼。 檔案的完整路徑是 client/src/app/calendar-events/calendar-events.component.html。 您會看到它與您先前查看的檔案和電子郵件元件非常類似。
<mgt-search-results class="search-results" entity-types="event" [queryString]="searchText" (dataChange)="dataChange($any($event))"> <template data-type="result-event"></template> </mgt-search-results>
這個 mgt-search-results 元件的範例設定方式與您先前查看的元件相同。 唯一的差別在於屬性
entity-types
設定event
為 ,用來搜尋行事曆事件,並提供空的範本。- 屬性
class
是用來指定search-results
CSS 類別應該套用至元件。 - 屬性
entity-types
是用來指定要搜尋的數據類型。 此處的值為event
。 - 屬性
queryString
是用來指定搜尋字詞。 - 當搜尋結果變更時,就會
dataChange
引發事件。 呼叫行事曆 事件 元件的dataChange()
函式、將結果傳遞至該函式,並在元件中更新名為data
的屬性。 - 已為元件定義空的範本。 在此案例中,我們會告知元件不要轉譯任何數據。 相反地,我們會使用標準數據系結自行轉譯數據。
- 屬性
緊接在calendar-events.component.html元件下方
mgt-search-results
, 您會發現用來呈現行事曆事件的數據系結。 這個範例會逐一查看 屬性,data
並寫出事件的開始日期、時間和主旨。 和等dayFromDateTime()
timeRangeFromEvent()
元件中包含的自定義函式會呼叫 以正確格式化數據。 HTML 系結也包含一個連結,可在 Outlook 中檢視行事曆事件,以及指定事件的位置。<div *ngIf="data.length"> <div class="root" *ngFor='let event of data'> <div class="time-container"> <div class="date">{{ dayFromDateTime(event.resource.start.dateTime)}}</div> <div class="time">{{ timeRangeFromEvent(event.resource) }}</div> </div> <div class="separator"> <div class="vertical-line top"></div> <div class="circle"> <div *ngIf="!event.resource.bodyPreview?.includes('Join Microsoft Teams Meeting')" class="inner-circle"></div> </div> <div class="vertical-line bottom"></div> </div> <div class="details"> <div class="subject">{{ event.resource.subject }}</div> <div class="location" *ngIf="event.resource.location?.displayName"> at <a href="https://bing.com/maps/default.aspx?where1={{event.resource.location.displayName}}" target="_blank" rel="noopener"><b>{{ event.resource.location.displayName }}</b></a> </div> <div class="attendees" *ngIf="event.resource.attendees?.length"> <span class="attendee" *ngFor="let attendee of event.resource.attendees"> <mgt-person person-query="{{attendee.emailAddress.name}}"></mgt-person> </span> </div> <div class="online-meeting" *ngIf="event.resource.bodyPreview?.includes('Join Microsoft Teams Meeting')"> <img class="online-meeting-icon" src="https://img.icons8.com/color/48/000000/microsoft-teams.png" title="Online Meeting" /> <a class="online-meeting-link" href="{{ event.resource.onlineMeetingUrl }}">Join Teams Meeting</a> </div> </div> </div> </div>
除了使用
search/query
API 搜尋行事曆事件之外,Microsoft Graph 也提供events
API,可用來搜尋行事曆活動。 在 graph.service.ts 中找到函searchCalendarEvents()
式。函
searchCalendarEvents()
式會建立開始和結束日期/時間值,用來定義要搜尋的時間週期。 然後,它會建立可用來呼叫events
Microsoft Graph 端點的 URL,並包含query
參數和開始和結束日期/時間變數。 然後會提出 GET 要求,並將結果傳回給呼叫端。async searchCalendarEvents(query:string) { if (!query) return []; const startDateTime = new Date(); const endDateTime = new Date(startDateTime.getTime() + (7 * 24 * 60 * 60 * 1000)); const url = `/me/events?startdatetime=${startDateTime.toISOString()}&enddatetime=${endDateTime.toISOString()}&$filter=contains(subject,'${query}')&orderby=start/dateTime`; const response = await Providers.globalProvider.graph.client.api(url).get(); return response.value; }
以下是所建立 URL 的明細:
-
/me/events
URL 的部分用來指定應該擷取已登入使用者的事件。 -
startdatetime
和enddatetime
參數是用來定義要搜尋的時間週期。 在此情況下,搜尋會傳回在接下來的 7 天內開始的事件。 -
$filter
查詢參數可用來依從 datagrid 選取的公司名稱值 (篩選結果query
,在此案例中為) 。 函contains()
式用來尋找query
行事曆事件的 屬性中的subject
值。 - 查詢
$orderby
參數可用來依start/dateTime
屬性排序結果。
-
url
建立 之後,會使用的值url
對 Microsoft 圖形 API 提出 GET 要求,並將結果傳回給呼叫端。如同先前的元件, 行事歷事件 元件 (calendar-events.component.ts 檔案) 呼叫
search()
並顯示結果。override async search(query: string) { this.data = await this.graphService.searchCalendarEvents(query); }
注意
您也可以從自訂 API 或伺服器端應用程式進行 Microsoft Graph 呼叫。 檢視下列教學課程,以查看從 Azure 函式呼叫 Microsoft 圖形 API 的範例。
您現在已看到使用 Microsoft Graph 來擷取檔案、聊天、電子郵件訊息和行事曆事件的範例。 相同的概念也可以套用至其他 Microsoft Graph API。 例如,您可以使用 Microsoft Graph 使用者 API 來搜尋組織中的使用者。 您也可以使用 Microsoft Graph 群組 API 來搜尋組織中的群組。 您可以在 檔案中檢視 Microsoft Graph API 的完整清單。
恭喜!
您已完成本教學課程
恭喜! 您已瞭解如何使用 Azure OpenAI 來增強用戶生產力、如何使用 Azure 通訊服務 整合通訊功能,以及如何使用 Microsoft Graph API 和元件來擷取及顯示組織數據。 藉由使用這些技術,您可以建立有效的解決方案,藉由將內容轉移降至最低,並提供必要的決策制定資訊,以提升用戶生產力。
清除 Azure 資源
清除您的 Azure 資源,以避免對您的帳戶產生額外費用。 移至 Azure 入口網站 並移除下列資源:
- Azure 認知搜尋 資源
- Azure 記憶體資源
- Azure OpenAI 資源
- Azure 通訊服務 資源
後續步驟
文件
- Azure OpenAI 文件
- 資料上的 Azure OpenAI
- Azure 通訊服務檔
- Microsoft Graph 檔
- Microsoft Graph 工具組檔
- Microsoft Teams 開發人員檔
訓練內容
在這個區段有遇到問題嗎? 如果有,請提供意見反應,好讓我們可以改善這個區段。