重複メッセージを避けるためのベストプラクティスの設計

Note

この記事では 、標準的なハーネスの特徴と挙動について説明します。 Access標準エージェントおよびエージェントフローで標準機能にアクセスする方法を学びましょう。

標準ハーネスでは、複数のコンポーネントがユーザーの要求を処理でき、それぞれが独自の視点から動作します。 トピックはメッセージやAdaptive Cardを表示でき、ツールはデータを返し、子供や接続されたエージェントは独自のコンテキストから応答できます。 オーケストレーション層は、ユーザーが受け取る応答と一致しないコンテキストから計画を継続します。 これらの視点が離れると、ユーザーは繰り返しメッセージや返答が見逃されたりすることがあります。 メーカーは古いモデルよりも新しいモデルでこの現象に遭遇することが多いです。

解決策を設計する前に、なぜ重複が発生するのかを理解しましょう。 標準ハーネスにおけるコンテキスト分布について詳しく学びましょう。

Note

繰り返しメッセージや重複メッセージは通常、コンテキスト管理に関する設計上の問題であり、バグではありません。 これは、ユーザーが応答を見たものの、計画を継続するコンポーネントが既に応答された内容について異なる情報を持っている場合に発生します。

これらのユースケースを理解するために、2つのサーフェスを別々に考えてみてください。ユーザー が見える出力 (チャットでユーザーが見るもの)と アクティブコンテキスト (コンポーネントが次に何をすべきかを決める際に利用可能な情報)です。 メイカーは能動的な文脈を直接見ていません。 したがって、各コンポーネントの視点を理解し、それらの視点を整合させるために入力と出力を活用することが重要です。

ライブエージェントの症状をデバッグするには、まず「 重複メッセージや回答 漏れのトラブルシューティング」から始め、その後本記事に戻って再設計の指針を得てください。

文脈を考慮した設計

リクエストが単一のステップで処理され、その後「 すべてのトピック終了」が続く場合、コンテキスト管理は働きません。 しかし、リクエストが複数のコンポーネントをチェーン化する必要がある場合や、ユーザーが同じセッション内で複数のリクエストを行った場合、コンテキスト管理が重要です。 ほとんどの実際のユースケースはセッションごとに複数のコンポーネントを通過するため、それに合わせて設計してください。

  • 1つのコンポーネントを終わらせてから、すべてのトピックを終了します。 単一のトピック、ツール、子エージェント、または接続されたエージェントがリクエストを処理し、セッションは終了します。 もしそのコンポーネントが完全な回答を書き、その完了を報告すれば、オーケストレーション層は別の応答を書く理由がありません。
  • セッションにはいくつかの要素があります。 セッションは、ユーザーに完全な回答を提供するまでに複数のコンポーネントを実行することができます。 セッションは複数のリクエストにまたがることもあります。 あるコンポーネントがリクエストの一部に答え、別のコンポーネントが残りに答えなければならない場合もあります。 動作するすべてのコンポーネントは、その動作を報告しなければなりません。 そうでなければ、後のコンポーネントが回答されていない文脈に反応し、再び反応することがあります。
文脈が重要な場合 Example サウンドデザイン
文脈は使いません トピックはメッセージやアダプティブカードで完全な回答を表示します。 End all topicsノードはオーケストレーション層が再び応答するのを防ぎます。
オーケストレーション層はコンテキストを使用します トピックはパートAの表を示し、オーケストレーション層は知識や他のエージェントを使ってパートBに答えます。 各コンポーネントは回答した内容を報告し、後のステップが必要な値を返すため、オーケストレーションレイヤーは二度応答しません。
コンポーネントはコンテキストを使用します トピックはユーザーにパートAに答え、別のエージェントがパートBを処理します。エージェントがAが応答していない親コンテキストを受け取った場合、再びAに応答します。 接続されたエージェントの親コンテキストを可能な限り除外し、コンポーネントは応答した内容と残っていることを確認する出力を返します。

起こったことを報告するコンポーネントを設計する

オーケストレーション層が以前のコンポーネントが完了した作業を検出できない場合、コンポーネントは繰り返しメッセージや重複メッセージを送信します。 重複メッセージを避けるために毎回同じ設計手法を用いてください。各コンポーネントにオーケストレーション層への行動を報告するよう指示します。 リクエストの各部分に対して、ユーザーが受け取る回答を書くコンポーネントを正確に割り当てます。 他のコンポーネントはそれぞれの作業をし、ユーザーに書き込むことなくコンテキストを返します。

これらの手法を一つのデザインアプローチとして組み合わせて活用しましょう:

  1. 何が起こったかを記録する出力を返します。 古いモデルでは出力だけで十分です。
  2. トピックやサブエージェントの説明に 、成功した実行の意味を定義する指示を追加してください。 このアプローチにより設計は堅牢になります。
  3. トップレベルの命令を追加 して、オーケストレーションレイヤーが応答する前に出力をチェックできるようにします。 新しいモデルはこのアプローチの恩恵を最も受けています。

カスタム出力をサポートするコンポーネントのみが出力を返し、記述命令を含めることができます。 カスタム出力をサポートしないコンポーネントについては、受信するコンテキストを制限し、トップレベル命令を追加することで重複メッセージを防ぎます。

コンポーネント ~を添えて報告する 固定
テーマ answered (真/偽)、 choiceReceived (真/偽)、および表示値または要約出力(テキスト) 出力を返し、トピック説明に命令を追加します。 重複メッセージを避けるミニエージェントとしてトピックを設計 する例は、トピックの説明例を提供します。
サブエージェント (子エージェントまたは関連エージェント) answered (真偽)、 interactionSummary (テキスト)、 openQuestions (テキスト) 出力を返し、スコープ入力を追加し、サブエージェントの記述に命令を追加します。 重複メッセージを避ける設計サブエージェント は、サブエージェントの説明例を提供します。
知識( 知識への呼びかけ) コンテキストをカスタマイズできず、答えを繰り返すかもしれません。 クリーンなトップレベルのコンテキストを保ち、送信されるリクエストに影響を与えましょう。
生成回答ノード コンテキストをカスタマイズできず、答えを繰り返す可能性があり、その答えが後で繰り返されることもあります。 整理されたトップレベルコンテキストを維持し、ノードの入力に書き込まれるリクエストに反映させ、ホストトピックから出力または回答済み状態の出力を返すこと。

繰り返しメッセージを避ける堅牢なトップレベル命令を設計します

出力によってオーケストレーションレイヤーは常に最新の情報を把握できます。 新しいモデルに対して応答前に出力を確認するよう指示するトップレベルの命令を追加してください。

以下のトップレベルのエージェント命令は、コンポーネントが直接ユーザーと通信するかどうかにかかわらず、さまざまなユースケースで動作するよう設計されたサンプルです。 必要に応じて編集やカスタマイズをしてください。

どのトピックやエージェントが呼ばれるたびに、返信を決める前に必ず「応答済み」のブール出力を確認してください。 トピックやエージェントはユーザーと独自のコミュニケーションチャネルを持っています。 「回答済み」が真の場合は、少なくとも1つの出力変数を使ってリクエストに適切に応答されたと常に仮定し、出力の記述に基づいてどの変数かを確認してください。 答えた内容に対してぎこちなく返事をしないで。 回答されていない出力だけを提供し、次のステップへ自然に会話を続けましょう。

チャネル 」という用語は、Teamsやウェブサイトのような統合チャネルを指すものではありません。 これはオーケストレーション層に、ユーザーがすでに答えを見ているか、トピックやカード、サブエージェントなど他のコンポーネントを通じて選択を行っている可能性があることを知らせるプロンプト装置です。 この表現は、モデルが回答する前に自分の回答を確認することを最も効果的に促します。

トピックを管理する

トピックはしばしばメッセージを表示したり、質問したり、アダプティブカードを提示したりすることでユーザーと直接コミュニケーションを取っています。 オーケストレーションコンテキストはトピックのテキストをプレーンテキストとして受け取りますが、ユーザーがそれを見たかどうかは記録しません。 コンテキストはまた、適応カードのアクションや選択を受け取りません。 トピックがユーザーに応答してもそのアクションをオーケストレーション層に報告しない場合、オーケストレーション層はそのリクエストを未解決とみなし、再度応答します。

ミニエージェントとしてトピックをデザインしましょう。 応答状態の出力を返してオーケストレーション層にリクエストが処理されたことを知らせ、トピックが表示した値や収集した選択で後回が必要な値を返します。 出力は、行動や結果を計画の他の部分に利用可能にします。 トピックの説明に、成功したランの意味を定義する指示を加えてください。

重複メッセージを避けるミニエージェントとしてのデザイントピックについて詳しく学びましょう。

子エージェントおよび接続エージェントの扱い

子エージェントやコネクテッドエージェントも他のコンポーネントと同様に設計してください。 ユーザーとのやり取りは親には見えず、親は出力を通じてしか何が起こったかを知らず、エージェントが終わった後に初めて知ることができます。

子エージェントや接続されたエージェントは、親エージェントのコンテキスト内に残る未回答のリクエストを受け取ることもあります。

各エージェントに対して、入力でタスクをスコープし、ユーザーに応答するか沈黙するかを指定し、親エージェントに何が起こったかを伝える出力を返します。

重複メッセージを避けるデザインサブエージェントについて詳しく学びましょう。

知識を管理する

知識は エージェントが呼び出す最上位の構成概念です。 エージェントの設計に基づくリクエストを受け取り、エージェントのコンテキストを受け取ります。 繰り返しメッセージの問題の多くは、エージェントのコンテキストに他のコンポーネントからの情報が欠けている場合に発生します。 エージェントが依頼をどのように定式化するかに影響を与えるための知識を設計します。 他の部品が正しく出力を使っているか確認してください。

生成された回答ノードを処理する

生成回答ノードはトピック内に存在し、知識から回答します。 親コンテキストと入力で渡された情報を受け取り、トップレベルの知識のように振る舞い、現在のコンテキストから回答を補強します。 回答をチャットペインに直接書き込むかトピック変数に保存することはできますが、トップレベルのコンテキストに単独で返すことはできません。 どんなトピックコンテンツでもそうですが、その答えはトピックが出力を返さない限り、トピック内に残ります。

生成回答ノードは、すべてのトピックに適用されるルール、すなわち結果をトピック出力として渡すというルール以外に特別な扱いは不要です。 ノードがトピック内のユーザーに応答した場合、回答済みの状態出力と表示値出力を追加します。 これらの出力はオーケストレーション層にリクエストが応答された記録を与え、後のステップで再度応答するのを防ぎます。

説明や指示が視点に合っていることを確認してください

説明や指示もコンテキスト契約の一部です。

この指示は以下のトピックに繋がります:

When the user asks about their account balance, call the Account balance topic.

この命令はオーケストレーション層に応答の所有権をルーティングし割り当てます:

When the user asks about their account balance, call the Account balance topic and give the balance.

トピックがすでにバランスを示している場合、2つ目の命令が2つ目の回答パスを作ります。 もしトピックが balanceValueを返さなければ、オーケストレーション層は再度そのトピックを呼び出すか、値がわからないと答えるかもしれません。

視点に合った説明や指示を使いましょう:

  • トピックの記述は、オーケストレーションレイヤーがトピックをいつどのように使うかを判断するのに役立ちます。 また、次に何をするか、何を出力するかの指示も守ります。
  • 連結エージェントの記述は親の視点から来ます。
  • 接続エージェント命令は接続エージェントの視点から読み込まれます。
  • トピックまたは接続エージェントの出力記述は、オーケストレーション層に返された値をどう解釈するかを伝えます。

ユーザーに答えを示し、 answered=trueを設定するトピックについては、いつそのトピックにルーティングするか、そして成功した実行とは何かを説明してください。

This topic handles account balance requests.
If its answered output is true, the user has already received their response and it should not be answered again.

出力のみを書くトピックの場合、いつトピックにルーティングするか、そしてどのように返信するかを説明してください。

This topic handles account balance requests and responds with the balance value in italics.

長い会話の文脈を回復する

コンポーネントが持っていた値は、2つの方法でアクティブコンテキストから離れることができます。 長時間のセッションでは、数ターン前に利用可能だった値が、もはやアクティブなコンテキストに含まれていないかもしれません。 あるコンポーネントが完全な結果を取得し、該当する部分を使って回答を生成し、その回答だけを返すため、残りの結果はオーケストレーション層に届かないようにします。 いずれにせよ、エージェントは再度データを取得したり、すでに持っている情報をユーザーに尋ねたりするかもしれませんが、ユーザーはそれを返答の見落としとして体験します。 オーケストレーションレイヤーは、その値を一度も受け取っていなかったかのように振る舞います。

重要な文脈を返して保存し、必要に応じて返しておくことでこのシナリオに備えましょう:

  • 回答した部分だけでなく、完全な結果を返してください。 取得された結果はしばしば複数のフィールド、多数の行、長いテキストを持ちます。 後のターンで必要とするすべてのデータを出力として返すため、オーケストレーション層は再取得せずにそれを保持できます。

  • 複数ターンにわたって値を保存して提供します。 適切なタイミングで、ツール呼び出しの前後に、入力・出力やグローバル変数を通じて値を保存または提供できるトピックにルーティングし、計画が値を取得したり再度要求したりしないようにします。

Tip

シームレスなエージェント的振る舞いは、あらゆる段階とあらゆる視点からコンテキストを考慮したエージェント設計に基づいています。