【BotSharp详细介绍——一步步实现MCP+LLM的聊天问答实例】
BotSharp详细介绍——一步步实现MCP+LLM的聊天问答实例
- 一、MCP原理介绍
- 二、创建BotSharp的项目,实现LLM推理机器人
- 1、新建一个 解决方案,结构如下:
- 2、先看下 MyWeatherPlugin
- 3、创建MyWeatherMcpAPI
- 三、创建 MCP Server
- 1、添加引用
- 2、添加工具包
- 四、搭建 MCP Client和 MCP Host
- 1、查看web api 项目有没有添加 MCP 引用
- 2、打开 MCP 开关
- 3、Program.cs中添加 mcp支持
- 4、修改 agent
- 五、简单集成下 BotSharp-UI
还是本着投石问路、抛砖引玉、以此来引出更多对BotSharp这个优秀C#的AI框架的讨论的文章的态度,这个例子仔细研究 BotSharp 框架的示例代码实现以下内容:
1、通过BotSharp框架搭建一个简单的LLM模型的聊天机器人;
2、搭建一个MCP Server;
3、简单调整下 BotSharp的聊天机器人,搭建MCP Client、MCP Host 实现 MCP增强的LLM推理问答;
4、简单集成下 BotSharp-UI.实现一个可视的界面
一、MCP原理介绍
MCP是Model Context Protocol的简称,是 指的用于根据模型的上下文进行通讯的协议。它的作用主要还是用于语言模型,MCP 真正实现之后,一般分为
1、MCP Client 端,
2、MCP Server 端,
3、MCP Host 端
在MCP Server端上部署让 语言模型 去判断后调用的 工具集合,
MCP Client 是相对于 MCP Server 而言的,与MCP Server建立一对一的联系,MCP Host中部署语言大模型,是实际上请求 MCP Server的一端,但是 MCP Client和 MCP Host 物理上是一起的。
MCP Host 部署的应用启动后,语言大模型就开始工作,可以实现聊天,推理问答。语言模型 在获取到用户提出的问题后,根据MCP Client 的设置信息,可以找到MCP Server,根据 当前 设置的 与MCP Server 通信是 SSE 模式还是 Stdio 模式,最终都是获取 MCP Server的 Tools 的列表,然后 根据 参数、Description等信息判断,来决定是否 调用 其中的某个Tool,调用的话,返回 Tool的返回信息,不调用的话,返回 大模型自己的推理结果。
二、创建BotSharp的项目,实现LLM推理机器人
1、新建一个 解决方案,结构如下:
2、先看下 MyWeatherPlugin
这个项目 还是参考 PizzaBot 创建的,只是把 functions 的目录删掉了。
这个项目的作用还是 注册 anget插件、注册conversation插件。
(这个例子里不再利用 大模型的function calling,所以不用 functions)
结构如图:
using.cs
global using System;
global using System.Collections.Generic;
global using System.Text;
global using System.Threading.Tasks;
global using System.ComponentModel.DataAnnotations;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using BotSharp.Abstraction.Plugins;
global using BotSharp.Abstraction.Functions;
global using BotSharp.Abstraction.Agents.Settings;
CommonAgentHook.cs
using BotSharp.Abstraction.Agents;namespace MyWeatherPlugin.Hooks
{public class CommonAgentHook : AgentHookBase{public override string SelfId => string.Empty;public CommonAgentHook(IServiceProvider services, AgentSettings settings): base(services, settings){}public override bool OnInstructionLoaded(string template, Dictionary<string, object> dict){dict["current_date"] = DateTime.Now.ToString("MM/dd/yyyy");dict["current_time"] = DateTime.Now.ToString("hh:mm tt");dict["current_weekday"] = DateTime.Now.DayOfWeek;return base.OnInstructionLoaded(template, dict);}}}
MyWeatherAgentHook.cs
using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Agents;
using BotSharp.Abstraction.Functions.Models;namespace MyWeatherPlugin.Hooks
{public class MyWeatherAgentHook : AgentHookBase{public override string SelfId => BuiltInAgentId.AIAssistant;public MyWeatherAgentHook(IServiceProvider services, AgentSettings settings): base(services, settings){}public override bool OnInstructionLoaded(string template, Dictionary<string, object> dict){return base.OnInstructionLoaded(template, dict);}}}
MyWeatherConversationHook.cs
using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.Conversations;namespace MyWeatherPlugin.Hooks
{public class MyWeatherConversationHook : ConversationHookBase{private readonly IServiceProvider _services;private readonly IConversationStateService _states;public MyWeatherConversationHook(IServiceProvider services,IConversationStateService states){_services = services;_states = states;}public override async Task OnPostbackMessageReceived(RoleDialogModel message, PostbackMessageModel replyMsg){if (replyMsg.FunctionName == "get_delicious_food"){// message.StopCompletion = true;}return;}public override Task OnTaskCompleted(RoleDialogModel message){return base.OnTaskCompleted(message);}#if USE_BOTSHARPpublic override async Task OnResponseGenerated(RoleDialogModel message){var agentService = _services.GetRequiredService<IAgentService>();var state = _services.GetRequiredService<IConversationStateService>();var agent = await agentService.LoadAgent(message.CurrentAgentId);if (agent.McpTools.Any(item => item.Functions.Any(x => x.Name == message.FunctionName))){var data = JsonDocument.Parse(JsonSerializer.Serialize(message.Data));state.SaveStateByArgs(data);}await base.OnResponseGenerated(message);}
#endif}}
MyWeatherPlugin.cs
using BotSharp.Abstraction.Agents;
using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Plugins;
using MyWeatherPlugin.Hooks;namespace MyWeatherPlugin
{public class MyWeatherPlugin: IBotSharpPlugin{public string Id => "1c8270eb-de63-4ca0-8903-654d83ce5ece";public string Name => "MyWeather AI Assistant";public string Description => "An example of an Weather AI Chatbot.";public string IconUrl => "https://cdn-icons-png.flaticon.com/512/6978/6978255.png";public string[] AgentIds => new[]{"c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd","01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a","6745151e-6d46-4a02-8de4-1c4f21c7da95","bba9c6a2-5efc-428c-8b4e-95fcc9d24e3e"};public void RegisterDI(IServiceCollection services, IConfiguration config){// Register hooksservices.AddScoped<IAgentHook, MyWeatherAgentHook>();//services.AddScoped<IConversationService, MyWeatherConversationHook>();}}
}
这个项目 在本例中没有特别的作用了,所以不过多介绍了,后续在 回调函数中增加一些信息时 ,会再次用到这个项目
3、创建MyWeatherMcpAPI
结构如下:
添加的nuget 引用如下:
这个例子中使用的 是spark max。
appsettings.json
{"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": "*","AllowedOrigins": ["http://localhost:5015","http://0.0.0.0:5015","https://botsharp.scisharpstack.org","https://chat.scisharpstack.org"],"Jwt": {"Issuer": "botsharp","Audience": "botsharp","Key": "31ba6052aa6f4569901facc3a41fcb4adfd9b46dd00c40af8a753fbdc2b89869"},"LlmProviders": [{"Provider": "llama-sharp","Models": [{"Name": "llama-2-7b-guanaco-qlora.Q2_K.gguf","Type": "chat"}]},{"Provider": "sparkdesk","Models": [{"Name": "max","Type": "chat","PromptCost": 0.0015,"CompletionCost": 0.002}]},{"Provider": "deepseek-ai","Models": [{"Name": "deepseek-chat","ApiKey": "你的 apikey","Endpoint": "https://api.deepseek.com/v1/","Type": "chat","PromptCost": 0.0015,"CompletionCost": 0.002}]}],"Router": {},"Evaluator": {"AgentId": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a"},"Agent": {"DataDir": "agents","TemplateFormat": "liquid","HostAgentId": "bba9c6a2-5efc-428c-8b4e-95fcc9d24e3e","EnableTranslator": false,"LlmConfig": {"Provider": "sparkdesk","Model": "max"//"Provider": "llama-sharp",//"Model": "llama-2-7b-guanaco-qlora.Q2_K.gguf"//"Provider": "deepseek-ai",//"Model": "deepseek-chat"}},"MCP": {"Enabled": false,"McpClientOptions": {"ClientInfo": {"Name": "SimpleToolsBotsharp","Version": "1.0.0"}},"McpServerConfigs": [{"Id": "FoodServer","Name": "FoodServer","TransportType": "sse","TransportOptions": [],"Location": "http://localhost:5103/sse"}]},"Conversation": {"DataDir": "conversations","ShowVerboseLog": false,"EnableLlmCompletionLog": false,"EnableExecutionLog": true,"EnableContentLog": true,"EnableStateLog": true,"EnableTranslationMemory": false,"CleanSetting": {"Enable": true,"BatchSize": 50,"MessageLimit": 2,"BufferHours": 12,"ExcludeAgentIds": []},"RateLimit": {"MaxConversationPerDay": 100,"MaxInputLengthPerRequest": 256,"MinTimeSecondsBetweenMessages": 2}},"ChatHub": {"EventDispatchBy": "group"},"LlamaSharp": {"Interactive": true,//如果使用LLama模型,需要下载到本地。还需要添加 更多的 nuget包,具体看见上一个示例"ModelDir": "F:/models", "DefaultModel": "llama-2-7b-guanaco-qlora.Q2_K.gguf","MaxContextLength": 1024,"NumberOfGpuLayer": 20},"SparkDesk": {"AppId": "你的appid","ApiKey": "你的appkey","ApiSecret": "你的 apisecret","ModelVersion": {"DisplayName": "max","Domain": "generalv3.5","AddressPart": "v3.5"}},"AzureOpenAi": {},"RoutingSpeeder": {},"Database": {"Default": "FileRepository","TablePrefix": "BotSharp","BotSharpMongoDb": "","Redis": "botsharp.redis.cache.windows.net:6380,password=,ssl=True,abortConnect=False","FileRepository": "data","Assemblies": [ "BotSharp.Core" ]},"Interpreter": {"Python": {"PythonDLL": "C:/Python313/python313.dll"}},"PluginLoader": {"Assemblies": ["BotSharp.Core","BotSharp.Core.Crontab","BotSharp.Logger","BotSharp.Plugin.OpenAI","BotSharp.Plugin.ChatHub","MyWeatherPlugin","BotSharp.Plugin.SparkDesk","BotSharp.Plugin.LLamaSharp","BotSharp.Plugin.DeepSeekAI","BotSharp.Plugin.ChatbotUI"],"ExcludedFunctions": ["McpToolAdapter"]}
}
因本例中使用的是 spark max ,所以 注意下,模型处 这几行要特别注意,
"SparkDesk": {"AppId": "你的appid","ApiKey": "你的appkey","ApiSecret": "你的 apisecret","ModelVersion": {"DisplayName": "max","Domain": "generalv3.5","AddressPart": "v3.5"}},LlmProviders": [{"Provider": "sparkdesk","Models": [{"Name": "max","Type": "chat","PromptCost": 0.0015,"CompletionCost": 0.002}]}]
另外因为暂时 还不使用 mcp 的功能,所以 MCP配置部分的 enable是 false
"MCP": {"Enabled": false,"McpClientOptions": {"ClientInfo": {"Name": "SimpleToolsBotsharp","Version": "1.0.0"}},"McpServerConfigs": [{"Id": "FoodServer","Name": "FoodServer","TransportType": "sse","TransportOptions": [],"Location": "http://localhost:5103/sse"}]},
然后看下 program.cs
此时 没有什么特殊的地方:
using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Messaging.JsonConverters;
using BotSharp.Abstraction.Users;
using BotSharp.Core;
using BotSharp.Core.Agents;
using BotSharp.Core.MCP;
using BotSharp.Logger;
using BotSharp.OpenAPI;
using BotSharp.Plugin.ChatHub;var builder = WebApplication.CreateBuilder(args);builder.Services.AddBotSharpCore(builder.Configuration, options =>
{options.JsonSerializerOptions.Converters.Add(new RichContentJsonConverter());options.JsonSerializerOptions.Converters.Add(new TemplateMessageJsonConverter());
}).AddBotSharpOpenAPI(builder.Configuration,
builder.Configuration.GetSection("AllowedOrigins").Get<string[]>() ?? new[]{"http://0.0.0.0:5015","https://botsharp.scisharpstack.org","https://chat.scisharpstack.org"}, builder.Environment, true).AddBotSharpLogger(builder.Configuration);builder.Services.AddControllers();
builder.Services.AddSignalR();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.MapHub<SignalRHub>("/chatHub");
app.UseMiddleware<WebSocketsMiddleware>();app.UseBotSharp().UseBotSharpOpenAPI(app.Environment);
app.Run();
此时 就可以启动 项目,然后 通过 postman 访问,
Postman的位置:
https://botsharp.verdure-hiro.cn/guide/quick-start/get-started
中的 postman 链接 如下
在 copy workspace、调整 依次 执行
New User Account
Get Access Token
Create Agent
New Conversation
sendMessage
的操作 ,便可以 实现 通过 spark max 模型 实现 问答。
三、创建 MCP Server
新建一个 .net 9 下的 Asp.net core web API项目
结构如下:
1、添加引用
2、添加工具包
要注意的是,一定注意 参数 和 descritpion,这是 决定 LLM 是否调用 tool或者 调用哪个一个tool的依据
GetDeliciousFood.cs
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;namespace MyMCPServer.Tools
{[McpServerToolType]public class GetDeliciousFood{[McpServerTool(Name = "get_delicious_food"), Description("是一个按照城市的名称返回当地的美食的工具。")]public static string Get_delicious_food([Description("用于获取城市"), Required] string city){if (city is null){throw new Exception("请输入城市!");}string result = string.Empty;switch (city){case "安庆":result = "山粉阮子、糍粑、鸡汤泡炒米、大饼子包油条";break;case "桐城":result = "桐城丰糕、桐城水碗、桐城水芹菜";break;case "青草":result = "麻丰糕、酱油干子、朝笏牌子";break;default:result = "都还挺不错";break;}return result; }}
}
Program.cs
var builder = WebApplication.CreateBuilder(args);// Add services to the container.
builder.Services.AddMcpServer().WithToolsFromAssembly().WithHttpTransport();builder.Services.AddControllers();var app = builder.Build();// Configure the HTTP request pipeline.
app.MapGet("/", () => "你是一个用于查询当地美食的MCP server!");
app.MapMcp();
app.Run();
启动后 可以直接 通过 npx 工具进行测试
1、要先安装 node.js
2、在cmd中 运行: npx @modelcontextprotocol/inspector
3、在浏览器中访问
1)先看下 mcp server 中的 launchSettings.json 中的 applicationUrl
2)按照上图 打开浏览器 访问 http://127.0.0.1:6274
3) 按照下图 操作
这样 MCP Server 就完成了,
四、搭建 MCP Client和 MCP Host
这步骤 其实就是调整下 刚才 BotSharp 创建的机器人就好。
1、查看web api 项目有没有添加 MCP 引用
添加 BotSharp.Core.MCP的引用。
appsettins.json中"PluginLoader要添加引用
2、打开 MCP 开关
"MCP": {
//注意,这个地方的开关调成true"Enabled": true,"McpClientOptions": {"ClientInfo": {"Name": "SimpleToolsBotsharp","Version": "1.0.0"}},//此处其实是注册 MCP Server,其实可以看到,//在 MCP Host 中,其实是可以注册多个 MCP Server的,//因为MCP开关已经打开,所以 下面的location 要正确"McpServerConfigs": [{"Id": "FoodServer","Name": "FoodServer","TransportType": "sse","TransportOptions": [],"Location": "http://localhost:5103/sse"}]},
3、Program.cs中添加 mcp支持
using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Messaging.JsonConverters;
using BotSharp.Abstraction.Users;
using BotSharp.Core;
using BotSharp.Core.Agents;
using BotSharp.Core.MCP;
using BotSharp.Logger;
using BotSharp.OpenAPI;
using BotSharp.Plugin.ChatHub;var builder = WebApplication.CreateBuilder(args);builder.Services.AddBotSharpCore(builder.Configuration, options =>
{options.JsonSerializerOptions.Converters.Add(new RichContentJsonConverter());options.JsonSerializerOptions.Converters.Add(new TemplateMessageJsonConverter());
}).AddBotSharpOpenAPI(builder.Configuration,
builder.Configuration.GetSection("AllowedOrigins").Get<string[]>() ?? new[]{"http://0.0.0.0:5015","https://botsharp.scisharpstack.org","https://chat.scisharpstack.org"}, builder.Environment, true).AddBotSharpLogger(builder.Configuration)// 此处需要添加mcp支持.AddBotSharpMCP(builder.Configuration);builder.Services.AddControllers();
builder.Services.AddSignalR();
var app = builder.Build();// Configure the HTTP request pipeline.
app.MapHub<SignalRHub>("/chatHub");
app.UseMiddleware<WebSocketsMiddleware>();app.UseBotSharp().UseBotSharpOpenAPI(app.Environment);//app.MapControllers();app.Run();
4、修改 agent
假设 在第一步创建 机器人时候 创建的 agent 是
bba9c6a2-5efc-428c-8b4e-95fcc9d24e3e
目录在:
MyWeatherMCPAPI\MyWeatherMcpAPI\bin\Debug\net9.0\data\agents
下,找到 agents\bba9c6a2-5efc-428c-8b4e-95fcc9d24e3e下的
agent.json 文件,打开它
{"id": "bba9c6a2-5efc-428c-8b4e-95fcc9d24e3e","name": "MyWeather AI Assistant","description": "MyWeather AI Assistant Tell You The Weather.","type": "task","createdDateTime": "2025-05-13T03:23:56.707197Z","updatedDateTime": "2025-05-13T03:23:56.7071974Z","llmConfig": {"is_inherit": false,"max_recursion_depth": 3,"provider": "sparkdesk","model": "max"},"isPublic": false,"disabled": false,"iconUrl": null,"profiles": [],"labels": [],"mergeUtility": false,"utilities": [],"mcpTools": [{"name": "FoodServer","server_id": "FoodServer","disabled": false,"functions": [{"name": "get_delicious_food"}]}],"rules": [],"knowledgeBases": [],"inheritAgentId": null,"routingRules": []
}
然后 启动 mcp host,还是通过 POST man来 调用,注意 此时可以直接 使用 SendMessage的方法了,但是注意 调整 参数 agentId 的值为 刚才的 agentid,本例为:bba9c6a2-5efc-428c-8b4e-95fcc9d24e3e
此时 如果 通过 sendMessage的方法 发送的文本 比如说:
city:桐城,那么 LLM 就会通过 参数及描述信息,决定调用tool:get_delicious_food 返回美食信息,如果 发送的文本 比如说是 天气怎样啊,那么 LLM 判断出 不需要调用 tool,就会根据 所选模型的自己的推理 进行返回,结果如图:
至此,MCP Client 和MCP Host 搭建完成 所用的LLM 是 Spark Max
五、简单集成下 BotSharp-UI
下载 BotSharp-UI:
https://github.com/SciSharp/BotSharp-UI
通过以下 命令 build:
git clone https://github.com/SciSharp/BotSharp-UI
cd BotSharp-UI
npm install
继续 run dev:
npm run dev
然后 修改下 后端地址:
注意,修改的地址 是MCP Host 的地址,也就是 LLM所在的Web API的地址。
修改后,按照 run dev 获取的地址 直接访问,
输入 用户名 密码后 (注意:此处 输入的 是在 postman 中 通过
New User Account
Get Access Token
方法 创建的 username 和 password),进入主界面,侧边栏里找到 conversation 菜单栏,直接点击,可以获取 如下界面:
至此,简单了集成了 botsharp-ui
相关文章:
【BotSharp详细介绍——一步步实现MCP+LLM的聊天问答实例】
BotSharp详细介绍——一步步实现MCPLLM的聊天问答实例 一、MCP原理介绍二、创建BotSharp的项目,实现LLM推理机器人1、新建一个 解决方案,结构如下:2、先看下 MyWeatherPlugin3、创建MyWeatherMcpAPI 三、创建 MCP Server1、添加引用2、添加工…...
[Linux性能优化] 线程卡顿优化。Linux加入USB(HID)热插拔线程占用CPU优化。Linux中CPU使用率过高优化
文章目录 [Linux性能优化] 线程卡顿优化。一、问题定位:CPU 资源分析二、线程卡顿现场复现线程优化前图片线程优化后图片 [Linux性能优化] 线程卡顿优化。 一、问题定位:CPU 资源分析 线程卡顿通常与 CPU 资源竞争、线程调度异常相关,第一步…...
鸿蒙OSUniApp 开发的文件上传与下载功能#三方框架 #Uniapp
使用 UniApp 开发的文件上传与下载功能 前言 在移动应用开发中,文件上传与下载是非常常见且重要的功能需求。无论是上传用户头像、提交表单附件,还是下载资源文件、缓存图片,这些需求几乎存在于每一个成熟的应用中。UniApp 作为一个跨平台开…...
【MySQL】基础知识
MySQL(一)基础知识 MySQL 一、结构 1.客户端 2.服务器 分布式系统 二、存储 1.空间 1.1内存 1.1.1速度 1.1.2稳定性 1.1.3大小 1.1.4使用 1.2硬盘 1.2.1速度 1.2.2稳定性 1.2.3大小 1.2.4【Java学习】反射-CSDN博客 2.体系 表-数据库-服务器 3.特点 3.1…...
产品销量数据爬虫通用模板
最近遇到各行各业的需要爬取销售数据,每次写一个教程相对麻烦,所以思前考后我还是觉得写一个通用模板更适合。所以模板需要足够的灵活性,让用户能够自定义选择器。比如,产品标题、价格、销量的CSS选择器可能因网站而异,…...
一文讲透 Vue3 + Three.js 材质属性之皮革篇【扫盲篇】
文章目录 前言一、Three.js材质系统基础1.1 为什么选择PBR材质?1.2 关键参数解析 二、不同类型皮革的材质配置2.1 牛皮材质实现2.2 羊皮材质实现2.3 仿皮材质实现 三、高级贴图技术3.1 贴图制作流程3.2 组合贴图实战 四、性能优化策略4.1 贴图压缩技术4.2 材质共享4…...
mysql读写分离
一、读写分离原理 客户端连接代理层,代理层(中间件)来实现读操作给从服务器,写操作给主服务器。 二、示例 mycat实现读写分离 读写分离在主从复制的基础上 1客户机1代理1主2从1、网络主 192.168.10.101从1 192.168.10.102从2 …...
Java集合框架
集合 概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能 和数组的区别 数组长度固定,集合长度不固定 数组可以存储基本类型和引用类型,集合只能存储引用类型 位置:java.util.* Collection体…...
salesforce如何导出所有字段
在 Salesforce 中,导出所有字段信息(包括字段名、API 名、字段类型、是否可报表、是否可搜索等)通常不是一个“一键完成”的操作,但可以通过几种方法实现。以下是常用的几种方法: ✅ 方法一:使用 Salesforc…...
一招解决Tailwindcss4.x与其他库样式冲突问题
当项目中引入tailwindcss,并与其他UI库混用时,可能会出现样式冲突问题,因为tailwindcss重置了一些基础样式,例如:引入tailwindcss后,原生button按钮没有了默认的样式。 在老版本中解决这个问题,…...
[Harmony]封装一个可视化的数据持久化工具
1.添加权限 在module.json5文件中添加权限 // 声明应用需要请求的权限列表 "requestPermissions": [{"name": "ohos.permission.DISTRIBUTED_DATASYNC", // 权限名称:分布式数据同步权限"reason": "$string:distrib…...
关于AI人工智能的知识图谱简介
人工智能是计算机科学的一个重要领域,旨在理解和构建智能行为。人工智能可以被划分为多个子领域或分支,包括机器学习、深度学习、自然语言处理(Natural Language Processing,NLP)、计算机视觉(Computer Vis…...
uniapp,小程序中实现文本“展开/收起“功能的最佳实践
文章目录 示例需求分析实现思路代码实现1. HTML结构2. 数据管理3. 展开/收起逻辑4. CSS样式 优化技巧1. 性能优化2. 防止事件冒泡3. 列表更新处理 实际效果总结 在移动端应用开发中,文本内容的"展开/收起"功能是提升用户体验的常见设计。当列表项中包含大…...
RabbitMQ 消息模式实战:从简单队列到复杂路由(一)
RabbitMQ 初相识 在当今分布式系统大行其道的技术领域中,消息队列作为实现系统间异步通信、解耦以及流量削峰的关键组件,发挥着不可或缺的作用。而 RabbitMQ,无疑是消息队列领域中一颗耀眼的明星。自 2007 年诞生以来,RabbitMQ 凭…...
阿里云ECS部署Dify
一:在ECS上面安装Docker 关防火墙 sudo systemctl stop firewalld 检查防火墙状态 systemctl status firewalld sudo yum install -y yum-utils device-mapper-persistent-data lvm2 设置阿里镜像源,安装并启动docker [base] nameCentOS-$releas…...
Missashe考研日记—Day37-Day43
Missashe考研日记—Day37-Day43 写在面前 本系列博客用于记录博主一周的学习进度,具体知识总结在目前已有的笔记中: 1.高数强化学习笔记2.计网复习笔记 本周五到周日有其他安排,所以今天就把这一周的先更新了。 专业课408 这周学了计网的…...
DB-GPT扩展自定义app配置说明
简介 文章主要介绍了如何扩展一个自定义app插件,这里先看下生成效果,生成的内容其实还是有问题的,后续博主会调整提示词看看能不能优化生成效果 修改代码 代码详情 # chat_di是从chat_normal复制过来的,这里只改了提示词 from d…...
2025年11月软考各科目难度及适合人群分析
2025上半年软考考试报名已结束,不少小伙伴已经在咨询下半年的考试科目了,今天就给大家推荐几个好考的科目。 一、2025下半年软考考试科目 2025下半年软考考试时间为11月8日至11日。 根据计考办发布的《关于2025年度计算机技术与软件专业技术资格&…...
vue异步导入
vue的异步导入 大家开发vue的时候或多或少路由的异步导入 component: () >import(“/views/A_centerControl/intelligent-control/access-user-group”),当然这是路由页面,那么组件也是可以异步导入的 使用方式 组件的异步导入非常简单,主要是一个…...
[IMX] 03.时钟树 - Clock Tree
目录 1.PLL 时钟源 2.Clock Tree 时钟树 3.ARM 内核时钟 3.1.频率设置 - CCM_ANALOG_PLL_ARMn 3.2.时钟分频 - CCM_CACRR 3.3.时钟源选择 - CCM_CCSR 3.4.修改 ARM 内核时钟 4.PFD 时钟 4.1.PLL2_PFD 频率 - CCM_ANALOG_PFD_528n 4.2.PLL3_PFD 频率 - CCM_ANALOG_PFD…...
低功耗实现方法思路总结
1.硬件选型最重要,比如stm 8l ,MSP430,瑞萨rl78,lpc11等 2.开发仿真务必使用高精度万用表如fluke 3.在整体规划层面,避免引脚未配置的浮空状态 a)在设计开发层面,对于使用的信号,使用上下拉电阻或者推挽…...
广州SMT贴片技术优势与工艺解析
内容概要 作为电子制造领域的关键技术,广州SMT贴片工艺凭借其高精度与高效性,已成为现代电子装配的核心支撑。本文通过系统性梳理表面贴装技术(SMT)的全流程,重点聚焦广州地区在该领域的独特技术优势。内容涵盖从焊膏…...
乡村地区无人机医药配送路径规划与优化仿真
本代码意在通过对无人机路径规划和载具选择进一步帮助乡村振兴,提高农村卫生条件,让患者足不出户就可享受到医疗服务,旨在完善乡村基础设施建设,积极响应国家“十四五”规划的号召。 先选择适合在该地区配送医药物资环境下的载具材…...
AWS Elastic Beanstalk部署极简Spring工程(EB CLI失败版)
弃用 这里我没有走通EB CLI方式部署。 问题 最近又加入了AWS项目组,又要再次在AWS云上面部署Spring服务,我这里使用的使用AWS中国云。需要使用AWS Elastic Beanstalk部署一个极简Spring工程。 EB CLI安装 安装EB CLI之前需要先在本地安装好Git&…...
[训练和优化] 3. 模型优化
👋 你好!这里有实用干货与深度分享✨✨ 若有帮助,欢迎: 👍 点赞 | ⭐ 收藏 | 💬 评论 | ➕ 关注 ,解锁更多精彩! 📁 收藏专栏即可第一时间获取最新推送🔔…...
element-ui的el-cascader增加全选按钮实现(附源码)
最近遇到了在级联选择器上添加全选框的需求 ,但是项目使用的是Vue2 Element UI的架构,而我们都知道Element UI提供的级联选择器el-cascader是不支持全选框的,而我又没有在网上找到适合我项目的实现,索性自己实现一个组件…...
OpenCV人脸识别EigenFace算法、案例解析
文章目录 前言一、EigenFace 核心原理二、Python 实战:手把手搭建 EigenFace 识别系统1. 环境准备2. 代码实现与步骤详解3. 加载数据集函数4. 训练EigenFace模型函数5. 预测函数6.主程序部分7. 可视化结果8. 代码分步解读 三、优化技巧四、总结 前言 在人脸识别领域…...
Python模块化编程
Python模块化编程 记得我刚学Python那会儿,特别喜欢把所有代码都写在一个文件里。直到有一天,我的项目膨胀到了2000多行代码,每次修改都要翻半天…这才痛定思痛,开始研究模块化编程。今天就跟大家聊聊这个让代码变得优雅的魔法。…...
Java对象的GC回收年龄的研究
目录 1、介绍 2、内存结构 2.1、普通对象 2.2、数组对象 2.3、数组长度作用 2.4、为什么 age 用 4 位? 3、对象头组成 3.1、Mark Word(标记字段) 3.2、Class Pointer(类指针) 4、GC 发生的位置 4.1、新生代…...
IT系统的基础设施:流量治理、服务治理、资源治理,还有数据治理。
文章目录 引言I IT系统的基础设施流量治理、服务治理、资源治理,还有数据治理。开发语言的选择数据治理(监控系统):整体运维的数据其他II 基础知识的重要性第一,知道原理第二,当遇到一些比较难解的问题时,基础知识就会派上用场。例子III 快速学会一门编程语言把语言照着…...
SpringBoot应用启动过程
Spring 应用抽象 Springboot 是一个用来快速创建 Spring 应用的微服务框架,启动引导器是org.springframework.boot.SpringApplication 这个类,每个 SpringApplication 实例就表示一个 Spring 应用的启动类;Spring 应用生命周期包括创建、启动…...
傻子学编程之——Java并发编程的问题与挑战
傻子学编程之——Java并发编程的问题与挑战 Java并发编程能让程序跑得更快,但也像走钢丝一样充满风险。本文用最直白的语言和代码示例,带你直面并发编程的四大「致命陷阱」,并给出解决方案。 一、资源竞争:多个线程打架怎么办&am…...
groovy 如何遍历 postgresql 所有的用户表 ?
在 Groovy 中遍历 PostgreSQL 所有用户表,你可以使用 JDBC 连接数据库并执行 SQL 查询。以下是一个完整的示例: Groovy 代码示例 import groovy.sql.Sqldef config [url: jdbc:postgresql://localhost:5432/your_database,user: your_username,passwo…...
CPU cache基本原理
CPU cache基本原理 存储器层次结构存储器层次结构中的缓存高速缓存存储器直接映射高速缓存组相联高速缓存全相联高速缓存 多核 CPU 下缓存问题内存的读写操作流程数据一致性与并发控制 高速缓存(cache)是一个小而快速地存储设备,它作为存储在…...
【Java学习笔记】【第一阶段项目实践】零钱通(面向过程版本)
零钱通(面向过程版本) 需求分析 1. 需要实现的功能 (1) 收益入账 (2) 消费 (3 )查看明细 (4 )退出系统 2. 代码优化部分 (1) 对用户输入 4 退出时,给出提示 “你确定要退出吗?y/n”,必须输入正确的 y/n,…...
Cursor无法使用C/C++调试的解决办法
背景 这几天在二开ffmpeg,发现用cursor无法使用cppdbg进行调试,只能上机gdb,比较麻烦。 配置文件 // launch.json {// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// Fo…...
VSTO(C#)Excel开发进阶2:操作图片 改变大小 滚动到可视区
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。 源码指引:github源码指引_初级代码游戏的博客-CSDN博客 入…...
嵌入式自学第二十二天(5.15)
顺序表和链表 优缺点 存储方式: 顺序表是一段连续的存储单元 链表是逻辑结构连续物理结构(在内存中的表现形式)不连续 时间性能, 查找顺序表O(1):下标直接查找 链表 O(n):从头指针往后遍历才能找到 插入和…...
高云FPGA-新增输出管脚约束
module led (input sys_clk, // clk inputinput sys_rst_n, // reset inputoutput reg [5:0] led, // 6 LEDS pinoutput reg gpio // 1 GPIO pin 25 ); 在原来的代码基础上新增加一个gpio输出,绑定到25管脚上 打开工程文件夹中的cts文件…...
Nginx 返回 504 状态码表示 网关超时(Gateway Timeout)原因排查
Nginx 返回 504 状态码表示 网关超时(Gateway Timeout),这意味着 Nginx 作为反向代理服务器,在等待上游服务器(如后端应用服务器、数据库服务器等)响应时,超过了预设的时间限制,最终…...
单片机 | 基于STM32的智能马桶设计
基于STM32的智能马桶设计结合了传感器技术、嵌入式控制及物联网功能,旨在提升用户体验并实现健康监测。以下是其设计原理、功能模块及代码框架的详细解析: 一、系统架构与核心功能 智能马桶的系统架构通常分为主控模块、传感器模块、执行器模块、通信模块及用户交互模块,主…...
2900. 最长相邻不相等子序列 I
2900. 最长相邻不相等子序列 I class Solution:def getLongestSubsequence(self, words: List[str], groups: List[int]) -> List[str]:n len(groups) # 获取 groups 列表的长度ans [] # 初始化一个空列表,用于存储结果for i, g in enumerate(groups): # 遍…...
欧姆龙 CJ/CP 系列 PLC 串口转网口模块:工业通信升级的智能之选
在工业自动化领域,欧姆龙 CJ/CP 系列 PLC 凭借高可靠性和灵活扩展性,广泛应用于汽车制造、食品加工、能源化工等关键行业。然而,传统串口通信的局限性(如距离受限、协议兼容性差、难以实现远程监控)却成为企业智能化升…...
BGP选路实验
一.需求 1.使用PreVal策略,确保R4通过R2到达192.168.10.0/24 2.使用As_Path策略,确保R4通过R3到达192.168.11.0/24 3.配置MED策略,确保R4通过R3到达192.168.12.0/24 4.使用Local Preference策略,确保R1通过R2到达192.168.1.0/2…...
Linux服务之lvs+keepalived nginx+keepalived负载均衡实例解析
目录 一.LVSKeepAlived高可用负载均衡集群的部署 二.NginxKeepAlived高可用负载均衡集群的部署 一.LVSKeepAlived高可用负载均衡集群的部署 实验环境 主keepalived:192.168.181.10 lvs (7-1) 备keepalived:192.168.181.10…...
idea整合maven环境配置
idea整合maven 提示:帮帮志会陆续更新非常多的IT技术知识,希望分享的内容对您有用。本章分享的是springboot的使用。前后每一小节的内容是存在的有:学习and理解的关联性。【帮帮志系列文章】:每个知识点,都是写出代码…...
pytest框架 - 第二集 allure报告
一、断言assert 二、Pytest 结合 allure-pytest 插件生成美观的 Allure 报告 (1) 安装 allure 环境 安装 allure-pytest 插件:pip install allure-pytest在 github 下载 allure 报告文件 地址:Releases allure-framework/allure2 GitHub下载&#x…...
互联网大厂Java求职面试:构建高并发直播平台的架构设计与优化
标题:互联网大厂Java求职面试:构建高并发直播平台的架构设计与优化 引言 在互联网大厂的Java求职面试中,技术总监级别的面试官通常会提出一系列复杂且前沿的技术问题,以评估候选人的真实技术水平。本篇文章将围绕构建一个千万级…...
Ruby 循环与迭代器
Ruby 循环与迭代器 循环迭代器timesuptostep 循环 。。。。 迭代器 迭代器本质上可以理解为是循环的一种类型 times 3.times do print "Ho! " end begin Ho! Ho! Ho! end上述代码表示我们对当前 block 部分中的内容循环三次。最终,我们打印出了三个…...
pyenv简单的Python版本管理器(macOS版)
问题 python版本是真的多,需要用一个版本管理器管理Python多版本安装在同一台机器的问题。接下来,我们就尝试使用pyenv来管理。 安装pyenv brew update brew install pyenv配置Zsh echo export PYENV_ROOT"$HOME/.pyenv" >> ~/.zshr…...