Agent Chat でのエージェントコラボレーションの探索 (試験段階)
警告
Semantic Kernel Agent Framework はまだ開発中であり、変更される可能性があります。
この説明に関連する詳細な API ドキュメントは、次のサイトで入手できます。
現在、エージェントは Java では使用できません。
Agent Chatとは
エージェント チャット は、異なる種類のエージェントであっても、複数のエージェント間の対話を可能にするフレームワークを提供します。 これにより、 Chat Completion Agent と Open AI Assistant Agent が同じ会話内で連携できるようになります。 エージェント チャット では、複数の応答または単一のエージェント応答を使用して、エージェント間のコラボレーションを開始するためのエントリ ポイントも定義します。
抽象クラスとして、カスタム シナリオをサポートするために Agent Chat をサブクラス化できます。
このようなサブクラスの 1 つである Agent Group Chat では、会話のダイナミクスを管理するための戦略ベースのアプローチを使用して、 Agent Chat の具体的な実装を提供します。
Agent グループ チャットの作成
Agent グループ チャットを作成するには、参加しているエージェントを指定するか、空のチャットを作成してから、エージェントの参加者を追加します。 Chat-Settings および Strategies の構成は、Agent グループ チャット初期化中にも実行されます。 これらの設定は、会話のダイナミクスがグループ内でどのように機能するかを定義します。
注: 既定の Chat-Settings は、1 つの応答に制限された会話になります。 _Chat-Settings の構成の詳細については、「 Agent Chat Behavior 」を参照してください。
Agents を使用したAgent グループ チャットの作成:
// Define agents
ChatCompletionAgent agent1 = ...;
OpenAIAssistantAgent agent2 = ...;
// Create chat with participating agents.
AgentGroupChat chat = new(agent1, agent2);
# Define agents
agent1 = ChatCompletionAgent(...)
agent2 = OpenAIAssistantAgent(...)
# Create chat with participating agents
chat = AgentGroupChat(agents=[agent1, agent2])
現在、エージェントは Java では使用できません。
Agents を Agent グループ チャットに追加する:
// Define agents
ChatCompletionAgent agent1 = ...;
OpenAIAssistantAgent agent2 = ...;
// Create an empty chat.
AgentGroupChat chat = new();
// Add agents to an existing chat.
chat.AddAgent(agent1);
chat.AddAgent(agent2);
# Define agents
agent1 = ChatCompletionAgent(...)
agent2 = OpenAIAssistantAgent(...)
# Create an empty chat
chat = AgentGroupChat()
# Add agents to an existing chat
chat.add_agent(agent=agent1)
chat.add_agent(agent=agent2)
現在、エージェントは Java では使用できません。
Agent グループ チャットの使用
エージェント チャット では、 Single-Turn と Multi-Turn の 2 つの操作モードがサポートされています。 single ターンでは、応答を提供する特定のエージェントが指定されます。 複数ターンでは、会話内のすべてのエージェントが、終了条件が満たされるまで順番に応答します。 どちらのモードでも、エージェントは互いに応答して共同作業を行い、定義された目標を達成できます。
入力の提供
Agent Chat に入力メッセージを追加するは、Chat History オブジェクトと同じパターンに従います。
AgentGroupChat chat = new();
chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, "<message content>"));
chat = AgentGroupChat()
await chat.add_chat_message(ChatMessageContent(role=AuthorRole.USER, content="<message content>"))
現在、エージェントは Java では使用できません。
シングルターン エージェント呼び出し
複数ターンの呼び出しでは、システムは次に応答するエージェントと会話を終了するタイミングを決定する必要があります。 これに対し、1 ターン呼び出しでは、指定したエージェントからの応答が返されるだけで、呼び出し元はエージェントの参加を直接管理できます。
エージェントは、シングルターン呼び出しを通じて Agent Chat に参加した後、複数ターン呼び出しの対象となる一連の agent に追加されます。
// Define an agent
ChatCompletionAgent agent = ...;
// Create an empty chat.
AgentGroupChat chat = new();
// Invoke an agent for its response
ChatMessageContent[] messages = await chat.InvokeAsync(agent).ToArrayAsync();
# Define an agent
agent = ChatCompletionAgent(...)
# Create an empty chat
chat = AgentGroupChat()
# Invoke an agent for its response(s)
async for message in chat.invoke(agent)
# process message response(s)
現在、エージェントは Java では使用できません。
マルチターン エージェントの呼び出し
エージェントコラボレーションでは、各ターンで応答するエージェントを決定するだけでなく、会話が意図した目標を達成したタイミングを評価するシステムが必要ですが、マルチターンコラボレーションの開始は簡単です。
エージェントの応答は、生成されると非同期的に返され、会話をリアルタイムで展開できます。
注: 以降のセクションでは、 Agent Selection と Chat Termination では、 Execution の設定 について詳しく説明します。 既定の 実行設定 ではシーケンシャルまたはラウンド ロビンの選択が採用され、エージェントの参加が 1 ターンに制限されます。
.NET Execution の設定 API: AgentGroupChatSettings
// Define agents
ChatCompletionAgent agent1 = ...;
OpenAIAssistantAgent agent2 = ...;
// Create chat with participating agents.
AgentGroupChat chat =
new(agent1, agent2)
{
// Override default execution settings
ExecutionSettings =
{
TerminationStrategy = { MaximumIterations = 10 }
}
};
// Invoke agents
await foreach (ChatMessageContent response in chat.InvokeAsync())
{
// Process agent response(s)...
}
# Define agents
agent1 = ChatCompletionAgent(...)
agent2 = OpenAIAssistantAgent(...)
# Create chat with participating agents
chat = AgentGroupChat(
agents=[agent1, agent2],
termination_strategy=DefaultTerminationStrategy(maximum_iterations=10),
)
async for response in chat.invoke():
# process agent response(s)
現在、エージェントは Java では使用できません。
チャット履歴へのアクセス
メッセージが呼び出しパターンを介して配信される場合でも、 Agent Chat 会話履歴には常にアクセスできます。 これにより、会話を通じて過去の交換を引き続き利用できるようになります。
注: 最新のメッセージが最初に提供されます (降順: 最新から最も古い順)。
// Define and use a chat
AgentGroupChat chat = ...;
// Access history for a previously utilized AgentGroupChat
ChatMessageContent[] history = await chat.GetChatMessagesAsync().ToArrayAsync();
# Define a group chat
chat = AgentGroupChat(...)
# Access history for a previously utilized AgentGroupChat
history = await chat.get_chat_messages()
現在、エージェントは Java では使用できません。
エージェントの種類や構成によって独自のバージョンの会話履歴が保持される場合があるため、エージェントを指定することで、エージェント固有の履歴も使用できます。 (例: OPEN AI Assistant と Chat Completion Agent)
// Agents to participate in chat
ChatCompletionAgent agent1 = ...;
OpenAIAssistantAgent agent2 = ...;
// Define a group chat
AgentGroupChat chat = ...;
// Access history for a previously utilized AgentGroupChat
ChatMessageContent[] history1 = await chat.GetChatMessagesAsync(agent1).ToArrayAsync();
ChatMessageContent[] history2 = await chat.GetChatMessagesAsync(agent2).ToArrayAsync();
# Agents to participate in a chat
agent1 = ChatCompletionAgent(...)
agent2 = OpenAIAssistantAgent(...)
# Define a group chat
chat = AgentGroupChat(...)
# Access history for a previously utilized AgentGroupChat
history1 = await chat.get_chat_messages(agent=agent1)
history2 = await chat.get_chat_messages(agent=agent2)
現在、エージェントは Java では使用できません。
Agent グループ チャット動作の定義
複雑なタスクを解決するためのエージェント間のコラボレーションは、エージェントのコア パターンです。 このパターンを効果的に使用するには、各ターンで応答するエージェントを決定するだけでなく、会話が目的の目標を達成したタイミングを評価するシステムが必要です。 そのためには、エージェントの選択を管理し、会話終了の明確な基準を確立し、ソリューションに向けたエージェント間のシームレスな協力を確保する必要があります。 これらの両方の側面は、 Execution Settings プロパティによって管理されます。
以降のセクション Agent Selection と Chat Termination では、これらの考慮事項について詳しく説明します。
エージェントの選択
複数ターン呼び出しでは、エージェントの選択は Selection Strategy によって導かれます。 この戦略は、特定のニーズに合わせて調整されたカスタム動作を実装するために拡張できる基底クラスによって定義されます。 便宜上、事前に定義された 2 つの具象 選択戦略 も利用でき、会話中にエージェントの選択を処理するためのすぐに使用できるアプローチが提供されます。
既知の場合は、最初のエージェントが常に最初のターンを実行するように指定できます。 履歴レジューサーを使用して、 Kernel 関数に基づく戦略を使用する場合にトークンの使用を制限することもできます。
.NET Selection Strategy API:
SelectionStrategy
SequentialSelectionStrategy
KernelFunctionSelectionStrategy
Microsoft.SemanticKernel.Agents.History
// Define the agent names for use in the function template
const string WriterName = "Writer";
const string ReviewerName = "Reviewer";
// Initialize a Kernel with a chat-completion service
Kernel kernel = ...;
// Create the agents
ChatCompletionAgent writerAgent =
new()
{
Name = WriterName,
Instructions = "<writer instructions>",
Kernel = kernel
};
ChatCompletionAgent reviewerAgent =
new()
{
Name = ReviewerName,
Instructions = "<reviewer instructions>",
Kernel = kernel
};
// Define a kernel function for the selection strategy
KernelFunction selectionFunction =
AgentGroupChat.CreatePromptFunctionForStrategy(
$$$"""
Determine which participant takes the next turn in a conversation based on the the most recent participant.
State only the name of the participant to take the next turn.
No participant should take more than one turn in a row.
Choose only from these participants:
- {{{ReviewerName}}}
- {{{WriterName}}}
Always follow these rules when selecting the next participant:
- After {{{WriterName}}}, it is {{{ReviewerName}}}'s turn.
- After {{{ReviewerName}}}, it is {{{WriterName}}}'s turn.
History:
{{$history}}
""",
safeParameterNames: "history");
// Define the selection strategy
KernelFunctionSelectionStrategy selectionStrategy =
new(selectionFunction, kernel)
{
// Always start with the writer agent.
InitialAgent = writerAgent,
// Parse the function response.
ResultParser = (result) => result.GetValue<string>() ?? WriterName,
// The prompt variable name for the history argument.
HistoryVariableName = "history",
// Save tokens by not including the entire history in the prompt
HistoryReducer = new ChatHistoryTruncationReducer(3),
};
// Create a chat using the defined selection strategy.
AgentGroupChat chat =
new(writerAgent, reviewerAgent)
{
ExecutionSettings = new() { SelectionStrategy = selectionStrategy }
};
REVIEWER_NAME = "Reviewer"
WRITER_NAME = "Writer"
agent_reviewer = ChatCompletionAgent(
service_id=REVIEWER_NAME,
kernel=kernel,
name=REVIEWER_NAME,
instructions="<instructions>",
)
agent_writer = ChatCompletionAgent(
service_id=WRITER_NAME,
kernel=kernel,
name=WRITER_NAME,
instructions="<instructions>",
)
selection_function = KernelFunctionFromPrompt(
function_name="selection",
prompt=f"""
Determine which participant takes the next turn in a conversation based on the the most recent participant.
State only the name of the participant to take the next turn.
No participant should take more than one turn in a row.
Choose only from these participants:
- {REVIEWER_NAME}
- {WRITER_NAME}
Always follow these rules when selecting the next participant:
- After user input, it is {WRITER_NAME}'s turn.
- After {WRITER_NAME} replies, it is {REVIEWER_NAME}'s turn.
- After {REVIEWER_NAME} provides feedback, it is {WRITER_NAME}'s turn.
History:
{{{{$history}}}}
""",
)
chat = AgentGroupChat(
agents=[agent_writer, agent_reviewer],
selection_strategy=KernelFunctionSelectionStrategy(
function=selection_function,
kernel=_create_kernel_with_chat_completion("selection"),
result_parser=lambda result: str(result.value[0]) if result.value is not None else COPYWRITER_NAME,
agent_variable_name="agents",
history_variable_name="history",
),
)
現在、エージェントは Java では使用できません。
チャット終了
マルチターン呼び出しでは、最後のターンがいつ行われる支配戦略によって決まります。 この戦略により、会話は適切な時点で終了します。
この戦略は、特定のニーズに合わせて調整されたカスタム動作を実装するために拡張できる基底クラスによって定義されます。 便宜上、サーバーで事前に定義された具体的な 選択戦略 も利用でき、 Agent Chat 会話の終了条件を定義するためのすぐに使用できるアプローチが提供されます。
.NET Selection Strategy API:
TerminationStrategy
RegexTerminationStrategy
KernelFunctionSelectionStrategy
KernelFunctionTerminationStrategy
AggregatorTerminationStrategy
Microsoft.SemanticKernel.Agents.History
// Initialize a Kernel with a chat-completion service
Kernel kernel = ...;
// Create the agents
ChatCompletionAgent writerAgent =
new()
{
Name = "Writer",
Instructions = "<writer instructions>",
Kernel = kernel
};
ChatCompletionAgent reviewerAgent =
new()
{
Name = "Reviewer",
Instructions = "<reviewer instructions>",
Kernel = kernel
};
// Define a kernel function for the selection strategy
KernelFunction terminationFunction =
AgentGroupChat.CreatePromptFunctionForStrategy(
$$$"""
Determine if the reviewer has approved. If so, respond with a single word: yes
History:
{{$history}}
""",
safeParameterNames: "history");
// Define the termination strategy
KernelFunctionTerminationStrategy terminationStrategy =
new(selectionFunction, kernel)
{
// Only the reviewer may give approval.
Agents = [reviewerAgent],
// Parse the function response.
ResultParser = (result) =>
result.GetValue<string>()?.Contains("yes", StringComparison.OrdinalIgnoreCase) ?? false,
// The prompt variable name for the history argument.
HistoryVariableName = "history",
// Save tokens by not including the entire history in the prompt
HistoryReducer = new ChatHistoryTruncationReducer(1),
// Limit total number of turns no matter what
MaximumIterations = 10,
};
// Create a chat using the defined termination strategy.
AgentGroupChat chat =
new(writerAgent, reviewerAgent)
{
ExecutionSettings = new() { TerminationStrategy = terminationStrategy }
};
REVIEWER_NAME = "Reviewer"
WRITER_NAME = "Writer"
agent_reviewer = ChatCompletionAgent(
service_id=REVIEWER_NAME,
kernel=kernel,
name=REVIEWER_NAME,
instructions="<instructions>",
)
agent_writer = ChatCompletionAgent(
service_id=WRITER_NAME,
kernel=kernel,
name=WRITER_NAME,
instructions="<instructions>",
)
termination_function = KernelFunctionFromPrompt(
function_name="termination",
prompt="""
Determine if the copy has been approved. If so, respond with a single word: yes
History:
{{$history}}
""",
)
chat = AgentGroupChat(
agents=[agent_writer, agent_reviewer],
termination_strategy=KernelFunctionTerminationStrategy(
agents=[agent_reviewer],
function=termination_function,
kernel=_create_kernel_with_chat_completion("termination"),
result_parser=lambda result: str(result.value[0]).lower() == "yes",
history_variable_name="history",
maximum_iterations=10,
),
)
現在、エージェントは Java では使用できません。
チャット完了状態のリセット
Agent グループ チャットが単一ターンまたは複数ターンのどちらの方法で呼び出されるかに関係なく、終了条件が満たされると、Agent グループ チャットの状態が更新され完了が示されます。 これにより、会話が完全に終了したときにシステムが認識されるようになります。 Agent グループ チャットインスタンスが Completed 状態に達した後も引き続き使用するには、この状態をリセットして、さらに対話できるようにする必要があります。 リセットしないと、追加の対話やエージェントの応答を行えなくなります。
複数ターン呼び出しが最大ターン制限に達した場合、システムはエージェントの呼び出しを停止しますが、インスタンスを completed としてマークしません。 これにより、 Completion 状態をリセットしなくても会話を拡張できます。
// Define an use chat
AgentGroupChat chat = ...;
// Evaluate if completion is met and reset.
if (chat.IsComplete)
{
// Opt to take action on the chat result...
// Reset completion state to continue use
chat.IsComplete = false;
}
# Define a group chat
chat = AgentGroupChat()
# Evaluate if completion is met and reset
if chat.is_complete:
# Reset completion state to continue use
chat.is_complete = False
現在、エージェントは Java では使用できません。
完全な会話状態をクリアする
Open AI Assistant が参加した Agent Chat の使用が完了したら、assistantに関連付けられているリモート threadを削除することが必要になる場合があります。 エージェント チャット は、リモート thread 定義の削除を含む、会話状態全体のリセットまたはクリアをサポートします。 これにより、チャットが終了しても、残りの会話データがアシスタントにリンクされたままではなくなります。
完全なリセットでは、Agent Chat に参加していたagentsが削除されず、Agent Chatが再利用できる状態になります。 これにより、同じエージェントを再初期化する必要なく、同じエージェントとの対話を継続でき、今後の会話がより効率的になります。
// Define an use chat
AgentGroupChat chat = ...;
// Clear the all conversation state
await chat.ResetAsync();
# Define a group chat
chat = AgentGroupChat()
# Clear the conversation state
await chat.reset()
現在、エージェントは Java では使用できません。
操作方法
Agent コラボレーションに Agent グループ チャットを使用するエンド ツー エンドの例については、次を参照してください。