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.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
{
public async Task<string> GetOrderInfoAsync(
string orderId)
{
// 模拟数据库查询
await Task.Delay(100);
return $@"订单信息查询成功:
- 订单号:{orderId}
- 客户姓名:张三
- 产品:Surface Laptop 5
- 状态:已发货
- 物流单号:SF1234567890";
}
public async Task<string> ProcessRefundAsync(
string orderId,
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.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.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.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.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.Text));
conversationHistory.Add(new UserChatMessage("My favorite programming language is C#."));
var response2 = await chatClient.CompleteChatAsync(conversationHistory);
conversationHistory.Add(new AssistantChatMessage(response2.Value.Content.Text));
// 稍后查询 - AI会从对话历史中回忆
conversationHistory.Add(new UserChatMessage("When do I prefer meetings?"));
var response3 = await chatClient.CompleteChatAsync(conversationHistory);
Console.WriteLine(response3.Value.Content.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($" {((UserChatMessage)userMessage).Content.Text}");
}
// 检查敏感内容
if (userMessage != null && ContainsSensitiveInfo(((UserChatMessage)userMessage).Content.Text))
{
Console.WriteLine(" Sensitive information detected");
return "I cannot process sensitive information.";
}
// 调用实际的API
var response = await _chatClient.CompleteChatAsync(messages, options);
var responseText = response.Value.Content.Text;
// 日志记录响应
Console.WriteLine($" {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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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(@"你是一级客户支持。处理常见问题。
如果问题复杂,在回复末尾添加 。"),
new UserChatMessage(ticket)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content.Text;
}
private async Task<string> Level2SupportAsync(string ticket, string level1Notes)
{
var messages = new List<ChatMessage>
{
new SystemChatMessage(@"你是二级技术支持。处理复杂技术问题。
如果需要专家介入,在回复末尾添加 。"),
new UserChatMessage($"工单:{ticket}\n\n一级支持记录:{level1Notes}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content.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.Text;
}
private bool RequiresEscalation(string result)
{
return result.Contains("");
}
private bool RequiresSpecialist(string result)
{
return result.Contains("");
}
}工作流检查点(概念性示例)
注意:此示例展示工作流状态保存的概念。实际实现需要自行设计状态持久化方案。
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.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.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.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)
}
};
}
public async Task<string> GetOrderInfoAsync(
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} 的订单。";
}
public async Task<string> ProcessRefundAsync(
string orderId,
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.Text}\n");
conversationHistory.Add(
new AssistantChatMessage(finalResponse.Value.Content.Text)
);
}
else
{
var response = completion.Value.Content.Text;
Console.WriteLine($"助手: {response}\n");
conversationHistory.Add(new AssistantChatMessage(response));
}
}
}
}
#### 运行结果示例=== 智能客户服务助手 ===
客户: 你好,我想查询订单 ORD-12345 的状态
助手: 您好!我已为您查询到订单信息:
[*]订单号:ORD-12345
[*]客户姓名:张三
[*]产品:Surface Laptop 5
[*]状态:已发货 ✅
[*]金额:¥8,999.00
[*]物流单号:SF1234567890
您的订单已经发货,可以使用物流单号追踪包裹位置。还有其他需要帮助的吗?
客户: 我对这个订单不满意,想申请退款
助手: 我理解您的情况。我已为您的订单 ORD-12345 提交了退款申请。
退款详情:
<ul>退款单号:RF-20260204143022
退款金额:¥8,999.00
预计到账日期:2026年2月9日
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! 感谢分享,学习下。 喜欢鼓捣这些软件,现在用得少,谢谢分享! 这个好,看起来很实用 谢谢楼主提供!
页:
[1]