MAF快速入门(17)用户智能体交互协议AG-UI(中)
目录简介1 什么是AG-UI ToolsBackend ToolsFrontend Tools2 快速开始前后端工具混合使用AG-UI Tools ServerAG-UI Tools Client测试场景1测试场景2测试场景33 小结示例源码简介大家好我是Edison。上一篇我们初步学习了AG-UI。本篇我们来了解AG-UI Tools 以及 实现一个前后端工具混合使用的案例。1 什么是AG-UI ToolsAG-UI Tools 是 AG-UI 的 工具系统分为 Backend Tools 和 Frontend Tools它们是AI Agent和外部世界交互的桥梁让AI Agent能够执行实际操作而不仅仅是生成文本。Backend Tools顾名思义Backend Tools即后端工具它在服务端执行主要用于做一些类似数据库查询、API调用 或 敏感操作等用途主要访问服务端资源安全性要求较高。何时需要使用Backend Tools 涉及敏感数据或 API 密钥 需要访问数据库或后端服务⚡ 计算密集型任务 需要服务端验证和审计Frontend Tools顾名思义Frontend Tools即前端工具它在客户端执行主要用于做一些类似GPS定位、剪贴板 或者 设备传感器等用途主要访问客户端设备资源安全性上仅需做客户端验证。何时需要使用Frontend Tools 需要访问设备功能GPS、相机等 需要读取本地资源剪贴板、文件 涉及用户隐私数据⚡ 需要快速响应的本地操作2 快速开始前后端工具混合使用假设我们有这样一个需求我们向Agent询问“附近有什么好吃的餐厅”AG-UI前端会使用前端工具获取当前定位信息然后将问题和定位发给AG-UI服务端服务端又调用服务端工具搜索附近的餐馆信息最后由大模型整合结果输出最终信息。整个调用流程如下图所示接下来我们就一步一步完成一个AG-UI Tools示例应用涉及到的Server 和 Client。AG-UI Tools Server首先我们创建一个ASP.NET Web应用安装以下NuGet包Microsoft.Agents.AI.Hosting.AGUI.AspNetCore Microsoft.Agents.AI.OpenAI Microsoft.Extensions.AI.OpenAI然后就是整个示例的核心部分我们一块一块来说1定义相关数据模型说明这里配置 JsonSerializerContext JSON源生成器主要用以提高序列化性能确保在Native AOT环境下也能够正常序列化即AOT友好。// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 数据模型定义 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ internal sealed class RestaurantSearchResult { public string Location { get; set; } string.Empty; public double SearchRadius { get; set; } public int TotalResults { get; set; } public NearbyRestaurant[] Restaurants { get; set; } []; } internal sealed class NearbyRestaurant { public string Name { get; set; } string.Empty; public string Cuisine { get; set; } string.Empty; public double Distance { get; set; } public double Rating { get; set; } public string Address { get; set; } string.Empty; } internal sealed class RestaurantDetail { public string Name { get; set; } string.Empty; public string Description { get; set; } string.Empty; public string OpeningHours { get; set; } string.Empty; public string PriceRange { get; set; } string.Empty; public string[] RecommendedDishes { get; set; } []; public string Phone { get; set; } string.Empty; public bool HasParking { get; set; } public bool AcceptsReservation { get; set; } } // JSON 序列化上下文 [JsonSerializable(typeof(RestaurantSearchResult))] [JsonSerializable(typeof(NearbyRestaurant))] [JsonSerializable(typeof(RestaurantDetail))] internal sealed partial class MixedToolsJsonContext : JsonSerializerContext;2定义backend toolsinternal class BackendTools { // 餐厅搜索工具后端执行 [Description(根据位置搜索附近的餐厅。Search for nearby restaurants based on location.)] public static RestaurantSearchResult SearchNearbyRestaurants( [Description(用户当前位置描述)] string location, [Description(搜索半径公里)] double radiusKm 2.0, [Description(菜系偏好可选)] string? cuisinePreference null) { Console.ForegroundColor ConsoleColor.Green; Console.WriteLine($\n [后端工具] SearchNearbyRestaurants); Console.WriteLine($ 位置: {location}); Console.WriteLine($ 半径: {radiusKm} km); Console.WriteLine($ ️ 菜系偏好: {cuisinePreference ?? 不限}); Console.ResetColor(); // 模拟数据库查询 var restaurants new ListNearbyRestaurant { new() { Name 老北京炸酱面, Cuisine 北京菜, Distance 0.5, Rating 4.7, Address ${location}东路100号 }, new() { Name 川香阁, Cuisine 川菜, Distance 0.8, Rating 4.5, Address ${location}西路200号 }, new() { Name 粤味轩, Cuisine 粤菜, Distance 1.2, Rating 4.8, Address ${location}南路300号 }, new() { Name 日式料理屋, Cuisine 日本料理, Distance 1.5, Rating 4.6, Address ${location}北路400号 }, new() { Name 烤匠, Cuisine 川菜, Distance 2.5, Rating 4.8, Address ${location}天府四街银泰城5楼 } }; // 如果有菜系偏好过滤结果 if (!string.IsNullOrEmpty(cuisinePreference)) { restaurants restaurants .Where(r r.Cuisine.Contains(cuisinePreference, StringComparison.OrdinalIgnoreCase)) .ToList(); } Console.ForegroundColor ConsoleColor.Green; Console.WriteLine($ ✅ 找到 {restaurants.Count} 家餐厅); Console.ResetColor(); return new RestaurantSearchResult { Location location, SearchRadius radiusKm, TotalResults restaurants.Count, Restaurants restaurants.ToArray() }; } // 获取餐厅详情后端执行 [Description(获取指定餐厅的详细信息包括营业时间、菜单推荐等。Get detailed information about a specific restaurant.)] public static RestaurantDetail GetRestaurantDetail( [Description(餐厅名称)] string restaurantName) { Console.ForegroundColor ConsoleColor.Green; Console.WriteLine($\n [后端工具] GetRestaurantDetail); Console.WriteLine($ 餐厅: {restaurantName}); Console.ResetColor(); // 模拟数据库查询 var detail new RestaurantDetail { Name restaurantName, Description ${restaurantName}是一家知名的特色餐厅拥有20年历史。, OpeningHours 10:00 - 22:00, PriceRange 人均 80-150 元, RecommendedDishes [招牌菜, 特色小吃, 主厨推荐], Phone 010-12345678, HasParking true, AcceptsReservation true }; Console.ForegroundColor ConsoleColor.Green; Console.WriteLine($ ✅ 获取成功); Console.ResetColor(); return detail; } }3创建应用并注册AG-UI服务// Step0. Create WebApplication builder var builder WebApplication.CreateBuilder(args); builder.Services.AddHttpClient().AddLogging(); // ⭐ 配置 JSON 序列化上下文 (用于数据模型的序列化) builder.Services.ConfigureHttpJsonOptions(options options.SerializerOptions.TypeInfoResolverChain.Add(MixedToolsJsonContext.Default)); // Step1. Register AG-UI services builder.Services.AddAGUI();4加载可用backend tools并创建Agent​​​​​​​var app builder.Build(); // Step3. Create AI Agent var jsonOptions app.Services.GetRequiredServiceIOptionsJsonOptions().Value; AITool[] backendTools [ AIFunctionFactory.Create(BackendTools.SearchNearbyRestaurants, serializerOptions: jsonOptions.SerializerOptions), AIFunctionFactory.Create(BackendTools.GetRestaurantDetail, serializerOptions: jsonOptions.SerializerOptions) ]; Console.WriteLine( 已注册后端工具); foreach (var tool in backendTools) { Console.WriteLine($ • {tool.Name} (服务端执行)); } Console.WriteLine( 前端工具将由客户端注册); var agent chatClient.AsIChatClient() .AsAIAgent( name: MixedToolsAssistant, instructions: 你是一个智能餐厅推荐助手具备以下能力 位置感知 - 可以获取用户的当前位置使用 GetUserLocation 工具 - 当用户说附近、周围时先获取位置 ️ 餐厅推荐 - 使用 SearchNearbyRestaurants 搜索附近餐厅 - 使用 GetRestaurantDetail 获取详细信息 使用流程 1. 如果用户问附近有什么餐厅先调用 GetUserLocation 获取位置 2. 然后调用 SearchNearbyRestaurants 搜索 3. 如果用户想了解某家餐厅调用 GetRestaurantDetail 请用中文友好地回答用户。 , tools: backendTools); Console.WriteLine(✅ AI Agent 创建成功);5映射AGUI端点并启动应用​​​​​​​// Step5. Mapping AG-UI Endpoints app.MapAGUI(/, agent); app.Run();AG-UI Tools Client首先我们创建一个控制台应用安装以下NuGet包​​​​​​​Microsoft.Agents.AI.AGUI Microsoft.Agents.AI然后定义frontend tools​​​​​​​internal class FrontendTools { // 获取用户位置前端工具 - 只有客户端能访问 GPS [Description(获取用户当前的地理位置信息。这是客户端设备功能用于获取 GPS 位置。Get the users current location from GPS.)] public static string GetUserLocation() { Console.ForegroundColor ConsoleColor.Magenta; Console.WriteLine(\n [前端工具] GetUserLocation); Console.WriteLine( 正在访问设备 GPS...); Console.ResetColor(); // 模拟 GPS 获取延迟 Thread.Sleep(800); // 模拟不同的位置随机选择 string[] locations [ 北京市朝阳区三里屯, 上海市浦东新区陆家嘴, 广州市天河区珠江新城, 深圳市南山区科技园, 成都市高新区天府软件园 ]; Random random new(); string location locations[random.Next(locations.Length)]; Console.ForegroundColor ConsoleColor.Magenta; Console.WriteLine($ ✅ GPS 定位成功: {location}); Console.ResetColor(); return location; } // 获取用户偏好设置前端工具 - 访问本地存储 [Description(获取用户保存的餐饮偏好设置。Get users saved dining preferences.)] public static string GetUserPreferences() { Console.ForegroundColor ConsoleColor.Magenta; Console.WriteLine(\n⚙️ [前端工具] GetUserPreferences); Console.WriteLine( 读取本地偏好设置...); Console.ResetColor(); // 模拟读取本地存储 Thread.Sleep(300); string preferences 偏好菜系: 川菜、粤菜; 价位: 中等; 忌口: 无; Console.ForegroundColor ConsoleColor.Magenta; Console.WriteLine($ ✅ 读取成功: {preferences}); Console.ResetColor(); return preferences; } }随后我们创建AG-UI Client 和 AI Agent​​​​​​​...... var serverEndpoint config.GetValuestring(AGUI_SERVER_URL) ?? https://localhost:8443; // 加载前端工具 AITool[] frontendTools [ AIFunctionFactory.Create(FrontendTools.GetUserLocation), AIFunctionFactory.Create(FrontendTools.GetUserPreferences) ]; Console.WriteLine( 已注册前端工具); foreach (var tool in frontendTools) { Console.WriteLine($ • {tool.Name} (客户端执行)); } Console.WriteLine( 后端工具由服务端提供 (SearchNearbyRestaurants, GetRestaurantDetail)); Console.WriteLine(); // Step1. Create HTTP Client using HttpClient httpClient new() { Timeout TimeSpan.FromSeconds(180) // 延长超时因为可能有多个工具调用 }; // Step2. Create AG-UI Client var chatClient new AGUIChatClient(httpClient, serverEndpoint); // Step3. Create AI Agent var agent chatClient.AsAIAgent( name: agui-client, description: AG-UI 混合工具客户端, tools: frontendTools); // 注册前端工具最后准备开始对话​​​​​​​// Step4. Prepare for Conversation var session await agent.GetNewSessionAsync(); var messages new ListChatMessage() { new ChatMessage(ChatRole.System, 你是一个智能餐厅推荐助手。 你可以使用多种工具来帮助用户找到合适的餐厅。 当用户问附近有什么餐厅时先获取他们的位置再搜索餐厅。 ) }; Console.WriteLine( 开始对话输入 :q 或 quit 退出\n); while (true) { Console.Write( 用户: ); string? message Console.ReadLine(); if (string.IsNullOrWhiteSpace(message)) { Console.WriteLine(⚠️ 消息不能为空请重新输入。); continue; } if (message is :q or quit) { Console.WriteLine(\n 再见); break; } // 添加用户消息 messages.Add(new ChatMessage(ChatRole.User, message)); // 统计工具调用 int frontendToolCalls 0; int backendToolCalls 0; bool isFirstUpdate true; Liststring toolCallChain []; Console.WriteLine(); Console.WriteLine(━━━━━━━━━━━━━━ 开始处理 ━━━━━━━━━━━━━━━); // 流式接收响应 Console.Write( 助手: ); await foreach (var update in agent.RunStreamingAsync(messages, session)) { var chatUpdate update.AsChatResponseUpdate(); if (isFirstUpdate) { Console.ForegroundColor ConsoleColor.DarkGray; Console.WriteLine($[ Run Started - Thread: {chatUpdate.ConversationId?.Substring(0, 8)}...]); Console.ResetColor(); isFirstUpdate false; } foreach (AIContent content in update.Contents) { switch (content) { case TextContent textContent: Console.ForegroundColor ConsoleColor.Cyan; Console.Write(textContent.Text); Console.ResetColor(); break; case FunctionCallContent functionCall: // 判断是前端还是后端工具 var isFrontendTool frontendTools.Any(t t.Name functionCall.Name); if (isFrontendTool) { frontendToolCalls; Console.ForegroundColor ConsoleColor.Magenta; Console.WriteLine($\n [前端工具调用] {functionCall.Name}); } else { backendToolCalls; Console.ForegroundColor ConsoleColor.Yellow; Console.WriteLine($\n️ [后端工具调用] {functionCall.Name}); // 显示后端工具参数 if (functionCall.Arguments ! null) { Console.WriteLine( 参数:); foreach (var kvp in functionCall.Arguments) { Console.WriteLine($ • {kvp.Key}: {kvp.Value}); } } } Console.ResetColor(); toolCallChain.Add(isFrontendTool ? ${functionCall.Name} : $️{functionCall.Name}); break; case FunctionResultContent functionResult: // 后端工具结果显示 if (!frontendTools.Any(t toolCallChain.LastOrDefault()?.Contains(t.Name) ?? false)) { Console.ForegroundColor ConsoleColor.Green; string resultPreview functionResult.Result?.ToString() ?? null; if (resultPreview.Length 150) { resultPreview resultPreview.Substring(0, 150) ...; } Console.WriteLine($ ✅ 结果: {resultPreview}); Console.ResetColor(); } break; case ErrorContent errorContent: Console.ForegroundColor ConsoleColor.Red; Console.WriteLine($\n❌ 错误: {errorContent.Message}); Console.ResetColor(); break; } } } // 显示工具调用链 Console.WriteLine(); Console.WriteLine(━━━━━━━━━━━━━━ 处理完成 ━━━━━━━━━━━━━━━); Console.ForegroundColor ConsoleColor.DarkGray; Console.WriteLine($[✅ Run Finished]); Console.WriteLine($ 前端工具调用: {frontendToolCalls}); Console.WriteLine($ ️ 后端工具调用: {backendToolCalls}); if (toolCallChain.Count 0) { Console.WriteLine($ 调用链: {string.Join( → , toolCallChain)}); } Console.ResetColor(); Console.WriteLine(); } Console.WriteLine( 再见); Console.ReadKey();测试场景1用户附近有什么好吃的餐厅调用链路GetUserLocation → ️SearchNearbyRestaurants测试场景2用户根据我的偏好推荐餐厅调用链路GetUserPreferences → GetUserLocation → ️SearchNearbyRestaurants测试场景3用户烤匠这家店怎么样调用链路️GetRestaurantDetail可以看到Agent可以自动协调工具调用顺序前后端工具能够实现协同工作同时我们也能看到完整的工具调用链路。3 小结本文介绍了AG-UI Tools即AG-UI的工具系统演示了一个结合前后端工具使用的混合模式案例通过案例可以了解如何在AG-UI中调用工具并观察调用链。示例源码Github: https://github.com/EdisonTalk/MAFDGitHub - mzhongl524/MAFD: Microsoft Agent Framwork Demos · GitHub2026-8月更新示例下一篇​​​​​​​引入地址

相关新闻

SpaceClaim实战:五大核心场景解析CAE几何前处理

SpaceClaim实战:五大核心场景解析CAE几何前处理

这次我们来看一个面向CAE仿真的几何处理工具——SpaceClaim。对于从事结构分析、流体仿真、热力学模拟的工程师来说,几何模型的前处理往往是耗时最长的环节。SpaceClaim作为一款直接建模工具,其核心价值在于能够快速、直观地修复、清理和简化复杂的CAD模…

2026/8/16 21:39:13 阅读更多 →
TWCC RTCP 反馈从进入 WebRTC 到驱动 GCC 计算目标码率的流程

TWCC RTCP 反馈从进入 WebRTC 到驱动 GCC 计算目标码率的流程

IncomingPacket│▼ ParseCompoundPacket│├─► 设置 packet_type_flags(标识包含哪些 RTCP 类型)├─► 设置 remote_ssrc(远端流标识)├─► 设置 nack_sequence_numbers(NACK 请求)├─► 设置 report…

2026/8/16 21:43:10 阅读更多 →
华为AIPL计划:昇腾生态下的AI实践教学标准化解决方案

华为AIPL计划:昇腾生态下的AI实践教学标准化解决方案

这次我们来看一个面向教育领域的重磅合作计划——华为 AIPL 基线合作伙伴计划。这不是一个具体的开源模型或工具,而是一个旨在将 AI 技术规模化引入高校实践教学的生态合作框架。对于高校教师、教育科技从业者以及关注昇腾生态的开发者来说,这个计划提供…

2026/8/15 21:29:49 阅读更多 →

最新新闻

nslookup命令使用说明

nslookup命令使用说明

个人建站,域名备案完成后,往往还要做域名解析服务,技术人员怎么能知道自己配置的DNS正确与否呢?NSLOOKUP查询域名信息的一个非常有用的命令,可以指定查询的类型,可以查到DNS记录的生存时间还可以指定使用哪…

2026/8/17 0:00:08 阅读更多 →
【原创唯一】基于SpringBoot+Vue的在线书店商城系统 课程设计/大作业/期末作业(源码+MySQL数据库+实验报告+PPT+远程部署)

【原创唯一】基于SpringBoot+Vue的在线书店商城系统 课程设计/大作业/期末作业(源码+MySQL数据库+实验报告+PPT+远程部署)

摘要 电子商务与移动支付的普及,线上购书已成为高校师生及社会公众获取图书的重要方式。传统线下书店在图书检索、库存查询、订单跟踪等方面存在信息分散、效率较低等问题。本文设计并实现了一套基于 B/S 架构的网上书店系统,采用前后端分离模式&#xf…

2026/8/17 0:00:08 阅读更多 →
飞书局域网文件传输实战:3种方案实现高速点对点传输

飞书局域网文件传输实战:3种方案实现高速点对点传输

1. 项目概述:为什么要在局域网内用飞书传文件? 飞书作为一款主流的协同办公套件,其核心功能是围绕云端协作设计的。无论是文档、表格还是文件,通常的分享逻辑都是“上传到云端 -> 生成链接 -> 分享给同事”。这个流程在互联…

2026/8/17 0:00:08 阅读更多 →
LabVIEW异步调用实战:解决界面卡顿与并行处理难题

LabVIEW异步调用实战:解决界面卡顿与并行处理难题

1. 项目概述:为什么异步调用是LabVIEW进阶的必经之路如果你在LabVIEW里写过稍微复杂点的程序,尤其是涉及到界面响应、多任务并行或者硬件IO等待,大概率会遇到一个头疼的问题:程序“卡”住了。前面板点不动,进度条不更新…

2026/8/17 0:00:08 阅读更多 →
LabVIEW异步调用实战:从原理到生产者消费者模式,解决界面卡顿与并行处理难题

LabVIEW异步调用实战:从原理到生产者消费者模式,解决界面卡顿与并行处理难题

1. 项目概述:为什么异步调用是LabVIEW进阶的必修课? 如果你用LabVIEW做过稍微复杂点的项目,尤其是涉及界面响应、多任务并行或者硬件IO等待的场景,大概率遇到过这样的窘境:前面板点个按钮,整个程序就“卡死…

2026/8/17 0:00:08 阅读更多 →
错误分享:误将磁盘分区类型选成磁盘名称

错误分享:误将磁盘分区类型选成磁盘名称

1.先删除原有分区2.fdisk重新创建3.发现进程被占用4.使用kill关不掉进程,加 -9 强制关闭5.关闭后重新使用fdisk创建,tips:记得改完后要使用 w 保存

2026/8/16 23:59:08 阅读更多 →

日新闻

LabVIEW异步调用实战:从原理到生产者消费者模式,解决界面卡顿与并行处理难题

LabVIEW异步调用实战:从原理到生产者消费者模式,解决界面卡顿与并行处理难题

1. 项目概述:为什么异步调用是LabVIEW进阶的必修课? 如果你用LabVIEW做过稍微复杂点的项目,尤其是涉及界面响应、多任务并行或者硬件IO等待的场景,大概率遇到过这样的窘境:前面板点个按钮,整个程序就“卡死…

2026/8/17 0:00:08 阅读更多 →
LabVIEW异步调用实战:解决界面卡顿与并行处理难题

LabVIEW异步调用实战:解决界面卡顿与并行处理难题

1. 项目概述:为什么异步调用是LabVIEW进阶的必经之路如果你在LabVIEW里写过稍微复杂点的程序,尤其是涉及到界面响应、多任务并行或者硬件IO等待,大概率会遇到一个头疼的问题:程序“卡”住了。前面板点不动,进度条不更新…

2026/8/17 0:00:08 阅读更多 →
飞书局域网文件传输实战:3种方案实现高速点对点传输

飞书局域网文件传输实战:3种方案实现高速点对点传输

1. 项目概述:为什么要在局域网内用飞书传文件? 飞书作为一款主流的协同办公套件,其核心功能是围绕云端协作设计的。无论是文档、表格还是文件,通常的分享逻辑都是“上传到云端 -> 生成链接 -> 分享给同事”。这个流程在互联…

2026/8/17 0:00:08 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/16 0:00:54 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/16 0:00:55 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/16 0:03:55 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/16 6:00:23 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/16 6:00:24 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/16 6:00:27 阅读更多 →