16AgentChat

AgentChat

AgentChat提供了一个框架,探讨多智能体(AI Agents)在对话场景中的协作机制,旨在通过分工合作提升复杂任务解决能力。该框架不仅要确定在每个回合中哪个Agent应该响应,还要评估对话何时达到预期目标并及时终止协作。

目前基于该框架可以实现多个不同类型的Agent的相互的交互。也就是多个ChatCompletionAgent能够在同一次对话中协同工作。

AgentChat 在SK中作为一个抽象基类存在,AgentGroupChatAgentChat的具体实现:

  • 定义了Agent之间协作的入口点,支持单个智能体或多个智能体启动
  • 支持两种响应模式:signle-turnmulti-turn
  • 内置多种 Agent 选择策略,也可灵活定制策略
  • 针对multi-turn内置了多种会话终止策略
  • 提供了状态管理功能

当前AgentChat 处于实验阶段,后期可能会有大的变更!!!

使用时要禁用warning:#pragma warning disable SKEXP0110

//通过引入Config/PrepareEnvWithDI.cs文件来快速安装依赖包并导入已抽象的类文件,然后注册并激活AI 服务:

#!import Config/PrepareEnvWithDI.cs

using PolyglotKernel= Microsoft.DotNet.Interactive.Kernel;// 引入交互式的内核命名空间,以便用户输入
var aiProviderCode = await PolyglotKernel.GetInputAsync("请输入AI服务提供商编码:");

var kernel = GetKernel(aiProviderCode);
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
#r "nuget:Microsoft.SemanticKernel.Agents.Core,*-*"
#r "nuget: Microsoft.SemanticKernel.Agents.OpenAI, *-*"

单智能体启动

using Microsoft.SemanticKernel.Agents;
using PolyglotKernel = Microsoft.DotNet.Interactive.Kernel;// 引入交互式的内核命名空间,以便用户输入

#pragma warning disable SKEXP0110

// Create an empty chat
AgentGroupChat chat = new ();

// Create a chat completion agent
ChatCompletionAgent agent =
    new()
    {
        Name = "QA-Agent",
        Instructions = "Ask me anything!",
        Kernel = kernel
    };

// Add the agent to the chat
chat.AddAgent(agent);

// Get a user request and then add it to the chat
var userRequest = await PolyglotKernel.GetInputAsync("请输入您的问题:");
ChatMessageContent message = new(AuthorRole.User, userRequest);
chat.AddChatMessage(message);

// Invoke the agent and display the response
await foreach (ChatMessageContent message in chat.InvokeAsync(agent))
{
    message.Display();
}

// Get the chat history for the agent
var agentHistory = await chat.GetChatMessagesAsync(agent).ToArrayAsync();

agentHistory.Display();

多智能体协作

以下的示例中将定义两个智能体,这两个智能体通过协作来实现用户文案的优化。

  • Reviewer Agent:审查并提供改进方向
  • Writer Agent:负责根据建议重写内容
const string ReviewerName = "Reviewer";
const string WriterName = "Writer";

定义剪贴板插件

using System.ComponentModel;
using System.Diagnostics;

private sealed class ClipboardAccess
{
    [KernelFunction]
    [Description("Copies the provided content to the clipboard.")]
    public static void SetClipboard(string content)
    {
        if (string.IsNullOrWhiteSpace(content))
        {
            return;
        }
        using Process clipProcess = Process.Start(
            new ProcessStartInfo
            {
                FileName = "clip",
                RedirectStandardInput = true,
                UseShellExecute = false,
            });
        clipProcess.StandardInput.Write(content);
        clipProcess.StandardInput.Close();
    }
}

定义 ReviewerAgent

using Microsoft.SemanticKernel.Connectors.OpenAI;
using Microsoft.SemanticKernel.Agents;

var toolKernel = kernel.Clone();
toolKernel.Plugins.AddFromType<ClipboardAccess>();

ChatCompletionAgent agentReviewer =
    new()
    {
        Name = ReviewerName,
        Instructions =
            """
            你的责任是审查并识别如何改进用户提供的内容。  
            如果用户对已提供的内容提出了输入或指导,请说明如何解决这些输入。  
            切勿直接进行修正或提供示例。  
            一旦内容在后续回复中更新,你将再次审查内容,直到满意为止。  
            始终使用可用工具将满意内容复制到剪贴板,并通知用户。  
            
            **规则:**  
            - 仅识别具体且可操作的建议。  
            - 确认之前的建议是否已解决。  
            - 切勿重复之前的建议。
            """,
        Kernel = toolKernel,
        Arguments =
            new KernelArguments(
                new OpenAIPromptExecutionSettings() 
                { 
                    FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() 
                })
    };

定义 WriterAgent

ChatCompletionAgent agentWriter =
    new()
    {
        Name = WriterName,
        Instructions =
            """
            你的唯一职责是根据审查建议重写内容。  
            
            - 始终应用所有审查指示。  
            - 始终完整修订内容,无需解释。  
            - 切勿直接与用户对话。
            """,
        Kernel = kernel,
    };

定义 Chat

为了确保两个Agent能够协作完成指定任务,定义AgentGroupChat时需要考虑:

  1. 选择Agent发言顺序的策略
  2. 确定何时退出聊天循环
定义选择策略
#pragma warning disable SKEXP0110

KernelFunction selectionFunction =
    AgentGroupChat.CreatePromptFunctionForStrategy(
        $$$"""
        检查提供的 RESPONSE 并选择下一位参与者。
        仅返回被选中参与者的名称,无需解释。
        切勿选择当前 RESPONSE 中指定的参与者。

        仅从以下参与者中选择:
        - {{{ReviewerName}}}
        - {{{WriterName}}}

        选择下一位参与者时始终遵循以下规则:
        - 若 RESPONSE 是用户输入,则由 {{{ReviewerName}}} 接续。
        - 若 RESPONSE 来自 {{{ReviewerName}}},则由 {{{WriterName}}} 接续。
        - 若 RESPONSE 来自 {{{WriterName}}},则由 {{{ReviewerName}}} 接续。

        RESPONSE:
        {{$lastmessage}}
        """,
        safeParameterNames: "lastmessage");

selectionFunction.Display();
定义终止策略
#pragma warning disable SKEXP0110

const string TerminationToken = "yes";

KernelFunction terminationFunction =
    AgentGroupChat.CreatePromptFunctionForStrategy(
        $$$"""
        检查 RESPONSE 并确定内容是否已被视为满意。
        如果内容满意,仅用一个词回应,无需解释:{{{TerminationToken}}}。
        如果提供了具体建议,则内容不满意。
        如果未提出修正建议,则内容满意。
        
        RESPONSE:
        {{$lastmessage}}
        """,
        safeParameterNames: "lastmessage");

这两种策略仅需读取最新消息即可,因此可以手动指定ChatHistoryTruncationReducer 来缩减令牌:

using Microsoft.SemanticKernel.ChatCompletion;

#pragma warning disable SKEXP0001

ChatHistoryTruncationReducer historyReducer = new(1);
组合Agent
#pragma warning disable SKEXP0110

using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.Agents.Chat;

AgentGroupChat chat =
    new(agentReviewer, agentWriter)
    {
        ExecutionSettings = new AgentGroupChatSettings
        {
            SelectionStrategy =
                new KernelFunctionSelectionStrategy(selectionFunction, kernel)
                {
                    // Always start with the editor agent.
                    InitialAgent = agentReviewer,
                    // Save tokens by only including the final response
                    HistoryReducer = historyReducer,
                    // The prompt variable name for the history argument.
                    HistoryVariableName = "lastmessage",
                    // Returns the entire result value as a string.
                    ResultParser = (result) => result.GetValue<string>() ?? agentReviewer.Name
                },
            TerminationStrategy =
                new KernelFunctionTerminationStrategy(terminationFunction, kernel)
                {
                    // Only evaluate for editor's response
                    Agents = [agentReviewer],
                    // Save tokens by only including the final response
                    HistoryReducer = historyReducer,
                    // The prompt variable name for the history argument.
                    HistoryVariableName = "lastmessage",
                    // Limit total number of turns
                    MaximumIterations = 12,
                    // Customer result parser to determine if the response is "yes"
                    ResultParser = (result) => result.GetValue<string>()?.Contains(TerminationToken, StringComparison.OrdinalIgnoreCase) ?? false
                }
        }
    };

Console.WriteLine("Ready!");
using System.Text.Json;
using PolyglotKernel = Microsoft.DotNet.Interactive.Kernel;// 引入交互式的内核命名空间,以便用户输入
#pragma warning disable SKEXP0001

bool isComplete = false;
do
{
    Console.WriteLine();
    Console.Write("> ");
    string input = await PolyglotKernel.GetInputAsync();
    if (string.IsNullOrWhiteSpace(input))
    {
        continue;
    }
    input = input.Trim();
    if (input.Equals("EXIT", StringComparison.OrdinalIgnoreCase))
    {
        isComplete = true;
        break;
    }
    if (input.Equals("RESET", StringComparison.OrdinalIgnoreCase))
    {
        await chat.ResetAsync();
        Console.WriteLine("[Conversation has been reset]");
        continue;
    }
    chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, input));
    chat.IsComplete = false;
    try
    {
        await foreach (ChatMessageContent response in chat.InvokeAsync())
        {
            Console.WriteLine();
            Console.WriteLine($"{response.AuthorName.ToUpperInvariant()}:{Environment.NewLine}{response.Content}");
        }
    }
    catch (HttpOperationException exception)
    {
        Console.WriteLine(exception.Message);
        if (exception.InnerException != null)
        {
            Console.WriteLine(exception.InnerException.Message);
            if (exception.InnerException.Data.Count > 0)
            {
                Console.WriteLine(JsonSerializer.Serialize(exception.InnerException.Data, new JsonSerializerOptions() { WriteIndented = true }));
            }
        }
    }
} while (!isComplete);

> 
REVIEWER:
你的内容提供了一些信息,但还需要进一步改善才能更加清晰和全面。以下是一些具体且可操作的建议:  

1. **结构化信息**:将信息分段,并使用标题或编号来帮助读者更容易地理解各个部分。例如,你可以使用“框架概述”、“响应模式”和“策略”这类小标题。

2. **详细描述每个要素**:当前内容提到了一些专业术语,如“响应模式”和“会话终止策略”。为每个术语添加简短的定义或描述,以帮助理解。例如,解释“signle-turn”和“multi-turn”模式的区别。

3. **实例说明**:提供使用场景或实例,展示`AgentChat`和`AgentGroupChat`在实际应用中的作用。这样可以让读者更具体地理解这些概念。

4. **逻辑流程**:阐述`AgentChat`框架运行的基本流程,比如如何确定哪个Agent响应,以及如何评估对话的终止。

5. **语言简化**:有些句子略显复杂,可以试着简化语言结构,使其更易读。

请根据这些建议进行修改,提升内容的可读性和完整性。

WRITER:
`AgentChat`框架旨在探讨多智能体在对话场景中的协作机制,以提高复杂任务的解决能力。其主要功能包括:  

### 框架概述  
- **任务分工**:通过明确哪个Agent在每个回合中响应,以及何时终止对话,确保协作高效进行。  
- **Agent交互**:支持`ChatCompletionAgent`和`OpenAIAssistantAgent`在同一对话中的协同工作。

### AgentChat在SK中的位置  
- 作为一个抽象基类存在,具体实现为`AgentGroupChat`。

### AgentGroupChat功能  
- **协作入口点**:定义了启动单个智能体或多个智能体的机制。  
- **响应模式**:支持`single-turn`和`multi-turn`两种模式,分别对应单步和多步对话策略。  
- **选择策略**:内置多种Agent选择策略,允许灵活定制以适应特定需求。  
- **会话终止策略**:特别针对`multi-turn`模式提供了多种终止选项,确保对话在适当时机结束。  
- **状态管理**:提供对会话状态的管理功能,便于对话流的控制和监控。

通过这些功能,`AgentGroupChat`框架在多Agent系统中提供了一种结构化的方法来处理复杂对话任务的分配和管理。

REVIEWER:
内容已经更新并复制到剪贴板。改进后的版本更具结构性和详细性。

> 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值