Microsoft Agent Framework 详解与实践
Microsoft Agent Framework 详解与实践
Microsoft Agent Framework 详解
重要说明:
- 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辅助编写函数。
2. 工作流(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<ChatMessage>
{
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<string> 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<string> 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<ChatMessage>
{
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<ChatMessage>
{
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<ChatMessage>
{
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<string> CompleteChatWithLoggingAsync(
List<ChatMessage> 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<ChatMessage>
{
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<string> 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<string> TriageAsync(string query)
{
var messages = new List<ChatMessage>
{
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<string> HandleTechnicalIssueAsync(string query)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是技术支持专家,负责解决技术问题。"),
new UserChatMessage(query)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> HandleBillingIssueAsync(string query)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是账单支持专家,负责处理账单相关问题。"),
new UserChatMessage(query)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> HandleGeneralQueryAsync(string query)
{
var messages = new List<ChatMessage>
{
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<string> 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<bool> ValidateOrderAsync(string orderId)
{
// 实现订单验证逻辑
await Task.Delay(100);
return orderId.StartsWith("ORD-");
}
private async Task ProcessPaymentAsync(string orderId)
{
// 实现支付处理逻辑
await Task.Delay(200);
}
private async Task<string> ShipOrderAsync(string orderId)
{
// 实现发货逻辑
await Task.Delay(150);
return $"订单 {orderId} 已发货";
}
private async Task<string> 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<string> 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<string> LoadDataAsync(string data)
{
await Task.Delay(100);
return data;
}
private async Task<string> StatisticalAnalysisAsync(string data)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是统计分析专家。"),
new UserChatMessage($"对以下数据进行统计分析:{data}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> SentimentAnalysisAsync(string data)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是情感分析专家。"),
new UserChatMessage($"对以下数据进行情感分析:{data}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> TrendAnalysisAsync(string data)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是趋势分析专家。"),
new UserChatMessage($"对以下数据进行趋势分析:{data}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> AggregateResultsAsync(
string statistical,
string sentiment,
string trend)
{
var messages = new List<ChatMessage>
{
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<string> 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<string> SearchAsync(string topic)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是信息搜索专家。"),
new UserChatMessage($"搜索关于 '{topic}' 的相关信息")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> AnalyzeAsync(string data)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是数据分析专家。"),
new UserChatMessage($"分析以下数据:{data}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> SummarizeAsync(string analysis)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是内容摘要专家。"),
new UserChatMessage($"总结以下分析:{analysis}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> ReviewAsync(string summary)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是质量审查专家。"),
new UserChatMessage($"审查以下摘要:{summary}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
}
2. 并发编排(Concurrent)(概念性示例)
using OpenAI.Chat;
public class ContentCreationWorkflow
{
private readonly ChatClient _chatClient;
public async Task<string> 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<string> CreateOutlineAsync(string topic)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是内容大纲设计专家。"),
new UserChatMessage($"为主题 '{topic}' 创建详细大纲")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> WriteSectionAsync(string outline, string sectionName)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage($"你是内容撰写专家,专注于撰写 {sectionName}。"),
new UserChatMessage($"根据以下大纲撰写 {sectionName}:\n{outline}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> EditAsync(string section1, string section2, string section3)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是内容编辑专家。"),
new UserChatMessage($@"整合并编辑以下内容:
部分1:{section1}
部分2:{section2}
部分3:{section3}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
}
3. 移交模式(Hand-off)(概念性示例)
using OpenAI.Chat;
public class SupportTicketWorkflow
{
private readonly ChatClient _chatClient;
public async Task<string> ExecuteAsync(string ticketDescription)
{
// 步骤1: 一级支持处理
var level1Result = await Level1SupportAsync(ticketDescription);
// 检查是否需要升级
if (RequiresEscalation(level1Result))
{
// 升级到二级支持
var level2Result = await Level2SupportAsync(ticketDescription, level1Result);
// 检查是否需要专家
if (RequiresSpecialist(level2Result))
{
return await SpecialistSupportAsync(ticketDescription, level1Result, level2Result);
}
return level2Result;
}
return level1Result;
}
private async Task<string> Level1SupportAsync(string ticket)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage(@"你是一级客户支持。处理常见问题。
如果问题复杂,在回复末尾添加 [ESCALATE]。"),
new UserChatMessage(ticket)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> Level2SupportAsync(string ticket, string level1Notes)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage(@"你是二级技术支持。处理复杂技术问题。
如果需要专家介入,在回复末尾添加 [SPECIALIST]。"),
new UserChatMessage($"工单:{ticket}\n\n一级支持记录:{level1Notes}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> SpecialistSupportAsync(
string ticket,
string level1Notes,
string level2Notes)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是技术专家,处理最复杂的技术问题。"),
new UserChatMessage($@"工单:{ticket}
一级支持记录:{level1Notes}
二级支持记录:{level2Notes}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private bool RequiresEscalation(string result)
{
return result.Contains("[ESCALATE]");
}
private bool RequiresSpecialist(string result)
{
return result.Contains("[SPECIALIST]");
}
}
工作流检查点(概念性示例)
注意:此示例展示工作流状态保存的概念。实际实现需要自行设计状态持久化方案。
using System.Text.Json;
using OpenAI.Chat;
// 工作流状态类
public class WorkflowState
{
public string CurrentStep { get; set; } = string.Empty;
public Dictionary<string, string> StepResults { get; set; } = new();
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime LastUpdated { get; set; } = DateTime.UtcNow;
}
// 带检查点的长时间运行工作流
public class LongRunningWorkflow
{
private readonly ChatClient _chatClient;
private readonly string _stateFilePath;
public LongRunningWorkflow(ChatClient chatClient, string stateFilePath = "workflow_state.json")
{
_chatClient = chatClient;
_stateFilePath = stateFilePath;
}
public async Task<string> ExecuteAsync(string input)
{
// 尝试恢复状态
var state = await LoadStateAsync() ?? new WorkflowState();
try
{
// 步骤1: 数据收集
if (string.IsNullOrEmpty(state.StepResults.GetValueOrDefault("collect")))
{
state.CurrentStep = "collect";
state.StepResults["collect"] = await CollectDataAsync(input);
await SaveStateAsync(state);
}
// 步骤2: 数据处理
if (string.IsNullOrEmpty(state.StepResults.GetValueOrDefault("process")))
{
state.CurrentStep = "process";
state.StepResults["process"] = await ProcessDataAsync(state.StepResults["collect"]);
await SaveStateAsync(state);
}
// 步骤3: 生成报告
if (string.IsNullOrEmpty(state.StepResults.GetValueOrDefault("report")))
{
state.CurrentStep = "report";
state.StepResults["report"] = await GenerateReportAsync(state.StepResults["process"]);
await SaveStateAsync(state);
}
// 完成后删除状态文件
if (File.Exists(_stateFilePath))
{
File.Delete(_stateFilePath);
}
return state.StepResults["report"];
}
catch (Exception ex)
{
// 异常时保存状态
await SaveStateAsync(state);
throw new Exception($"工作流在步骤 {state.CurrentStep} 失败", ex);
}
}
public async Task<string> ResumeAsync()
{
var state = await LoadStateAsync();
if (state == null)
{
throw new InvalidOperationException("没有可恢复的工作流状态");
}
Console.WriteLine($"从步骤 {state.CurrentStep} 恢复工作流...");
return await ExecuteAsync(string.Empty);
}
private async Task<WorkflowState?> LoadStateAsync()
{
if (!File.Exists(_stateFilePath))
{
return null;
}
var json = await File.ReadAllTextAsync(_stateFilePath);
return JsonSerializer.Deserialize<WorkflowState>(json);
}
private async Task SaveStateAsync(WorkflowState state)
{
state.LastUpdated = DateTime.UtcNow;
var json = JsonSerializer.Serialize(state, new JsonSerializerOptions
{
WriteIndented = true
});
await File.WriteAllTextAsync(_stateFilePath, json);
}
private async Task<string> CollectDataAsync(string input)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是数据收集专家。"),
new UserChatMessage($"收集关于 '{input}' 的数据")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> ProcessDataAsync(string data)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是数据处理专家。"),
new UserChatMessage($"处理以下数据:{data}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> GenerateReportAsync(string processedData)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是报告生成专家。"),
new UserChatMessage($"基于以下处理后的数据生成报告:{processedData}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
}
// 使用示例
var workflow = new LongRunningWorkflow(chatClient);
try
{
var result = await workflow.ExecuteAsync("市场趋势分析");
Console.WriteLine(result);
}
catch (Exception)
{
// 如果失败,可以稍后恢复
Console.WriteLine("工作流已暂停,稍后可恢复...");
// 恢复工作流
var resumedResult = await workflow.ResumeAsync();
Console.WriteLine(resumedResult);
}
具体案例
案例1:智能客户服务助手
场景描述
构建一个智能客户服务系统,能够理解客户问题、查询订单信息、处理退款请求。
完整实现
using System;
using System.ComponentModel;
using System.Text.Json;
using System.Threading.Tasks;
using Azure;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Extensions.Configuration;
using OpenAI.Chat;
namespace CustomerServiceDemo
{
// 1. 定义服务工具类
public class CustomerServiceTools
{
private readonly Dictionary<string, OrderInfo> _mockOrderDatabase;
public CustomerServiceTools()
{
// 初始化模拟订单数据库
_mockOrderDatabase = new Dictionary<string, OrderInfo>
{
["ORD-12345"] = new OrderInfo
{
OrderId = "ORD-12345",
CustomerName = "张三",
Product = "Surface Laptop 5",
Status = "已发货",
TrackingNumber = "SF1234567890",
Amount = 8999.00m,
OrderDate = DateTime.Now.AddDays(-3)
}
};
}
[Description("Search for customer order by order ID")]
public async Task<string> GetOrderInfoAsync(
[Description("Order ID to search, format like ORD-12345")] string orderId)
{
await Task.Delay(100);
if (_mockOrderDatabase.TryGetValue(orderId, out var order))
{
return $@"订单信息查询成功:
- 订单号:{order.OrderId}
- 客户姓名:{order.CustomerName}
- 产品:{order.Product}
- 状态:{order.Status}
- 金额:¥{order.Amount:N2}
- 物流单号:{order.TrackingNumber}";
}
return $"未找到订单号为 {orderId} 的订单。";
}
[Description("Process refund request for an order")]
public async Task<string> ProcessRefundAsync(
[Description("Order ID to refund")] string orderId,
[Description("Refund reason provided by customer")] string reason)
{
await Task.Delay(200);
if (!_mockOrderDatabase.TryGetValue(orderId, out var order))
{
return $"无法处理退款:未找到订单号 {orderId}。";
}
var refundId = $"RF-{DateTime.Now:yyyyMMddHHmmss}";
var estimatedDate = DateTime.Now.AddDays(5);
return $@"退款申请已成功提交:
- 退款单号:{refundId}
- 订单号:{orderId}
- 退款金额:¥{order.Amount:N2}
- 退款原因:{reason}
- 预计到账日期:{estimatedDate:yyyy年MM月dd日}";
}
}
// 2. 数据模型
public class OrderInfo
{
public string OrderId { get; set; } = string.Empty;
public string CustomerName { get; set; } = string.Empty;
public string Product { get; set; } = string.Empty;
public string Status { get; set; } = string.Empty;
public string TrackingNumber { get; set; } = string.Empty;
public decimal Amount { get; set; }
public DateTime OrderDate { get; set; }
}
// 3. 主程序
class Program
{
static async Task Main(string[] args)
{
// 配置Azure OpenAI客户端
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var openAIClient = new AzureOpenAIClient(
new Uri(configuration["AzureOpenAI:Endpoint"]),
new AzureKeyCredential(configuration["AzureOpenAI:ApiKey"])
);
var chatClient = openAIClient.GetChatClient(
configuration["AzureOpenAI:DeploymentName"]
);
// 创建工具实例
var tools = new CustomerServiceTools();
// 定义系统提示词
var systemPrompt = @"你是一个专业的客户服务助手。职责包括:
1. 友好地回答客户问题
2. 查询订单信息
3. 处理退款请求
请始终保持礼貌和专业,提供准确的信息。";
// 创建对话历史
var conversationHistory = new List<ChatMessage>
{
new SystemChatMessage(systemPrompt)
};
Console.WriteLine("=== 智能客户服务助手 ===\n");
// 对话1:查询订单
await ProcessUserRequest(
chatClient,
conversationHistory,
tools,
"你好,我想查询订单 ORD-12345 的状态"
);
// 对话2:申请退款
await ProcessUserRequest(
chatClient,
conversationHistory,
tools,
"我对这个订单不满意,想申请退款"
);
}
static async Task ProcessUserRequest(
ChatClient chatClient,
List<ChatMessage> conversationHistory,
CustomerServiceTools tools,
string userMessage)
{
Console.WriteLine($"客户: {userMessage}");
// 添加用户消息
conversationHistory.Add(new UserChatMessage(userMessage));
// 定义工具
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"}
},
"required": ["orderId"]
}
""")
));
chatOptions.Tools.Add(ChatTool.CreateFunctionTool(
"ProcessRefund",
"Process refund request",
BinaryData.FromString("""
{
"type": "object",
"properties": {
"orderId": {"type": "string"},
"reason": {"type": "string"}
},
"required": ["orderId", "reason"]
}
""")
));
// 调用AI
var completion = await chatClient.CompleteChatAsync(
conversationHistory,
chatOptions
);
// 处理工具调用
if (completion.Value.FinishReason == ChatFinishReason.ToolCalls)
{
conversationHistory.Add(new AssistantChatMessage(completion.Value));
foreach (var toolCall in completion.Value.ToolCalls)
{
var args = JsonDocument.Parse(toolCall.FunctionArguments.ToString());
var result = toolCall.FunctionName switch
{
"GetOrderInfo" => await tools.GetOrderInfoAsync(
args.RootElement.GetProperty("orderId").GetString()!
),
"ProcessRefund" => await tools.ProcessRefundAsync(
args.RootElement.GetProperty("orderId").GetString()!,
args.RootElement.GetProperty("reason").GetString()!
),
_ => "未知工具"
};
conversationHistory.Add(new ToolChatMessage(toolCall.Id, result));
}
// 获取最终响应
var finalResponse = await chatClient.CompleteChatAsync(
conversationHistory,
chatOptions
);
Console.WriteLine($"助手: {finalResponse.Value.Content[0].Text}\n");
conversationHistory.Add(
new AssistantChatMessage(finalResponse.Value.Content[0].Text)
);
}
else
{
var response = completion.Value.Content[0].Text;
Console.WriteLine($"助手: {response}\n");
conversationHistory.Add(new AssistantChatMessage(response));
}
}
}
}
#### 运行结果示例
=== 智能客户服务助手 ===
客户: 你好,我想查询订单 ORD-12345 的状态
助手: 您好!我已为您查询到订单信息:
- 订单号:ORD-12345
- 客户姓名:张三
- 产品:Surface Laptop 5
- 状态:已发货 ✅
- 金额:¥8,999.00
- 物流单号:SF1234567890
您的订单已经发货,可以使用物流单号追踪包裹位置。还有其他需要帮助的吗?
客户: 我对这个订单不满意,想申请退款
助手: 我理解您的情况。我已为您的订单 ORD-12345 提交了退款申请。
退款详情:
- 退款单号:RF-20260204143022
- 退款金额:¥8,999.00
- 预计到账日期:2026年2月9日 💰
退款将原路返回您的支付账户。如有任何问题,请随时联系我们。
### 案例2:代码审查工作流
> **注意**:此案例展示工作流概念,实际的 Agent Framework Workflow API 仍在开发中。
#### 场景描述
创建一个多代理工作流,自动审查代码变更,包括代码风格检查、安全审查、性能分析。
#### 工作流设计
开始
↓
并行审查
├─ 风格审查代理
├─ 安全审查代理
└─ 性能审查代理
↓
汇总代理
↓
生成报告
#### 概念性实现
```csharp
// 概念性的多代理工作流示例
// 实际实现需要等待 Agent Framework Workflow API 正式发布
public class CodeReviewWorkflow
{
private readonly ChatClient _chatClient;
public async Task<string> ExecuteAsync(string code)
{
// 1. 并行执行三种审查
var styleTask = ReviewStyleAsync(code);
var securityTask = ReviewSecurityAsync(code);
var performanceTask = ReviewPerformanceAsync(code);
await Task.WhenAll(styleTask, securityTask, performanceTask);
// 2. 汇总结果
var summary = await SummarizeResultsAsync(
styleTask.Result,
securityTask.Result,
performanceTask.Result
);
return summary;
}
private async Task<string> ReviewStyleAsync(string code)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage(@"你是C#代码风格审查专家。检查:
1. 命名规范(PascalCase, camelCase)
2. 代码格式和缩进
3. 注释质量"),
new UserChatMessage($"审查以下代码:\n{code}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> ReviewSecurityAsync(string code)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage(@"你是安全审查专家。检查:
1. SQL注入风险
2. XSS漏洞
3. 输入验证
4. 敏感数据处理"),
new UserChatMessage($"审查以下代码:\n{code}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> ReviewPerformanceAsync(string code)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage(@"你是性能优化专家。检查:
1. N+1查询问题
2. 不必要的循环
3. 异步使用是否正确
4. 缓存策略"),
new UserChatMessage($"审查以下代码:\n{code}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> SummarizeResultsAsync(
string styleReview,
string securityReview,
string performanceReview)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是代码审查总结专家。"),
new UserChatMessage($@"汇总以下审查结果:
风格审查:
{styleReview}
安全审查:
{securityReview}
性能审查:
{performanceReview}
生成综合审查报告,包括:
1. 总体评分
2. 主要问题列表(按优先级)
3. 行动建议")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
}
预期输出示例
=== 代码审查报告 ===
生成时间:2026-02-04 14:35:22
## 总体评分:45/100
### 严重问题(Critical)
1. **SQL注入漏洞** [安全]
- 位置:GetUser方法
- 描述:直接拼接SQL参数,存在严重的SQL注入风险
- 建议:使用参数化查询或ORM(Entity Framework)
```csharp
var query = "SELECT * FROM Users WHERE Id = @Id";
// 使用参数化查询
2. **硬编码连接字符串** [安全]
- 位置:类字段
- 描述:连接字符串硬编码在代码中
- 建议:使用配置文件和Secret Manager
### 高优先级问题(High)
3. **N+1查询问题** [性能]
- 位置:CreateUser方法
- 描述:循环中可能触发多次数据库查询
- 建议:使用数据库唯一索引或单次查询验证
4. **缺少输入验证** [安全]
- 位置:CreateUser方法
- 描述:未验证email格式和name长度
- 建议:使用数据注解或FluentValidation
### 中优先级问题(Medium)
5. **命名不规范** [风格]
- 位置:变量命名
- 描述:局部变量应使用camelCase
- 建议:重命名为descriptive名称
6. **缺少异步操作** [性能]
- 位置:所有数据库操作
- 描述:未使用async/await
- 建议:改用异步方法
## 行动建议
### 立即修复(Critical & High)
1. 重构GetUser方法,使用参数化查询
2. 将连接字符串移至配置
3. 优化CreateUser中的查询逻辑
4. 添加输入验证
### 后续改进(Medium & Low)
1. 统一命名规范
2. 重构为异步方法
3. 添加日志记录
4. 实现依赖注入
### 架构建议
- 考虑使用仓储模式(Repository Pattern)
- 引入Entity Framework Core
- 实现工作单元(Unit of Work)
- 添加全局异常处理中间件
案例3:研究助手系统(概念性示例)
注意:此案例为概念性设计,展示顺序工作流的思路。
场景描述
创建一个研究助手系统,能够搜索资料、分析数据、生成报告。
工作流设计
开始
↓
搜索文献
↓
分析数据
↓
生成报告
↓
结束
概念性实现
// 概念性的研究助手工作流
// 展示顺序处理的思路
public class ResearchAssistantWorkflow
{
private readonly ChatClient _chatClient;
public async Task<string> ExecuteAsync(string topic)
{
Console.WriteLine($"🔍 研究主题: {topic}\n");
// 1. 搜索文献
Console.WriteLine("📚 正在搜索相关文献...");
var papers = await SearchPapersAsync(topic);
// 2. 分析数据
Console.WriteLine("📈 正在分析数据...");
var analysis = await AnalyzeDataAsync(papers);
// 3. 生成报告
Console.WriteLine("📄 正在生成报告...");
var report = await GenerateReportAsync(analysis);
Console.WriteLine("✅ 研究完成!");
return report;
}
private async Task<string> SearchPapersAsync(string topic)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是学术搜索专家,负责查找相关论文。"),
new UserChatMessage($"查找关于 '{topic}' 的学术论文,列出标题、作者和摘要。")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> AnalyzeDataAsync(string papers)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是数据分析专家,负责从文献中提取关键信息。"),
new UserChatMessage($@"分析以下文献:
{papers}
提取:
1. 主要发现
2. 研究趋势
3. 关键作者
4. 统计数据")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> GenerateReportAsync(string analysis)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("你是研究报告撰写专家。"),
new UserChatMessage($@"基于以下分析生成研究报告:
{analysis}
报告应包括:
1. 执行摘要
2. 主要发现
3. 数据分析
4. 结论和建议
使用Markdown格式。")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
}
使用示例
var workflow = new ResearchAssistantWorkflow(chatClient);
var report = await workflow.ExecuteAsync("AI代理框架的最新发展");
// 保存报告
await File.WriteAllTextAsync(
$"research-{DateTime.Now:yyyyMMdd}.md",
report
);
高级特性
注意:以下高级特性示例为概念性设计,展示未来可能的功能。
1. MCP(Model Context Protocol)集成(概念性示例)
说明:MCP 集成功能仍在开发中,此示例展示概念。
using OpenAI.Chat;
using System.Net.Http;
// MCP概念性集成示例
public class MCPIntegration
{
private readonly ChatClient _chatClient;
private readonly HttpClient _httpClient;
public MCPIntegration(ChatClient chatClient)
{
_chatClient = chatClient;
_httpClient = new HttpClient { BaseAddress = new Uri("http://localhost:3000") };
}
public async Task<string> CallExternalToolAsync(string toolName, string parameters)
{
// 调用外部MCP服务器
var response = await _httpClient.PostAsJsonAsync($"/tools/{toolName}", new { parameters });
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
public async Task<string> ProcessWithExternalToolsAsync(string userInput)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("You can use external tools via MCP."),
new UserChatMessage(userInput)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
}
2. 遥测和监控
using Microsoft.Extensions.Logging;
using OpenAI.Chat;
// 创建带日志记录的聊天客户端包装器
public class TelemetryEnabledChatClient
{
private readonly ChatClient _chatClient;
private readonly ILogger _logger;
public TelemetryEnabledChatClient(ChatClient chatClient, ILoggerFactory loggerFactory)
{
_chatClient = chatClient;
_logger = loggerFactory.CreateLogger<TelemetryEnabledChatClient>();
}
public async Task<string> CompleteChatAsync(List<ChatMessage> messages)
{
var startTime = DateTime.UtcNow;
try
{
_logger.LogInformation("开始处理聊天请求,消息数: {Count}", messages.Count);
var response = await _chatClient.CompleteChatAsync(messages);
var responseText = response.Value.Content[0].Text;
var duration = DateTime.UtcNow - startTime;
_logger.LogInformation(
"聊天请求完成,耗时: {Duration}ms, 响应长度: {Length}",
duration.TotalMilliseconds,
responseText.Length
);
return responseText;
}
catch (Exception ex)
{
_logger.LogError(ex, "聊天请求失败");
throw;
}
}
}
// 使用示例
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
builder.SetMinimumLevel(LogLevel.Information);
});
var telemetryClient = new TelemetryEnabledChatClient(chatClient, loggerFactory);
var response = await telemetryClient.CompleteChatAsync(messages);
3. 人机协作(Human-in-the-Loop)(概念性示例)
using OpenAI.Chat;
// 需要人工审批的工作流
public class ApprovalWorkflow
{
private readonly ChatClient _chatClient;
public async Task<string> ExecuteAsync(string request)
{
// 步骤1: 处理请求
var processedRequest = await ProcessRequestAsync(request);
// 步骤2: 请求人工审批
Console.WriteLine($"需要审批: {processedRequest}");
Console.Write("是否批准? (y/n): ");
var approval = Console.ReadLine()?.ToLower() == "y";
// 步骤3: 根据审批结果执行操作
if (approval)
{
return await ExecuteActionAsync(processedRequest);
}
else
{
return await RejectActionAsync(processedRequest);
}
}
private async Task<string> ProcessRequestAsync(string request)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("分析并格式化请求。"),
new UserChatMessage(request)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task<string> ExecuteActionAsync(string request)
{
await Task.Delay(100);
return $"已执行操作: {request}";
}
private async Task<string> RejectActionAsync(string request)
{
await Task.Delay(100);
return $"操作被拒绝: {request}";
}
}
4. 自定义模型提供者(概念性示例)
using System.Net.Http;
using System.Text.Json;
// 自定义模型客户端包装器
public class CustomModelClient
{
private readonly HttpClient _httpClient;
public CustomModelClient(string baseUrl, string apiKey)
{
_httpClient = new HttpClient
{
BaseAddress = new Uri(baseUrl)
};
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
}
public async Task<string> GetChatCompletionAsync(string systemPrompt, string userMessage)
{
var request = new
{
messages = new[]
{
new { role = "system", content = systemPrompt },
new { role = "user", content = userMessage }
},
temperature = 0.7
};
var response = await _httpClient.PostAsJsonAsync("/v1/chat/completions", request);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<JsonDocument>();
return result.RootElement
.GetProperty("choices")[0]
.GetProperty("message")
.GetProperty("content")
.GetString() ?? string.Empty;
}
}
// 使用示例
var customClient = new CustomModelClient("https://api.custom-model.com", "your-api-key");
var response = await customClient.GetChatCompletionAsync(
"You are a helpful assistant",
"Tell me a joke"
);
5. 流式响应
using OpenAI.Chat;
// 流式响应示例
public class StreamingChatClient
{
private readonly ChatClient _chatClient;
public async Task StreamChatAsync(List<ChatMessage> messages)
{
var streamingOptions = new ChatCompletionOptions();
await foreach (var update in _chatClient.CompleteChatStreamingAsync(messages, streamingOptions))
{
foreach (var contentPart in update.ContentUpdate)
{
Console.Write(contentPart.Text);
await Task.Delay(10); // 模拟打字效果
}
}
Console.WriteLine(); // 换行
}
}
// 使用示例
var streamingClient = new StreamingChatClient(chatClient);
var messages = new List<ChatMessage>
{
new SystemChatMessage("You are a storyteller."),
new UserChatMessage("Write a long story about a brave knight.")
};
await streamingClient.StreamChatAsync(messages);
最佳实践
1. 代理设计原则
✅ 推荐做法
using OpenAI.Chat;
using System.ComponentModel;
// 1. 清晰的系统提示词
var messages = new List<ChatMessage>
{
new SystemChatMessage(@"你是专业的技术支持工程师。
职责:
- 诊断技术问题
- 提供解决方案
- 记录问题详情
原则:
- 始终礼貌专业
- 提供具体可行的建议
- 遇到不确定情况要求用户提供更多信息")
};
// 2. 合理的工具分组
public class TechnicalSupportTools
{
[Description("Run diagnostic tests")]
public DiagnosticResult RunDiagnostics(string systemId)
{
return new DiagnosticResult { SystemId = systemId, Status = "OK" };
}
[Description("Create support log entry")]
public LogEntry CreateLog(string description)
{
return new LogEntry { Id = Guid.NewGuid(), Description = description };
}
[Description("Search knowledge base for solutions")]
public Solution SearchKnowledgeBase(string query)
{
return new Solution { Query = query, Answer = "解决方案..." };
}
}
// 3. 使用强类型返回值
public class UserInfo
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
}
[Description("Get user information")]
public UserInfo GetUser(int userId)
{
return new UserInfo { Id = userId, Name = "张三", Email = "zhangsan@example.com" };
}
❌ 避免的做法
// 1. 模糊的指令
var messages = new List<ChatMessage>
{
new SystemChatMessage("Help users") // 太简单,缺少具体指导
};
// 2. 过多的工具(>20个)
// 避免在单次调用中定义太多工具,这会让模型困惑
// 应该按功能分组或按场景动态提供工具
// 3. 使用string返回所有数据
[Description("Get data")]
public string GetAllData() // 应该使用强类型
{
return "id:1,name:test,..."; // 难以解析,容易出错
}
2. 工作流设计模式(概念性示例)
using OpenAI.Chat;
// 使用工厂模式构建复杂工作流
public class WorkflowFactory
{
private readonly ChatClient _chatClient;
public WorkflowFactory(ChatClient chatClient)
{
_chatClient = chatClient;
}
public OrderProcessingWorkflow CreateOrderProcessingWorkflow()
{
return new OrderProcessingWorkflow(_chatClient);
}
}
public class OrderProcessingWorkflow
{
private readonly ChatClient _chatClient;
private readonly Dictionary<string, string> _checkpoints = new();
public OrderProcessingWorkflow(ChatClient chatClient)
{
_chatClient = chatClient;
}
public async Task<string> ExecuteAsync(string orderId)
{
try
{
// 阶段1: 验证
var validationResult = await ValidateOrderAsync(orderId);
_checkpoints["validation"] = validationResult;
// 阶段2: 支付
var paymentResult = await ProcessPaymentAsync(orderId);
_checkpoints["payment"] = paymentResult;
// 阶段3: 履行
var fulfillmentResult = await FulfillOrderAsync(orderId);
_checkpoints["fulfillment"] = fulfillmentResult;
return fulfillmentResult;
}
catch (PaymentException ex)
{
return await HandlePaymentErrorAsync(orderId, ex);
}
}
private async Task<string> ValidateOrderAsync(string orderId)
{
await Task.Delay(100);
return $"订单 {orderId} 验证通过";
}
private async Task<string> ProcessPaymentAsync(string orderId)
{
await Task.Delay(200);
return $"订单 {orderId} 支付完成";
}
private async Task<string> FulfillOrderAsync(string orderId)
{
await Task.Delay(150);
return $"订单 {orderId} 已发货";
}
private async Task<string> HandlePaymentErrorAsync(string orderId, PaymentException ex)
{
await Task.Delay(100);
return $"订单 {orderId} 支付失败: {ex.Message}";
}
}
public class PaymentException : Exception
{
public PaymentException(string message) : base(message) { }
}
3. 错误处理策略
using OpenAI.Chat;
using Azure;
using Microsoft.Extensions.Logging;
using Polly;
// 实现重试策略
public class ResilientChatClient
{
private readonly ChatClient _chatClient;
private readonly ILogger _logger;
private readonly IAsyncPolicy _retryPolicy;
public ResilientChatClient(ChatClient chatClient, ILogger<ResilientChatClient> logger)
{
_chatClient = chatClient;
_logger = logger;
// 配置重试策略
_retryPolicy = Policy
.Handle<RequestFailedException>(ex => ex.Status == 429) // 速率限制
.Or<HttpRequestException>()
.WaitAndRetryAsync(
3,
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (exception, timespan, retryCount, context) =>
{
_logger.LogWarning(
"重试第 {RetryCount} 次,等待 {Delay}ms。原因: {Exception}",
retryCount,
timespan.TotalMilliseconds,
exception.Message
);
}
);
}
public async Task<string> CompleteChatWithRetryAsync(List<ChatMessage> messages)
{
return await _retryPolicy.ExecuteAsync(async () =>
{
try
{
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
catch (RequestFailedException ex) when (ex.Status == 429)
{
// 速率限制 - 可重试
_logger.LogWarning("遇到速率限制: {Message}", ex.Message);
throw;
}
catch (RequestFailedException ex) when (ex.Status >= 500)
{
// 服务器错误 - 可重试
_logger.LogError("服务器错误: {Message}", ex.Message);
throw;
}
catch (RequestFailedException ex)
{
// 客户端错误 - 不可重试
_logger.LogError("请求失败: {Message}", ex.Message);
return "抱歉,请求处理失败。请检查输入并重试。";
}
catch (Exception ex)
{
// 其他错误
_logger.LogError(ex, "未预期的错误");
return "抱歉,服务暂时不可用。";
}
});
}
}
// 使用示例
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
var logger = loggerFactory.CreateLogger<ResilientChatClient>();
var resilientClient = new ResilientChatClient(chatClient, logger);
var messages = new List<ChatMessage>
{
new SystemChatMessage("You are a helpful assistant."),
new UserChatMessage("Tell me a joke.")
};
var response = await resilientClient.CompleteChatWithRetryAsync(messages);
4. 安全考虑
using OpenAI.Chat;
using Microsoft.Extensions.Logging;
using System.Text.RegularExpressions;
// 1. 输入验证
public class SecureChatClient
{
private readonly ChatClient _chatClient;
private readonly ILogger _logger;
public SecureChatClient(ChatClient chatClient, ILogger<SecureChatClient> logger)
{
_chatClient = chatClient;
_logger = logger;
}
public async Task<string> ProcessInputAsync(string userInput)
{
// 验证输入长度
if (userInput.Length > 10000)
{
throw new ArgumentException("输入内容过长");
}
// 检测注入攻击
if (ContainsInjectionPatterns(userInput))
{
_logger.LogWarning("检测到潜在的注入攻击");
return "检测到无效输入";
}
// 过滤敏感信息
var sanitizedInput = FilterSensitiveData(userInput);
var messages = new List<ChatMessage>
{
new SystemChatMessage("You are a helpful assistant."),
new UserChatMessage(sanitizedInput)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private bool ContainsInjectionPatterns(string input)
{
// 检测常见的注入模式
var patterns = new[]
{
@"<script[^>]*>.*?</script>", // XSS
@"javascript:", // JavaScript URL
@"onerror\s*=", // 事件处理器
@"eval\s*\(", // eval调用
};
foreach (var pattern in patterns)
{
if (Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase))
{
return true;
}
}
return false;
}
private string FilterSensitiveData(string text)
{
// 移除信用卡号
text = Regex.Replace(text, @"\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}", "****-****-****-****");
// 移除邮箱地址(可选)
// text = Regex.Replace(text, @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b", "[邮箱]");
// 移除电话号码
text = Regex.Replace(text, @"\d{3}[-\s]?\d{4}[-\s]?\d{4}", "***-****-****");
return text;
}
}
// 2. 敏感信息过滤中间件
public class SensitiveDataFilterMiddleware
{
private readonly ChatClient _chatClient;
public async Task<string> CompleteChatAsync(List<ChatMessage> messages)
{
// 过滤请求中的敏感信息
var filteredMessages = messages.Select(msg =>
{
if (msg is UserChatMessage userMsg)
{
var content = userMsg.Content[0].Text;
var filtered = FilterSensitiveData(content);
return new UserChatMessage(filtered);
}
return msg;
}).ToList();
var response = await _chatClient.CompleteChatAsync(filteredMessages);
var responseText = response.Value.Content[0].Text;
// 过滤响应中的敏感信息
return FilterSensitiveData(responseText);
}
private string FilterSensitiveData(string text)
{
// 移除信用卡号、密码等
return Regex.Replace(text, @"\d{4}-\d{4}-\d{4}-\d{4}", "****-****-****-****");
}
}
// 3. 访问控制示例(ASP.NET Core)
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[Authorize(Roles = "Admin")]
public class AgentController : ControllerBase
{
private readonly ChatClient _chatClient;
[HttpPost("run")]
public async Task<IActionResult> RunAgent([FromBody] AgentRequest request)
{
// 验证用户权限
if (!User.HasClaim("AgentAccess", "true"))
{
return Forbid();
}
// 验证输入
if (string.IsNullOrWhiteSpace(request.Input))
{
return BadRequest("输入不能为空");
}
var messages = new List<ChatMessage>
{
new SystemChatMessage("You are a helpful assistant."),
new UserChatMessage(request.Input)
};
var response = await _chatClient.CompleteChatAsync(messages);
return Ok(new { response = response.Value.Content[0].Text });
}
}
public class AgentRequest
{
public string Input { get; set; } = string.Empty;
}
5. 性能优化
using OpenAI.Chat;
using Microsoft.Extensions.Caching.Memory;
using System.Collections.Concurrent;
// 1. 使用缓存
public class CachedChatClient
{
private readonly IMemoryCache _cache;
private readonly ChatClient _chatClient;
public CachedChatClient(ChatClient chatClient, IMemoryCache cache)
{
_chatClient = chatClient;
_cache = cache;
}
public async Task<string> CompleteChatAsync(string systemPrompt, string userInput)
{
var cacheKey = $"chat_response_{userInput.GetHashCode()}";
if (_cache.TryGetValue(cacheKey, out string? cachedResponse) && cachedResponse != null)
{
Console.WriteLine("从缓存返回结果");
return cachedResponse;
}
var messages = new List<ChatMessage>
{
new SystemChatMessage(systemPrompt),
new UserChatMessage(userInput)
};
var response = await _chatClient.CompleteChatAsync(messages);
var responseText = response.Value.Content[0].Text;
// 缓存10分钟
_cache.Set(cacheKey, responseText, TimeSpan.FromMinutes(10));
return responseText;
}
}
// 2. 批处理
public class BatchChatProcessor
{
private readonly ChatClient _chatClient;
public async Task<List<string>> ProcessBatchAsync(List<string> inputs)
{
// 并行处理多个请求
var tasks = inputs
.Select(input => ProcessSingleAsync(input))
.ToList();
return (await Task.WhenAll(tasks)).ToList();
}
private async Task<string> ProcessSingleAsync(string input)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage("You are a helpful assistant."),
new UserChatMessage(input)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
}
// 3. 请求限流和资源管理
public class RateLimitedChatClient
{
private readonly ChatClient _chatClient;
private readonly SemaphoreSlim _semaphore;
private readonly ConcurrentQueue<DateTime> _requestTimes;
private readonly int _maxRequestsPerMinute;
public RateLimitedChatClient(ChatClient chatClient, int maxRequestsPerMinute = 60)
{
_chatClient = chatClient;
_maxRequestsPerMinute = maxRequestsPerMinute;
_semaphore = new SemaphoreSlim(10); // 最多10个并发请求
_requestTimes = new ConcurrentQueue<DateTime>();
}
public async Task<string> CompleteChatAsync(List<ChatMessage> messages)
{
await _semaphore.WaitAsync();
try
{
// 检查速率限制
await EnforceRateLimitAsync();
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
finally
{
_semaphore.Release();
}
}
private async Task EnforceRateLimitAsync()
{
var now = DateTime.UtcNow;
var oneMinuteAgo = now.AddMinutes(-1);
// 清理1分钟前的请求记录
while (_requestTimes.TryPeek(out var oldestTime) && oldestTime < oneMinuteAgo)
{
_requestTimes.TryDequeue(out _);
}
// 如果达到限制,等待
while (_requestTimes.Count >= _maxRequestsPerMinute)
{
await Task.Delay(1000); // 等待1秒
// 再次清理
oneMinuteAgo = DateTime.UtcNow.AddMinutes(-1);
while (_requestTimes.TryPeek(out var oldestTime) && oldestTime < oneMinuteAgo)
{
_requestTimes.TryDequeue(out _);
}
}
// 记录新请求
_requestTimes.Enqueue(DateTime.UtcNow);
}
}
// 使用示例
var memoryCache = new MemoryCache(new MemoryCacheOptions());
var cachedClient = new CachedChatClient(chatClient, memoryCache);
// 批处理
var batchProcessor = new BatchChatProcessor(chatClient);
var inputs = new List<string> { "Question 1", "Question 2", "Question 3" };
var results = await batchProcessor.ProcessBatchAsync(inputs);
// 限流
var rateLimitedClient = new RateLimitedChatClient(chatClient, maxRequestsPerMinute: 60);
var response = await rateLimitedClient.CompleteChatAsync(messages);
6. 测试策略
using Xunit;
using Moq;
using OpenAI.Chat;
using Azure.AI.OpenAI;
public class ChatClientTests
{
[Fact]
public async Task Should_Call_Function_Tool_Correctly()
{
// Arrange
var mockTools = new Mock<ICalculatorTools>();
mockTools
.Setup(t => t.Add(It.IsAny<int>(), It.IsAny<int>()))
.Returns((int a, int b) => a + b);
// 在实际测试中,你需要使用真实的 ChatClient 或 Mock
// 这里展示测试工具调用逻辑的概念
// Act
var result = mockTools.Object.Add(5, 5);
// Assert
Assert.Equal(10, result);
mockTools.Verify(t => t.Add(5, 5), Times.Once);
}
[Fact]
public async Task Workflow_Should_Execute_In_Correct_Order()
{
// Arrange
var executionOrder = new List<string>();
var workflow = new TestWorkflow(executionOrder);
// Act
await workflow.ExecuteAsync("test input");
// Assert
Assert.Equal(new[] { "Step1", "Step2", "Step3" }, executionOrder);
}
[Fact]
public async Task Should_Handle_Error_Gracefully()
{
// Arrange
var mockClient = new Mock<IChatClientWrapper>();
mockClient
.Setup(c => c.CompleteChatAsync(It.IsAny<List<ChatMessage>>()))
.ThrowsAsync(new InvalidOperationException("API Error"));
// Act & Assert
await Assert.ThrowsAsync<InvalidOperationException>(
() => mockClient.Object.CompleteChatAsync(new List<ChatMessage>())
);
}
}
// 测试用的工作流类
public class TestWorkflow
{
private readonly List<string> _executionOrder;
public TestWorkflow(List<string> executionOrder)
{
_executionOrder = executionOrder;
}
public async Task ExecuteAsync(string input)
{
_executionOrder.Add("Step1");
await Task.Delay(10);
_executionOrder.Add("Step2");
await Task.Delay(10);
_executionOrder.Add("Step3");
await Task.Delay(10);
}
}
// 测试用的接口
public interface ICalculatorTools
{
int Add(int a, int b);
int Subtract(int a, int b);
}
public interface IChatClientWrapper
{
Task<string> CompleteChatAsync(List<ChatMessage> messages);
}
// 集成测试示例
public class IntegrationTests : IClassFixture<TestFixture>
{
private readonly TestFixture _fixture;
public IntegrationTests(TestFixture fixture)
{
_fixture = fixture;
}
[Fact]
public async Task Should_Complete_Chat_Successfully()
{
// Arrange
var messages = new List<ChatMessage>
{
new SystemChatMessage("You are a helpful assistant."),
new UserChatMessage("Say hello")
};
// Act
var response = await _fixture.ChatClient.CompleteChatAsync(messages);
// Assert
Assert.NotNull(response);
Assert.NotEmpty(response.Value.Content[0].Text);
}
}
// 测试固件
public class TestFixture : IDisposable
{
public ChatClient ChatClient { get; }
public TestFixture()
{
// 从测试配置中初始化客户端
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
var apiKey = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT");
if (!string.IsNullOrEmpty(endpoint) && !string.IsNullOrEmpty(apiKey))
{
var client = new AzureOpenAIClient(
new Uri(endpoint),
new AzureKeyCredential(apiKey)
);
ChatClient = client.GetChatClient(deploymentName);
}
}
public void Dispose()
{
// 清理资源
}
}
总结
Microsoft Agent Framework的核心优势
- 统一平台:整合Semantic Kernel和AutoGen的精华
- 企业就绪:提供生产环境所需的完整特性
- 灵活强大:支持从简单代理到复杂多代理工作流
- 类型安全:强类型系统减少运行时错误
- 易于扩展:支持自定义模型、工具和中间件
适用场景总结
| 场景类型 | 推荐方案 | 关键特性 |
|---|---|---|
| 简单问答 | 单个AI代理 | 快速响应、低成本 |
| 工具调用 | 带工具的代理 | 外部集成、自动决策 |
| 多步骤任务 | 工作流 | 结构化、可控制 |
| 复杂系统 | 多代理工作流 | 协作、专业化、可扩展 |
| 长期运行 | 带检查点的工作流 | 状态保存、可恢复 |
| 人机协作 | 人工审批工作流 | 请求/响应模式 |
开发建议
- 从简单开始:先用单个代理验证概念
- 逐步扩展:根据需要添加工具和工作流
- 重视安全:始终验证输入和过滤敏感信息
- 监控性能:使用遥测跟踪代理行为
- 充分测试:编写单元测试和集成测试
- 遵循最佳实践:参考官方文档和社区示例
学习资源
官方资源
- 官方文档:https://learn.microsoft.com/en-us/agent-framework/
- GitHub仓库:https://github.com/microsoft/agent-framework
- 示例代码:https://github.com/microsoft/agent-framework/tree/main/samples
未来展望
Microsoft Agent Framework正处于快速发展阶段,未来可期待:
- 更多模型提供者支持
- 增强的工作流可视化工具
- 更丰富的预构建代理模板
- 改进的调试和监控工具
- 更广泛的社区生态系统
更多推荐



所有评论(0)