OpenAI、コミュニケーション、組織のデータ機能を基幹業務アプリに統合する
レベル: 中間
このチュートリアルでは、Azure OpenAI、Azure Communication Services、および Microsoft Graph/Microsoft Graph Toolkit を基幹業務 (LOB) アプリケーションに統合して、ユーザーの生産性を向上させ、ユーザー エクスペリエンスを向上させ、LOB アプリを次のレベルに引き上げる方法について説明します。
- AI: ユーザーが自然言語で質問し、データベースのクエリに使用できる SQL に回答を変換したり、ユーザーが電子メールや SMS メッセージを自動的に生成するために使用できるルールを定義したり、自然言語を使用して独自のカスタム データ ソースからデータを取得する方法を学習したりできます。 これらの機能には Azure OpenAI が使用されます。
- コミュニケーション: Azure Communication Servicesを使用して、顧客へのアプリ内通話とEmail/SMS 機能を有効にします。
- 組織データ: ユーザーがコンテキストの切り替えを回避するために顧客と連携する場合に必要な関連する組織データ (ドキュメント、チャット、メール、予定表イベント) を取り込みます。 この種の組織データへのアクセスを提供すると、必要な特定のデータと機能がアプリで直接提供されるため、ユーザーが Outlook、Teams、OneDrive、その他のカスタム アプリ、電話などに切り替える必要がなくなります。 この機能には、Microsoft Graph と Microsoft Graph Toolkit が使用されます。
アプリケーションは、ユーザーが顧客と関連データを管理できるシンプルな顧客管理アプリです。 これは、TypeScript を使用して構築されたフロントエンドで構成され、バックエンド API を呼び出してデータの取得、AI 機能の操作、電子メール/SMS メッセージの送信、組織データの取得を行います。 このチュートリアルで説明するアプリケーション ソリューションの概要を次に示します。
このチュートリアルでは、必要な Azure および Microsoft 365 リソースを設定するプロセスについて説明します。 また、AI、通信、組織のデータ機能を実装するために使用されるコードについても説明します。 コードをコピーして貼り付ける必要はありませんが、いくつかの演習では、さまざまなシナリオを試すためにコードを変更する必要があります。
このチュートリアルで構築する内容
独自の冒険を選択する
チュートリアル全体を最初から最後まで完了するか、関心のある特定のトピックを完了することができます。 このチュートリアルは、次のトピック領域に分かれています。
- プロジェクト演習 (必須の演習 ) を複製します。
- AI 演習: Azure OpenAI リソース を作成し、それを使用して自然言語を SQL に変換し、電子メール/SMS メッセージを生成し、独自のデータとドキュメントを操作します。
- コミュニケーション演習: Azure Communication Services リソースを作成し、それを使用してアプリから電話をかけ、メール/SMS メッセージを送信します。
- 組織データの演習: Microsoft Graph と Microsoft Graph Toolkit を使用して組織データを認証し、アプリケーションにプルできるように、Microsoft Entra IDアプリの登録を作成します。
前提条件
- ノード - このプロジェクトでは、ノード 16 以降と npm 7 以降が使用されます
- git
- Visual Studio Code (Visual Studio Code をお勧めしますが、任意のエディターを使用できます)
- Azure サブスクリプション
- Microsoft 365 開発者テナント
- Docker Desktop 、または Podman などの別の OCI (Open Container Initiative) 準拠のコンテナー ランタイム、またはコンテナーを実行できる nerdctl 。
このチュートリアルで使用される Microsoft Cloud Technologies
- Microsoft Entra ID
- Azure Communication Services
- Azure OpenAI Service
- Microsoft Graph
- Microsoft Graph Toolkit
プロジェクトを複製する
このチュートリアルで使用するコード プロジェクトは、 で 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 を使用しますが、任意のコード エディターを使用してサンプル プロジェクトを操作できます。
次のフォルダーとファイルに注目してください。
- client: クライアント側のアプリケーション コード。
- server: サーバー側 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 で次の値を更新します。 これらの値は、ローカル PostgreSQL データベースに接続するために API サーバーによって使用されます。
POSTGRES_USER=web POSTGRES_PASSWORD=web-password
プロジェクトの準備ができたので、いくつかのアプリケーション機能を試して、それらがどのように構築されているかを学習しましょう。 下の [ 次へ ] ボタンを選択して、目次を使用して特定の演習を続行またはジャンプします。
AI: Azure OpenAI リソースを作成し、モデルをデプロイする
アプリケーションで Azure OpenAI の使用を開始するには、Azure OpenAI サービスを作成し、自然言語から SQL への変換、電子メール/SMS メッセージ コンテンツの生成などのタスクを実行するために使用できるモデルをデプロイする必要があります。
この演習では、以下のことを行います。
- Azure OpenAI Service リソースを作成します。
- モデルをデプロイします。
- Azure OpenAI Service リソースの値で .env ファイルを更新します。
Azure OpenAI サービス リソースを作成する
ブラウザーでAzure portalにアクセスし、サインインします。
ポータル ページの上部にある検索バーに「openai」と入力し、表示されるオプションから [Azure OpenAI] を選択します。
ツール バーの [ 作成 ] を選択します。
注意
サブスクリプションで Azure OpenAI を有効にするアプリケーション フォームの入力に関するメッセージが表示される場合は、[ ここをクリックして Azure OpenAI サービスへのアクセスを要求する ] リンクを選択し、フォームに入力します。 フォームを完了したら、Azure OpenAI チームが要求を承認するまで待つ必要があります。 承認通知を受け取ったら、この演習に戻ってリソースを作成できます。
このチュートリアルでは Azure OpenAI に焦点を当てていますが、OpenAI API キーがあり、Azure OpenAI へのアクセスを待っている間に使用する場合は、このセクションをスキップして、下 の「プロジェクトの .env ファイルを更新 する」セクションに直接移動できます。 .env ファイルで OpenAI API キーを に
OPENAI_API_KEY
割り当てます (OpenAI に関連するその他.env
の手順は無視できます)。 Azure OpenAI にアクセスしたら、この演習を見直し、リソースとモデルを作成し、Azure OpenAI リソースの値を使用して .env ファイルを更新します。次のタスクを実行します。
- Azure サブスクリプションを選択します。
- 使用するリソース グループを選択します (必要に応じて新しいリソース グループを作成します)。
- 使用するリージョンを選択します。
- リソース名を入力します。 これは一意の値である必要があります。
- Standard S0 価格レベルを選択します。
[確認と送信] 画面が表示されるまで、[次へ] を選択します。 [作成] を選択します
Azure OpenAI リソースが作成されたら、そのリソースに移動し、[リソース管理] セクションで [キーとエンドポイント] を選択します。
[キー 1] と [エンドポイント] の値を見つけます。 次のセクションでは両方の値を使用して、ローカル ファイルにコピーします。
[リソース管理] セクションで [モデル デプロイ] を選択します。
[ デプロイの管理 ] ボタンを選択して、Azure OpenAI Studio に移動します。
ツール バーの [ 新しいデプロイの作成 ] を選択します。
次の値を入力します。
- モデル: gpt-35-turbo。
- モデルのバージョン: 既定値に自動更新します。
- デプロイ名: gpt-35-turbo。
注意
Azure OpenAI では、 さまざまな種類のモデルがサポートされています。 各モデルを使用して、さまざまなシナリオを処理できます。
[作成] を選択します
モデルがデプロイされたら、[プレイグラウンド] セクションで [完了] を選択します。
[デプロイ] ドロップダウンから gpt-35-turbo モデルを選択します。 [例] ドロップダウンから [メールの生成] を選択します。
少し時間を取って、提供されているプロンプト テキストを読んでください。 [ 生成] を選択すると、モデルによって生成されるテキストが表示されます。
警告
モデルの準備ができていないというエラー メッセージが表示される場合は、数分待ってからやり直してください。 モデルが完全にデプロイされ、使用できる状態になるまで数分かかる場合があります。
"完了操作は指定したモデルでは動作しません" というエラーが表示される場合、通常は、既定のバージョンではなく新しいモデル バージョンを選択したことを意味します。 [ デプロイ] を 選択し、前に作成したモデルを削除します。 新しい gpt-35-turbo モデルデプロイを作成し、[ Auto-update to default for the Model version]\( モデル バージョンの既定値に自動更新\) を選択し、 gpt-35-turbo という名前を付け、モデルが完全にデプロイされるのを待ちます。 デプロイされたら、 プレイグラウンド に戻り、もう一度完了を試します。
[ 再生成 を複数回行う] を選択します。 テキストは毎回異なります。
画面の右側に、 Temperature などのプロパティが表示されます。 [温度] の値を 0 に変更し、もう一度 [再生成] を選択します。 生成された電子メール テキストを読み取る。
[最後に 1 回 再生成 する] を選択し、メール テキストが以前に生成されたテキストと同じであることに注意してください。
注意
温度を下げることは、モデルがより反復的で決定的な応答を生成することを意味します。 温度を上げると、予期しない反応や創造的な反応が増えます。
プロジェクトのファイルを .env
更新する
Visual Studio Code に戻るし、プロジェクトの
.env
ルートにあるファイルを開きます。Azure OpenAI リソースから KEY 1 の値をコピーし、openai-acs-msgraph フォルダーのルートにある .env ファイル内の に割り当てます
OPENAI_API_KEY
。OPENAI_API_KEY=<KEY_1_VALUE>
*Endpoint 値をコピーし、.env ファイル内の に
OPENAI_ENDPOINT
割り当てます。 文字が/
存在する場合は、値の末尾から文字を削除します。OPENAI_ENDPOINT=<ENDPOINT_VALUE>
注意
と の値
OPENAI_MODEL
が既に .env ファイルに設定されていることがわかります。OPENAI_API_VERSION
モデル値は gpt-35-turbo に設定されています。これは、この演習で前に作成したモデル名と一致する必要があります。 API バージョンは、 Azure OpenAI リファレンス ドキュメントで定義されているサポートされている値に設定されています。.env ファイルを保存します。
Application Services を起動する
次に、データベース、API サーバー、Web サーバーなどのアプリケーション サービスを起動します。
次の手順では、Visual Studio Code で 3 つのターミナル ウィンドウを作成します。
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、または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
を クライアント フォルダーに追加し、次のコマンドを実行して依存関係をインストールし、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) に戻るし、データ グリッドの下にあるページの [カスタム クエリ] セクションを見つけます。 サンプル クエリ値が既に含まれていることに注意してください。 すべての注文の合計収益を取得します。会社別にグループ化し、市を含めます。
[ クエリの実行 ] ボタンを選択します。 これにより、ユーザーの自然言語クエリが 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 クエリが表示されていることを確認します。 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"] }
ブラウザーに戻るし、[データのリセット] を選択して、すべての顧客を再びデータ グリッドに表示します。
SQL コードに対する自然言語の探索
ヒント
Visual Studio Code を使用している場合は、次を選択してファイルを直接開くことができます。
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
次に、開くファイルの名前を入力します。
注意
この演習の目的は、自然言語で可能なものを SQL 機能に示し、その使用方法を示します。 前に説明したように、実装を続行する前に、この種類の AI がorganizationに適しているかどうかを検討することが重要です。 また、不正アクセスを防ぎ、機密データを保護するために 、適切なプロンプト ルールとデータベース セキュリティ対策を計画することも不可欠 です。
自然言語から 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 を、SQL クエリを実行し、データベースから結果を返す という名前
queryDb
の関数に渡します。
- ユーザー クエリ値を から
エディターで サーバー/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()
の関数が呼び出され、 とuserPrompt
のsystemPrompt
値が渡されます。 - 結果がチェックされ、生成された 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 ボットに対する自然言語" です。
データベース内のテーブル名と列が定義されています。 プロンプトに含まれる大まかなスキーマは 、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 オブジェクト (およびそれ以外の何も) を常に返すように定義されています。
返される JSON オブジェクトの型の例を示します。
ユーザー プロンプトの例と、想定される SQL クエリとパラメーター値が提供されます。 これは 、"少数ショット" 学習と呼ばれます。 LLM は大量のデータに対してトレーニングされますが、いくつかの例だけで新しいタスクに適応できます。 もう 1 つの方法は、例が提供されておらず、モデルが正しい SQL クエリとパラメーター値を生成することが期待される "ゼロショット" 学習です。
システム プロンプトの下部で 2 つの重要なルールが繰り返され、"recency bias" が回避されます。
この関数は
getSQLFromNLP()
、サーバー/openAI.ts ファイルにある という名前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 && useBYOD) { return getAzureOpenAIBYODCompletion(systemPrompt, userPrompt, temperature); } if (isAzureOpenAI) { return getAzureOpenAICompletion(systemPrompt, userPrompt, temperature); } return getOpenAICompletion(systemPrompt, userPrompt, temperature); }
注意
このチュートリアルでは Azure OpenAI に焦点を当てますが、.env ファイルに値のみを指定
OPENAI_API_KEY
した場合、アプリケーションでは代わりに OpenAI が使用されます。 Azure OpenAI の代わりに 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 を呼び出すために使用される値を作成し、環境変数から URL にエンドポイント、モデル、API のバージョン値を埋め込みます。、、および
messages
をmessageData
含むtemperature
max_token
オブジェクトを作成して、Azure OpenAI に送信します。-
max_tokens
: 完了時に生成するトークンの最大数。 プロンプトのトークン数と max_tokens の合計は、モデルのコンテキスト長を超えることはできません。 古いモデルのコンテキスト長は 2,048 トークンですが、新しい モデル では、使用されているモデルに応じて 4,096、8,192、さらには 32,768 トークンがサポートされています。 -
temperature
: 使用するサンプリング温度。 値が大きいほど、モデルはより多くのリスクを取ることを意味します。 よりクリエイティブなアプリケーションの場合は 0.9、明確に定義された回答の場合は 0 を試してください。 -
messages
: チャット入力候補を生成するメッセージをチャット形式で表します。 この例では、システム用とユーザー用の 2 つのメッセージが渡されます。 システム メッセージは、使用される全体的な動作とルールを定義し、ユーザー メッセージはユーザーが提供するプロンプト テキストを定義します。
-
と
headersBody
の値をfetchUrl
Azure OpenAI に送信する を呼び出しますfetchAndParse()
。値を取得して応答を処理します
completion.choices[0].message.content
。 応答に予想される結果が含まれている場合、コードは応答から JSON オブジェクトを抽出して返します。注意
これらのパラメーターとその他の詳細については、 Azure OpenAI リファレンス ドキュメントを参照してください。
関数で次の行を
getSQLFromNLP()
コメントアウトします。// if (isProhibitedQuery(queryData.sql)) { // queryData.sql = ''; // }
openAI.ts保存します。 API サーバーは TypeScript コードを自動的に再構築し、サーバーを再起動します。
ブラウザーに戻るし、[カスタム クエリ] 入力に「データベースからすべてのテーブル名を選択する」と入力します。 [クエリの実行] を選択します。 テーブル名は表示されますか?
サーバー/openAI.tsの 関数に
getSQLFromNLP()
戻るし、システム プロンプトの セクションにRules:
次の規則を追加し、ファイルを保存します。- Do not allow the SELECT query to return table names, function names, or procedure names.
ブラウザーに戻るし、次のタスクを実行します。
- [ データベースからすべてのテーブル名を選択] を [ カスタム クエリ ] 入力に入力します。 [クエリの実行] を選択します。 テーブル名は表示されますか?
- データベースからすべての関数名を選択します。[カスタム クエリ] 入力に「Select all function 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.
[ Select all table names from the database query]\(データベース クエリからすべてのテーブル名を選択する\ ) をもう一度実行します。
ブラウザーにメッセージが表示されます。 次の規則により、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 の知識の必要性が減り、操作が高速化される可能性があります。
生産性の向上: ビジネス アナリスト、マーケティング担当者、エグゼクティブ、その他の非技術ユーザーは、技術専門家に頼らなくてもデータベースから貴重な情報を取得できるため、効率が向上します。
広範なアプリケーション: 高度な言語モデルを使用することで、アプリケーションは幅広いユーザーとユース ケースに対応するように設計できます。
考慮事項:
セキュリティ: 最大の懸念事項の 1 つはセキュリティです。 ユーザーが自然言語を使用してデータベースを操作できる場合は、承認されていないアクセスや悪意のあるクエリを防ぐために、堅牢なセキュリティ対策が必要です。 ユーザーがデータを変更できないように、読み取り専用モードを実装することを検討できます。
データのプライバシー: 特定のデータは機密性が高く、簡単にアクセスできないようにする必要があるため、適切な保護とユーザーのアクセス許可が設定されていることを確認する必要があります。
精度: 自然言語処理は大幅に改善されていますが、完璧ではありません。 ユーザー クエリを誤って解釈すると、不正確な結果や予期しない動作が発生する可能性があります。 予期しない結果がどのように処理されるかを計画する必要があります。
効率性: 自然言語クエリから返される SQL が効率的であるという保証はありません。 場合によっては、後処理ルールで SQL クエリに関する問題が検出された場合に、Azure OpenAI への追加の呼び出しが必要になる場合があります。
トレーニングとユーザー適応: クエリを正しく作成するには、ユーザーをトレーニングする必要があります。 SQL を学習するよりも簡単ですが、まだ学習曲線が関係している可能性があります。
次の演習に進む前に、いくつかの最後の点を考慮する必要があります。
- ここでは、"あなたがすべきという意味ではないからといって" が適用されることを覚えておいてください。 自然言語を SQL にアプリケーションに統合する前に、細心の注意と慎重な計画を行ってください。 潜在的なリスクを理解し、それらを計画することが重要です。
- この種のテクノロジを使用する前に、チーム、データベース管理者、セキュリティ チーム、利害関係者、その他の関係者と潜在的なシナリオについて話し合い、organizationに適していることを確認します。 SQL に対する自然言語がセキュリティ、プライバシー、およびorganizationのその他の要件を満たしているかどうかを検討することが重要です。
- セキュリティは主な懸念事項であり、計画、開発、デプロイのプロセスに組み込まれている必要があります。
- SQL に対する自然言語は非常に強力ですが、プロンプトに必要なルールがあり、後処理機能が含まれていることを確認するために、慎重な計画を立てる必要があります。 この種の機能を実装してテストし、予期しない結果が返されるシナリオを考慮するために、追加の時間を計画します。
- Azure OpenAI を使用すると、顧客は OpenAI と同じモデルを実行しながら、Microsoft Azure のセキュリティ機能を使用できます。 Azure OpenAI では、プライベート ネットワーク、リージョンの可用性、責任ある AI コンテンツのフィルター処理が提供されます。 Azure OpenAI Service のデータ、プライバシー、セキュリティの詳細を確認してください。
Azure OpenAI を使用して自然言語を SQL に変換する方法を確認し、この種の機能を実装することの長所と短所について学習しました。 次の演習では、Azure OpenAI を使用して電子メールと SMS メッセージを生成する方法について説明します。
AI: 完了の生成
SQL の自然言語機能に加えて、Azure OpenAI Service を使用して電子メールと SMS メッセージを生成して、ユーザーの生産性を向上させ、コミュニケーション ワークフローを合理化することもできます。 Azure OpenAI の言語生成機能を利用することで、ユーザーは "Order is delayed 5 days" などの特定のルールを定義でき、システムはそれらのルールに基づいてコンテキストに応じて適切な電子メールと SMS メッセージを自動的に生成します。
この機能は、ユーザーにとって "ジャンプ スタート" として機能し、送信前に簡単にカスタマイズできる慎重に作成されたメッセージ テンプレートをユーザーに提供します。 その結果、メッセージの作成に必要な時間と労力が大幅に削減され、ユーザーは他の重要なタスクに集中できるようになります。 さらに、Azure OpenAI の言語生成テクノロジを自動化ワークフローに統合できるため、システムは定義済みのトリガーに応じて自律的にメッセージを生成して送信できます。 このレベルの自動化により、通信プロセスが高速化されるだけでなく、さまざまなシナリオで一貫性のある正確なメッセージングが保証されます。
この演習では、以下のことを行います。
- さまざまな GPT プロンプトを試してください。
- GPT プロンプトを使用して、メールおよび SMS メッセージの入力候補を生成します。
- GPT の入力候補を有効にするコードを調べる。
- プロンプト エンジニアリングの重要性と、プロンプトにルールを含める方法について説明します。
まず、電子メールと SMS メッセージを生成するために使用できるさまざまなルールを試してみましょう。
GPT 入力候補機能の使用
前の 演習 では、データベース、API、アプリケーションを開始しました。 ファイルも更新しました
.env
。 これらの手順を完了していない場合は、演習の最後の手順に従って続行してください。ブラウザー (http://localhost:4200) に戻るし、データグリッド内の任意の行で [顧客に連絡] を選択し、[Email/SMS Customer] を選択して[メッセージ ジェネレーター] 画面に移動します。
これにより、Azure OpenAI を使用して、定義したメッセージ ルールを Email/SMS メッセージに変換します。 次のタスクを実行します。
[Order is delayed 5 days]\(注文が 5 日遅れる\) などのルールを入力し、[Generate Email/SMS Messages]\(Email/SMS メッセージの生成\) ボタンを選択します。
メールの件名と本文と、SMS 用に生成された短いメッセージが表示されます。
注意
Azure Communication Servicesはまだ有効になっていないため、メールまたは SMS メッセージを送信することはできません。
ブラウザーで電子メール/SMS ダイアログ ウィンドウを閉じます。 この機能の動作を確認したので、それがどのように実装されているかを調べてみましょう。
GPT 入力候補コードの探索
ヒント
Visual Studio Code を使用している場合は、次を選択してファイルを直接開くことができます。
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
次に、開くファイルの名前を入力します。
サーバー/apiRoutes.ts ファイルを開き、ルートを
completeEmailSmsMessages
見つけます。 [Email/SMS メッセージの生成] ボタンが選択されている場合、この API はアプリのフロントエンド部分によって呼び出されます。 ユーザー プロンプト、会社、連絡先の名前の値を本文から取得し、サーバー/openAI.ts ファイルの関数に渡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); });
サーバー/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
は、電子メールと SMS メッセージを生成できる AI アシスタントが必要であることを定義するために使用されます。 にはsystemPrompt
次も含まれます。- メッセージのトーン、開始と終了の形式、SMS メッセージの最大長などを制御するために従うアシスタントの規則。
- 応答に含める必要があるデータに関する情報 - この場合は JSON オブジェクトで、JSON オブジェクトのみ。
- システム プロンプトの下部で 2 つの重要なルールが再び繰り返され 、"recency bias" が回避されます。
-
userPrompt
は、電子メールおよび SMS メッセージの生成時にエンド ユーザーが含めるルールと連絡先名を定義するために使用されます。 前 に入力した Order is delayed 5 days ルールは にuserPrompt
含まれています。 - 関数は、前に
callOpenAI()
調べた関数を呼び出して、電子メールと SMS の入力候補を生成します。
-
ブラウザーに戻るし、ページを更新し、任意の行の [顧客に連絡] を選択し、その後に [Email/SMS Customer] を選択して、メッセージ ジェネレーター画面に再度アクセスします。
メッセージ ジェネレーターの入力に次の規則を入力します。
- 注文は予定より前です。
- 顧客に二度と注文しないように伝えます。私たちは彼らのビジネスを望んでいません。
[Email/SMS メッセージの生成] を選択し、メッセージをメモします。 システム プロンプトのルールは
All messages should have a friendly tone and never use inappropriate language.
、ユーザー プロンプトで負のルールをオーバーライドしています。エディターでサーバー/openAI.ts* に戻るし、関数の
All messages should have a friendly tone and never use inappropriate language.
プロンプトからルールをcompleteEmailSMSMessages()
削除します。 ファイルを保存します。ブラウザーで電子メール/SMS メッセージ ジェネレーターに戻るし、同じルールをもう一度実行します。
- 注文は予定より前です。
- 顧客に二度と注文しないように伝えます。私たちは彼らのビジネスを望んでいません。
[generate Email/SMS Messages]\(Email/SMS メッセージの生成\) を選択し、返されたメッセージに注目します。
これらのシナリオで何が起こっているか。 Azure OpenAI を使用する場合は、 コンテンツ フィルター処理 が適用され、適切な言語が常に使用されるようになります。 OpenAI を使用している場合は、システム プロンプトで定義されているルールを使用して、返されるメッセージが適切であることを確認します。
注意
これは、適切な結果が返されるように、適切な情報とルールを使用してプロンプトをエンジニアリングすることの重要性を示しています。 このプロセスの詳細については、 プロンプト エンジニアリングの概要に関するドキュメントを 参照してください。
で
completeEmailSMSMessages()
行った変更を元にsystemPrompt
戻し、ファイルを保存し、もう一度再実行しますが、ルールのみを使用Order is ahead of schedule.
します (負の規則は含めないでください)。 今回は、期待どおりに返された電子メールと SMS メッセージが表示されます。次の演習に進む前に、いくつかの最後の点を考慮する必要があります。
- 生成されたメッセージを確認するには、人間をループに含める必要があります。 この例の Azure OpenAI 入力候補では、提案された電子メールメッセージと SMS メッセージが返されますが、ユーザーは送信前に上書きできます。 メールを自動化する場合は、承認されたメッセージが確実に送信されるように、何らかの種類の人間によるレビュー プロセスを用意することが重要です。 AI はオートパイロットではなく、copilot であると見なします。
- 入力候補は、プロンプトに追加するルールと同じくらい適切です。 時間をかけて、プロンプトと返される入力候補をテストします。 他のプロジェクト関係者を招待して、完了を確認します。
- 予期しない結果が適切に処理されるように、後処理コードを含める必要がある場合があります。
- システム プロンプトを使用して、AI アシスタントが従う必要があるルールと情報を定義します。 ユーザー プロンプトを使用して、エンド ユーザーが入力候補に含めるルールと情報を定義します。
AI: 独自のデータを取り込む
Azure OpenAI 自然言語処理 (NLP) と補完機能の統合により、ユーザーの生産性を向上させる大きな可能性があります。 適切なプロンプトとルールを活用することで、AI アシスタントは、電子メール メッセージ、SMS メッセージなど、さまざまな形式の通信を効率的に生成できます。 この機能により、ユーザーの効率が向上し、ワークフローが合理化されます。
この機能自体は非常に強力ですが、ユーザーが会社のカスタム データに基づいて入力候補を生成する必要がある場合があります。 たとえば、ユーザーがインストールの問題を顧客に支援しているときに移動するのが困難な製品マニュアルのコレクションがあるとします。 または、医療上の利点に関連する包括的な一連のよく寄せられる質問 (FAQ) を維持して、ユーザーが必要な回答を読み取り、回答を得ることを困難にする可能性があります。 このような場合や他の多くの場合、Azure OpenAI Service を使用すると、独自のデータを活用して補完を生成し、ユーザーの質問に対するより調整されたコンテキストに応じた正確な回答を確保できます。
Azure OpenAI ドキュメントから "Bring Your Own Data" 機能がどのように機能するかの概要を次に示します。
注意
独自のデータに基づく Azure OpenAI の主な特徴の 1 つは、モデルの出力を強化する方法でデータを取得して利用できることです。 独自のデータに基づく Azure OpenAI は、Azure Cognitive Search と連携し、ユーザー入力と提供された会話履歴に基づいて、指定されたデータ ソースからどのデータを取得するかを決定します。 その後、このデータは拡張され、OpenAI モデルに対するプロンプトとして再送信されます。取得された情報は元のプロンプトに追加されます。 取得されたデータはプロンプトに追加されますが、結果として得られた入力は他のプロンプトと同様にモデルによって処理されます。 データが取得され、プロンプトがモデルに送信されると、モデルはこの情報を使用して候補を提供します。
この演習では、以下のことを行います。
- Azure AI Studioを使用してカスタム データ ソースを作成します。
- Azure AI Studioを使用して埋め込みモデルをデプロイします。
- カスタム ドキュメントをアップロードします。
- チャット プレイグラウンドでチャット セッションを開始し、独自のデータに基づいて入力候補を生成することを試します。
- Azure Cognitive Searchと Azure OpenAI を使用して、独自のデータに基づいて入力候補を生成するコードを調べる。
埋め込みモデルをデプロイし、Azure AI Studioにカスタム データ ソースを追加することから始めましょう。
Azure AI Studioへのカスタム データ ソースの追加
Azure OpenAI Studio に移動し、Azure OpenAI リソースにアクセスできる資格情報でサインインします。
ナビゲーション メニューから [ デプロイ] を選択します。
[ 新しいデプロイの作成 ] を選択し、次の値を入力します。
- モデル: text-embedding-ada-002。
- モデル のバージョン: 既定値。
- デプロイ名: text-embedding-ada-002。
モデルが作成されたら、ナビゲーション メニューから [Azure OpenAI ] を選択してようこそ画面に移動します。
ようこそ画面で [ Bring your own data]\(独自のデータを持ち込む \) タイルを見つけて、[ 今すぐ試す] を選択します。
[データ ソースの選択] ドロップダウンから [ ファイルのアップロード ] を選択 します。
[ Azure Blob Storage リソースの選択 ] ドロップダウンで、[ 新しい Azure Blob Storage リソースの作成] を選択します。
これにより、次のタスクを実行できるAzure portalが表示されます。
- byodstorage[Your Last Name]などのストレージ アカウントの一意の名前を入力します。
- 場所に近いリージョンを選択します。
- [ 確認] の後に [作成] を 選択します。
BLOB ストレージ リソースが作成されたら、[Azure AI Studio] ダイアログに戻り、[Azure Blob Storage リソースの選択] ドロップダウンから新しく作成した BLOB ストレージ リソースを選択します。 一覧に表示されない場合は、ドロップダウンの横にある更新アイコンを選択します。
ストレージ アカウントにアクセスするには、クロスオリジン リソース共有 (CORS) を有効にする必要があります。 [Azure AI Studio] ダイアログで [CORS を有効にする] を選択します。
[リソースAzure Cognitive Search選択] ドロップダウンで、[新しいAzure Cognitive Search リソースの作成] を選択します。
これにより、次のタスクを実行できるAzure portalに戻ります。
- byodsearch[Your Last Name]など、Cognitive Search リソースの一意の名前を入力します。
- 場所に近いリージョンを選択します。
- [ 価格レベル ] セクションで、[ 価格レベルの変更 ] を選択し、[ 基本 ] の後に [選択] を選択します。 Free レベルはサポートされていないため、このチュートリアルの最後に Cognitive Search リソースをクリーンします。
- [ 確認] の後に [作成] を 選択します。
Cognitive Search リソースが作成されたら、リソースの [概要 ] ページに移動し、 URL の値をローカル ファイルにコピーします。
左側のナビゲーション メニューで [ キー ] を選択し、[ プライマリ管理者キー ] の値をローカル ファイルにコピーします。 これらの値は、演習の後半で必要になります。
左側のナビゲーション メニューで [ セマンティック ランカー ] を選択し、[ Free ] が選択されていることを確認します。
注意
特定のリージョンでセマンティック ランカーを使用できるかどうかをチェックするには、Azure Web サイトの [リージョン別に利用可能な製品] ページを確認して、リージョンが一覧表示されているかどうかを確認します。
Azure AI Studio [データの追加] ダイアログに戻るし、[リソースの選択] ドロップダウンから新しく作成した検索リソースAzure Cognitive Search選択します。 一覧に表示されない場合は、ドロップダウンの横にある更新アイコンを選択します。
[インデックス名の入力] の値 に byod-search-index の値 を入力します 。
[ Add vector search to this search resource]\(この検索リソースにベクター検索を追加する\ ) チェック ボックスをオンにします。
[ 埋め込みモデルの選択 ] ドロップダウンで、前に作成 した text-embedding-ada-002 モデルを選択します。
チェック ボックスをオンにし、[ 次へ] を選択します。
[ ファイルのアップロード ] ダイアログで、 ファイルの [参照] を選択します。
プロジェクトの 顧客ドキュメント フォルダー (プロジェクトのルートにあります) に移動し、次のファイルを選択します。
- クロック A102 インストール Instructions.docx
- 会社 FAQs.docx
注意
この機能は現在、ローカル インデックスの作成に使用するファイル形式 (.txt、.md、.html、.pdf、.docx、.pptx) をサポートしています。
[Upload files](ファイルのアップロード) を選択します。 ファイルは、前に作成した BLOB ストレージ リソースの fileupload-byod-search-index コンテナーにアップロードされます。
[ 次へ ] を選択して、[ データ管理 ] ダイアログに移動します。
[ 検索の種類 ] ドロップダウンで、[ ハイブリッド + セマンティック] を選択します。
注意
このオプションは、キーワード (keyword)とベクター検索のサポートを提供します。 結果が返されると、ディープ ラーニング モデルを使用してセカンダリ ランク付けプロセスが結果セットに適用され、ユーザーの検索関連性が向上します。 セマンティック検索の詳細については、Azure Cognitive Searchドキュメントのセマンティック検索を参照してください。
セマンティック検索とベクター埋め込みの使用に関連するコストを確認するには、チェック ボックスをオンにします。
[ 次へ] を選択し、詳細を確認して、[ 保存して閉じる] を選択します。
カスタム データがアップロードされたので、データのインデックスが作成され、 チャット プレイグラウンドで使用できるようになります。 このプロセスは数分かかることがあります。 完了したら、次のセクションに進みます。
チャット プレイグラウンドでのカスタム データ ソースの使用
Azure AI Studioでページの [チャット セッション] セクションを見つけて、次のユーザー メッセージを入力します。
What safety rules are required to install a clock?
次のような結果が表示されます。
チャット応答の [1 参照 ] セクションを展開すると、 Clock A102 Installation Instructions.docx ファイルが一覧表示され、それを選択してドキュメントを表示できます。
次の ユーザー メッセージを入力します。
What should I do to mount the clock on the wall?
次のような結果が表示されます。
次に、会社の FAQ ドキュメントを試してみましょう。 [ユーザー メッセージ] フィールドに次のテキストを入力します。
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." }
カスタム データ ソースを作成し、チャットプレイグラウンドで実験したので、プロジェクトのアプリケーションで使用する方法を見てみましょう。
アプリケーションでの Bring Your Own Data 機能の使用
Visual Studio Code でプロジェクトに戻るし、.env ファイルを開きます。 Cognitive Services エンドポイント、キー、インデックス名を使用して、次の値を更新します。 この演習の前半で、エンドポイントとキーをローカル ファイルにコピーしました。
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 Installation Instructions.docx ドキュメントから結果が返されます。 このドキュメントは、プロジェクトのルートにある 顧客ドキュメント フォルダーでも使用できます。
コードの精査
ヒント
Visual Studio Code を使用している場合は、次を選択してファイルを直接開くことができます。
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
次に、開くファイルの名前を入力します。
Visual Studio Code でプロジェクトのソース コードに戻るします。
サーバー/apiRoutes.ts ファイルを開き、ルートを
completeBYOD
見つけます。 この API は、[チャット ヘルプ] ダイアログで [ ヘルプの取得 ] ボタンが選択されている場合に呼び出されます。 要求本文からユーザー プロンプトを取得し、サーバー/openAI.ts ファイル内の関数に渡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); });
サーバー/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 と共に Cognitive Search を使用するかどうかを示すブール値。 この場合は、 にtrue
設定されているため、Cognitive Search 機能が使用されます。
-
- パラメーターには
関数は
callOpenAI()
、useBYOD
呼び出す OpenAI 関数を決定するために使用されるパラメーターを受け取ります。 この場合、 は にtrue
設定useBYOD
され、関数が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); }
getAzureOpenAIBYODCompletion()
サーバー/openAI.tsで関数を見つけます。 これは前に調べた関数とよく似ていますgetAzureOpenAICompletion()
が、Azure OpenAI で使用できる "Bring your own data" シナリオに固有のいくつかの重要な違いを強調する別の関数として示されています。値には
fetchUrl
URL にextensions
セグメントが含まれますが、標準の Azure OpenAI API の URL には含まれません。const fetchUrl = `${OPENAI_ENDPOINT}/openai/deployments/${OPENAI_MODEL}/extensions/chat/completions?api-version=${OPENAI_API_VERSION}`;
dataSources
プロパティは、Azure OpenAI にmessageData
送信されるオブジェクトに追加されます。dataSources
プロパティには、この演習で前にファイルに.env
追加された Cognitive Search リソースの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
には、Cognitive Search の結果を取得した後に Azure OpenAI を呼び出すために使用される プロパティとchatgpt_key
プロパティが含まれますchatpgpt_url
。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 によって返される応答には、 と
assistant
のロールtool
を含む 2 つの混乱が含まれます。 サンプル アプリケーションでは、 の 2 番目のassistant
メッセージをrole
使用して、要求した情報をユーザーに提供します。 応答の作成に使用したドキュメントに関する追加情報を提供する場合 (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 の "Bring Your Own Data" 機能は現在プレビュー段階です。 現時点では、運用環境のアプリケーションで使用することはお勧めしません。
- サンプル アプリケーションでは、Azure Cognitive Searchで 1 つのインデックスを使用します。 Azure OpenAI では、複数のインデックスとデータ ソースを使用できます。 関数の プロパティは
dataSources
getAzureOpenAIBYODCompletion()
、必要に応じて複数のデータ ソースを含むように更新できます。 - この種のシナリオでは、セキュリティを慎重に評価する必要があります。 ユーザーは質問をしたり、アクセスできないドキュメントから結果を取得したりすることはできません。
Azure OpenAI、プロンプト、入力候補、および独自のデータの使用方法について学習したので、次の演習に進み、通信機能を使用してアプリケーションを強化する方法を学習しましょう。 Azure OpenAI の詳細については、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 機能を備えた無料電話番号を追加します。
- メール ドメインを接続します。
- ACS リソースの値を使用して、プロジェクトの .env ファイルを更新します。
Azure Communication Services リソースを作成する
ブラウザーのAzure portalにアクセスし、まだサインインしていない場合はサインインします。
ページ上部の検索バーに「Communication Services」と入力し、表示されるオプションから [Communication Services] を選択します。
ツール バーの [ 作成 ] を選択します。
次のタスクを実行します。
- Azure サブスクリプションを選択します。
- 使用するリソース グループを選択します (存在しない場合は新しいリソース グループを作成します)。
- ACS リソース名を入力します。 これは一意の値である必要があります。
- データの場所を選択します。
[ 確認と作成] の後に [作成] を 選択します。
新しいAzure Communication Services リソースが正常に作成されました。 次に、電話通話と SMS 機能を有効にします。 また、メール ドメインをリソースに接続します。
電話通話と SMS 機能を有効にする
電話番号を追加し、電話番号で通話機能が有効になっていることを確認します。 この電話番号を使用して、アプリから電話に発信します。
[リソース] メニューから を選択
Phone numbers
します。ツール バーで を選択
+ Get
し (または[ 数値を取得 ] ボタンを選択)、次の情報を入力します。-
国または地域:
United States
-
ユース ケース: 選択
An application will be making calls or sending SMS mesages
- 番号の種類: フリーダイヤル
注意
無料電話番号を作成するには、Azure サブスクリプションにクレジット カードが必要です。 ファイルにカードがない場合は、電話番号の追加をスキップして、メール ドメインを接続する演習の次のセクションに進んでください。 アプリは引き続き使用できますが、電話番号を呼び出すことはできません。
-
呼び出し:
Make calls
-
SMS:
Send and receive SMS
-
国または地域:
[ 次へ: 数値] を選択します。
プレフィックス (例:
877
) を選択し、数量を 1 のままにします。 [Search] を選択します。フリーダイヤル番号が表示されたら、[ 次へ: 概要] を選択します。
詳細を確認し、[ 注文] を選択して 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 addresses]\(アドレスからメール\) を選択します。
- MailFrom 値をファイルにコピーします。 後で .env ファイルを更新するときに使用します。
- Azure Communication Services リソースに戻るし、[リソース] メニューから を選択
Domains
します。 - 前の手順の値を
MailFrom
選択Add domain
して入力します (正しいサブスクリプション、リソース グループ、電子メール サービスを選択してください)。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
: SMS メッセージを送信するために他の国で追加の検証が必要であるため、米国ベースの電話番号 (現在) を指定する必要があります。 米国ベースの数値がない場合は、空のままにしておくことができます。
アプリケーション サーバーと API サーバーを起動/再起動する
この時点まで完了した演習に基づいて、次 のいずれかの 手順を実行します。
前の演習でデータベース、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 データベースを開始するには、次 のいずれかの オプションを選択します。
Docker Desktop をインストールして実行している場合は、ターミナル ウィンドウで を実行
docker-compose up
し、Enter キーを押します。podman-compose がインストールされ、実行されている Podman がある場合は、ターミナル ウィンドウで を実行
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
を クライアント フォルダーに追加し、次のコマンドを実行して依存関係をインストールし、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) に戻るし、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()
を呼び出して、Azure Communication Servicesアクセス トークンをacsService.getAcsToken()
取得します。 - ページに "電話ダイヤラー" を追加します。 ヘッダーの電話番号入力をクリックすると、ダイヤラーを確認できます。
- 関数と 関数をそれぞれ使用して、呼び出しを
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); }) ); } }
この関数は、次のアクションを実行します。
- 関数を呼び出して ACS userId とアクセス トークンを取得します
acsService.getAcsToken()
。 - アクセス トークンが取得されると、コードは次のアクションを実行します。
- の新しいインスタンス
CallClient
を作成し、AzureCommunicationTokenCredential
アクセス トークンを使用します。 - オブジェクトと
AzureCommunicationTokenCredential
オブジェクトを使用して、 のCallAgent
新しいインスタンスをCallClient
作成します。 後で、呼び出しの開始と終了に使用されることがわかりますCallAgent
。
- の新しいインスタンス
- 関数を呼び出して ACS userId とアクセス トークンを取得します
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 とアクセス トークンを取得し、クライアントに返します。 サーバー/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()
取得します。 - と
token
の値を含むオブジェクトをuserId
返します。
- 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 サーバーから取得されます。 - トークンは、 オブジェクトと
CallAgent
オブジェクトをCallClient
作成するために使用されます。 - オブジェクトは
CallAgent
、 関数と 関数をそれぞれ呼び出して呼び出しをcallAgent.startCall()
開始およびcallAgent.hangUp()
終了するために使用されます。
- ACS userId とアクセス トークンは、 関数を使用して
電話通話をアプリケーションに統合する方法を学習したので、Azure Communication Servicesを使用して電子メールと SMS メッセージを送信することに焦点を当ててみましょう。
通信: Emailおよび SMS メッセージの送信
電話に加えて、Azure Communication Servicesは電子メールや SMS メッセージを送信することもできます。 これは、アプリケーションから直接顧客または他のユーザーにメッセージを送信する場合に便利です。
この演習では、以下のことを行います。
- アプリケーションからメールと SMS メッセージを送信する方法について説明します。
- 電子メールと SMS 機能の実装方法については、コードを参照してください。
Emailと 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>
続行する前に 、演習 を完了していることを確認します。
ブラウザー () に戻るし、[Contact Customer]\(http://localhost:4200顧客に連絡\) を選択し、最初の行で [Email/SMS Customer] を選択します。
[Email/SMS] タブを選択し、次のタスクを実行します。
- [件名] と [本文] Email入力し、[Email送信] ボタンを選択します。
- SMS メッセージを入力し、[ SMS の送信 ] ボタンを選択します。
メールと 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 です。
データグリッドで [顧客に連絡] を選択し、その後に Email/SMS Customer を選択すると、
customer-list
コンポーネントにダイアログ ボックスが表示されます。 これは、customer-list.component.ts ファイルの 関数によって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()
、次のタスクを実行します。- オブジェクト (datagrid の行を
data
表す) に およびemail
プロパティが含まれているphone
かどうかを確認します。 その場合は、ダイアログにdialogData
渡す情報を含む オブジェクトが作成されます。 - ダイアログ ボックスを
EmailSmsDialogComponent
開き、オブジェクトをdialogData
渡します。 - ダイアログ ボックスの
afterClosed()
イベントをサブスクライブします。 このイベントは、ダイアログ ボックスが閉じられたときに発生します。 オブジェクトにはresponse
、ダイアログ ボックスに入力された情報が含まれています。
- オブジェクト (datagrid の行を
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
割り当てられているかどうかを確認します。 - が true の場合
acsEmailEnabled
、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) ); }
の
AcsService
関数はsendEmail()
、次のタスクを実行します。- 関数を
http.post()
呼び出し、電子メールの件名、メッセージ、顧客名、および顧客のメール アドレスを渡します。 関数はhttp.post()
、API 呼び出しからの応答を含む RxJS 監視可能な を返します。 - RxJS
catchError
演算子を使用して、http.post()
関数によって返されたすべてのエラーを処理します。
- 関数を
次に、アプリケーションが 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
割り当てられているかどうかを確認します。 - が true の場合
acsPhoneEnabled
、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
catchError
演算子を使用して、http.post()
関数によって返されたすべてのエラーを処理します。
- 関数を
最後に、アプリケーションが ACS SMS 機能とどのように対話するかを調べてみましょう。 acs.ts ファイルを開きます。 ファイルへの完全なパスは server/typescript/acs.ts で、 関数を
sendSms()
見つけます。関数は
sendSms()
、次のタスクを実行します。新
SmsClient
しいオブジェクトを作成し、ACS 接続文字列を渡します (この値は環境変数からACS_CONNECTION_STRING
取得されます)。const smsClient = new SmsClient(connectionString);
関数を
smsClient.send()
呼び出し、ACS 電話番号 ()、顧客の電話番号 (to
from
)、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 の ID と
channel
を見つけますteam
。 - プロジェクトの .env ファイルを、Microsoft Entra IDアプリ登録の値で更新します。
Microsoft Entra ID アプリ登録を作成する
[Azure portal] に移動し、[Microsoft Entra ID] を選択します。
[ アプリの登録 ] タブの後に [ + 新規登録] を選択します。
次に示すように、新しいアプリ登録フォームの詳細を入力し、[ 登録] を選択します。
- 名前: microsoft-graph-app
- サポートされているアカウントの種類: 任意の組織のディレクトリ内のアカウント (任意のMicrosoft Entra ID テナント - マルチテナント)
- リダイレクト URI:
- [シングルページ アプリケーション (SPA)] を選択し、[リダイレクト URI] フィールドに「」と入力
http://localhost:4200
します。
- [シングルページ アプリケーション (SPA)] を選択し、[リダイレクト URI] フィールドに「」と入力
- [登録] を選択して、アプリの登録を作成します。
[リソース] メニューの [ 概要 ] を選択し、値を
Application (client) ID
クリップボードにコピーします。
プロジェクトの .env ファイルを更新する
エディターで .env ファイルを開き、 に値
ENTRAID_CLIENT_ID
をApplication (client) ID
割り当てます。ENTRAID_CLIENT_ID=<APPLICATION_CLIENT_ID_VALUE>
アプリから Teams チャネルにメッセージを送信できるようにする場合は、Microsoft 365 開発テナント アカウントを使用して Microsoft Teams にサインインします。
サインインしたら、チームを展開し、アプリからメッセージを送信するチャネルを見つけます。 たとえば、[ 会社 ] チームと [全般 ] チャネル (または使用する任意のチーム/チャネル) を選択できます。
チーム ヘッダーで、3 つのドット (...) をクリックし、 を選択します
Get link to team
。ポップアップ ウィンドウに表示されるリンクでは、チーム ID は の後
team/
の文字と数字の文字列です。 たとえば、リンク "https://teams.microsoft.com/l/team/19%3ae9b9.../"" では、チーム ID は 19%3ae9b9..です。 次の/
文字まで。チーム ID をコピーし、.env ファイル内の に
TEAM_ID
割り当てます。チャネル ヘッダーで、3 つのドット (...) をクリックし、 を選択します
Get link to channel
。ポップアップ ウィンドウに表示されるリンクでは、チャネル ID は の後
channel/
の文字と数字の文字列です。 たとえば、リンク "https://teams.microsoft.com/l/channel/19%3aQK02.../"" では、チャネル ID は 19%3aQK02..です。 次の/
文字まで。チャネル ID をコピーし、.env ファイル内の に
CHANNEL_ID
割り当てます。続行する前に env ファイルを保存します。
アプリケーション サーバーと API サーバーの起動/再起動
ここまで完了した演習に基づいて、次 のいずれかの 手順を実行します。
前の演習でデータベース、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 データベースを開始するには、次 のいずれかの オプションを選択します。
Docker Desktop がインストールされ、実行されている場合は、ターミナル ウィンドウで を実行
docker-compose up
し、Enter キーを押します。podman-compose がインストールされ、実行されている Podman がある場合は、ターミナル ウィンドウで を実行
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
を サーバー/typescript フォルダーに追加し、次のコマンドを実行して依存関係をインストールし、API サーバーを起動します。npm install
npm start
+ Visual Studio Code ターミナル ツール バーのアイコンをもう一度押して、3 番目のターミナル ウィンドウを作成します。
cd
を クライアント フォルダーに追加し、次のコマンドを実行して依存関係をインストールし、Web サーバーを起動します。npm install
npm start
ブラウザーが起動し、 に http://localhost:4200移動します。
組織データ: ユーザーのサインインとアクセス トークンの取得
Microsoft Graph が組織のデータにアクセスするには、ユーザーがMicrosoft Entra IDで認証する必要があります。 この演習では、Microsoft Graph Toolkit のコンポーネントを使用してユーザーを mgt-login
認証し、アクセス トークンを取得する方法について説明します。 その後、アクセス トークンを使用して Microsoft Graph を呼び出すことができます。
注意
Microsoft Graph を初めて使用する場合は、「 Microsoft Graph の基礎 」ラーニング パスで詳細を確認できます。
この演習では、以下のことを行います。
- ユーザーの認証と組織データの取得に使用できるように、Microsoft Entra ID アプリを Microsoft Graph Toolkit に関連付ける方法について説明します。
- スコープの重要性について説明します。
- Microsoft Graph Toolkit の 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 Developer テナントの管理者ユーザー アカウントを使用してサインインします。
ヒント
Microsoft 365 開発者テナント管理者アカウントでサインインします。 Microsoft 365 管理センターに移動すると、開発者テナント内の他のユーザーを表示できます。
アプリケーションに初めてサインインする場合は、アプリケーションによって要求されたアクセス許可に同意するように求められます。 これらのアクセス許可 ("スコープ" とも呼ばれます) の詳細については、次のセクションでコードを調べる際に学習します。 [同意する] を選択して続行します。
サインインすると、ヘッダーにユーザーの名前が表示されます。
サインイン コードの探索
サインインしたので、ユーザーのサインインとアクセス トークンとユーザー プロファイルの取得に使用されるコードを見てみましょう。 Microsoft Graph Toolkit の一部である mgt-login Web コンポーネントについて学習します。
ヒント
Visual Studio Code を使用している場合は、次を選択してファイルを直接開くことができます。
- Windows/Linux: Ctrl + P
- Mac: Cmd + P
次に、開くファイルの名前を入力します。
クライアント/package.jsonを開き、パッケージが依存関係に含まれていることに注意してください
@microsoft/mgt
。 このパッケージには、MSAL (Microsoft Authentication Library) プロバイダーの機能と、 mgt-login などの Web コンポーネントが含まれており、ユーザーのサインインや組織データの取得と表示に使用できます。mgt-login コンポーネントを使用してユーザーをサインインさせるには、Microsoft Entra ID アプリのクライアント 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クライアント ID と、アプリがアクセスをscopes
要求する を渡します。scopes
は、アプリがアクセスする Microsoft Graph リソースへのアクセスを要求するために使用されます。 オブジェクトがMsal2Provider
作成されると、Microsoft Graph Toolkit コンポーネントが Microsoft Graph からデータをProviders.globalProvider
取得するために使用する オブジェクトに割り当てられます。エディター で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 コンポーネントの表示は、 に
true
設定されている値によってfeatureFlags.microsoft365Enabled
異なります。 このカスタム フラグは、環境変数が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 チャネルにチャット メッセージを送信する方法について説明します。
注意
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 Developer テナントのユーザーとサインインします。
注意
mgt-login Web コンポーネントは、ユーザーの認証に加えて、ファイル、チャット、電子メール、予定表イベント、その他の組織データにアクセスするために Microsoft Graph で使用できるアクセス トークンも取得します。 アクセス トークンには、前に見たスコープ (アクセス許可) (、
Files.Read.All
、 などChat.ReadWrite
) が含まれています。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 を使用して取得されます。 データが読み込まれると、タブ付きインターフェイスの datagrid の下に表示されます。 Microsoft 365 開発者テナントにユーザーのファイル、チャット、メール、予定表イベントをまだ追加していないため、この時点でデータが表示されない可能性があることをメンションすることが重要です。 次の手順で修正してみましょう。
Microsoft 365 テナントには、この段階で Adatum Corporation に関連する組織データがない可能性があります。 サンプル データを追加するには、次のいずれかのアクションを実行します。
Microsoft 365 Developer テナントの資格情報を https://onedrive.com 使用して、アクセスしてサインインしてファイルを追加します。
- 左側のナビゲーションで [ マイ ファイル ] を選択します。
- メニューから [ アップロード ] を選択し、[ フォルダー] を 選択します。
- 複製したプロジェクトから openai-acs-msgraph/customer documents フォルダーを選択します。
Microsoft 365 Developer テナントの資格情報を https://teams.microsoft.com 使用して、 にアクセスしてサインインすることで、チャット メッセージと予定表イベントを追加します。
左側のナビゲーションで [ Teams ] を選択します。
チームとチャネルを選択します。
[ 新しい会話] を選択します。
Adatum Corporation の新しい注文を入力し、[送信] ボタンを選択します。
Adventure Works Cycles、Contoso Pharmaceuticals、Tailwind Traders など、アプリケーションで使用されている他の企業メンションチャット メッセージを自由に追加できます。
左側のナビゲーションで [ 予定表] を 選択します。
[ 新しい会議] を選択します。
タイトルと本文に「Meet with Adatum Corporation about project schedule」と入力します。
[保存] を選択します。
Microsoft 365 Developer テナントの資格情報を https://outlook.com 使用してアクセスしてサインインすることで、メールを追加します。
[ 新しいメール] を選択します。
[ 宛先 ] フィールドに個人のメール アドレスを入力します。
件名と本文に必要なものについては、「 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 Toolkit の一部であり、名前が示すように、Microsoft Graph からの検索結果を表示するために使用されます。 コンポーネントは、この例では次の機能を使用します。
属性は
class
、CSS クラスをコンポーネントにsearch-results
適用するように指定するために使用されます。属性は
entity-types
、検索するデータの種類を指定するために使用されます。 この場合、値はdriveItem
OneDrive for Business 内のファイルを検索するために使用されます。属性は
queryString
、検索用語を指定するために使用されます。 この場合、値は、データ グリッド内のsearchText
行に対してユーザーが [関連コンテンツの表示] を選択したときにファイル コンポーネントに渡されるプロパティにバインドされます。 周りのqueryString
角かっこは、 プロパティが値にsearchText
バインドされていることを示します。このイベントは
dataChange
、検索結果が変更されたときに発生します。 この場合、files コンポーネントで という名前dataChange()
の顧客関数が呼び出され、イベント データが関数に渡されます。 かっこdataChange
は、イベントが関数にdataChange()
バインドされていることを示します。カスタム テンプレートが指定されていないので、組み込
mgt-search-results
みの既定のテンプレートを使用して検索結果が表示されます。
mgt-search-results などのコンポーネントを使用する代わりに、コードを使用して Microsoft Graph API を直接呼び出すこともできます。 そのしくみを確認するには、 graph.service.ts ファイルを開き、 関数を
searchFiles()
見つけます。 ファイルの完全なパスは、 client/src/app/core/graph.service.tsです。パラメーターが 関数に
query
渡されていることがわかります。 これは、ユーザーがデータ グリッド内の行の [関連コンテンツの表示 ] を選択すると渡される検索用語です。 検索語句が渡されない場合は、空の配列が返されます。async searchFiles(query: string) { const files: DriveItem[] = []; if (!query) return files; ... }
次に、実行する検索の種類を定義するフィルターが作成されます。 この場合、コードは OneDrive for Business 内のファイルを検索しているため
driveItem
、コンポーネントで前に見たのとmgt-search-results
同じように使用されます。 これは、前に見た mgt-search-results コンポーネントに をentity-types
渡driveItem
すのと同じです。 パラメーターはquery
、 とContentType:Document
共にフィルターにqueryString
追加されます。const filter = { "requests": [ { "entityTypes": [ "driveItem" ], "query": { "queryString": `${query} AND ContentType:Document` } } ] };
その後、 関数を使用して
Providers.globalProvider.graph.client.api()
Microsoft Graph APIを/search/query
呼び出します。 オブジェクトは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 コンポーネントが使用されているためにコメントアウトされますが、ユーザーがデータグリッド内の行に 対して [関連コンテンツの表示 ] を選択したときに、関数を使用して 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 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 に投稿し、結果を、検索用語に一致する 、channelId
、messageId
に関するteamId
情報を持つオブジェクトの配列に変換します。 - Teams チャネル メッセージを取得するために、API に対して 2 回目の呼び出しが
/teams/${chat.teamId}/channels/${chat.channelId}/messages/${chat.messageId}
行われ、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 Material カード コンポーネントを使用して検索結果を表示します。<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 チャネルにメッセージを送信することもできます。 これを行うには、Microsoft Graph のエンドポイントを
/teams/${teamId}/channels/${channelId}/messages
呼び出します。次のコードでは、 と
channelId
の値を含むteamId
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 コンポーネントを使用して、Microsoft Teams からOneDrive for Businessおよびチャットからファイルを取得する方法について学習しました。 また、Microsoft Teams チャネルにメッセージを送信する方法についても学習しました。 この演習では、Microsoft Graph からメール メッセージと予定表イベントを取得し、それらをアプリケーションに統合する方法について説明します。
この演習では、以下のことを行います。
- Microsoft Graph Toolkit の 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
、CSS クラスをコンポーネントにsearch-results
適用するように指定するために使用されます。 - 属性は
entity-types
、検索するデータの種類を指定するために使用されます。 この場合、値はmessage
です。 - 属性は
queryString
、検索用語を指定するために使用されます。 - このイベントは
dataChange
、検索結果が変更されたときに発生します。 emails コンポーネントの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 が用意されています。 前に見た API は
/search/query
確かに使用できますが、より簡単なオプションはmessages
API です。この API を呼び出す方法を確認するには、 graph.service.ts に戻り、 関数を
searchEmailMessages()
見つけます。 Microsoft Graph のエンドポイントを呼び出すために使用できる URL をmessages
作成し、パラメーターに値を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
、CSS クラスをコンポーネントにsearch-results
適用するように指定するために使用されます。 - 属性は
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>
Microsoft Graph には、API を使用して予定表イベントを
search/query
検索するだけでなく、予定表イベントの検索にも使用できる API も用意events
されています。 graph.service.tsでsearchCalendarEvents()
関数を見つけます。関数は
searchCalendarEvents()
、検索する期間を定義するために使用される開始日と終了日時の値を作成します。 次に、Microsoft Graph のエンドポイントを呼び出events
すために使用できる URL を作成し、パラメーターと start 変数と end 日付/時刻変数を含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 Graph APIに GET 要求が行われ、結果が呼び出し元に返されます。前のコンポーネントと同様に、 calendar-events コンポーネント (calendar-events.component.ts ファイル) が呼び出
search()
され、結果が表示されます。override async search(query: string) { this.data = await this.graphService.searchCalendarEvents(query); }
注意
カスタム API またはサーバー側アプリケーションから Microsoft Graph 呼び出しを行うこともできます。 Azure 関数から Microsoft Graph APIを呼び出す例については、次のチュートリアルを参照してください。
これで、Microsoft Graph を使用してファイル、チャット、電子メール メッセージ、予定表イベントを取得する例を見てきました。 同じ概念を他の Microsoft Graph API にも適用できます。 たとえば、Microsoft Graph users API を使用して、organization内のユーザーを検索できます。 Microsoft Graph グループ API を使用して、organization内のグループを検索することもできます。 Microsoft Graph API の完全な一覧は 、ドキュメントで確認できます。
おめでとうございます。
このチュートリアルは完了しました
おめでとうございます。 Azure OpenAI を使用してユーザーの生産性を向上させる方法、Azure Communication Servicesを使用して通信機能を統合する方法、および Microsoft Graph API とコンポーネントを使用して組織データを取得および表示する方法について学習しました。 これらのテクノロジを使用すると、コンテキストシフトを最小限に抑え、必要な意思決定情報を提供することで、ユーザーの生産性を向上させる効果的なソリューションを作成できます。
Azure リソースのクリーンアップ
アカウントに追加料金が発生しないように、Azure リソースをクリーンアップします。 Azure portalに移動し、次のリソースを削除します。
- Azure Cognitive Search リソース
- Azure Storage リソース
- 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 ツールキットの概要
- Teams Toolkit for Visual Studio Code を使用して Microsoft Teams 用アプリをビルドして展開する
このセクションに問題がある場合 このセクションを改善できるよう、フィードバックをお送りください。