Skip to content

运行代理

基本代理抽象公开用于运行代理的各种选项。调用方可以选择提供零条、一条或多条输入消息,也可以在流式处理和非流式处理之间选择。


流式处理和非流式处理

非流式处理 - RunAsync

使用 RunAsync 方法获取完整的代理响应:

csharp
Console.WriteLine(
    await agent.RunAsync("What is the weather like in Amsterdam?"));

RunAsync 返回一个 AgentResponse 对象,其中包含 LLM 生成的完整回复内容。所有内容(包括工具调用结果、文本、文件等)都在一个对象中返回。

流式处理 - RunStreamingAsync

使用 RunStreamingAsync 方法逐 Token 获取响应:

csharp
await foreach (var update in agent
    .RunStreamingAsync("What is the weather like in Amsterdam?"))
{
    Console.Write(update);
}

流式输出让 Agent 在 LLM 生成的同时逐步返回结果,用户界面可以实现"打字机效果",大幅改善等待体验。

代理运行选项

AgentRunOptions 允许为每次调用传递自定义选项:

csharp
var chatOptions = new ChatOptions()
{
    Tools = [AIFunctionFactory.Create(GetWeather)]
};

Console.WriteLine(await agent.RunAsync(
    "What is the weather like in Amsterdam?",
    options: new ChatClientAgentRunOptions(chatOptions)));

当调用方知道代理的具体类型时,可以传递类型特定的选项(如 ChatClientAgentRunOptions),这些选项会与代理级别的默认选项合并。

响应类型

来自代理的流式和非流式响应都包含代理生成的所有内容,可能包括:

  • 用户问题的答案(文本)
  • 函数工具调用信息
  • 工具调用结果
  • 推理文本
  • 状态更新

提取文本结果

由于并非所有返回的内容都是结果,需要聚合所有 TextContent 项来提取纯文本:

csharp
// 非流式
var response = await agent.RunAsync("What is the weather like in Amsterdam?");
Console.WriteLine(response.Text);         // 聚合的文本
Console.WriteLine(response.Messages.Count); // 包含所有内容的消息数

// 流式
await foreach (var update in agent
    .RunStreamingAsync("What is the weather like in Amsterdam?"))
{
    Console.WriteLine(update.Text);        // 当前更新的文本片段
    Console.WriteLine(update.Contents.Count); // 包含的内容项数
}

消息类型

Agent 的输入和输出表示为消息。消息细分为内容项。MAF 使用 Microsoft.Extensions.AI 抽象提供的消息和内容类型:

类型说明
TextContent文本内容,既可以是输入也可以是输出。通常包含 Agent 的文本结果
DataContent二进制内容,用于传入和传出图像、音频或视频数据
UriContent指向托管内容(如图像、音频、视频)的 URL
FunctionCallContentLLM 调用函数工具的请求
FunctionResultContent函数工具调用的结果
csharp
// 解析响应中的不同内容类型
foreach (var content in response)
{
    switch (content)
    {
        case TextContent text:
            Console.WriteLine($"文本: {text.Text}");
            break;
        case DataContent data:
            Console.WriteLine($"数据: {data.Data.Length} bytes");
            break;
        case UriContent uri:
            Console.WriteLine($"URI: {uri.Uri}");
            break;
        case FunctionCallContent fnCall:
            Console.WriteLine($"函数调用: {fnCall.Name}");
            break;
        case FunctionResultContent fnResult:
            Console.WriteLine($"函数结果: {fnResult.Result}");
            break;
    }
}

要点Text 属性是在 AgentResponseAgentResponseUpdate 上都可用的便捷属性,自动聚合所有 TextContent 项。对于只需获取纯文本结果的场景,是最简方式。


下一步:代理管道 — 理解三层管道架构。

学而不思则罔,思而不学则殆