探索代理程式聊天中的代理程式共同作業 (實驗性)
警告
語意核心代理程式架構是實驗性的,仍在開發中,而且可能會變更。
如需此討論的詳細 API 檔,請參閱:
代理程式目前無法在Java中使用。
什麼是 代理程式聊天?
代理程式聊天 提供一種架構,可讓您在多個代理程式之間進行互動,即使這些代理程式屬於不同類型的代理程式也一樣。 這可讓聊天完成代理程式和開放式 AI 助理代理程式在相同的交談中一起運作。 代理程式聊天 也會定義起始代理程式之間共同作業的進入點,無論是透過多個回應還是單一代理程序回應。
身為抽象類, 代理程式聊天 可以子類別化以支援自定義案例。
其中一個這類子類別「代理程式群組聊天」會使用策略型方法來管理交談動態,提供代理程式聊天的具體實作。
建立 代理程式群組聊天
若要建立 代理程式群組聊天,您可以指定參與的代理程式,或建立空的聊天,然後新增代理程序參與者。 設定聊天設定和策略也會在代理程式群組聊天初始化期間執行。 這些設定會定義交談動態在群組內運作的方式。
注意:預設 的 Chat-Settings 會產生限制為單一回應的交談。 如需設定_Chat設定的詳細資訊,請參閱 代理程式聊天 行為 。
建立與代理程式的代理程式群組聊天:
// 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中使用。
將代理程式新增至代理程式群組聊天:
// 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中使用。
使用 代理程式群組聊天
代理程式聊天 支援兩種作業模式: 單一回合 和 多回合。 在 單一回合中,會指定特定代理程式來提供回應。 在 多回合中,交談中的所有代理程式都會輪流回應,直到符合終止準則為止。 在這兩種模式中,代理程式可以透過彼此回應來達成定義的目標來共同作業。
提供輸入
將輸入訊息新增至 代理程式聊天 會遵循與使用 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中使用。
單一回合代理程序調用
在多回合調用中,系統必須決定下一個回應的代理程式,以及對話應該結束的時機。 相反地,單一回合調用只會從指定的代理程式傳回回應,讓呼叫端能夠直接管理代理程序參與。
在代理程式透過單一回合調用參與 代理程式聊天 之後,它會新增至符合多回合調用資格的 代理程式 集合。
// 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中使用。
多回合代理程序調用
雖然代理程式共同作業要求系統必須就緒,不僅會決定哪些代理程式應該在每個回合期間回應,而且會評估交談何時達到其預期目標,但起始多回合共同作業仍然相當簡單。
代理程式回應會在產生時以異步方式傳回,讓交談能夠實時展開。
注意:在下列各節中, 代理程式選取 和 聊天終止將詳細探討 執行設定 。 默認 的執行設定 會採用循序或迴圈配置資源選取,並將代理程序參與限制為單一回合。
.NET 執行設定 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中使用。
存取聊天記錄
代理程式聊天交談歷程記錄一律可供存取,即使訊息是透過調用模式傳遞。 這可確保過去交換在整個交談中仍可供使用。
注意:會先提供最新的訊息(遞減順序:最新到最舊)。
// 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中使用。
由於不同的代理程式類型或組態可能會維護自己的交談歷程記錄版本,代理程式特定的歷程記錄也可透過指定代理程式來使用。 (例如: 開啟 AI 助理 與 聊天完成代理程式。
// 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中使用。
定義 代理程式群組聊天 行為
代理程式之間的共同作業來解決複雜的工作是核心代理模式。 若要有效地使用此模式,系統必須就緒,不僅會決定哪些代理程式應該在每個回合期間回應,而且會評估交談何時達到其預期目標。 這需要管理代理程序選擇,並建立交談終止的明確準則,以確保代理程式之間的順暢合作,以達成解決方案。 這兩個層面都是由 [執行設定 ] 屬性所控管。
下列各節「 代理程式選取 」和 「聊天終止」將詳細探討這些考慮。
代理程序選取
在多回合調用中,代理程式選取是由 選取策略引導。 此策略是由基類所定義,可擴充以實作針對特定需求量身打造的自定義行為。 為了方便起見,也提供兩個預先定義的具體 選取策略 ,提供在交談期間處理代理程式選取的現成使用方法。
如果已知,可能會指定初始代理程式,以一律先進行第一回合。 使用以核心函式為基礎的策略時,也可以使用歷程記錄歸納器來限制令牌使用量。
.NET 選取策略 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中使用。
聊天終止
在 多回合 調用中,終止 策略 會決定何時進行最終回合。 此策略可確保對話會在適當的時間點結束。
此策略是由基類所定義,可擴充以實作針對特定需求量身打造的自定義行為。 為了方便起見,您也可以使用伺服器預先定義的具體選擇策略,提供現成的方法,以定義代理程式聊天交談的終止準則。
.NET 選取策略 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中使用。
重設聊天完成狀態
不論代理程式群組聊天是使用單回合或多回合方法叫用,代理程式群組聊天的狀態都會更新,以指出在符合終止準則之後完成。 這可確保系統會在對話完全結束時辨識。 若要在達到已完成狀態之後繼續使用代理程式群組聊天實例,必須重設此狀態,才能允許進一步互動。 若未重設,將無法進行其他互動或代理程序回應。
在達到最大回合限制的多回合調用的情況下,系統會停止代理程序調用,但不會將實例標示為 已完成。 這可讓您擴充交談的可能性,而不需要重設 完成 狀態。
// 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 的代理程式聊天完成時,可能需要刪除與助理相關聯的遠端線程。 代理程式聊天 支援重設或清除整個交談狀態,包括刪除任何遠端 線程 定義。 這可確保聊天結束后,沒有任何剩餘的交談數據會與助理連結。
完整重設不會移除已加入代理程式聊天的代理程式,並讓代理程式聊天處於可重複使用的狀態。 這可讓您接續與相同代理程序的互動,而不需要重新初始化它們,讓未來的交談更有效率。
// 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中使用。
作法
如需使用 代理程式群組聊天 進行 代理程式 共同作業的端對端範例,請參閱: