当前位置: 首页 > article >正文

实战探索 Microsoft Agent Framework:构建我的第一个 MAF 智能体应用

1. 初识 Microsoft Agent Framework第一次听说 Microsoft Agent Framework简称 MAF是在一个技术社区里当时看到有人分享用这个框架快速搭建了一个智能客服系统。作为一个长期在 AI 领域摸爬滚打的老兵我立刻被这个新框架吸引住了。MAF 给我的第一印象就像是把 Semantic Kernel 和 AutoGen 这两个框架的优点都吸收进来还加入了不少新特性。简单来说MAF 是微软推出的一个开源开发套件专门用来构建人工智能代理和多智能体工作流。它支持 .NET 和 Python 两种语言这点对开发者特别友好。我特别喜欢它的设计理念 - 不是简单地封装大模型 API而是提供了一套完整的工具链让开发者能轻松实现多轮对话、函数调用、工具集成这些高级功能。2. 环境搭建与基础配置2.1 创建项目与安装依赖我决定从一个最简单的控制台项目开始。打开终端运行dotnet new console -o MyFirstMAFAgent然后进入项目目录安装核心包。这里要注意 MAF 目前还是预览版需要加上 --prerelease 参数dotnet add package Azure.AI.OpenAI --prerelease dotnet add package Microsoft.Agents.AI.OpenAI --prerelease我在实际操作时遇到了一个版本冲突问题。Azure.AI.OpenAI 2.8.1-beta.1 这个版本会和其他包产生依赖冲突后来我把版本降到 2.7.0-beta2 就解决了。这也是为什么我建议新手在 IDE比如 Visual Studio里安装包更方便可以直接看到依赖关系。2.2 配置模型访问接下来要配置大模型访问。我创建了一个简单的 ModelProvider 类来管理配置public class ModelProvider { public string ApiKey { get; init; } string.Empty; public string ModelId { get; init; } string.Empty; public string Endpoint { get; init; } string.Empty; }然后在 appsettings.json 里配置参数{ ModelProvider: { EndPoint: https://api.moonshot.cn/v1, ApiKey: 你的API_KEY, ModelId: kimi-k2-0905-preview } }读取配置的代码也很简单var config new ConfigurationBuilder() .AddJsonFile(appsettings.json) .Build(); var modelProvider new ModelProvider { ApiKey config[ModelProvider:ApiKey], ModelId config[ModelProvider:ModelId], Endpoint config[ModelProvider:Endpoint] };3. 创建第一个智能体3.1 基础聊天智能体现在可以创建我们的第一个智能体了我决定从一个笑话机器人开始var agent new OpenAIClient( new ApiKeyCredential(modelProvider.ApiKey), new OpenAIClientOptions { Endpoint new Uri(modelProvider.Endpoint) }) .GetChatClient(modelProvider.ModelId) .CreateAIAgent( instructions: 你是个幽默大师擅长讲冷笑话, name: 笑话机器人); await foreach (var update in agent.RunStreamingAsync(讲个关于程序员的冷笑话)) { Console.Write(update); }运行这个程序你会看到一个关于程序员的冷笑话。这里有几个关键点CreateAIAgent方法创建了一个智能体实例instructions参数定义了智能体的行为特征RunStreamingAsync实现了流式输出3.2 视觉智能体MAF 还支持视觉能力。我尝试创建一个能分析图片的智能体var agent new OpenAIClient( new ApiKeyCredential(modelProvider.ApiKey), new OpenAIClientOptions { Endpoint new Uri(modelProvider.Endpoint) }) .GetChatClient(qwen-vl-plus) // 注意要换支持视觉的模型 .CreateAIAgent( instructions: 你是一个图片分析专家, name: 视觉助手); var message new ChatMessage(ChatRole.User, [ new TextContent(描述这张图片的内容), new UriContent(https://example.com/image.jpg, image/jpeg) ]); await foreach (var update in agent.RunStreamingAsync(message)) { Console.Write(update); }4. 实现功能工具集成4.1 基础函数工具智能体的真正威力在于它能调用外部工具。我创建了一个查询天气的函数var agent new OpenAIClient( new ApiKeyCredential(modelProvider.ApiKey), new OpenAIClientOptions { Endpoint new Uri(modelProvider.Endpoint) }) .GetChatClient(modelProvider.ModelId) .CreateAIAgent( instructions: 你是一个智能助手, tools: [AIFunctionFactory.Create(GetWeather)]); Console.WriteLine(await agent.RunAsync(北京的天气怎么样?)); [Description(获取指定城市的天气信息)] static string GetWeather([Description(要查询的城市名称)] string location) { // 这里应该是调用真实天气API return $今天{city}的天气是晴天气温25℃; }4.2 需要人工审批的函数在实际业务中有些操作需要人工审批。MAF 提供了很好的支持var weatherFunc AIFunctionFactory.Create(GetWeather); var approvalFunc new ApprovalRequiredAIFunction(weatherFunc); var agent new OpenAIClient( new ApiKeyCredential(modelProvider.ApiKey), new OpenAIClientOptions { Endpoint new Uri(modelProvider.Endpoint) }) .GetChatClient(modelProvider.ModelId) .CreateAIAgent( instructions: 你是一个需要审批的助手, tools: [approvalFunc]); var thread agent.GetNewThread(); var response await agent.RunAsync(帮我预定会议室, thread); // 获取需要审批的请求 var approvalRequests response.Messages .SelectMany(x x.Contents) .OfTypeFunctionApprovalRequestContent() .ToList(); if (approvalRequests.Any()) { Console.WriteLine($需要审批的操作: {approvalRequests[0].FunctionCall.Name}); var approvalMessage new ChatMessage(ChatRole.User, [ approvalRequests[0].CreateResponse(true) // true表示批准 ]); Console.WriteLine(await agent.RunAsync(approvalMessage, thread)); }5. 部署为可调用服务5.1 创建 MCP 服务MAF 最酷的功能之一是可以把智能体部署为 MCP 服务var agent new OpenAIClient( new ApiKeyCredential(modelProvider.ApiKey), new OpenAIClientOptions { Endpoint new Uri(modelProvider.Endpoint) }) .GetChatClient(modelProvider.ModelId) .CreateAIAgent( instructions: 你是一个笑话服务, name: 笑话服务); var mcpTool McpServerTool.Create(agent.AsAIFunction()); var builder Host.CreateEmptyApplicationBuilder(); builder.Services .AddMcpServer() .WithStdioServerTransport() .WithTools([mcpTool]); await builder.Build().RunAsync();5.2 客户端调用其他应用可以通过标准方式调用这个服务var client new McpClient(); var result await client.InvokeToolAsync(笑话服务, 讲个笑话); Console.WriteLine(result);6. 实战构建天气查询助手现在让我们把这些知识综合起来构建一个完整的天气查询助手。6.1 项目结构设计我创建了如下项目结构WeatherAssistant/ ├── Services/ │ ├── WeatherService.cs ├── Agents/ │ ├── WeatherAgent.cs ├── Program.csWeatherService 封装了真实的天气 API 调用public class WeatherService { [Description(获取城市天气信息)] public async Taskstring GetWeatherAsync( [Description(城市名称)] string city) { // 这里调用真实天气API return ${city}今天晴转多云气温20-28℃; } }6.2 智能体实现WeatherAgent 类封装了智能体逻辑public class WeatherAgent { private readonly OpenAIClient _client; private readonly string _modelId; public WeatherAgent(OpenAIClient client, string modelId) { _client client; _modelId modelId; } public AIAgent CreateAgent() { var weatherService new WeatherService(); var weatherFunc AIFunctionFactory.Create(weatherService.GetWeatherAsync); return _client.GetChatClient(_modelId) .CreateAIAgent( instructions: 你是一个专业的天气查询助手, name: 天气助手, tools: [weatherFunc]); } }6.3 主程序集成最后在 Program.cs 中集成所有组件var modelProvider // 初始化模型配置 var client new OpenAIClient( new ApiKeyCredential(modelProvider.ApiKey), new OpenAIClientOptions { Endpoint new Uri(modelProvider.Endpoint) }); var agent new WeatherAgent(client, modelProvider.ModelId).CreateAgent(); while (true) { Console.Write(你想查询哪个城市的天气); var city Console.ReadLine(); if (string.IsNullOrEmpty(city)) break; var response await agent.RunAsync(${city}的天气怎么样); Console.WriteLine(response); }7. 调试与优化技巧在实际开发中我发现了一些有用的调试技巧日志记录MAF 提供了丰富的日志接口可以记录智能体的思考过程builder.Services.AddLogging(configure configure.AddConsole().SetMinimumLevel(LogLevel.Debug));超时设置对于长时间运行的操作记得设置合理的超时var options new OpenAIClientOptions { Endpoint new Uri(modelProvider.Endpoint), RetryPolicy new RetryPolicy(maxRetries: 2), NetworkTimeout TimeSpan.FromSeconds(30) };性能监控可以使用 Application Insights 等工具监控智能体性能builder.Services.AddApplicationInsightsTelemetry();8. 进阶功能探索完成基础项目后我开始尝试一些更高级的功能8.1 多智能体协作MAF 支持创建多个智能体协同工作var translator client.GetChatClient(modelId) .CreateAIAgent(你是一个专业翻译负责中英互译); var summarizer client.GetChatClient(modelId) .CreateAIAgent(你是一个摘要专家负责总结内容); var workflow new WorkflowBuilder() .AddAgent(translator) .AddAgent(summarizer) .Build(); var result await workflow.RunAsync(请把这篇英文文章翻译成中文并总结);8.2 记忆与上下文智能体可以记住对话历史var thread agent.GetNewThread(); await agent.RunAsync(我叫张三, thread); var response await agent.RunAsync(我叫什么名字, thread); Console.WriteLine(response); // 输出你叫张三8.3 自定义中间件可以插入自定义中间件来修改智能体行为public class LoggingMiddleware : IAgentMiddleware { public async Task InvokeAsync(AgentContext context, NextMiddleware next) { Console.WriteLine($收到请求: {context.Request}); await next(context); Console.WriteLine($返回响应: {context.Response}); } } // 注册中间件 agent.UseMiddlewareLoggingMiddleware();9. 项目部署与运维当项目开发完成后需要考虑部署问题9.1 容器化部署我通常使用 Docker 容器来部署 MAF 应用FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /src COPY . . RUN dotnet publish -c Release -o /app FROM mcr.microsoft.com/dotnet/aspnet:8.0 WORKDIR /app COPY --frombuild /app . ENTRYPOINT [dotnet, WeatherAssistant.dll]9.2 性能优化对于生产环境我推荐以下优化措施使用连接池管理模型客户端实现响应缓存对耗时操作使用异步处理9.3 监控与告警完善的监控系统对智能体应用至关重要。我通常会配置请求成功率监控响应时间监控异常告警10. 经验总结与避坑指南经过这个项目的实践我总结了以下几点经验版本兼容性问题MAF 目前还是预览版不同版本间可能存在兼容性问题。建议锁定特定版本号。模型选择不同模型对函数调用的支持程度不同。如果发现函数调用不工作可以尝试换一个模型。错误处理智能体可能会产生意外输出一定要做好输入验证和输出过滤。测试策略智能体行为具有一定不可预测性需要设计专门的测试用例来验证各种边界情况。成本控制频繁调用大模型可能产生高昂费用建议实现使用量监控和限流机制。在实际项目中我还发现 MAF 的一个隐藏优势 - 它很好地抽象了底层模型差异。这意味着你可以轻松切换不同的模型提供商而不用重写业务逻辑。比如今天用 OpenAI明天想换成国产模型只需要修改配置即可。

相关文章:

实战探索 Microsoft Agent Framework:构建我的第一个 MAF 智能体应用

1. 初识 Microsoft Agent Framework 第一次听说 Microsoft Agent Framework(简称 MAF)是在一个技术社区里,当时看到有人分享用这个框架快速搭建了一个智能客服系统。作为一个长期在 AI 领域摸爬滚打的老兵,我立刻被这个新框架吸引…...

银河麒麟V10 SP1上编译Qt5.15.10,我踩过的那些依赖包的坑(保姆级避坑指南)

银河麒麟V10 SP1编译Qt5.15.10:深度解析依赖包陷阱与实战排错指南 当你在银河麒麟V10 SP1系统上尝试编译Qt5.15.10时,是否经历过这样的场景:满怀信心地执行./configure命令,却在几分钟后看到满屏红色错误提示?作为一款…...

Go语言如何做Feature Flag_Go语言功能开关教程【核心】

Go 的 flag 包仅支持启动时解析,不适用于运行时功能开关;应选用 Unleash/LaunchDarkly 等支持状态同步的 SDK,或用 atomic.Bool/sync.Map 手写轻量方案,同时重视评估上下文(如用户 ID)对灰度精度的关键影响…...

从DDR4到DDR5,我的PCB布线避坑血泪史:信号、电源、时序一个都不能错

从DDR4到DDR5的PCB设计实战:一位工程师的避坑指南 第一次拿到DDR5的设计需求时,我自信满满地以为这不过是DDR4的"小升级版"。直到项目进入调试阶段,那些诡异的信号完整性问题、莫名其妙的时序错误和电源噪声导致的随机崩溃&#xf…...

emcc邮箱配置

1.配置邮箱-获取授权码 邮箱授权码是专门用于第三方客户端(如 EMCC)登录 SMTP/IMAP 服务的专用密码(每种邮箱的授权码获取方式相似,具体参照邮箱类型获取)配置emcc 2、1 获取ssl密钥(在emcc服务器执行&…...

Matlab多尺度形态学在眼前节组织提取中的应用:原理与代码实现

Matlab基于多尺度形态学提取眼前节组织 多尺度形态学分割的基本原理:数学形态学是处理和分析几何结构的一种基本技术,是一种基于集合理论技术,通常应用于图像处理中,是一种非常有用的图像分割工具。 代码可正常运行眼科图像处理中…...

别再乱买网卡了!手把手教你用Kali Linux和特定型号网卡(如TP-Link TL-WN722N)抓取Wi-Fi握手包

别再乱买网卡了!Kali Linux无线安全测试硬件选型与实战指南 当你第一次打开Kali Linux准备学习无线网络安全时,最令人沮丧的瞬间莫过于:跟着教程输入airmon-ng start wlan0后,屏幕上跳出"Device not supported"的红色警…...

杰理蓝牙芯片的key文件机制解析:从原理到实践

1. 杰理蓝牙芯片key文件机制揭秘 第一次接触杰理蓝牙芯片的开发者,往往会在项目初期就被一个神秘文件难住——key文件。这个看似简单的文件背后,却藏着杰理芯片架构设计的核心逻辑。我在调试AC6905芯片时就踩过坑:当时直接烧录了未加密的固件…...

最新出炉!2026年金三银四Java初中高级面试1000问

跳槽结果有人欢喜有人愁,找到好的下家固然可喜,跳槽结果不理想的朋友也不必丧气,只要扎实提升自己的技术,弄明白大厂面试官的出题逻辑,进大厂必是水到渠成。 之前有位粉丝让我写一篇怎么进大厂的文章,这是…...

TortoiseSVN与BeyondCompare高效协作:从配置到实战的完整指南

1. 为什么需要TortoiseSVN与BeyondCompare集成 如果你经常使用TortoiseSVN进行版本控制,肯定遇到过内置差异查看器不够直观的问题。默认的diff工具只能显示简单的文本对比,对于代码变更的识别效率很低。而BeyondCompare作为专业的文件对比工具&#xff0…...

你的Modbus通信稳定吗?用这5个C语言测试用例彻底验证CRC-16校验码

你的Modbus通信稳定吗?用这5个C语言测试用例彻底验证CRC-16校验码 在工业自动化领域,Modbus协议因其简单可靠而广泛应用,但许多工程师都曾遇到过这样的场景:实验室测试一切正常,到了现场却频繁出现通信中断或数据错误。…...

DrissionPage实战:H5与原生App的无缝自动化测试融合

1. 移动端自动化测试的现状与痛点 现在做移动端自动化测试的同行们应该都深有体会,设备碎片化问题越来越严重。光是安卓阵营就有上百种屏幕分辨率和系统版本组合,更别说还要兼顾iOS生态。我去年接手的一个电商项目,光是测试机就堆满了半个柜子…...

如何专业优化Windows系统音频:Equalizer APO实战配置完全指南

如何专业优化Windows系统音频:Equalizer APO实战配置完全指南 【免费下载链接】equalizerapo Equalizer APO mirror 项目地址: https://gitcode.com/gh_mirrors/eq/equalizerapo 你是否厌倦了Windows系统音质平淡无力,玩游戏时听不清敌人脚步声&a…...

golang如何使用BubbleTea开发终端UI_golang BubbleTea终端UI开发攻略

Bubble Tea要求Model为值类型以确保状态更新生效,Update须秒级返回且不可阻塞,View需防panic,跨平台构建Windows需加.exe后缀并注意编码。Model 必须是值类型,否则状态更新会失效Bubble Tea 的 Update 函数返回新模型实例&#xf…...

Docker 和 Kubernetes 部署 Java 应用最佳实践:构建现代化容器化系统

Docker 和 Kubernetes 部署 Java 应用最佳实践:构建现代化容器化系统别叫我大神,叫我 Alex 就好。今天我们来聊聊 Docker 和 Kubernetes 部署 Java 应用的最佳实践,这些实践可以帮助我们更高效地管理和运行容器化应用。一、引言 容器化技术已…...

龙旗科技年营收421亿:同比降9% 顺为去年清仓,套现超12亿 小米减持

雷递网 雷建平 4月14日龙旗科技日前发布截至2025年的年报,年报显示,龙旗科技2025年营收为421.25亿,较上年同期的463.82亿元下降9.18%。龙旗科技2025年净利为5.85亿,较上年同期的5亿元增长16.76%;扣非后净利为3.23亿元&…...

为什么宝塔面板网站加载出现致命的500内部服务器错误_查看PHP错误运行日志或关闭面板防跨站目录

500错误主因是PHP未捕获致命错误且日志未输出,需检查log_errorsOn、error_log路径可写、open_basedir白名单及catch_workers_outputyes。500 错误大概率不是宝塔面板本身的问题,而是 PHP 执行时抛出了未捕获的致命错误(比如 Parse error、Fat…...

滴滴2025年年报: 用户数达7.49亿 活跃司机3500万

雷递网 雷建平 4月14日滴滴(DiDi Global)今日发布20-F文件,文件显示,2025年滴滴年度活跃用户7.49亿,活跃司机和骑手3500万。截至2025年12月31日,滴滴一共有22335人。其中,滴滴一共有运营及支持人…...

2026年毕业季论文写作:我踩过的坑和用过的工具

又到一年毕业季,朋友圈里不少人开始熬夜改论文。回想自己写毕业论文那段时间,最头疼的不是内容本身,而是“不知道怎么下手”——选题定了又改、改了又定;框架搭起来总觉得哪里不对;好不容易写出初稿,参考文…...

如何有效应对多动倾向带来的课堂行为问题?

有效识别和分析多动症的特点及其在课堂中的表现 多动症的学生通常在课堂中表现出一系列明确的特征。首先,他们可能会表现出持续的注意力不集中,无法长时间专注于老师讲解的内容。其次,这些学生常常表现出冲动行为,可能会在课堂上打…...

黄山派LVGL8实战:用Gui Guider的MultiLanguage模板快速做个多语言Demo

黄山派LVGL8多语言界面开发实战:基于Gui Guider的高效解决方案 在嵌入式设备开发中,用户界面的多语言支持一直是让开发者头疼的问题。传统方法需要手动管理字符串资源,不仅效率低下,还容易出错。本文将带你使用Gui Guider的MultiL…...

佳能打印机报错5b00,1700,p07,e08这些错误解决方法,只需用清零软件清零即可修好了。

下载:点这里下载 备用下载:https://pan.baidu.com/s/1WrPFvdV8sq-qI3_NgO2EvA?pwd0000 常见型号如下: G系列 G1000、G1100、G1200、G1400、G1500、G1800、G1900、G1010、G1110、G1120、G1410、G1420、G1411、G1510、G1520、G1810、G1820、…...

大学生英语学习实测:低压力碎片化阅读,轻松养成长期学习习惯

不少大学生的英语学习,一直陷入恶性循环:单词书本本堆积,学习软件来回更换,每日打卡的计划屡屡中断。等到面对四六级考试时,依旧存在阅读缓慢、写作匮乏、听力薄弱等问题。其实大多数人并非不够努力,而是传…...

别再让UI卡死了!C# UDP接收数据,用异步和Task轻松搞定后台监听

现代C# UDP通信实践:用异步编程拯救你的UI线程 在桌面应用开发中,实时数据接收是许多场景的核心需求——从工业传感器监控到金融行情展示,再到游戏服务器状态更新。传统多线程方案虽然能解决问题,却常常带来UI卡顿、资源泄漏等&qu…...

电化学信号区分算法开发

电化学相似信号区分算法 1. 问题定义与数据生成 import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy.signal import gaussian, convolve from sklearn.model_selection import train_test_split...

2026年怎么安装OpenClaw?6分钟本地保姆级集成及百炼Coding Plan指南

2026年怎么安装OpenClaw?6分钟本地保姆级集成及百炼Coding Plan指南。本文面向零基础用户,完整说明在轻量服务器与本地Windows11、macOS、Linux系统中部署OpenClaw(Clawdbot)的流程,包含环境配置、服务启动、Skills集成…...

面试官:聊聊Redis中RDBAOF持久化原理!

Redis 中数据的持久化前言我们知道 Redis 是内存数据库,所有操作都在内存上完成。内存的话,服务器断电,内存上面的数据就会丢失了。这个问题显然是需要解决的。Redis 中引入了持久化来避免数据的丢失,主要有两种持久化的方式 RDB …...

C# 实现Workstation相关功能

以下是实现Workstation相关功能的C#代码示例&#xff0c;包含基础框架和关键功能模块&#xff1a;基础类结构public class WorkstationManager {private List<Workstation> _workstations new List<Workstation>();public void AddWorkstation(string name, strin…...

【Bootloader实战解析】基于UDS与CAN实现单片机固件无感升级

1. 为什么需要无感固件升级&#xff1f; 想象一下你的手机系统更新&#xff1a;点击"立即安装"后&#xff0c;系统自动下载更新包&#xff0c;重启时完成安装&#xff0c;整个过程无需连接电脑或使用特殊工具。这种"无感升级"体验在汽车电子和工业控制领域…...

【VsCode】告别配置焦虑:一文详解MSVC cl.exe编译C++的完整工作流

1. 为什么选择MSVC cl.exe编译C&#xff1f; 很多刚接触C开发的朋友都会遇到一个灵魂拷问&#xff1a;明明装了Visual Studio&#xff0c;为什么还要折腾VsCode&#xff1f;更让人头大的是&#xff0c;明明电脑里就有现成的MSVC编译器&#xff0c;却总是习惯性去下载MinGW。作为…...