OpenAI、コミュニケーション、組織データ機能を基幹業務アプリに統合する
レベル: 中級
このチュートリアルでは、Azure OpenAI、Azure Communication Services、Microsoft Graph/Microsoft Graph Toolkit を基幹業務 (LOB) アプリケーションに統合して、ユーザーの生産性を向上させ、ユーザー エクスペリエンスを向上させ、LOB アプリを次のレベルに引き上げる方法について説明します。 アプリケーションの主な機能は次のとおりです。
- AI: ユーザーが自然言語で質問し、その回答をデータベースのクエリに使用できる SQL に変換したり、電子メールや SMS メッセージを自動的に生成するために使用できるルールを定義したり、自然言語を使用して独自のカスタム データ ソースからデータを取得する方法を学習したりできます。 これらの機能には Azure OpenAI が使用されます。
- 通信: Azure Communication Services を使用して、顧客へのアプリ内通話と電子メール/SMS 機能を有効にします。
- 組織データ: コンテキストの切り替えを回避するために、ユーザーが顧客と連携する場合にユーザーが必要とする可能性がある関連する組織データ (ドキュメント、チャット、電子メール、予定表イベント) を取り込みます。 この種類の組織データへのアクセスを提供すると、ユーザーが Outlook、Teams、OneDrive、その他のカスタム アプリ、電話などに切り替える必要が減ります。これは、必要な特定のデータと機能がアプリで直接提供されるためです。 この機能には、Microsoft Graph と Microsoft Graph Toolkit が使用されます。
このアプリケーションは、ユーザーが顧客と関連データを管理できるシンプルな顧客管理アプリです。 これは、バックエンド API を呼び出してデータの取得、AI 機能の操作、電子メール/SMS メッセージの送信、組織データのプルを行う TypeScript を使用して構築されたフロントエンドで構成されています。 このチュートリアルで説明するアプリケーション ソリューションの概要を次に示します。
このチュートリアルでは、必要な Azure と Microsoft 365 のリソースを設定するプロセスについて説明します。 また、AI、通信、組織のデータ機能を実装するために使用されるコードについても説明します。 コードをコピーして貼り付ける必要はありませんが、一部の演習では、さまざまなシナリオを試すためにコードを変更する必要があります。
このチュートリアルで構築する内容
あなた自身の冒険を選ぶ
チュートリアル全体を最初から最後まで完了するか、関心のある特定のトピックを完了することができます。 このチュートリアルは、次のトピックに分かれています。
- Project Exercise (必須の演習) を複製します。
- AI 演習: Azure OpenAI リソースを作成し それを使用して自然言語を SQL に変換し、電子メール/SMS メッセージを生成し、独自のデータとドキュメントを操作します。
- 通信の演習: Azure Communication Services リソースを作成し それを使用してアプリから電話をかけ、電子メール/SMS メッセージを送信します。
- 組織データの演習: Microsoft Entra ID アプリの登録を作成します Microsoft Graph と Microsoft Graph Toolkit を使用して組織データを認証し、アプリケーションにプルできるようにします。
前提条件
- Node - Node 20+ と npm 10+ がこのプロジェクトに使用されます
- git
- Visual Studio Code (Visual Studio Code をお勧めしますが、任意のエディターを使用できます)
- Azure サブスクリプション
- Microsoft 365 開発者テナント
- Docker Desktop または別の OCI (Open Container Initiative) に準拠しているコンテナー ランタイム ( Podman、 nerdctl など コンテナーを実行できます。
このチュートリアルで使用する Microsoft Cloud Technologies
- Azure Communication Services
- Azure OpenAI Service
- Microsoft Entra ID
- Microsoft Graph
- Microsoft Graph Toolkit
プロジェクトを複製する
このチュートリアルで使用するコード プロジェクトは、 https://github.com/microsoft/MicrosoftCloudで入手できます。 プロジェクトのリポジトリには、プロジェクトの実行に必要なクライアント側とサーバー側のコードの両方が含まれており、人工知能 (AI)、通信、組織データに関連する統合機能を調べることができます。 さらに、プロジェクトは、独自のアプリケーションに同様の機能を組み込む際に役立つリソースとして機能します。
この演習では、次のことを行います。
- GitHub リポジトリを複製します。
- .env ファイルをプロジェクトに追加して更新します。
先に進む前に、このチュートリアルの「 Prerequisites 」セクションで説明されているように、すべての前提条件がインストールされ、構成されていることを確認してください。
GitHub リポジトリを複製し、 .env
ファイルを作成する
次のコマンドを実行して、 Microsoft Cloud GitHub リポジトリ をマシンに複製します。
git clone https://github.com/microsoft/MicrosoftCloud
Visual Studio Code で MicrosoftCloud/samples/openai-acs-msgraph フォルダーを開きます。
Note
このチュートリアルでは Visual Studio Code を使用しますが、任意のコード エディターを使用してサンプル プロジェクトを操作できます。
次のフォルダーとファイルに注目してください。
- client: クライアント側のアプリケーション コード。
- server: サーバー側 API コード。
- docker-compose.yml: ローカル PostgreSQL データベースの実行に使用されます。
プロジェクトのルートにある .env.example の名前を .env に変更します。
.env ファイルを開き、含まれているキーを確認します。
ENTRAID_CLIENT_ID= TEAM_ID= CHANNEL_ID= OPENAI_API_KEY= OPENAI_ENDPOINT= OPENAI_MODEL=gpt-4o OPENAI_API_VERSION=2024-05-01-preview POSTGRES_USER= POSTGRES_PASSWORD= ACS_CONNECTION_STRING= ACS_PHONE_NUMBER= ACS_EMAIL_ADDRESS= CUSTOMER_EMAIL_ADDRESS= CUSTOMER_PHONE_NUMBER= API_PORT=3000 AZURE_AI_SEARCH_ENDPOINT= AZURE_AI_SEARCH_KEY= AZURE_AI_SEARCH_INDEX=
.env の次の値を更新します。 これらの値は、ローカル PostgreSQL データベースに接続するために API サーバーによって使用されます。
POSTGRES_USER=web POSTGRES_PASSWORD=web-password
プロジェクトの準備ができたので、いくつかのアプリケーション機能を試して、それらがどのように構築されているかを学びましょう。 下の Next ボタンを選択して、目次を使用して特定の演習を続行またはジャンプします。
AI: Azure OpenAI リソースを作成してモデルをデプロイする
アプリケーションで Azure OpenAI の使用を開始するには、Azure OpenAI サービスを作成し、自然言語から SQL への変換、電子メール/SMS メッセージ コンテンツの生成などのタスクを実行するために使用できるモデルをデプロイする必要があります。
この演習では、次のことを行います。
- Azure OpenAI サービス リソースを作成します。
- モデルをデプロイします。
- .env ファイルを Azure OpenAI サービス リソースの値で更新します。
Azure OpenAI サービス リソースを作成する
ブラウザーで Azure ポータル にアクセスし、サインインします。
ポータル ページの上部にある検索バーに「openaiを入力し表示されるオプションから Azure OpenAI を選択します。
ツール バーの Create を選択します。
Note
このチュートリアルでは Azure OpenAI に焦点を当てていますが、OpenAI API キーがあり、それを使用する場合は、このセクションをスキップして、以下の「 プロジェクトの .env ファイルを更新する 」セクションに直接進むことができます。
OPENAI_API_KEY
ファイル内のに OpenAI API キーを割り当てます (OpenAI に関連するその他の.env
指示は無視できます)。Azure OpenAI モデルは、特定のリージョンで利用できます。 このチュートリアルで使用する gpt-4o モデルをサポートするリージョンについては、 Azure OpenAI モデルの可用性 ドキュメントを参照してください。
次のタスクを実行します。
- Azure サブスクリプションを選択します。
- 使用するリソース グループを選択します (必要に応じて新しいリソース グループを作成します)。
- 前に確認したドキュメントに基づいて、gpt-4o モデルがサポートされているリージョンを選択します。
- リソース名を入力します。 これは一意の値である必要があります。
- Standard S0 価格レベルを選択します。
Review + submit画面が表示されるまで、[次へ] を選択します。 [作成] を選択します
Azure OpenAI リソースが作成されたら、それに移動し、 Resource Management -->Keys と Endpoint を選択します。
KEY 1 と Endpoint の値を見つけます。 次のセクションでは両方の値を使用して、ローカル ファイルにコピーします。
Resource Management -->Model デプロイを選択します。
[Manage Deployments] ボタンを選択して、Azure OpenAI Studio に移動します。
ツール バー [モデルのデプロイ -->基本モデルのデプロイ を選択します。
モデルの一覧から gpt-4o を選択し、 Confirm を選択します。
Note
Azure OpenAI では、 さまざまな種類のモデルがサポートされています。 各モデルを使用して、さまざまなシナリオを処理できます。
次のダイアログが表示されます。 少し時間を取って、提供されている既定値を調べます。
分あたりのレート制限 (千単位) 値を 100K に変更。 これにより、モデルに対してより多くの要求を行い、次の手順を実行する際にレート制限に達しないようにすることができます。
[デプロイ] を選択します。
モデルがデプロイされたら、 Playgrounds -->Chat を選択します。
Deployment ドロップダウンに、gpt-4o モデルが表示されます。
System メッセージ指定されたテキストを読み取ります。 これにより、ユーザーが操作する方法がモデルに指示されます。
チャット領域でテキスト ボックスを見つけて、「 Summarize what Generative AI」と入力し、その使用方法を確認します。 Enter を選択してモデルにメッセージを送信し、応答を生成します。
他のプロンプトと応答を試します。 たとえば、 フランスの首都に関する短い履歴を入力し 生成された応答に注目します。
プロジェクトの .env
ファイルを更新する
Visual Studio Code に戻り、プロジェクトのルートにある
.env
ファイルを開きます。Azure OpenAI リソースから KEY 1 の値をコピーし、
OPENAI_API_KEY
フォルダーのルートにある .env ファイル内のに割り当てます。OPENAI_API_KEY=<KEY_1_VALUE>
*Endpoint 値をコピーし、
OPENAI_ENDPOINT
ファイル内のに割り当てます。/
文字が存在する場合は、値の末尾から削除します。OPENAI_ENDPOINT=<ENDPOINT_VALUE>
Note
OPENAI_MODEL
とOPENAI_API_VERSION
の値が既に .env ファイルに設定されていることがわかります。 モデル値は gpt-4o に設定されます。これは、この演習で前に作成したモデル デプロイ名と一致します。 API バージョンは、 Azure OpenAI リファレンス ドキュメントで定義されているサポートされている値に設定されます。.env ファイルを保存します。
Application Services を開始する
次に、データベース、API サーバー、Web サーバーなどのアプリケーション サービスを起動します。
次の手順では、Visual Studio Code で 3 つのターミナル ウィンドウを作成します。
Visual Studio Code ファイルの一覧で .env ファイルを右クリックし、 統合ターミナルで開くを選択します。 続行する前に、ターミナルがプロジェクトのルート ( openai-acs-msgraph ) にあることを確認します。
PostgreSQL データベース 開始するには、次のオプションの 1 つ から選択します。
Docker Desktopをインストールして実行している場合は、ターミナル ウィンドウで
docker-compose up
を実行し、Enter キーを押します。podman に podman-compose インストールして実行している場合は、ターミナル ウィンドウで
podman-compose up
を実行し、 Enter キーを押します。Docker Desktop、Podman、nerdctl、またはインストールした別のコンテナー ランタイムを使用して PostgreSQL コンテナーを直接実行するには、ターミナル ウィンドウで次のコマンドを実行します。
Mac、Linux、または Linux 用 Windows サブシステム (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 ターミナル ツール バーの+ アイコンを押して、2 番目のターミナル ウィンドウを作成します。
cd
を server/typescript フォルダーに移動し、次のコマンドを実行して依存関係をインストールし、API サーバーを起動します。npm install
npm start
Visual Studio Code ターミナル ツール バーの + アイコンをもう一度押して 3 番目のターミナル ウィンドウを作成します。
cd
client フォルダーに移動し、次のコマンドを実行して依存関係をインストールし、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 の下にあるページの Custom Query セクションを見つけます。 サンプル クエリ値が既に含まれていることに注意してください。 すべての注文の合計収益を取得します。会社別にグループ化し、市区町村を含めます。
[クエリの実行] ボタンを選択します。 これにより、ユーザーの自然言語クエリが Azure OpenAI に渡され、SQL に変換されます。 その後、SQL クエリを使用してデータベースのクエリを実行し、潜在的な結果を返します。
次の Custom クエリを実行します。
Get the total revenue for Adventure Works Cycles. Include the contact information as well.
Visual Studio Code で API サーバーを実行しているターミナル ウィンドウを表示すると、Azure OpenAI から返された SQL クエリが表示されます。 JSON データは、サーバー側 API によって 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"] }
ブラウザーに戻り、 Reset Data を選択して、すべての顧客をデータ グリッドに再び表示します。
自然言語から SQL コードへの探索
ヒント
Visual Studio Code を使用している場合は、次を選択してファイルを直接開くことができます。
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
次に、開くファイルの名前を入力します。
Note
この演習の目的は、自然言語を使用して可能な機能を SQL 機能に示し、使用を開始する方法を示することです。 前述のように、実装を続行する前に、この種の AI が組織に適しているかどうかを検討することが重要です。 また、不正アクセスを防ぎ、機密データを保護するために適切なプロンプト ルールとデータベース セキュリティ対策を計画することもです。
これで、自然言語から SQL への機能の動作を確認したので、それがどのように実装されているかを調べてみましょう。
server/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.prompt
からユーザー クエリ値を取得し、userPrompt
という名前の変数に割り当てます。 この値は、GPT プロンプトで使用されます。 - 自然言語を SQL に変換するために、
getSQLFromNLP()
関数を呼び出します。 - 生成された SQL を、SQL クエリを実行する
queryDb
という名前の関数に渡され、データベースから結果が返されます。
-
エディターで server/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 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. - Return a JSON object with the following structure: { "sql": "", "paramValues": [] } Examples: 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"] } `; 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 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. - Return a JSON object with the following structure: { "sql": "", "paramValues": [] } Examples: 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"] } `;
使用する AI アシスタントの種類が定義されています。 この場合は、"SQL ボットに対する自然言語" です。
データベース内のテーブル名と列が定義されます。 プロンプトに含まれる大まかなスキーマは、 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 インジェクション攻撃を回避するために、任意の文字列値をパラメーター化されたクエリ値に変換するルールが定義されています。
ルールは、SQL クエリとそのパラメーター値を含む JSON オブジェクトを常に返すように定義されています。
ユーザー プロンプトの例と、想定される SQL クエリとパラメーター値が提供されます。 これは、 "few-shot" 学習と呼ばれます。 LLM は大量のデータに対してトレーニングされますが、いくつかの例だけで新しいタスクに適応できます。 もう 1 つの方法は、例が提供されておらず、モデルが正しい SQL クエリとパラメーター値を生成することが期待される"ゼロショット" 学習です。
getSQLFromNLP()
関数は、callOpenAI()
ファイルにある という名前の関数にシステム プロンプトとユーザー プロンプトを送信します。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) { if (useBYOD) { return getAzureOpenAIBYODCompletion(systemPrompt, userPrompt, temperature); } return getAzureOpenAICompletion(systemPrompt, userPrompt, temperature); } return getOpenAICompletion(systemPrompt, userPrompt, temperature); }
Note
このチュートリアルでは Azure OpenAI に焦点を当てますが、
OPENAI_API_KEY
ファイルに値のみを指定した場合、アプリケーションでは代わりに OpenAI が使用されます。 Azure OpenAI の代わりに OpenAI を使用することを選択した場合、場合によっては異なる結果が表示されることがあります。getAzureOpenAICompletion()
関数を見つけます。async function getAzureOpenAICompletion(systemPrompt: string, userPrompt: string, temperature: number): Promise<string> { const completion = await createAzureOpenAICompletion(systemPrompt, userPrompt, temperature); let content = completion.choices[0]?.message?.content?.trim() ?? ''; console.log('Azure OpenAI Output: \n', content); if (content && content.includes('{') && content.includes('}')) { content = extractJson(content); } return content; }
この関数は、次のことを行います。
パラメーター:
-
systemPrompt
、userPrompt
、およびtemperature
が主なパラメーターです。-
systemPrompt
: Azure OpenAI モデルにそのロールと従う規則を通知します。 -
userPrompt
: 自然言語入力や出力を生成するためのルールなど、ユーザーが指定した情報が含まれます。 -
temperature
: モデルの応答の創造性レベルを決定します。 値を大きくすると、クリエイティブな出力が増えます。
-
-
完了の生成:
- 関数は、
createAzureOpenAICompletion()
、systemPrompt
、およびuserPrompt
を使用してtemperature
を呼び出して完了を生成します。 - 入力候補の最初の選択肢からコンテンツが抽出され、余分な空白がトリミングされます。
- コンテンツに JSON に似た構造 (
{
と}
の存在によって示される) が含まれている場合は、JSON コンテンツが抽出されます。
- 関数は、
ログと戻り値:
- この関数は、Azure OpenAI 出力をコンソールに記録します。
- 処理されたコンテンツを文字列として返します。
createAzureOpenAICompletion()
関数を見つけます。async function createAzureOpenAICompletion(systemPrompt: string, userPrompt: string, temperature: number, dataSources?: any[]): Promise<any> { const baseEnvVars = ['OPENAI_API_KEY', 'OPENAI_ENDPOINT', 'OPENAI_MODEL']; const byodEnvVars = ['AZURE_AI_SEARCH_ENDPOINT', 'AZURE_AI_SEARCH_KEY', 'AZURE_AI_SEARCH_INDEX']; const requiredEnvVars = dataSources ? [...baseEnvVars, ...byodEnvVars] : baseEnvVars; checkRequiredEnvVars(requiredEnvVars); const config = { apiKey: OPENAI_API_KEY, endpoint: OPENAI_ENDPOINT, apiVersion: OPENAI_API_VERSION, deployment: OPENAI_MODEL }; const aoai = new AzureOpenAI(config); const completion = await aoai.chat.completions.create({ model: OPENAI_MODEL, // gpt-4o, gpt-3.5-turbo, etc. Pulled from .env file max_tokens: 1024, temperature, response_format: { type: "json_object", }, messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt } ], // @ts-expect-error data_sources is a custom property used with the "Azure Add Your Data" feature data_sources: dataSources }); return completion; } function checkRequiredEnvVars(requiredEnvVars: string[]) { for (const envVar of requiredEnvVars) { if (!process.env[envVar]) { throw new Error(`Missing ${envVar} in environment variables.`); } } }
この関数は、次のことを行います。
パラメーター:
-
systemPrompt
、userPrompt
、およびtemperature
は、前に説明した主要なパラメーターです。 - 省略可能な
dataSources
パラメーターでは、このチュートリアルの後半で説明する "Azure Bring Your Own Data" 機能がサポートされます。
-
環境変数チェック:
- この関数は、不可欠な環境変数が存在することを確認し、存在しない場合はエラーをスローします。
構成オブジェクト:
-
config
オブジェクトは、.env
ファイルの値 (OPENAI_API_KEY
、OPENAI_ENDPOINT
、OPENAI_API_VERSION
、OPENAI_MODEL
) を使用して作成されます。 これらの値は、Azure OpenAI を呼び出すための URL を構築するために使用されます。
-
AzureOpenAI インスタンス:
-
AzureOpenAI
のインスタンスが、config
オブジェクトを使用して作成されます。AzureOpenAI
シンボルはopenai
パッケージの一部であり、ファイルの先頭にインポートする必要があります。
-
完了の生成:
-
chat.completions.create()
関数は、次のプロパティを使用して呼び出されます。-
model
:.env
ファイルで定義されている GPT モデル (gpt-4o、gpt-3.5-turbo など) を指定します。 -
max_tokens
: 完了のトークンの最大数を定義します。 -
temperature
:サンプリング温度を設定します。 値が大きいほど (0.9 など)、クリエイティブな反応が増え、値が小さい (0 など) ほど決定的な回答が生成されます。 -
response_format
: 応答形式を定義します。 ここでは、JSON オブジェクトを返すように設定されています。 JSON モードの詳細については、 Azure OpenAI リファレンス ドキュメントを参照してください。 -
messages
: チャットの完了を生成するためのメッセージが含まれます。 この例には、システムからのメッセージ (動作とルールの定義) とユーザーからのメッセージ (プロンプト テキストを含む) の 2 つのメッセージが含まれています。
-
-
戻り値:
- この関数は、Azure OpenAI によって生成された完了オブジェクトを返します。
getSQLFromNLP()
関数の次の行をコメント アウトします。// if (isProhibitedQuery(queryData.sql)) { // queryData.sql = ''; // }
openAI.ts保存します。 API サーバーは、TypeScript コードを自動的に再構築し、サーバーを再起動します。
ブラウザーに戻り、「データベースからすべてのテーブル名を選択するCustom クエリ入力」と入力します。 [クエリの実行] を選択します。 テーブル名は表示されますか?
getSQLFromNLP()
の関数に戻り、システム プロンプトのRules:
セクションに次の規則を追加して、ファイルを保存します。- Do not allow the SELECT query to return table names, function names, or procedure names.
ブラウザーに戻り、次のタスクを実行します。
- データベースからすべてのテーブル名を選択Custom クエリ入力に入力します。 [クエリの実行] を選択します。 テーブル名は表示されますか?
- database. からすべての関数名を Custom Query 入力に入力し、もう一度 実行クエリを選択します。 関数名は表示されますか?
質問: モデルは、プロンプトで定義したルールに常に従いますか?
回答: いいえ。 OpenAI モデルは、定義したルールと一致しない場合に予期しない結果を返す可能性があることに注意してください。 コードで計画することが重要です。
server/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_proc', '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)); }
Note
これはデモ コードに過ぎないことに注意してください。 自然言語を SQL に変換する場合は、特定のユース ケースに対応するために他の禁止キーワードが必要になる場合があります。 これは、有効な SQL クエリのみが返され、データベースに対して実行されるように注意して計画し、使用する必要がある機能です。 禁止されたキーワードに加えて、セキュリティも考慮する必要があります。
server/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.
ブラウザーに戻り、Custom クエリにデータベースからすべてのテーブル名を選択入力しもう一度入力し、実行クエリ ボタンを選択します。
テーブルの結果は表示されますか? 規則が設定されていない場合でも、
isProhibitedQuery()
後処理コードでは、その種類のクエリがデータベースに対して実行されることを禁止します。前に説明したように、基幹業務アプリケーションで自然言語を SQL に統合することは、ユーザーにとって非常に有益ですが、独自の一連の考慮事項が付属しています。
長所:
使いやすさ: この機能により、技術的な専門知識がなくてもデータベースの操作にユーザーがアクセスしやすくなり、SQL の知識の必要性が減り、操作が高速化される可能性があります。
生産性の向上: ビジネス アナリスト、マーケティング担当者、エグゼクティブ、その他の非技術ユーザーは、技術専門家に頼ることなくデータベースから貴重な情報を取得できるため、効率が向上します。
広範なアプリケーション: 高度な言語モデルを使用することで、アプリケーションは幅広いユーザーやユース ケースに対応するように設計できます。
考慮事項:
セキュリティ: 最大の懸念事項の 1 つはセキュリティです。 ユーザーが自然言語を使用してデータベースを操作できる場合は、承認されていないアクセスや悪意のあるクエリを防ぐために、堅牢なセキュリティ対策が必要です。 ユーザーがデータを変更できないように、読み取り専用モードを実装することを検討できます。
データのプライバシー: 特定のデータは機密性が高く、簡単にアクセスできないようにする必要があるため、適切な保護とユーザーのアクセス許可を確保する必要があります。
精度:自然言語処理は大幅に改善されていますが、完璧ではありません。 ユーザー クエリを誤って解釈すると、不正確な結果や予期しない動作が発生する可能性があります。 予期しない結果がどのように処理されるかを計画する必要があります。
効率性: 自然言語クエリから返される SQL が効率的であるという保証はありません。 場合によっては、後処理ルールで SQL クエリの問題が検出された場合に、Azure OpenAI への追加の呼び出しが必要になる場合があります。
トレーニングとユーザー適応: クエリを正しく作成するには、ユーザーをトレーニングする必要があります。 SQL を学習するよりも簡単ですが、学習曲線が必要な場合もあります。
次の演習に進む前に、いくつかの最後の点を考慮する必要があります。
- ここで適用されるのは、"必要とは言えないからといって" という点に注意してください。 自然言語を SQL にアプリケーションに統合する前に、細心の注意と慎重な計画を使用してください。 潜在的なリスクを理解し、それらを計画することが重要です。
- この種のテクノロジを使用する前に、チーム、データベース管理者、セキュリティ チーム、利害関係者、およびその他の関係者と潜在的なシナリオについて話し合い、組織に適していることを確認します。 SQL に対する自然言語が、セキュリティ、プライバシー、および組織が持つその他の要件を満たしているかどうかを検討することが重要です。
- セキュリティは主な懸念事項であり、計画、開発、デプロイのプロセスに組み込まれている必要があります。
- SQL に対する自然言語は非常に強力ですが、プロンプトに必要なルールがあり、後処理機能が含まれていることを確認するために、慎重な計画を立てなければなりません。 この種の機能を実装してテストし、予期しない結果が返されるシナリオを考慮して、追加の時間を計画します。
- Azure OpenAI を使用すると、顧客は OpenAI と同じモデルを実行しながら、Microsoft Azure のセキュリティ機能を使用できます。 Azure OpenAI では、プライベート ネットワーク、リージョンの可用性、責任ある AI コンテンツのフィルター処理が提供されます。 Azure OpenAI Service の Data、プライバシー、セキュリティの詳細。
これで、Azure OpenAI を使用して自然言語を SQL に変換する方法を確認し、この種の機能を実装することの長所と短所について学習しました。 次の演習では、Azure OpenAI を使用して電子メールメッセージと SMS メッセージを生成する方法について説明します。
AI: 完了の生成
SQL の自然言語機能に加えて、Azure OpenAI Service を使用して電子メールと SMS メッセージを生成し、ユーザーの生産性を向上させ、通信ワークフローを合理化することもできます。 Azure OpenAI の言語生成機能を利用することで、ユーザーは "Order is delayed 5 days" などの特定のルールを定義でき、システムはそれらのルールに基づいてコンテキストに応じて適切な電子メールおよび SMS メッセージを自動的に生成します。
この機能は、ユーザーのジャンプ スタートとして機能し、送信前に簡単にカスタマイズできる、慎重に作成されたメッセージ テンプレートをユーザーに提供します。 その結果、メッセージの作成に必要な時間と労力が大幅に削減され、ユーザーは他の重要なタスクに集中できるようになります。 さらに、Azure OpenAI の言語生成テクノロジを自動化ワークフローに統合できるため、システムは定義済みのトリガーに応答して自律的にメッセージを生成および送信できます。 このレベルの自動化により、通信プロセスが高速化されるだけでなく、さまざまなシナリオで一貫性のある正確なメッセージングが保証されます。
この演習では、次のことを行います。
- さまざまなプロンプトを試してみてください。
- プロンプトを使用して、電子メールおよび SMS メッセージの入力候補を生成します。
- AI 入力候補を有効にするコードを調べる。
- プロンプト エンジニアリングの重要性と、プロンプトにルールを含める方法について説明します。
まず、電子メールと SMS メッセージの生成に使用できるさまざまなルールを試してみましょう。
AI 入力候補機能の使用
前の演習ではデータベース、API、アプリケーションを開始しました。 また、
.env
ファイルも更新しました。 これらの手順を完了していない場合は、演習の最後の手順に従って続行してください。ブラウザー (http://localhost:4200) に戻り、データ グリッド内の任意の行で Contact Customer を選択し、その後に Email/SMS Customer を選択して、 Message Generator 画面に移動します。
これにより、Azure OpenAI を使用して、定義したメッセージ ルールを電子メール/SMS メッセージに変換します。 次のタスクを実行します。
入力に Order is delayed 5 days などのルールを入力し、 [電子メール/SMS メッセージの生成 ] ボタンを選択します。
電子メールに対して件名と本文が生成され、SMS 用に生成された短いメッセージが表示されます。
Note
Azure Communication Services はまだ有効になっていないため、電子メールまたは SMS メッセージを送信することはできません。
ブラウザーで電子メール/SMS ダイアログ ウィンドウを閉じます。 この機能の動作を確認したので、その実装方法を調べてみましょう。
AI 入力候補コードの探索
ヒント
Visual Studio Code を使用している場合は、次を選択してファイルを直接開くことができます。
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
次に、開くファイルの名前を入力します。
server/apiRoutes.ts ファイルを開き、
completeEmailSmsMessages
ルートを見つけます。 この API は、 Generate Email/SMS Messages ボタンが選択されている場合に、アプリのフロントエンド部分によって呼び出されます。 ユーザー プロンプト、会社、連絡先の名前の値を本文から取得し、completeEmailSMSMessages()
ファイルの関数に渡します。 その後、結果がクライアントに返されます。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); });
server/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. `; 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
は、電子メールと SMS メッセージを生成できる AI アシスタントが必要であることを定義するために使用されます。systemPrompt
には次も含まれます。- アシスタントがメッセージのトーン、開始と終了の形式、SMS メッセージの最大長などを制御するためのルール。
- 応答に含める必要があるデータ (この場合は JSON オブジェクト) に関する情報。
-
userPrompt
は、エンド ユーザーが電子メールおよび SMS メッセージを生成する場合に含めるルールと連絡先の名前を定義するために使用されます。 Order は 5 日間遅延前に入力したルールがuserPrompt
に含まれます。 - この関数は、前に調査した
callOpenAI()
関数を呼び出して、電子メールと SMS の入力候補を生成します。
-
ブラウザーに戻り、ページを更新し、任意の行で Contact Customer を選択し、その後に Email/SMS CustomerMessage Generator 画面に戻ります。
Message Generator 入力に次の規則を入力します。
- 注文はスケジュールより前です。
- 顧客に二度と注文しないように指示してください。私たちは彼らのビジネスを望んでいません。
[電子メール/SMS メッセージの生成]を選択しメッセージを書き留めます。 システム プロンプトの
All messages should have a friendly tone and never use inappropriate language.
ルールは、ユーザー プロンプトの負のルールをオーバーライドしています。エディターで server/openAI.ts* に戻り、
All messages should have a friendly tone and never use inappropriate language.
関数のプロンプトからcompleteEmailSMSMessages()
ルールを削除します。 ファイルを保存します。ブラウザーで電子メール/SMS メッセージ ジェネレーターに戻り、同じルールをもう一度実行します。
- 注文はスケジュールより前です。
- 顧客に二度と注文しないように指示してください。私たちは彼らのビジネスを望んでいません。
[Generate Email/SMS Messages]\(電子メール/SMS メッセージの生成\) を選択し返されたメッセージに注目します。
これらのシナリオで何が起こっていますか? Azure OpenAI を使用する場合は、適切な言語が常に使用されるようにフィルター処理を適用できます。 OpenAI を使用している場合は、返されるメッセージが適切であることを確認するために、システム プロンプトで定義されている規則が使用されます。
Note
これは、適切な結果が返されるように、適切な情報とルールを使用してプロンプトをエンジニアリングすることの重要性を示しています。 このプロセスの詳細については、 エンジニアリングを促すイントロダクション ドキュメントを参照してください。
systemPrompt
でcompleteEmailSMSMessages()
に加えた変更を元に戻し、ファイルを保存して、もう一度実行しますが、Order is ahead of schedule.
規則のみを使用します (負の規則は含めないでください)。 今回は、期待どおりに返された電子メールと SMS メッセージが表示されます。次の演習に進む前に、いくつかの最後の点を考慮する必要があります。
- 生成されたメッセージを確認するには、人間をループ内に含める必要があります。 この例の Azure OpenAI 入力候補では、推奨される電子メールメッセージと SMS メッセージが返されますが、ユーザーは送信前に上書きできます。 メールを自動化する場合は、承認されたメッセージが確実に送信されるように、何らかの種類の人間によるレビュー プロセスを用意することが重要です。 AI はオートパイロットではなく、副操縦であると見なします。
- 入力候補は、プロンプトに追加するルールと同じくらい適切です。 時間をかけてプロンプトと返される入力候補をテストします。 Prompt フローを使用して、AI アプリケーションのプロトタイプ作成、実験、反復、デプロイを簡略化する包括的なソリューションを作成することを検討してください。 他のプロジェクト関係者にも、完了を確認するよう招待します。
- 予期しない結果が適切に処理されるように、後処理コードを含める必要がある場合があります。
- システム プロンプトを使用して、AI アシスタントが従うべきルールと情報を定義します。 ユーザー プロンプトを使用して、エンド ユーザーが入力候補に含めるルールと情報を定義します。
AI: データに対する Azure OpenAI
Azure OpenAI 自然言語処理 (NLP) と完了機能の統合により、ユーザーの生産性を向上させる大きな可能性が提供されます。 適切なプロンプトとルールを活用することで、AI アシスタントは、電子メール メッセージ、SMS メッセージなど、さまざまな形式の通信を効率的に生成できます。 この機能により、ユーザーの効率が向上し、ワークフローが合理化されます。
この機能自体は非常に強力ですが、ユーザーが会社のカスタム データに基づいて完了を生成する必要がある場合があります。 たとえば、ユーザーがインストールの問題を顧客に支援する際に移動するのが困難な製品マニュアルのコレクションがあるとします。 または、医療上の利点に関連する包括的な一連のよく寄せられる質問 (FAQ) を維持して、ユーザーが必要な回答を読み取り、取得することが困難であることを証明できます。 このような場合や他の多くの場合、Azure OpenAI Service を使用すると、独自のデータを活用して補完を生成し、ユーザーの質問に対するより調整されたコンテキストに応じた正確な応答を実現できます。
Azure OpenAI ドキュメントから "Bring your own data" 機能がどのように機能するかの概要を次に示します。
Note
独自のデータに基づく Azure OpenAI の主な特徴の 1 つは、モデルの出力を強化する方法でデータを取得して利用できることです。 独自のデータに基づく Azure OpenAI は、Azure AI Search と連携し、ユーザー入力と提供された会話履歴に基づいて、指定されたデータ ソースからどのデータを取得するかを決定します。 その後、このデータは拡張され、OpenAI モデルに対するプロンプトとして再送信されます。取得された情報は元のプロンプトに追加されます。 取得されたデータはプロンプトに追加されますが、結果として得られた入力は他のプロンプトと同様にモデルによって処理されます。 データが取得され、プロンプトがモデルに送信されると、モデルはこの情報を使用して候補を提供します。
この演習では、次のことを行います。
- Azure AI Foundry ポータルを使用してカスタム データ ソースを作成します。
- Azure AI Foundry ポータルを使用して埋め込みモデルをデプロイします。
- カスタム ドキュメントをアップロードします。
- チャット プレイグラウンドでチャット セッションを開始し、独自のデータに基づいて完了を生成する実験を行います。
- Azure AI Search と Azure OpenAI を使用して、独自のデータに基づいて入力候補を生成するコードについて説明します。
埋め込みモデルをデプロイし、Azure AI Foundry にカスタム データ ソースを追加することから始めましょう。
Azure AI Foundry へのカスタム データ ソースの追加
Azure OpenAI Studio に移動し Azure OpenAI リソースにアクセスできる資格情報でサインインします。
ナビゲーション メニューから Deployments を選択します。
ツール バーの [ モデルの選択 -->Deploy 基本モデル を選択します。
モデルの一覧から text-embedding-ada-002 モデルを選択し、 Confirm を選択します。
次のオプションを選択します。
- デプロイ名: text-embedding-ada-002
- モデル バージョン: Default
- 展開の種類: Standard
- 分あたりのレート制限 (千単位) 値を 120K に設定します
- コンテンツ フィルター: DefaultV2
- 動的クォートを有効にする: Enabled
[デプロイ] ボタンを選択します。
モデルが作成されたら、ナビゲーション メニューから Home を選択してようこそ画面に移動します。
ようこそ画面で Bring 独自のデータ タイルを見つけて、 今すぐ選択します。
[データの追加 選択し データ ソースの追加 を選択します。
[データ ソースの 選択 ドロップダウンで、 ファイルのアップロードを選択します。
Azure Blob Storage リソースの選択ドロップダウンで、新しい Azure Blob Storage リソースを作成しますを選択します。
Subscription ドロップダウンで Azure サブスクリプションを選択します。
Azure Blob Storage リソースの選択ドロップダウンで、新しい Azure Blob Storage リソースを作成しますを選択します。
これにより、次のタスクを実行できる Azure portal にアクセスできます。
- byodstorage[Your Last Name]など、ストレージ アカウントの一意の名前を入力します。
- 場所に近いリージョンを選択します。
- Reviewの後に Create を選択します。
BLOB ストレージ リソースが作成されたら、Azure AI Foundry ダイアログに戻り、新しく作成した BLOB ストレージ リソースを [Azure Blob Storage リソースの選択] ドロップダウンから選択します。 一覧に表示されない場合は、ドロップダウンの横にある更新アイコンを選択します。
ストレージ アカウントにアクセスするには、クロスオリジン リソース共有 (CORS) を有効にする必要があります。 [Azure AI Foundry] ダイアログ [CORS を有効にする] を選択します。
Azure AI Search リソースの選択ドロップダウンで、新しい Azure AI Search リソースの作成を選択します。
これにより、次のタスクを実行できる Azure portal に戻ります。
- byodsearch-[Your Last Name]など、AI Search リソースの一意の名前を入力します。
- 場所に近いリージョンを選択します。
- [ Pricing レベル セクションで、 Change 価格レベル を選択し、 Basic の後に Select を選択します。 Free レベルはサポートされていないため、このチュートリアルの最後に AI Search リソースをクリーンアップします。
- Reviewの後に Create を選択します。
AI Search リソースが作成されたら、リソース Overview ページに移動し、 Url 値をローカル ファイルにコピーします。
ナビゲーション メニューで Settings -->Keys を選択します。
API アクセス制御 ページで、Both を選択して、マネージド ID またはキーを使用してサービスにアクセスできるようにします。 確認を求められたら [はい] を選択します。
Note
ロールの割り当てを追加するには最大 10 分かかるため、この演習では API キーを使用しますが、少しの追加作業で、システム割り当てマネージド ID がサービスに安全にアクセスできるようにすることができます。
左側のナビゲーション メニューで Keys を選択し、 Primary 管理キー 値をローカル ファイルにコピーします。 URL とキーの値は、演習の後半で必要になります。
ナビゲーション メニューで Settings -->Semantic ranker を選択し、 Free が選択されていることを確認します。
Note
セマンティック ランカーが特定のリージョンで使用可能かどうかを確認するには、Azure Web サイトの [リージョン別に利用可能な製品の確認] ページで、リージョンが一覧表示されているかどうかを確認します。
Azure AI Foundry
[データ の追加] ダイアログに戻り、[Azure AI Search リソースの選択] ドロップダウンから新しく作成した検索リソースを選択します。 一覧に表示されない場合は、ドロップダウンの横にある更新アイコンを選択します。 にbyod-search-indexの値を入力します。インデックス名値を入力します。
ベクター検索をこの検索リソースに追加チェック ボックスをオンにします。
埋め込みモデルの選択ドロップダウンで、前に作成した text-embedding-ada-002 モデルを選択します。
[ ファイルのアップロード ダイアログで、ファイル [ファイルの参照]を選択します。
プロジェクトの customer documents フォルダー (プロジェクトのルートにあります) に移動し、次のファイルを選択します。
- クロック A102 のインストールInstructions.docx
- 会社FAQs.docx
Note
この機能は現在、ローカル インデックスの作成に使用できるファイル形式 (.txt、.md、.html、.pdf、.docx、.pptx) をサポートしています。
[Upload files](ファイルのアップロード) を選択します。 ファイルは、先ほど作成した BLOB ストレージ リソースの fileupload-byod-search-index コンテナーにアップロードされます。
[次へを選択して、Data 管理 ダイアログに移動します。
[ 検索の種類 ドロップダウンで、 Hybrid + semantic を選択します。
Note
このオプションでは、キーワード検索とベクター検索がサポートされます。 結果が返されると、ディープ ラーニング モデルを使用してセカンダリ ランク付けプロセスが結果セットに適用され、ユーザーの検索の関連性が向上します。 セマンティック検索の詳細については、Azure AI Search の Semantic 検索 ドキュメントを参照してください。
サイズの選択値が 1024 に設定されていることを確認します。
[次へ] を選択します。
Azure リソース認証の種類で、API キーを選択します。 適切な認証の種類の選択の詳細については、 Azure AI Search 認証のドキュメントを参照してください。
[次へ] を選択します。
詳細を確認し、 保存して閉じるを選択します。
カスタム データがアップロードされたので、データのインデックスが作成され、 Chat プレイグラウンドで使用できるようになります。 このプロセスには数分かかることがあります。 完了したら、次のセクションに進みます。
チャット プレイグラウンドでのカスタム データ ソースの使用
Azure OpenAI Studio でページの Chat セッション セクションを見つけて、次の User クエリを入力します。
What safety rules are required to install a clock?
ユーザー クエリを送信すると、次のような結果が表示されます。
チャット応答の [ 1 参照 セクションを展開し、 Clock A102 Installation Instructions.docx ファイルが一覧表示されていること、およびドキュメントを表示するために選択できることを確認します。
次の User メッセージを入力します。
What should I do to mount the clock on the wall?
次のような結果が表示されます。
次に、会社の FAQ ドキュメントを試してみましょう。 User query フィールドに次のテキストを入力します。
What is the company's policy on vacation time?
その要求に関する情報が見つからなかったことがわかります。
User query フィールドに次のテキストを入力します。
How should I handle refund requests?
次のような結果が表示されます。
チャット応答の [ 1 参照 セクションを展開し、 Company FAQs.docx ファイルが一覧表示され、それを選択してドキュメントを表示できることを確認します。
Chat プレイグラウンドのツール バーで[コードの表示]を選択。
異なる言語を切り替え、エンドポイントを表示し、エンドポイントのキーにアクセスできることに注意してください。 サンプル コードダイアログ ウィンドウを閉じます。
チャット メッセージの上にある Show raw JSON トグルをオンにします。 チャット セッションは、次のようなメッセージで始まることがわかります。
{ "role": "system", "content": "You are an AI assistant that helps people find information." }
カスタム データ ソースを作成し、チャットプレイグラウンドで実験したので、プロジェクトのアプリケーションで使用する方法を見てみましょう。
アプリケーションで Bring Your Own Data Feature を使用する
VS Code でプロジェクトに戻り、 .env ファイルを開きます。 AI Services エンドポイント、キー、およびインデックス名を使用して、次の値を更新します。 この演習の前半で、エンドポイントとキーをローカル ファイルにコピーしました。
AZURE_AI_SEARCH_ENDPOINT=<AI_SERVICES_ENDPOINT_VALUE> AZURE_AI_SEARCH_KEY=<AI_SERVICES_KEY_VALUE> AZURE_AI_SEARCH_INDEX=byod-search-index
前の演習ではデータベース、API、アプリケーションを開始しました。 また、
.env
ファイルも更新しました。 これらの手順を完了していない場合は、先に進む前に、前の演習の最後の手順に従ってください。アプリケーションがブラウザーに読み込まれたら、アプリケーションの右上にある Chat ヘルプ アイコンを選択します。
チャット ダイアログに次のテキストが表示されます。
How should I handle a company refund request?
Get ヘルプ ボタンを選択します。 Azure OpenAI Studio で前にアップロードした Company FAQs.docx ドキュメントから結果が返されます。 ドキュメントを読み進める場合は、プロジェクトのルートにある customer documents フォルダーにあります。
テキストを次のように変更し、 [ヘルプの表示 ] ボタンを選択します。
What safety rules are required to install a clock?
Azure OpenAI Studio で前にアップロードした Clock A102 Installation Instructions.docx ドキュメントから結果が返されます。 このドキュメントは、プロジェクトのルートにある customer documents フォルダーでも使用できます。
コードの探索
ヒント
Visual Studio Code を使用している場合は、次を選択してファイルを直接開くことができます。
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
次に、開くファイルの名前を入力します。
Visual Studio Code でプロジェクトのソース コードに戻ります。
server/apiRoutes.ts ファイルを開き、
completeBYOD
ルートを見つけます。 この API は、[チャット ヘルプ] ダイアログで Get Help ボタンが選択されている場合に呼び出されます。 要求本文からユーザー プロンプトを取得し、completeBYOD()
ファイルの関数に渡します。 その後、結果がクライアントに返されます。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 in documents.'; return await callOpenAI(systemPrompt, userPrompt, 0, true); }
この関数には、次の機能があります。
-
userPrompt
パラメーターには、ユーザーがチャット ヘルプ ダイアログに入力した情報が含まれます。 -
systemPrompt
変数は、ユーザーが情報を見つけられるように設計された AI アシスタントが使用されることを定義します。 -
callOpenAI()
は、Azure OpenAI API を呼び出して結果を返すために使用されます。systemPrompt
とuserPrompt
の値と、次のパラメーターが渡されます。-
temperature
- 応答に含める創造性の量。 この場合、ユーザーは一貫性のある (あまりクリエイティブではない) 回答を必要とするため、値は 0 に設定されます。 -
useBYOD
- AZURE OpenAI と共に AI Search を使用するかどうかを示すブール値。 この場合、AI 検索機能が使用されるように、true
に設定されます。
-
-
callOpenAI()
関数は、呼び出す OpenAI 関数を決定するために使用されるuseBYOD
パラメーターを受け取ります。 この場合、useBYOD
関数が呼び出されるように、true
をgetAzureOpenAIBYODCompletion()
に設定します。function callOpenAI(systemPrompt: string, userPrompt: string, temperature = 0, useBYOD = false) { const isAzureOpenAI = OPENAI_API_KEY && OPENAI_ENDPOINT && OPENAI_MODEL; if (isAzureOpenAI) { if (useBYOD) { return getAzureOpenAIBYODCompletion(systemPrompt, userPrompt, temperature); } return getAzureOpenAICompletion(systemPrompt, userPrompt, temperature); } return getOpenAICompletion(systemPrompt, userPrompt, temperature); }
getAzureOpenAIBYODCompletion()
で関数を見つけます。 これは、前に調べたgetAzureOpenAICompletion()
関数とよく似ていますが、Azure OpenAI で使用できる "Azure OpenAI on your data" シナリオに固有のいくつかの主な違いを強調するための別の関数として示されています。async function getAzureOpenAIBYODCompletion(systemPrompt: string, userPrompt: string, temperature: number): Promise<string> { const dataSources = [ { type: 'azure_search', parameters: { authentication: { type: 'api_key', key: AZURE_AI_SEARCH_KEY }, endpoint: AZURE_AI_SEARCH_ENDPOINT, index_name: AZURE_AI_SEARCH_INDEX } } ]; const completion = await createAzureOpenAICompletion(systemPrompt, userPrompt, temperature, dataSources) as AzureOpenAIYourDataResponse; console.log('Azure OpenAI Add Your Own Data Output: \n', completion.choices[0]?.message); for (let citation of completion.choices[0]?.message?.context?.citations ?? []) { console.log('Citation Path:', citation.filepath); } return completion.choices[0]?.message?.content?.trim() ?? ''; }
getAzureOpenAIBYODCompletion()
関数の次の機能に注意してください。- この演習の前半で
dataSources
ファイルに追加された AI Search リソースのkey
、endpoint
、index_name
の値を含む.env
プロパティが作成されます。 -
createAzureOpenAICompletion()
関数は、systemPrompt
、userPrompt
、temperature
、およびdataSources
の値で呼び出されます。 この関数は、Azure OpenAI API を呼び出して結果を返すために使用されます。 - 応答が返されると、ドキュメントの引用文献がコンソールに記録されます。 その後、完了メッセージの内容が呼び出し元に返されます。
- この演習の前半で
次の演習に進む前に、いくつかの最後の点を考慮する必要があります。
- サンプル アプリケーションでは、Azure AI Search で 1 つのインデックスを使用します。 Azure OpenAI では、複数のインデックスとデータ ソースを使用できます。
dataSources
関数のgetAzureOpenAIBYODCompletion()
プロパティは、必要に応じて複数のデータ ソースを含むように更新できます。 - セキュリティは、この種のシナリオで慎重に評価する必要があります。 ユーザーは質問をしたり、アクセスできないドキュメントから結果を取得したりすることはできません。
- サンプル アプリケーションでは、Azure AI Search で 1 つのインデックスを使用します。 Azure OpenAI では、複数のインデックスとデータ ソースを使用できます。
Azure OpenAI、プロンプト、入力候補、独自のデータの使用方法について学習したので、次の演習に進み、通信機能を使用してアプリケーションを強化する方法を学習しましょう。 Azure OpenAI の詳細については、 Get started with Azure OpenAI Service トレーニング コンテンツをご覧ください。 Azure OpenAI で独自のデータを使用する方法の詳細については、 Azure OpenAI のデータに関するドキュメント 参照してください。
通信: Azure Communication Services リソースの作成
効果的な通信は、カスタム ビジネス アプリケーションを成功させるために不可欠です。 Azure Communication Services (ACS) を使用すると、電話、ライブ チャット、オーディオ/ビデオ通話、電子メールおよび SMS メッセージングなどの機能をアプリケーションに追加できます。 前に、Azure OpenAI で電子メールおよび SMS メッセージの入力候補を生成する方法について学習しました。 次に、メッセージを送信する方法について説明します。 ACS と OpenAI を組み合わせることで、コミュニケーションを簡素化し、対話を改善し、ビジネスの生産性を向上させることで、アプリケーションを強化できます。
この演習では、次のことを行います。
- Azure Communication Services (ACS) リソースを作成します。
- 通話機能と SMS 機能を備えたフリーダイヤルの電話番号を追加します。
- メール ドメインを接続します。
- プロジェクトの .env ファイルを ACS リソースの値で更新します。
Azure Communication Services リソースを作成する
ブラウザーで Azure ポータル にアクセスし、まだサインインしていない場合はサインインします。
ページ上部検索バーに「communication services」と入力し表示されるオプションから Communication Services を選択します。
ツール バーの Create を選択します。
次のタスクを実行します。
- Azure サブスクリプションを選択します。
- 使用するリソース グループを選択します (存在しない場合は新しいリソース グループを作成します)。
- ACS リソース名を入力します。 これは一意の値である必要があります。
- データの場所を選択します。
Review + Createを選択し、その後に Create を選択します。
新しい Azure Communication Services リソースが正常に作成されました。 次に、電話通話と SMS 機能を有効にします。 また、メール ドメインをリソースに接続します。
電話通話と SMS 機能を有効にする
電話番号を追加し、電話番号で通話機能が有効になっていることを確認します。 この電話番号を使用して、アプリから電話に発信します。
リソース メニューから Telephony と SMS -->Phone 番号 を選択します。
ツール バーの + Get を選択し (または、[ 数値の取得 ] ボタンを選択して)、次の情報を入力します。
-
国または地域:
United States
-
数値の種類:
Toll-free
Note
無料電話番号を作成するには、Azure サブスクリプションにクレジット カードが必要です。 ファイルにカードがない場合は、電話番号の追加をスキップして、メール ドメインを接続する演習の次のセクションに進んでください。 アプリは引き続き使用できますが、電話番号を呼び出すことはできません。
- 番号: 一覧に表示 電話番号の 1 つ [カートに追加] を選択します。
-
国または地域:
[次へ ] を選択し電話番号の詳細を確認し、[今すぐ ]を選択。
Note
米国とカナダでは、フリーダイヤル番号の SMS 認証が必須になりました。 SMS メッセージングを有効にするには、電話番号の購入後に確認を送信する必要があります。 このチュートリアルではそのプロセスを実行しませんが、リソース メニューから Telephony と SMS -->Regulatory Documents を選択し、必要な検証ドキュメントを追加できます。
電話番号が作成されたら、それを選択して Features パネルにアクセスします。 次の値が設定されていることを確認します (既定で設定する必要があります)。
- [ Calling セクションで、
Make calls
を選択します。 - [ SMS セクションで、
Send and receive SMS
を選択します。 - [保存] を選択します。
- [ Calling セクションで、
後で使用するために、電話番号の値をファイルにコピーします。 電話番号は、
+12345678900
という一般的なパターンに従う必要があります。
メール ドメインを接続する
次のタスクを実行して、ACS リソースの接続された電子メール ドメインを作成し、電子メールを送信できるようにします。 これは、アプリから電子メールを送信するために使用されます。
- [リソース] メニューから Email -->Domains を選択します。
- ツール バーから Connect domain を選択します。
- Subscription および Resource グループを選択。
-
Email Service ドロップダウンで、
Add an email service
を選択します。 - 電子メール サービスに
acs-demo-email-service
などの名前を付けます。 - Review + createを選択し、その後に Create を選択します。
- デプロイが完了したら、
Go to resource
を選択し、1-click add
を選択して無料の Azure サブドメインを追加します。 - サブドメインが追加されたら (デプロイされるまでにしばらく時間がかかります)、それを選択します。
- AzureManagedDomain画面が表示されたら、[リソース] メニューから Email services -->MailFrom addresses を選択します。
- MailFrom 値をファイルにコピーします。 後で .env ファイルを更新するときに使用します。
- Azure Communication Services リソースに戻り、リソース メニューから Email -->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
: ACS リソースのconnection string
セクションの値。ACS_PHONE_NUMBER
: フリーダイヤル番号をACS_PHONE_NUMBER
値に割り当てます。ACS_EMAIL_ADDRESS
: メールの "MailTo" アドレス値を割り当てます。CUSTOMER_EMAIL_ADDRESS
: アプリからメールを送信するメール アドレスを割り当てます (アプリのデータベース内の顧客データはサンプル データのみであるため)。 個人用メール アドレスを使用できます。CUSTOMER_PHONE_NUMBER
: SMS メッセージを送信するために他の国で追加の検証が必要なため、米国ベースの電話番号 (現在) を指定する必要があります。 米国ベースの番号がない場合は、空のままにしておくことができます。
アプリケーションおよび API サーバーの起動/再起動
ここまでに完了した演習に基づいて、次の手順の 1 つ実行します。
前の演習でデータベース、API サーバー、Web サーバーを起動した場合は、API サーバーと Web サーバーを停止し、再起動して .env ファイルの変更を取得する必要があります。 データベースは実行したままにしておくことができます。
API サーバーと Web サーバーを実行しているターミナル ウィンドウを見つけて、 CTRL + C キーを押して停止します。 各ターミナル ウィンドウに「
npm start
」と入力し、 Enter キーを押して、もう一度起動します。 次の演習に進みます。データベース、API サーバー、および Web サーバーをまだ起動していない場合は、次の手順を実行します。
次の手順では、Visual Studio Code で 3 つのターミナル ウィンドウを作成します。
Visual Studio Code ファイルの一覧で .env ファイルを右クリックし、 統合ターミナルで開くを選択します。 続行する前に、ターミナルがプロジェクトのルート ( openai-acs-msgraph ) にあることを確認します。
PostgreSQL データベース 開始するには、次のオプションの 1 つ から選択します。
Docker Desktopをインストールして実行している場合は、ターミナル ウィンドウで
docker-compose up
を実行し、Enter キーを押します。podman に podman-compose インストールして実行している場合は、ターミナル ウィンドウで
podman-compose up
を実行し、 Enter キーを押します。Docker Desktop、Podman、nerdctl、またはインストールした別のコンテナー ランタイムを使用して PostgreSQL コンテナーを直接実行するには、ターミナル ウィンドウで次のコマンドを実行します。
Mac、Linux、または Linux 用 Windows サブシステム (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 ターミナル ツール バーの+ アイコンを押して、2 番目のターミナル ウィンドウを作成します。
cd
を server/typescript フォルダーに移動し、次のコマンドを実行して依存関係をインストールし、API サーバーを起動します。npm install
npm start
Visual Studio Code ターミナル ツール バーの + アイコンをもう一度押して 3 番目のターミナル ウィンドウを作成します。
cd
client フォルダーに移動し、次のコマンドを実行して依存関係をインストールし、Web サーバーを起動します。npm install
npm start
ブラウザーが起動し、 http://localhost:4200されます。
コミュニケーション: 電話をかける
Azure Communication Services の電話呼び出し機能をカスタム基幹業務 (LOB) アプリケーションに統合すると、企業とそのユーザーにいくつかの重要な利点があります。
- 従業員、顧客、パートナー間のシームレスでリアルタイムなコミュニケーションを LOB アプリケーション内から直接行えるようにし、複数のプラットフォームまたはデバイスを切り替える必要がなくなります。
- ユーザー エクスペリエンスを強化し、全体的な運用効率を向上させます。
- ユーザーが関連するサポート チームや分野の専門家とすばやく簡単に接続できるため、迅速な問題解決を容易にします。
この演習では、次のことを行います。
- アプリケーションの電話呼び出し機能を調べる。
- このコードを見て、電話呼び出し機能の構築方法について説明します。
電話通話機能の使用
前の演習ではAzure Communication Services (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) に戻り、データ グリッドを見つけて、最初の行で Contact Customer 次に Call Customer を選択します。
電話呼び出しコンポーネントがヘッダーに追加されます。 通話する電話番号を入力し (+で始まり、国番号が含まれていることを確認します)、 Callを選択します。 マイクへのアクセスを許可するように求められます。
[ Hang Up を選択して通話を終了します。 Close を選択して通話コンポーネントを閉じます。
電話呼び出しコードの探索
ヒント
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 }); }
Note
イベント バス コードは、 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です。 次の主な機能に注意してください。
-
acsService.getAcsToken()
でngOnInit()
関数を呼び出して、Azure Communication Services アクセス トークンを取得します。 - ページに "電話ダイヤラー" を追加します。 ヘッダーの電話番号入力をクリックすると、ダイヤラーを確認できます。
-
startCall()
関数とendCall()
関数をそれぞれ使用して呼び出しを開始および終了します。
-
電話をかけるコードを見る前に、ACS アクセス トークンがどのように取得され、電話呼び出しオブジェクトがどのように作成されるかを調べてみましょう。
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
の新しいインスタンスを作成します。 -
CallAgent
オブジェクトとCallClient
オブジェクトを使用して、AzureCommunicationTokenCredential
の新しいインスタンスを作成します。 後で、呼び出しの開始と終了にCallAgent
が使用されていることがわかります。
- アクセス トークンを使用して、
-
acs.services.tsを開き、
getAcsToken()
関数を見つけます。 ファイルへの完全なパスは、 client/src/app/core/acs.service.tsです。 この関数は、API サーバーによって公開される/acstoken
ルートに対して HTTP GET 要求を行います。getAcsToken(): Observable<AcsUser> { return this.http.get<AcsUser>(this.apiUrl + 'acstoken') .pipe( catchError(this.handleError) ); }
createACSToken()
という名前の API サーバー関数は、userId とアクセス トークンを取得し、クライアントに返します。 server/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, token } = await tokenClient.createUserAndToken(["voip"]); return { userId: user.communicationUserId, token }; }
この関数は次のアクションを実行します。
- ACS
connectionString
値が使用可能かどうかを確認します。 そうでない場合は、空のuserId
とtoken
を持つオブジェクトを返します。 -
CommunicationIdentityClient
の新しいインスタンスを作成し、connectionString
値を渡します。 - "voip" スコープの
tokenClient.createUserAndToken()
を使用して、新しいユーザーとトークンを作成します。 -
userId
値とtoken
値を含むオブジェクトを返します。
- ACS
userId とトークンの取得方法を確認したので、
phone-call.component.ts
に戻り、startCall()
関数を見つけます。この関数は、電話呼び出しコンポーネントで Call が選択されている場合に呼び出されます。 前に説明した
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; // Adding event handlers to monitor call state this.call?.on('stateChanged', () => { console.log('Call state changed: ', this.call?.state); if (this.call?.state === 'Disconnected') { console.log('Call ended. Reason: ', this.call.callEndReason); this.inCall = false; } }); }
endCall()
関数は、電話呼び出しコンポーネントで Hang Up が選択されたときに呼び出されます。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.createUserAndToken()
関数を使用して API サーバーから取得されます。 - トークンは、
CallClient
とCallAgent
オブジェクトを作成するために使用されます。 -
CallAgent
オブジェクトは、callAgent.startCall()
関数とcallAgent.hangUp()
関数をそれぞれ呼び出すことによって、呼び出しを開始および終了するために使用されます。
- ACS userId とアクセス トークンは、
電話呼び出しをアプリケーションに統合する方法を学習したので、Azure Communication Services を使用して電子メールと SMS メッセージを送信することに焦点を切り替えてみましょう。
通信: 電子メールおよび SMS メッセージの送信
Azure Communication Services では、通話に加えて、電子メールおよび SMS メッセージを送信することもできます。 これは、アプリケーションから直接顧客または他のユーザーにメッセージを送信する場合に便利です。
この演習では、次のことを行います。
- アプリケーションから電子メールと SMS メッセージを送信する方法について説明します。
- 電子メールと SMS 機能の実装方法については、コードを確認してください。
電子メールと SMS 機能の使用
前の演習ではAzure Communication Services (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>
続行する前に、 exercise が完了していることを確認します。
ブラウザー (http://localhost:4200) に戻り、最初の行で Contact CustomerEmail/SMS Customer を選択します。
Email/SMS タブを選択し、次のタスクを実行します。
- 電子メール Subject と Body を入力し、 [電子メールの送信 ] ボタンを選択します。
- SMS メッセージを入力し、 Send SMS ボタンを選択します。
Note
米国とカナダでは、フリーダイヤル番号の SMS 認証が必須になりました。 SMS メッセージングを有効にするには、電話番号の購入後に確認を送信する必要があります。 このチュートリアルではこのプロセスを実行しませんが、Azure portal で Azure Communication Services リソースから Telephony と SMS -->Regulatory Documents を選択し、必要な検証ドキュメントを追加できます。
電子メールと SMS メッセージを受信したことを確認します。 SMS 機能は、前のメモに記載されている規制ドキュメントを送信した場合にのみ機能します。 リマインダーとして、電子メール メッセージは
CUSTOMER_EMAIL_ADDRESS
に対して定義された値に送信され、SMS メッセージはCUSTOMER_PHONE_NUMBER
ファイル内のに定義された値に送信されます。 SMS メッセージに使用する米国ベースの電話番号を指定できなかった場合は、その手順をスキップできます。Note
CUSTOMER_EMAIL_ADDRESS
ファイルでに定義したアドレスのメール メッセージが受信トレイに表示されない場合は、スパム フォルダーを確認してください。
電子メール コードの探索
ヒント
Visual Studio Code を使用している場合は、次を選択してファイルを直接開くことができます。
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
次に、開くファイルの名前を入力します。
customers-list.component.ts ファイルを開きます。 ファイルへの完全なパスは、 client/src/app/customers-list/customers-list.component.tsです。
データ グリッドで Contact CustomerEmail/SMS Customer を選択すると、
customer-list
コンポーネントにダイアログ ボックスが表示されます。 これは、openEmailSmsDialog()
ファイルの関数によって処理されます。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
オブジェクト (データ グリッドの行を表します) に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 機能を 1 つの場所に統合できます。
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) ); }
sendEmail()
のAcsService
関数は、次のタスクを実行します。-
http.post()
関数を呼び出し、電子メールの件名、メッセージ、顧客名、顧客の電子メール アドレスを渡します。http.post()
関数は、API 呼び出しからの応答を含む RxJS 監視可能なオブジェクトを返します。 - RxJS
http.post()
演算子を使用して、catchError
関数によって返されるすべてのエラーを処理します。
-
次に、アプリケーションが ACS 電子メール機能とどのように対話するかを調べてみましょう。 acs.ts ファイルを開き、
sendEmail()
関数を見つけます。 ファイルへの完全なパスは server/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()
関数を使用して電子メールを送信し、応答を返します。 この例では、関数は 1 人の受信者にのみ送信しますが、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()
関数は、API 呼び出しからの応答を含む RxJS 監視可能なオブジェクトを返します。 - RxJS
http.post()
演算子を使用して、catchError
関数によって返されるすべてのエラーを処理します。
-
最後に、アプリケーションが ACS SMS 機能とどのように対話するかを調べてみましょう。 acs.ts ファイルを開きます。 ファイルへの完全なパスは server/typescript/acs.ts であり、
sendSms()
関数を見つけます。sendSms()
関数は、次のタスクを実行します。新しい
SmsClient
オブジェクトを作成し、ACS 接続文字列を渡します (この値はACS_CONNECTION_STRING
環境変数から取得されます)。const smsClient = new SmsClient(connectionString);
smsClient.send()
関数を呼び出し、ACS の電話番号 (from
)、顧客の電話番号 (to
)、SMS メッセージを渡します。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
オブジェクトを使用して、電子メールおよび SMS メッセージを送信します。
電子メールと SMS メッセージを送信する方法を学習したので、組織データをアプリケーションに統合することに焦点を当ててみましょう。
組織データ: Microsoft Entra ID アプリ登録の作成
組織データ (メール、ファイル、チャット、予定表イベント) をカスタム アプリケーションに直接統合することで、ユーザーの生産性を向上させます。 Microsoft Graph API と Microsoft Entra ID を使用すると、アプリ内で関連するデータをシームレスに取得して表示できるため、ユーザーがコンテキストを切り替える必要が減ります。 顧客に送信されたメールを参照する場合でも、Teams メッセージを確認する場合でも、ファイルにアクセスする場合でも、ユーザーはアプリを離れることなく必要な情報をすばやく見つけることができ、意思決定プロセスを合理化できます。
この演習では、次のことを行います。
- Microsoft Graph が組織のデータにアクセスしてアプリに取り込むことができるように、Microsoft Entra ID アプリの登録を作成します。
- チャット メッセージを特定のチャネルに送信するために必要なMicrosoft Teamsから
team
ID とchannel
ID を見つけます。 - プロジェクトの .env ファイルを Microsoft Entra ID アプリ登録の値で更新します。
Microsoft Entra ID アプリ登録を作成する
Azure ポータルに移動しMicrosoft Entra ID選択します。
Manage -->アプリの登録 の後に + 新規登録 を選択します。
次に示すように、新しいアプリ登録フォームの詳細を入力し、 Registerを選択します。
- 名前: microsoft-graph-app
- サポートされているアカウントの種類: 任意の組織ディレクトリの Accounts (任意の Microsoft Entra ID テナント - マルチテナント)
- リダイレクト URI:
-
Single-page アプリケーション (SPA) を選択し、
http://localhost:4200
フィールドにを入力します。
-
Single-page アプリケーション (SPA) を選択し、
- [登録] を選択して、アプリの登録を作成します。
リソース メニューで Overview を選択し、
Application (client) ID
の値をクリップボードにコピーします。
プロジェクトの .env ファイルを更新する
エディターで .env ファイルを開き、
Application (client) ID
値をENTRAID_CLIENT_ID
に割り当てます。ENTRAID_CLIENT_ID=<APPLICATION_CLIENT_ID_VALUE>
アプリから Teams チャネルにメッセージを送信できるようにする場合は、Microsoft 365 開発テナント アカウントを使用して Microsoft Teams にサインインします (このチュートリアルの事前の質問に記載されています)。
サインインしたら、チームを展開し、アプリからメッセージを送信するチャネルを見つけます。 たとえば、 Company チームと General チャネル (または使用する任意のチーム/チャネル) を選択できます。
チーム ヘッダーで、3 つのドット (...) をクリックし、 チームへのリンクを取得を選択します。
ポップアップ ウィンドウに表示されるリンクでは、チーム ID は
team/
後の文字と数字の文字列です。 たとえば、リンク "https://teams.microsoft.com/l/team/19%3ae9b9.../"" では、チーム ID は 19%3ae9b9... 次の/
文字まで。チーム ID をコピーし、
TEAM_ID
ファイル内のに割り当てます。チャネル ヘッダーで、3 つのドット (...) をクリックし、チャネルへの Get リンクを選択します。
ポップアップ ウィンドウに表示されるリンクでは、チャネル ID は
channel/
後の文字と数字の文字列です。 たとえば、リンク "https://teams.microsoft.com/l/channel/19%3aQK02.../" では、チャネル ID は 19%3aQK02... 次の/
文字まで。チャネル ID をコピーし、
CHANNEL_ID
ファイル内のに割り当てます。続行する前に、 env ファイルを保存します。
アプリケーションおよび API サーバーの起動/再起動
ここまでに完了した演習に基づいて、次の手順の 1 つ実行します。
前の演習でデータベース、API サーバー、Web サーバーを起動した場合は、API サーバーと Web サーバーを停止し、再起動して .env ファイルの変更を取得する必要があります。 データベースは実行したままにしておくことができます。
API サーバーと Web サーバーを実行しているターミナル ウィンドウを見つけて、 CTRL + C キーを押して停止します。 各ターミナル ウィンドウに「
npm start
」と入力し、 Enter キーを押して、もう一度起動します。 次の演習に進みます。データベース、API サーバー、および Web サーバーをまだ起動していない場合は、次の手順を実行します。
次の手順では、Visual Studio Code で 3 つのターミナル ウィンドウを作成します。
Visual Studio Code ファイルの一覧で .env ファイルを右クリックし、 統合ターミナルで開くを選択します。 続行する前に、ターミナルがプロジェクトのルート ( openai-acs-msgraph ) にあることを確認します。
PostgreSQL データベース 開始するには、次のオプションの 1 つ から選択します。
Docker Desktopをインストールして実行している場合は、ターミナル ウィンドウで
docker-compose up
を実行し、Enter キーを押します。podman に podman-compose インストールして実行している場合は、ターミナル ウィンドウで
podman-compose up
を実行し、 Enter キーを押します。Docker Desktop、Podman、nerdctl、またはインストールした別のコンテナー ランタイムを使用して PostgreSQL コンテナーを直接実行するには、ターミナル ウィンドウで次のコマンドを実行します。
Mac、Linux、または Linux 用 Windows サブシステム (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 ターミナル ツール バーの+ アイコンを押して、2 番目のターミナル ウィンドウを作成します。
cd
を server/typescript フォルダーに移動し、次のコマンドを実行して依存関係をインストールし、API サーバーを起動します。npm install
npm start
Visual Studio Code ターミナル ツール バーの + アイコンをもう一度押して 3 番目のターミナル ウィンドウを作成します。
cd
client フォルダーに移動し、次のコマンドを実行して依存関係をインストールし、Web サーバーを起動します。npm install
npm start
ブラウザーが起動し、 http://localhost:4200されます。
組織データ: ユーザーのサインインとアクセス トークンの取得
Microsoft Graph が組織データにアクセスするには、ユーザーが Microsoft Entra ID で認証する必要があります。 この演習では、Microsoft Graph Toolkit の mgt-login
コンポーネントを使用して、ユーザーを認証し、アクセス トークンを取得する方法について説明します。 その後、アクセス トークンを使用して Microsoft Graph を呼び出すことができます。
Note
Microsoft Graph を初めて使用する場合は、 Microsoft Graph の基礎 ラーニング パスを参照してください。
この演習では、次のことを行います。
- Microsoft Entra ID アプリを Microsoft Graph Toolkit に関連付けてユーザーを認証し、組織データを取得する方法について説明します。
- スコープの重要性について説明します。
- Microsoft Graph Toolkit の mgt-login コンポーネントを使用してユーザーを認証し、アクセス トークンを取得する方法について説明します。
サインイン機能の使用
前の演習では、Microsoft Entra ID でアプリ登録を作成し、アプリケーション サーバーと API サーバーを起動しました。 また、
.env
ファイル内の次の値も更新しました (TEAM_ID
とCHANNEL_ID
は省略可能です)。ENTRAID_CLIENT_ID=<APPLICATION_CLIENT_ID_VALUE> TEAM_ID=<TEAMS_TEAM_ID> CHANNEL_ID=<TEAMS_CHANNEL_ID>
続行する前に、 前の演習 が完了していることを確認します。
ブラウザー (http://localhost:4200) に戻り、ヘッダーで [ サインイン を選択し、Microsoft 365 Developer テナントの管理者ユーザー アカウントを使用してサインインします。
ヒント
Microsoft 365 開発者テナント管理者アカウントでサインインします。 Microsoft 365 管理センターに移動すると、開発者テナント内の他のユーザーを表示できます。
アプリケーションに初めてサインインする場合は、アプリケーションによって要求されたアクセス許可に同意するように求められます。 これらのアクセス許可 ("スコープ" とも呼ばれます) の詳細については、次のセクションでコードを調べる際に学習します。 [同意する] を選択して続行します。
サインインすると、ヘッダーに表示されるユーザーの名前が表示されます。
サインイン コードの探索
サインインしたので、ユーザーのサインインに使用するコードを見て、アクセス トークンとユーザー プロファイルを取得しましょう。 Microsoft Graph Toolkit の一部である mgt-login Web コンポーネントについて学習します。
ヒント
Visual Studio Code を使用している場合は、次を選択してファイルを直接開くことができます。
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
次に、開くファイルの名前を入力します。
client/package.jsonを開き、
@microsoft/mgt
パッケージと@microsoft/mgt-components
パッケージが依存関係に含まれていることに注意してください。@microsoft/mgt
パッケージには、MSAL (Microsoft Authentication Library) プロバイダーの機能と、ユーザーのサインインや組織データの取得と表示に使用できる mgt-login などの Web コンポーネントが含まれています。client/src/main.ts を開き、
@microsoft/mgt-components
パッケージから次のインポートが行われます。 インポートされたシンボルは、アプリケーションで使用される Microsoft Graph Toolkit コンポーネントを登録するために使用されます。import { registerMgtLoginComponent, registerMgtSearchResultsComponent, registerMgtPersonComponent, } from '@microsoft/mgt-components';
ファイルの一番下までスクロールし、次のコードを書き留めます。
registerMgtLoginComponent(); registerMgtSearchResultsComponent(); registerMgtPersonComponent();
このコードは、
mgt-login
、mgt-search-results
、およびmgt-person
Web コンポーネントを登録し、アプリケーションで使用できるようにします。mgt-login コンポーネントを使用してユーザーをサインインさせるには、Microsoft Entra ID アプリのクライアント ID (として
ENTRAID_CLIENT_ID
ファイルに格納) を参照して使用する必要があります。graph.service.tsを開き、
init()
関数を見つけます。 ファイルへの完全なパスは client/src/app/core/graph.service.ts です。 次のインポートとコードが表示されます。import { Msal2Provider, Providers, ProviderState } from '@microsoft/mgt'; init() { if (!this.featureFlags.microsoft365Enabled) return; if (!Providers.globalProvider) { console.log('Initializing Microsoft Graph global provider...'); Providers.globalProvider = new Msal2Provider({ clientId: ENTRAID_CLIENT_ID, scopes: ['User.Read', 'Presence.Read', 'Chat.ReadWrite', 'Calendars.Read', 'ChannelMessage.Read.All', 'ChannelMessage.Send', 'Files.Read.All', 'Mail.Read'] }); } else { console.log('Global provider already initialized'); } }
このコードは、新しい
Msal2Provider
オブジェクトを作成し、アプリの登録から Microsoft Entra ID クライアント ID と、アプリがアクセスを要求するscopes
を渡します。scopes
は、アプリがアクセスする Microsoft Graph リソースへのアクセスを要求するために使用されます。Msal2Provider
オブジェクトが作成されると、Providers.globalProvider
オブジェクトに割り当てられます。このオブジェクトは、Microsoft Graph Toolkit コンポーネントによって Microsoft Graph からデータを取得するために使用されます。エディターで header.component.html を開き、 mgt-login コンポーネントを見つけます。 ファイルへの完全なパスは client/src/app/header/header.component.html。
@if (this.featureFlags.microsoft365Enabled) { <mgt-login 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
関数を見つけます。 この関数は、loginCompleted
イベントが生成されたときに呼び出され、Providers.globalProvider
を使用してサインインしているユーザーのプロファイルの取得を処理します。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 Toolkit ドキュメントを参照してください。
アプリケーションにログインしたので、組織のデータを取得する方法を見てみましょう。
組織データ: ファイルの取得、チャット、Teams へのメッセージの送信
今日のデジタル環境では、ユーザーはメール、チャット、ファイル、予定表イベントなど、さまざまな組織データを操作します。 これにより、頻繁なコンテキストシフト (タスクまたはアプリケーションの切り替え) が発生し、フォーカスが中断され、生産性が低下する可能性があります。 たとえば、プロジェクトで作業しているユーザーは、現在のアプリケーションから Outlook に切り替えて、メールで重要な詳細を見つけたり、OneDrive for Business に切り替えて関連ファイルを見つけたりする必要がある場合があります。 この前後のアクションにより、フォーカスが中断され、目の前のタスクに費やされる可能性のある時間が無駄になります。
効率を高めるために、ユーザーが日常的に使用するアプリケーションに組織データを直接統合できます。 組織のデータをアプリケーションに取り込むことで、ユーザーはよりシームレスに情報にアクセスして管理でき、コンテキストの変化を最小限に抑え、生産性を向上させることができます。 さらに、この統合により、貴重な分析情報とコンテキストが提供され、ユーザーは情報に基づいた意思決定を行い、より効果的に作業できるようになります。
この演習では、次のことを行います。
- Microsoft Graph Toolkit の mgt-search-results Web コンポーネントを使用してファイルを検索する方法について説明します。
- Microsoft Graph を直接呼び出して OneDrive for Business からファイルを取得し、Microsoft Teamsからメッセージをチャットする方法について説明します。
- Microsoft Graph を使用してMicrosoft Teams チャネルにチャット メッセージを送信する方法について説明します。
組織データ機能の使用
前の演習では 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)。 まだサインインしていない場合は、ヘッダーで Sign In を選択し、Microsoft 365 Developer テナントのユーザーとサインインします。
Note
ユーザーの認証に加えて、 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'] });
データ グリッドの [Adatum Corporation 行に対して関連コンテンツの表示を選択します。 これにより、ファイル、チャット、メール、予定表イベントなどの組織データが Microsoft Graph を使用して取得されます。 データが読み込まれると、タブ付きインターフェイスのデータ グリッドの下に表示されます。 Microsoft 365 開発者テナントにユーザーのファイル、チャット、電子メール、予定表イベントをまだ追加していないため、この時点ではデータが表示されない可能性があることを言及することが重要です。 次の手順で修正してみましょう。
この段階では、Microsoft 365 テナントに Adatum Corporation の関連する組織データがない可能性があります。 サンプル データを追加するには、次のいずれかの操作を実行します。
https://onedrive.comにアクセスし、Microsoft 365 Developer テナントの資格情報を使用してサインインすることで、ファイルを追加します。
- 左側のナビゲーションで マイ ファイル を選択します。
- [+ 新規追加] を選択しメニューから [フォルダーのアップロードをします。
- 複製したプロジェクトから openai-acs-msgraph/customer documents フォルダーを選択します。
https://teams.microsoft.comにアクセスし、Microsoft 365 Developer テナントの資格情報を使用してサインインすることで、チャット メッセージと予定表イベントを追加します。
左側のナビゲーションで Teams を選択します。
チームとチャネルを選択します。
投稿の開始を選択します。
件名と、メッセージ本文に追加する追加のテキストに Adatum Corporation の新しい注文を入力します。 [転記] ボタンを選択します。
Adventure Works Cycles、Contoso Pharmaceuticals、Tailwind Traders など、アプリケーションで使用されている他の企業に言及するチャット メッセージを追加してください。
左側のナビゲーションで Calendar を選択します。
[新しい会議選択します。
タイトルと本文に「Meet with Adatum Corporation about project schedule」と入力します。
[保存] を選択します。
https://outlook.comにアクセスし、Microsoft 365 Developer テナントの資格情報を使用してサインインして、電子メールを追加します。
[新しいメールを選択します。
To フィールドに個人の電子メール アドレスを入力します。
件名と本文に必要なものについては Adatum Corporation の新しい注文を入力します。
[Send] を選択します。
ブラウザーでアプリケーションに戻り、ページを更新します。 Adatum Corporation 行[関連コンテンツの表示]もう一度選択します。 前の手順で実行したタスクに応じて、タブにデータが表示されます。
アプリケーションで組織のデータ機能を有効にするコードを調べてみましょう。 データを取得するために、アプリケーションのクライアント側の部分は、前に見た mgt-login コンポーネントによって取得されたアクセス トークンを使用して、Microsoft Graph API を呼び出します。
ファイル検索コードの探索
ヒント
Visual Studio Code を使用している場合は、次を選択してファイルを直接開くことができます。
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
次に、開くファイルの名前を入力します。
まず、OneDrive for Business からファイル データを取得する方法を見てみましょう。 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 for Business でファイルを検索するために使用されます。queryString
属性は、検索語句を指定するために使用されます。 この場合、ユーザーがデータ グリッド内の行に対してsearchText
を選択すると、files コンポーネントに渡される プロパティに値がバインドされます。queryString
の周りの角かっこは、プロパティがsearchText
値にバインドされていることを示します。dataChange
イベントは、検索結果が変更されたときに発生します。 この場合、dataChange()
という名前の顧客関数が files コンポーネントで呼び出され、イベント データが関数に渡されます。dataChange
のかっこは、イベントがdataChange()
関数にバインドされていることを示します。カスタム テンプレートは指定されていないため、
mgt-search-results
に組み込まれている既定のテンプレートを使用して検索結果が表示されます。
mgt-search-results などのコンポーネントを使用する代わりに、コードを使用して Microsoft Graph API を直接呼び出します。 そのしくみを確認するには、 graph.service.ts ファイルを開き、
searchFiles()
関数を見つけます。 ファイルへの完全なパスは client/src/app/core/graph.service.ts です。query
パラメーターが関数に渡されていることがわかります。 これは、ユーザーがデータ グリッド内の行に対して View Related Content を選択すると渡される検索用語です。 検索語句が渡されない場合は、空の配列が返されます。async searchFiles(query: string) { const files: DriveItem[] = []; if (!query) return files; ... }
次に、実行する検索の種類を定義するフィルターが作成されます。 この場合、コードは OneDrive for Business でファイルを検索しているため、
driveItem
コンポーネントで前に見たのと同じようにmgt-search-results
が使用されます。 これは、前に確認したdriveItem
コンポーネントのentity-types
にを渡すのと同じです。query
パラメーターは、queryString
と共にContentType:Document
フィルターに追加されます。const filter = { "requests": [ { "entityTypes": [ "driveItem" ], "query": { "queryString": `${query} AND ContentType:Document` } } ] };
その後、
/search/query
関数を使用して、Providers.globalProvider.graph.client.api()
Microsoft Graph API に対して呼び出しが行われます。filter
オブジェクトは、API にデータを送信するpost()
関数に渡されます。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 コンポーネントが多くの作業を行い、記述する必要があるコードの量を大幅に削減していることがわかります。 ただし、API に送信されるデータや結果の処理方法をより詳細に制御するために、Microsoft Graph を直接呼び出すシナリオが存在する場合があります。
files.component.ts ファイルを開き、
search()
関数を見つけます。 ファイルへの完全なパスは、 client/src/app/files/files.component.tsです。mgt-search-results コンポーネントが使用されているため、この関数の本文はコメント アウトされますが、ユーザーがデータ グリッド内の行に対して View Related Content を選択したときに、この関数を使用して Microsoft Graph を呼び出すことができます。
search()
関数は、searchFiles()
でを呼び出し、query
パラメーター (この例の会社名) を渡します。 検索の結果は、コンポーネントのdata
プロパティに割り当てられます。override async search(query: string) { this.data = await this.graphService.searchFiles(query); }
ファイル コンポーネントでは、
data
プロパティを使用して検索結果を表示できます。 これは、カスタム HTML バインドを使用するか、mgt-file-list
という名前の別の Microsoft Graph Toolkit コントロールを使用して処理できます。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 に投稿し、検索語句に一致するteamId
、channelId
、messageId
に関する情報を持つオブジェクトの配列に結果を変換します。 - Teams チャネル メッセージを取得するために、
/teams/${chat.teamId}/channels/${chat.channelId}/messages/${chat.messageId}
API に対して 2 回目の呼び出しが行われ、teamId
、channelId
、およびmessageId
が渡されます。 これにより、メッセージの完全な詳細が返されます。 - 追加のフィルター 処理タスクが実行され、結果のメッセージが
searchChatMessages()
から呼び出し元に返されます。
- フィルター データを Microsoft Graph の
chats.component.ts ファイルを開き、
search()
関数を見つけます。 ファイルの完全なパスは client/src/app/chats/chats.component.ts です。search()
関数は、searchChatMessages()
でを呼び出し、query
パラメーターを渡します。override async search(query: string) { this.data = await this.graphService.searchChatMessages(query); }
検索の結果はコンポーネントの
data
プロパティに割り当てられ、データ バインディングを使用して結果配列を反復処理し、データをレンダリングします。 次の使用例は、 Angular Material カード コンポーネントを使用して検索結果を表示します。@if (this.data.length) { <div> @for (chatMessage of this.data;track chatMessage.id) { <mat-card> <mat-card-header> <mat-card-title [innerHTML]="chatMessage.summary"></mat-card-title> <!-- <mat-card-subtitle [innerHTML]="chatMessage.body"></mat-card-subtitle> --> </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 チャネルにメッセージを送信することもできます。 これを行うには、Microsoft Graph の
/teams/${teamId}/channels/${channelId}/messages
エンドポイントを呼び出します。次のコードでは、
teamId
とchannelId
の値を含む URL が作成されていることがわかります。 この例では、環境変数の値はチーム ID とチャネル ID に使用されますが、これらの値は 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 Graph Toolkit の mgt-search-results コンポーネントを使用して、OneDrive for Business からファイルとチャットをMicrosoft Teamsから取得する方法について説明しました。 また、Microsoft Teams チャネルにメッセージを送信する方法についても学習しました。 この演習では、Microsoft Graph から電子メール メッセージと予定表イベントを取得し、それらをアプリケーションに統合する方法について説明します。
この演習では、次のことを行います。
- Microsoft Graph Toolkit の mgt-search-results Web コンポーネントを使用してメールや予定表イベントを検索する方法について説明します。
- mgt-search-results コンポーネントをカスタマイズして、検索結果をカスタムの方法でレンダリングする方法について説明します。
- Microsoft Graph を直接呼び出して、メールと予定表イベントを取得する方法について説明します。
電子メール メッセージ検索コードの探索
ヒント
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
プロパティを反復処理し、電子メールの件名、本文のプレビュー、および完全な電子メール メッセージを表示するリンクを書き出します。@if (this.data.length) { <div> @for (email of this.data;track $index) { <mat-card> <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()
関数を見つけます。 Microsoft Graph のmessages
エンドポイントを呼び出すために使用できる 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にある emails コンポーネントは
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
イベントは、検索結果が変更されたときに発生します。 calendar event コンポーネントのdataChange()
関数が呼び出され、結果が渡され、コンポーネントでdata
という名前のプロパティが更新されます。 - コンポーネントに対して空のテンプレートが定義されています。 このシナリオでは、データをレンダリングしないようにコンポーネントに指示しています。 代わりに、標準のデータ バインディングを使用してデータを自分でレンダリングします。
-
mgt-search-results
の コンポーネントのすぐ下に、カレンダー イベントのレンダリングに使用されるデータ バインディングが表示されます。 この例では、data
プロパティを反復処理し、イベントの開始日、時刻、および件名を書き出します。dayFromDateTime()
やtimeRangeFromEvent()
などのコンポーネントに含まれるカスタム関数は、データを適切に書式設定するために呼び出されます。 HTML バインドには、Outlook の予定表イベントを表示するためのリンクと、イベントが指定されている場合のイベントの場所も含まれます。@if (this.data.length) { <div> @for (event of this.data;track $index) { <div class="root"> <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"> @if (!this.event.resource.bodyPreview?.includes('Join Microsoft Teams Meeting')) { <div class="inner-circle"></div> } </div> <div class="vertical-line bottom"></div> </div> <div class="details"> <div class="subject">{{ event.resource.subject }}</div> @if (this.event.resource.location?.displayName) { <div class="location"> 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> } @if (this.event.resource.attendees?.length) { <div class="attendees"> @for (attendee of this.event.resource.attendees;track attendee.emailAddress.name) { <span class="attendee"> <mgt-person person-query="{{attendee.emailAddress.name}}"></mgt-person> </span> } </div> } @if (this.event.resource.bodyPreview?.includes('Join Microsoft Teams Meeting')) { <div class="online-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> }
Microsoft Graph には、
search/query
API を使用して予定表イベントを検索するだけでなく、予定表イベントの検索にも使用できるevents
API も用意されています。searchCalendarEvents()
で関数を見つけます。searchCalendarEvents()
関数は、検索する期間を定義するために使用される開始日時値と終了日時値を作成します。 次に、Microsoft Graph のevents
エンドポイントを呼び出すために使用できる 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 の内訳を次に示します。
- URL の
/me/events
部分は、サインインしているユーザーのイベントを取得する必要があることを指定するために使用されます。 -
startdatetime
パラメーターとenddatetime
パラメーターを使用して、検索する期間を定義します。 この場合、検索は今後 7 日以内に開始されるイベントを返します。 -
$filter
クエリ パラメーターは、query
値 (この場合はデータ グリッドから選択された会社名) で結果をフィルター処理するために使用されます。contains()
関数は、カレンダー イベントのquery
プロパティでsubject
値を検索するために使用されます。 -
$orderby
クエリ パラメーターは、start/dateTime
プロパティで結果を並べ替えるために使用されます。
- URL の
url
が作成されると、url
の値を使用して Microsoft Graph API に対して GET 要求が行われ、結果が呼び出し元に返されます。前のコンポーネントと同様に、 calendar-events コンポーネント (calendar-events.component.ts ファイル) は
search()
を呼び出して結果を表示します。override async search(query: string) { this.data = await this.graphService.searchCalendarEvents(query); }
Note
カスタム API またはサーバー側アプリケーションから Microsoft Graph 呼び出しを行うことができます。 チュートリアルを参照して Azure 関数から Microsoft Graph API を呼び出す例を確認します。
Microsoft Graph を使用してファイル、チャット、電子メール メッセージ、予定表イベントを取得する例を見てきました。 同じ概念を他の Microsoft Graph API にも適用できます。 たとえば、Microsoft Graph users API を使用して、組織内のユーザーを検索できます。 Microsoft Graph groups API を使用して、組織内のグループを検索することもできます。 Microsoft Graph API の完全な一覧 ドキュメントで確認できます。
おめでとうございます。
このチュートリアルを完了しました
おめでとうございます。 このチュートリアルでは、次の方法を学習しました。
- Azure OpenAI を使用して、ユーザーの生産性を向上させることができます。
- Azure Communication Services を使用して、通信機能を統合できます。
- Microsoft Graph API とコンポーネントを使用して、組織データの取得と表示を行うことができます。
これらのテクノロジを使用すると、コンテキストの変化を最小限に抑え、必要な意思決定情報を提供することで、ユーザーの生産性を向上させる効果的なソリューションを作成できます。
Azure リソースのクリーンアップ
Azure リソースをクリーンアップして、アカウントに対する課金を増やさないようにします。 Azure portal に移動し、次のリソースを削除します。
- Azure AI Search リソース
- Azure Storage リソース
- Azure OpenAI リソース (最初にモデルを削除してから、Azure OpenAI リソースを削除してください)
- Azure Communication Services リソース
次のステップ
ドキュメント
- Azure OpenAI ドキュメント
- 独自のデータに基づく Azure OpenAI
- Azure Communication Services のドキュメント
- Microsoft Graph のドキュメント
- Microsoft Graph Toolkit のドキュメント
- Microsoft Teams開発者向けドキュメント
トレーニング コンテンツ
- Azure OpenAI Service でプロンプト エンジニアリングを適用する
- Azure OpenAI Service で作業を開始する
- Azure Communication Services の概要
- Microsoft Graph の基礎
- ビデオ コース: 初心者向けの Microsoft Graph の基礎
- JavaScript 開発用の Microsoft Graph シナリオを調べる
- ASP.NET Core 開発の Microsoft Graph シナリオを確認する
- Microsoft Graph Toolkit の概要
- Teams Toolkit for Visual Studio Code を使用してMicrosoft Teams用アプリをビルドして展開する
このセクションに問題がある場合 このセクションを改善できるよう、フィードバックをお送りください。