echarts升级为echarts的常见问题

蝗曝植莆重要说明:

Microsoft Agent Framework 目前处于公开预览版(Public Preview)阶段

本文档中的代码示例基于 Azure OpenAI SDK 实现,展示 Function Calling 和 AI 代理的核心概念

部分工作流(Workflow)示例为概念性设计,展示多代理协作的思路

概述

什么是Microsoft Agent Framework

Microsoft Agent Framework 是微软开源的AI代理开发工具包,用于构建智能AI代理和多代理工作流系统。它支持 .NET 和 Python 两种开发语言,是 Semantic Kernel 和 AutoGen 项目的直接继承者和统一版本。

项目背景

设计理念:结合 AutoGen 的简洁抽象和 Semantic Kernel 的企业级特性

开源地址:https://github.com/microsoft/agent-framework

当前状态:公开预览版(Public Preview)

核心价值

统一框架:整合了Semantic Kernel和AutoGen的最佳特性

企业级特性:提供会话状态管理、类型安全、过滤器、遥测等

灵活架构:支持单代理和多代理编排模式

显式控制:通过工作流提供对多代理执行路径的精确控制

长期运行:强大的状态管理系统支持长时间运行和人机协作场景

核心概念

  1. AI代理(AI Agents)

定义

AI代理是使用大型语言模型(LLM)处理用户输入、做出决策、调用工具和MCP服务器执行操作,并生成响应的智能实体。

核心组件

用户输入 → AI代理 → 工具调用 → 外部服务

↓ ↓

LLM处理 MCP服务器

↓ ↓

决策逻辑 ← 执行结果 ←

响应生成

增强组件

会话(Session):管理多轮对话状态

上下文提供者(Context Provider):提供代理记忆能力

中间件(Middleware):拦截和增强代理行为

工具集成:通过MCP客户端集成外部工具

适用场景

? 适合使用AI代理的场景:

客户支持:处理多模态查询(文本、语音、图像)

教育辅导:利用外部知识库提供个性化辅导

代码生成与调试:辅助开发者进行实现、代码审查和调试

研究助手:搜索网络、总结文档、整合多源信息

动态任务处理:需要自主决策、临时规划和试错探索的场景

? 不适合使用AI代理的场景:

高度结构化且需要严格遵循预定义规则的任务

可以直接编写函数处理的确定性任务

简单的CRUD操作

需要100%确定性结果的场景

关键原则:如果可以编写函数来处理任务,就直接编写函数,而不是使用AI代理。可以用AI辅助编写函数。

  1. 工作流(Workflows)

定义

工作流是一种图形化的执行流程,它可以连接多个AI代理和函数来执行复杂的多步骤任务,同时保持一致性和可靠性。

工作流结构

开始节点

AI代理1 → 决策节点 → AI代理2

↓ ↓ ↓

函数调用 ← 条件路由 → 并行处理

↓ ↓

结束节点 ← 汇总结果 ←

核心特性

模块化:可分解为更小的可重用组件

代理集成:可整合多个AI代理和非代理组件

类型安全:强类型确保组件间消息正确流转

灵活控制流:支持条件路由、并行处理和动态执行路径

外部集成:内置请求/响应模式用于系统集成

检查点机制:保存工作流状态,支持恢复和续接

多代理编排:内置顺序、并发、移交等编排模式

可组合性:工作流可嵌套或组合创建更复杂流程

AI代理 vs 工作流对比

特性 AI代理 工作流

执行方式 LLM驱动的动态步骤 预定义的操作序列

决策方式 基于对话上下文和可用工具自动决定 明确定义的流程路径

适用任务 非结构化、需要探索的任务 结构化、多步骤的复杂任务

控制程度 较低(LLM自主决策) 较高(显式定义)

可预测性 较低 较高

安装与配置

.NET环境要求

前置条件

  • .NET 8.0 SDK 或更高版本

  • Azure OpenAI 资源(已部署模型,如 gpt-4o-mini)

  • Azure CLI(已安装并认证,可选)

创建项目

创建新控制台应用

dotnet new console -o AgentFrameworkDemo

cd AgentFrameworkDemo

安装NuGet包

安装核心包(实际使用的包)

dotnet add package Azure.AI.OpenAI --prerelease

dotnet add package Azure.Identity

dotnet add package Microsoft.Extensions.Configuration.Json

注意:Microsoft.Agents.AI 包仍在开发中

当前示例使用 Azure.AI.OpenAI 实现相同功能

配置Azure认证

使用Azure CLI登录(可选)

az login

确保账户具有以下角色之一:

- Cognitive Services OpenAI User

- Cognitive Services OpenAI Contributor

创建配置文件

创建 appsettings.json 文件:

{

"AzureOpenAI": {

"Endpoint": "https://your-resource.openai.azure.com/",

"DeploymentName": "gpt-4o-mini",

"ApiKey": ""

}

}

注意:

Endpoint: 你的 Azure OpenAI 资源端点

DeploymentName: 部署的模型名称(如 gpt-4o-mini, gpt-4o)

ApiKey: 可留空使用 Azure CLI 认证,或填入 API 密钥

快速入门

基础AI代理示例(C#)

注意:Microsoft Agent Framework 目前仍在预览阶段,本示例使用 Azure OpenAI SDK 实现相同的功能。

using System;

using Azure;

using Azure.AI.OpenAI;

using Azure.Identity;

using Microsoft.Extensions.Configuration;

using OpenAI.Chat;

// 加载配置

var configuration = new ConfigurationBuilder()

.AddJsonFile("appsettings.json")

.Build();

var endpoint = configuration["AzureOpenAI:Endpoint"];

var deploymentName = configuration["AzureOpenAI:DeploymentName"];

var apiKey = configuration["AzureOpenAI:ApiKey"];

// 创建Azure OpenAI客户端

AzureOpenAIClient openAIClient;

if (!string.IsNullOrEmpty(apiKey))

{

// 使用API Key认证

openAIClient = new AzureOpenAIClient(

new Uri(endpoint),

new AzureKeyCredential(apiKey)

);

}

else

{

// 使用Azure CLI认证

openAIClient = new AzureOpenAIClient(

new Uri(endpoint),

new AzureCliCredential()

);

}

// 获取聊天客户端

var chatClient = openAIClient.GetChatClient(deploymentName);

// 创建对话

var messages = new List

{

new SystemChatMessage("You are good at telling jokes."),

new UserChatMessage("Tell me a joke about a pirate.")

};

var response = await chatClient.CompleteChatAsync(messages);

Console.WriteLine(response.Value.Content[0].Text);

配置文件示例

创建 appsettings.json 文件:

{

"AzureOpenAI": {

"Endpoint": "https://your-resource.openai.azure.com/",

"DeploymentName": "gpt-4o-mini",

"ApiKey": ""

}

}

Python快速示例

import asyncio

from agent_framework.azure import AzureAIClient

from azure.identity.aio import AzureCliCredential

async def main():

async with (

AzureCliCredential() as credential,

AzureAIClient(async_credential=credential).as_agent(

name="JokeAgent",

instructions="You are good at telling jokes.",

) as agent,

):

result = await agent.run("Tell me a joke about a pirate.")

print(result.text)

if name == "main":

asyncio.run(main())

AI代理详解

代理工具(Agent Tools / Function Calling)

定义工具函数

using System.ComponentModel;

public class CustomerServiceTools

{

Description("Search for customer order by order ID")

public async Task GetOrderInfoAsync(

Description("Order ID to search, format like ORD-12345")\] string orderId) { // 模拟数据库查询 await Task.Delay(100); return $@"订单信息查询成功: - 订单号:{orderId} - 客户姓名:张三 - 产品:Surface Laptop 5 - 状态:已发货 - 物流单号:SF1234567890"; } \[Description("Process refund request for an order")

public async Task ProcessRefundAsync(

Description("Order ID to refund")\] string orderId, \[Description("Refund reason provided by customer")\] string reason) { await Task.Delay(200); var refundId = $"RF-{DateTime.Now:yyyyMMddHHmmss}"; return $@"退款申请已成功提交: - 退款单号:{refundId} - 订单号:{orderId} - 退款原因:{reason} - 预计处理时间:3-5个工作日"; } } 使用 Function Calling using OpenAI.Chat; // 创建工具实例 var tools = new CustomerServiceTools(); // 定义工具(Function Calling) var chatOptions = new ChatCompletionOptions(); chatOptions.Tools.Add(ChatTool.CreateFunctionTool( "GetOrderInfo", "Search for customer order by order ID", BinaryData.FromString(""" { "type": "object", "properties": { "orderId": { "type": "string", "description": "Order ID to search, format like ORD-12345" } }, "required": \["orderId"

}

""")

));

chatOptions.Tools.Add(ChatTool.CreateFunctionTool(

"ProcessRefund",

"Process refund request for an order",

BinaryData.FromString("""

{

"type": "object",

"properties": {

"orderId": {

"type": "string",

"description": "Order ID to refund"

},

"reason": {

"type": "string",

"description": "Refund reason provided by customer"

}

},

"required": ["orderId", "reason"]

}

""")

));

// 调用AI并处理工具调用

var messages = new List

{

new SystemChatMessage("你是专业的客户服务助手"),

new UserChatMessage("查询订单 ORD-12345")

};

var completion = await chatClient.CompleteChatAsync(messages, chatOptions);

// 检查是否需要调用工具

if (completion.Value.FinishReason == ChatFinishReason.ToolCalls)

{

// 添加助手消息到历史

messages.Add(new AssistantChatMessage(completion.Value));

// 执行工具调用

foreach (var toolCall in completion.Value.ToolCalls)

{

var functionName = toolCall.FunctionName;

var arguments = JsonDocument.Parse(toolCall.FunctionArguments.ToString());

string result = functionName switch

{

"GetOrderInfo" => await tools.GetOrderInfoAsync(

arguments.RootElement.GetProperty("orderId").GetString()!

),

"ProcessRefund" => await tools.ProcessRefundAsync(

arguments.RootElement.GetProperty("orderId").GetString()!,

arguments.RootElement.GetProperty("reason").GetString()!

),

_ => "未知工具"

};

// 添加工具结果到历史

messages.Add(new ToolChatMessage(toolCall.Id, result));

}

// 再次调用AI生成最终响应

var finalResponse = await chatClient.CompleteChatAsync(messages, chatOptions);

Console.WriteLine(finalResponse.Value.Content[0].Text);

}

多轮对话(Multi-turn Conversation)

using OpenAI.Chat;

// 创建对话历史以保持上下文

var conversationHistory = new List

{

new SystemChatMessage("You are a helpful assistant.")

};

// 第一轮对话

conversationHistory.Add(new UserChatMessage("My name is John."));

var response1 = await chatClient.CompleteChatAsync(conversationHistory);

var assistantMessage1 = response1.Value.Content[0].Text;

Console.WriteLine(assistantMessage1);

// 将助手响应添加到历史

conversationHistory.Add(new AssistantChatMessage(assistantMessage1));

// 第二轮对话(AI记得之前的上下文)

conversationHistory.Add(new UserChatMessage("What's my name?"));

var response2 = await chatClient.CompleteChatAsync(conversationHistory);

var assistantMessage2 = response2.Value.Content[0].Text;

Console.WriteLine(assistantMessage2); // 输出:Your name is John.

// 将响应添加到历史

conversationHistory.Add(new AssistantChatMessage(assistantMessage2));

// 第三轮对话

conversationHistory.Add(new UserChatMessage("Tell me a joke about my name."));

var response3 = await chatClient.CompleteChatAsync(conversationHistory);

Console.WriteLine(response3.Value.Content[0].Text);

代理记忆(Agent Memory)

注意:此示例展示记忆管理概念,实际实现通过维护对话历史来管理上下文。

using OpenAI.Chat;

// 使用对话历史实现记忆功能

var conversationHistory = new List

{

new SystemChatMessage("You are a personal assistant. Remember user preferences.")

};

// 用户设置偏好

conversationHistory.Add(new UserChatMessage("Remember that I prefer meetings in the morning."));

var response1 = await chatClient.CompleteChatAsync(conversationHistory);

conversationHistory.Add(new AssistantChatMessage(response1.Value.Content[0].Text));

conversationHistory.Add(new UserChatMessage("My favorite programming language is C#."));

var response2 = await chatClient.CompleteChatAsync(conversationHistory);

conversationHistory.Add(new AssistantChatMessage(response2.Value.Content[0].Text));

// 稍后查询 - AI会从对话历史中回忆

conversationHistory.Add(new UserChatMessage("When do I prefer meetings?"));

var response3 = await chatClient.CompleteChatAsync(conversationHistory);

Console.WriteLine(response3.Value.Content[0].Text); // 输出:You prefer meetings in the morning.

代理中间件(Agent Middleware)

注意:此示例展示中间件概念,实际实现可以通过包装函数来实现类似功能。

using OpenAI.Chat;

// 创建包装类实现日志和过滤功能

public class ChatClientWrapper

{

private readonly ChatClient _chatClient;

public ChatClientWrapper(ChatClient chatClient)

{

_chatClient = chatClient;

}

public async Task CompleteChatWithLoggingAsync(

List messages,

ChatCompletionOptions? options = null)

{

// 日志记录请求

var userMessage = messages.LastOrDefault(m => m is UserChatMessage);

if (userMessage != null)

{

Console.WriteLine($"[Request] {((UserChatMessage)userMessage).Content[0].Text}");

}

// 检查敏感内容

if (userMessage != null && ContainsSensitiveInfo(((UserChatMessage)userMessage).Content[0].Text))

{

Console.WriteLine("[Filter] Sensitive information detected");

return "I cannot process sensitive information.";

}

// 调用实际的API

var response = await _chatClient.CompleteChatAsync(messages, options);

var responseText = response.Value.Content[0].Text;

// 日志记录响应

Console.WriteLine($"[Response] {responseText}");

return responseText;

}

private bool ContainsSensitiveInfo(string message)

{

// 实现敏感信息检测逻辑

return message.Contains("password") || message.Contains("credit card");

}

}

// 使用示例

var wrapper = new ChatClientWrapper(chatClient);

var messages = new List

{

new SystemChatMessage("You are a helpful assistant."),

new UserChatMessage("Tell me a joke.")

};

var response = await wrapper.CompleteChatWithLoggingAsync(messages);

工作流详解

重要说明:以下工作流示例为概念性设计,展示多代理协作的思路。Microsoft Agent Framework 的工作流 API 仍在开发中,实际实现需要通过组合多个 ChatClient 调用来完成。

基础工作流结构(概念性示例)

using OpenAI.Chat;

using System.Text.Json;

// 概念性的客户支持工作流实现

public class CustomerSupportWorkflow

{

private readonly ChatClient _chatClient;

public CustomerSupportWorkflow(ChatClient chatClient)

{

_chatClient = chatClient;

}

public async Task ExecuteAsync(string userQuery)

{

// 步骤1: 意图识别

var intent = await TriageAsync(userQuery);

// 步骤2: 根据意图路由到专门的处理逻辑

return intent switch

{

"technical" => await HandleTechnicalIssueAsync(userQuery),

"billing" => await HandleBillingIssueAsync(userQuery),

_ => await HandleGeneralQueryAsync(userQuery)

};

}

private async Task TriageAsync(string query)

{

var messages = new List

{

new SystemChatMessage(@"你是客户服务分类助手。分析用户问题并返回以下类别之一:

  • technical: 技术问题

  • billing: 账单问题

  • general: 一般咨询

只返回类别名称,不要其他内容。"),

new UserChatMessage(query)

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text.Trim().ToLower();

}

private async Task HandleTechnicalIssueAsync(string query)

{

var messages = new List

{

new SystemChatMessage("你是技术支持专家,负责解决技术问题。"),

new UserChatMessage(query)

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

private async Task HandleBillingIssueAsync(string query)

{

var messages = new List

{

new SystemChatMessage("你是账单支持专家,负责处理账单相关问题。"),

new UserChatMessage(query)

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

private async Task HandleGeneralQueryAsync(string query)

{

var messages = new List

{

new SystemChatMessage("你是客户服务代表,负责回答一般性问题。"),

new UserChatMessage(query)

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

}

条件路由(概念性示例)

using OpenAI.Chat;

public class OrderProcessingWorkflow

{

private readonly ChatClient _chatClient;

public async Task ExecuteAsync(string orderId)

{

// 步骤1: 验证订单

var isValid = await ValidateOrderAsync(orderId);

if (isValid)

{

// 步骤2: 处理支付

await ProcessPaymentAsync(orderId);

// 步骤3: 发货

return await ShipOrderAsync(orderId);

}

else

{

// 通知客户

return await NotifyCustomerAsync(orderId, "订单验证失败");

}

}

private async Task ValidateOrderAsync(string orderId)

{

// 实现订单验证逻辑

await Task.Delay(100);

return orderId.StartsWith("ORD-");

}

private async Task ProcessPaymentAsync(string orderId)

{

// 实现支付处理逻辑

await Task.Delay(200);

}

private async Task ShipOrderAsync(string orderId)

{

// 实现发货逻辑

await Task.Delay(150);

return $"订单 {orderId} 已发货";

}

private async Task NotifyCustomerAsync(string orderId, string reason)

{

// 实现客户通知逻辑

await Task.Delay(100);

return $"订单 {orderId} 处理失败: {reason}";

}

}

并行处理(概念性示例)

using OpenAI.Chat;

public class DataAnalysisWorkflow

{

private readonly ChatClient _chatClient;

public async Task ExecuteAsync(string data)

{

// 步骤1: 加载数据

var loadedData = await LoadDataAsync(data);

// 步骤2: 并行执行三种分析

var statisticalTask = StatisticalAnalysisAsync(loadedData);

var sentimentTask = SentimentAnalysisAsync(loadedData);

var trendTask = TrendAnalysisAsync(loadedData);

await Task.WhenAll(statisticalTask, sentimentTask, trendTask);

// 步骤3: 汇总结果

return await AggregateResultsAsync(

statisticalTask.Result,

sentimentTask.Result,

trendTask.Result

);

}

private async Task LoadDataAsync(string data)

{

await Task.Delay(100);

return data;

}

private async Task StatisticalAnalysisAsync(string data)

{

var messages = new List

{

new SystemChatMessage("你是统计分析专家。"),

new UserChatMessage($"对以下数据进行统计分析:{data}")

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

private async Task SentimentAnalysisAsync(string data)

{

var messages = new List

{

new SystemChatMessage("你是情感分析专家。"),

new UserChatMessage($"对以下数据进行情感分析:{data}")

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

private async Task TrendAnalysisAsync(string data)

{

var messages = new List

{

new SystemChatMessage("你是趋势分析专家。"),

new UserChatMessage($"对以下数据进行趋势分析:{data}")

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

private async Task AggregateResultsAsync(

string statistical,

string sentiment,

string trend)

{

var messages = new List

{

new SystemChatMessage("你是数据分析总结专家。"),

new UserChatMessage($@"汇总以下分析结果:

统计分析:{statistical}

情感分析:{sentiment}

趋势分析:{trend}")

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

}

多代理编排模式

  1. 顺序编排(Sequential)(概念性示例)

using OpenAI.Chat;

public class ResearchWorkflow

{

private readonly ChatClient _chatClient;

public async Task ExecuteAsync(string topic)

{

// 步骤1: 搜索信息

var searchResults = await SearchAsync(topic);

// 步骤2: 分析数据

var analysis = await AnalyzeAsync(searchResults);

// 步骤3: 生成摘要

var summary = await SummarizeAsync(analysis);

// 步骤4: 审查结果

return await ReviewAsync(summary);

}

private async Task SearchAsync(string topic)

{

var messages = new List

{

new SystemChatMessage("你是信息搜索专家。"),

new UserChatMessage($"搜索关于 '{topic}' 的相关信息")

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

private async Task AnalyzeAsync(string data)

{

var messages = new List

{

new SystemChatMessage("你是数据分析专家。"),

new UserChatMessage($"分析以下数据:{data}")

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

private async Task SummarizeAsync(string analysis)

{

var messages = new List

{

new SystemChatMessage("你是内容摘要专家。"),

new UserChatMessage($"总结以下分析:{analysis}")

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

private async Task ReviewAsync(string summary)

{

var messages = new List

{

new SystemChatMessage("你是质量审查专家。"),

new UserChatMessage($"审查以下摘要:{summary}")

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

}

  1. 并发编排(Concurrent)(概念性示例)

using OpenAI.Chat;

public class ContentCreationWorkflow

{

private readonly ChatClient _chatClient;

public async Task ExecuteAsync(string topic)

{

// 步骤1: 生成大纲

var outline = await CreateOutlineAsync(topic);

// 步骤2: 并行撰写各部分

var section1Task = WriteSectionAsync(outline, "section1");

var section2Task = WriteSectionAsync(outline, "section2");

var section3Task = WriteSectionAsync(outline, "section3");

await Task.WhenAll(section1Task, section2Task, section3Task);

// 步骤3: 编辑整合

return await EditAsync(section1Task.Result, section2Task.Result, section3Task.Result);

}

private async Task CreateOutlineAsync(string topic)

{

var messages = new List

{

new SystemChatMessage("你是内容大纲设计专家。"),

new UserChatMessage($"为主题 '{topic}' 创建详细大纲")

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

private async Task WriteSectionAsync(string outline, string sectionName)

{

var messages = new List

{

new SystemChatMessage($"你是内容撰写专家,专注于撰写 {sectionName}。"),

new UserChatMessage($"根据以下大纲撰写 {sectionName}:\n{outline}")

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

private async Task EditAsync(string section1, string section2, string section3)

{

var messages = new List

{

new SystemChatMessage("你是内容编辑专家。"),

new UserChatMessage($@"整合并编辑以下内容:

部分1:{section1}

部分2:{section2}

部分3:{section3}")

};

var response = await _chatClient.CompleteChatAsync(messages);

return response.Value.Content[0].Text;

}

}