ET实现游戏中聊天系统逻辑思路(服务端)

news2024/11/24 3:08:19

目录

一、准备工作

1.1 前言

1.2 完善聊天服务器

1.3 自定义聊天服消息

二、玩家登录聊天服 

2.1 Gate网关与聊天服通讯

2.2 保存玩家实体映射实例ID

三、处理聊天逻辑

3.1 发送聊天消息的定义

3.2 定义聊天记录组件 

3.3 编写发送聊天消息处理类

ET是一个游戏框架,用的编程语言是C#,游戏引擎是Unity,框架作者:熊猫  ET社区

聊天系统在各种网络游戏中也是必备的功能,我们可以通过系统进行世界聊天、私聊、发红包、组队等功能,实现游戏的社交属性。


(网上找的聊天框图片)

下面我将以我的开发经验记录用ET框架实现聊天系统的过程,有不足之处欢迎大家评论区讨论。

一、准备工作

1.1 前言

前几篇文章里实现的功能(商城、邮件)都是在Map服务器中实现的,我们实现聊天功能要单独起一个聊天服务器ChatInfo,来建立玩家实体映射来实现聊天消息的通讯。

下面这篇文章介绍的是ET框架单独起服务器的流程:

ET框架新起一个服务及实现服务之间的消息通讯_et startsceneconfig-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_48512649/article/details/136732262

按照流程新起一个聊天服务器ChatInfo


1.2 完善聊天服务器

创建组件ChatInfoUnitsComponent用来管理所有玩家映射实体,并把此组件挂载到聊天服中

namespace ET.Server
{
    [ComponentOf(typeof(Scene))]
    public class ChatInfoUnitsComponent : Entity,IAwake,IDestroy
    {
        public Dictionary<long, ChatInfoUnit> ChatInfoUnitsDict = new Dictionary<long, ChatInfoUnit>();
    }
}

ChatInfoUnit用来保存玩家在聊天服中的基本信息,(每个玩家对应一个ChatInfoUnit

namespace ET.Server
{
    [ChildOf(typeof(ChatInfoUnitsComponent))]

    public class ChatInfoUnit : Entity,IAwake,IDestroy
    {
        public long GateSessionActorId;

        public string Name;  //姓名

        public long UnitId;  
        
        public int Gender;  //性别
        
        public int Level;   //等级

        public int HeadImg;  //头像

        //私聊信息
        public Dictionary<long, List<PrivateTalk>> PrivateTalkInfo = new Dictionary<long, List<PrivateTalk>>();
        
        public int AreaId = 1;  //地区

        public int ServerId = 2;  //服务器ID

        public int Online = 0;    //是否在线
    }
}

1.3 自定义聊天服消息

ET框架网络通讯消息_et mongohelper.deserialize-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_48512649/article/details/134028530

聊天服中发送和接收消息我们进行自定义,用来针对玩家级别的消息转发

namespace ET
{
    // 不需要返回消息
    public interface IActorChatInfoMessage: IActorMessage
    {
    }

    public interface IActorChatInfoRequest: IActorRequest
    {
    }

    public interface IActorChatInfoResponse: IActorResponse
    {
    }
}

NetServerComponentOnReadEvent中判断,

如果消息类型是IActorChatInfoRequestIActorChatInfoMessage则进行处理

其中player.ChatInfoInstanceId会在2.2中讲解是如何保存的

 case IActorChatInfoRequest actorChatInfoRequest:
 {
      Player player = session.GetComponent<SessionPlayerComponent>().Player;
      if (player == null || player.IsDisposed || player.ChatInfoInstanceId == 0)
      {
             break;
      }
                
      int rpcId          = actorChatInfoRequest.RpcId; // 这里要保存客户端的rpcId
      long instanceId    = session.InstanceId;
      IResponse iresponse = await ActorMessageSenderComponent.Instance.Call(player.ChatInfoInstanceId, actorChatInfoRequest);
      iresponse.RpcId     = rpcId;
      // session可能已经断开了,所以这里需要判断
      if (session.InstanceId == instanceId)
      {
           session.Send(iresponse);
      }
      break;
  }
  case IActorChatInfoMessage actorChatInfoMessage:
  {
       Player player = session.GetComponent<SessionPlayerComponent>().Player;
       if (player == null || player.IsDisposed || player.ChatInfoInstanceId == 0)
       {
           break;
       }
                    
       ActorMessageSenderComponent.Instance.Send(player.ChatInfoInstanceId, actorChatInfoMessage);
           break;
  }            

二、玩家登录聊天服 

在玩家登录游戏的流程中会发送这样一条消息

G2C_EnterGame g2CEnterGame = (G2C_EnterGame)await gateSession.Call(new C2G_EnterGame() { });

在这个消息的处理类中要做的事:

  • 从数据库或缓存中加载出玩家Unit实体及其相关组件
  • 玩家Unit上线后的初始化操作
  • 玩家登录聊天服

我们重点看C2G_EnterGameHandler中玩家登录聊天服的实现

玩家登录聊天服的过程其实就是在聊天服生成玩家实体映射信息、获取并保存玩家实体映射信息的实例Id,有了实例Id后就可以与聊天服进行玩家级别的消息通讯了

2.1 Gate网关与聊天服通讯

private async ETTask<long> EnterWorldChatServer(Unit unit,int guildId)
{
   UserCacheProto1 ucp = UnitHelper.GetUserCacheForChat(unit,guildId);

   //读取配置表获取聊天服配置信息
   StartSceneConfig startSceneConfig = StartSceneConfigCategory.Instance.GetBySceneName(unit.DomainZone(), "ChatInfo");

   //网关服发送消息登录聊天服
   Chat2G_EnterChat chat2GEnterChat = (Chat2G_EnterChat)await ActorMessageSenderComponent.Instance.Call(startSceneConfig.InstanceId, new G2Chat_EnterChat()
   {
                
      UserInfo = ucp,
                
      GateSessionActorId = unit.GetComponent<UnitGateComponent>().GateSessionActorId
    });
            
      return chat2GEnterChat.ChatInfoUnitInstanceId;
}

网关服和聊天服通讯属于内部消息,所以Chat2G_EnterChat消息定义在InnerMessage.proto

//ResponseType Chat2G_EnterChat
message G2Chat_EnterChat // IActorRequest
{
    int32 RpcId = 90;
	int64 GateSessionActorId = 1;
	UserCacheProto1 UserInfo = 1;
}

message Chat2G_EnterChat // IActorResponse
{
    int32 RpcId = 90;
    int32 Error = 91;
    string Message = 92;
	int64 ChatInfoUnitInstanceId = 1;
}


//UserCacheProto1 用于玩家信息聊天传输的载体
//UserCacheProto1 定义在OuterMessage.proto中
message UserCacheProto1
{
	string Name = 1;
	int32 Gender = 2;
	int32 Level = 3;
	int32 HeadImg = 4;
	int64 UnitId = 5;
}

消息处理类

namespace ET.Server
{
    [ActorMessageHandler(SceneType.ChatInfo)]
    [FriendOf(typeof(ChatInfoUnit))]
    public class G2Chat_EnterChatHandler : AMActorRpcHandler<Scene, G2Chat_EnterChat, Chat2G_EnterChat>
    {
        protected override async ETTask Run(Scene scene, G2Chat_EnterChat request, Chat2G_EnterChat response)
        {
            //获取管理所有玩家映射实体的组件
            ChatInfoUnitsComponent chatInfoUnitsComponent = scene.GetComponent<ChatInfoUnitsComponent>();

            //获得具体的玩家映射信息
            ChatInfoUnit chatInfoUnit = chatInfoUnitsComponent.Get(request.UserInfo.UnitId);
            int flag = 0;
            if ( chatInfoUnit == null )
            { 
                chatInfoUnit  = chatInfoUnitsComponent.AddChildWithId<ChatInfoUnit>(request.UserInfo.UnitId);
                //挂载邮箱组件才会有消息处理能力(玩家级别的消息处理)
                chatInfoUnit.AddComponent<MailBoxComponent>();
                flag = 1;
            }

            chatInfoUnit.Logon(request.UserInfo, request.GateSessionActorId);
            
            if (flag == 1)
            {
                chatInfoUnitsComponent.Add(chatInfoUnit);
            }
            response.ChatInfoUnitInstanceId = chatInfoUnit.InstanceId;
            await ETTask.CompletedTask;
        }
    }
}

管理所有玩家映射实体ChatInfoUnitsComponent组件的具体行为:ChatInfoUnitsComponentSystem

using System.Collections.Generic;

namespace ET.Server
{
    public class ChatInfoUnitsComponentDestroy : DestroySystem<ChatInfoUnitsComponent>
    {
        protected override void Destroy(ChatInfoUnitsComponent self)
        {
            foreach (var chatInfoUnit in self.ChatInfoUnitsDict.Values)
            {
                chatInfoUnit?.Dispose();
            }
        }
    }
    
    [FriendOf(typeof(ChatInfoUnit))]
    [FriendOf(typeof(ChatInfoUnitsComponent))]
    [FriendOf(typeof(UserCacheInfo))]
    public static class ChatInfoUnitsComponentSystem
    {
        //从数据库中加载玩家的相关聊天信息
        public static async ETTask LoadInfo(this ChatInfoUnitsComponent self)
        {
            var userCacheList = await  DBManagerComponent.Instance.GetZoneDB(self.DomainZone()).Query<UserCacheInfo>(d => true,collection:"UserCachesComponent");
            foreach ( UserCacheInfo userCache in userCacheList )
            {
                ChatInfoUnit chatInfoUnit = self.AddChildWithId<ChatInfoUnit>(userCache.UnitId);
                chatInfoUnit.AddComponent<MailBoxComponent>();
                chatInfoUnit.Name               = userCache.Name;
                chatInfoUnit.GateSessionActorId = 0;
                chatInfoUnit.UnitId = userCache.UnitId;
                chatInfoUnit.Gender = userCache.Gender;
                chatInfoUnit.Level = userCache.Level;
                chatInfoUnit.HeadImg = userCache.HeadImg;
                chatInfoUnit.TitleImg = userCache.TitleImg;
                chatInfoUnit.Online = 0;
                self.ChatInfoUnitsDict.Add(userCache.UnitId,chatInfoUnit);
            }
        }
        
        //将玩家实体映射信息添加到组件中
        public static void Add(this ChatInfoUnitsComponent self, ChatInfoUnit chatInfoUnit)
        {
            if (self.ChatInfoUnitsDict.ContainsKey(chatInfoUnit.Id))
            {
                return;
            }
            self.ChatInfoUnitsDict.Add(chatInfoUnit.Id, chatInfoUnit);
        }

        //尝试从组件中获取玩家实体映射信息
        public static ChatInfoUnit Get(this ChatInfoUnitsComponent self, long id)
        {
            self.ChatInfoUnitsDict.TryGetValue(id, out ChatInfoUnit chatInfoUnit);
            return chatInfoUnit;
        }

        //移除玩家实体映射信息
        public static void Remove(this ChatInfoUnitsComponent self, long id)
        {
            if (self.ChatInfoUnitsDict.TryGetValue(id, out ChatInfoUnit chatInfoUnit))
            {
                self.ChatInfoUnitsDict.Remove(id);
                chatInfoUnit?.Dispose();
            }
        }
        
        public static void Leave(this ChatInfoUnitsComponent self, long id)
        {
            if (self.ChatInfoUnitsDict.TryGetValue(id, out ChatInfoUnit chatInfoUnit))
            {
                self.Get(id).Leave();
                //chatInfoUnit?.Dispose();
            }
        }
        

        public static List<ChatInfoForList> GetChatInfo(this ChatInfoUnitsComponent self,int type, int index)
        {
            List<ChatInfoForList> cil = new List<ChatInfoForList>();

            return cil;
        }
    }
}

2.2 保存玩家实体映射实例ID

经过Gate网关发送了G2Chat_EnterChat消息,我们可以看到把聊天服中玩家实体映射实例ID返回回来了。


玩家新增字段ChatInfoInstanceId用于保存聊天服玩家实体映射实例ID信息

 在C2G_EnterGameHandler这一消息处理类中进行保存:

player.ChatInfoInstanceId = await this.EnterWorldChatServer(unit,gi.GuildId); //登录聊天服

保存好ChatInfoInstanceId后我们就可以使用自定义聊天服消息进行通讯了。

三、处理聊天逻辑

 前边工作都做好后我们开始实现聊天相关的逻辑。

3.1 发送聊天消息的定义

我们都知道,当我们聊天的时候在输入框输入内容,点击发送,我们输入的内容就会出现在聊天框中,当别人发送消息时我们也会看到聊天框新弹出消息内容。


聊天过程:客户端 ——》聊天服,外部消息所以定义到OutMessage.proto

//ResponseType Chat2C_SendChatInfo
message C2Chat_SendChatInfo // IActorChatInfoRequest
{
	int32 RpcId         = 1;
	int32 ChatType = 2;   //聊天类型
	string Text = 3;     //聊天内容
	int64 UnitId = 4;   //玩家ID
}

message Chat2C_SendChatInfo // IActorChatInfoResponse
{
	int32 RpcId    = 90;
	int32 Error    = 91;
	string Message = 92;
}

message ChatInfoForList
{
	UserCacheProto1 UserInfo = 1;  //玩家实体映射信息
	ChatMessage2 ChatMessage = 2;  //封装的聊天信息
}

message ChatMessage2
{
	int32 ChatType = 1;      //聊天类型
	string Text = 2;         //聊天内容
	int64 Timestamp = 3;     //发送时间
}

3.2 定义聊天记录组件 

namespace ET.Server
{
    [ComponentOf(typeof(Scene))]
    public class ChatInfoListsComponent : Entity,IAwake,IDestroy,IDeserialize,ITransfer,IUnitCache
    {
        [BsonIgnore]
        public Dictionary<long, ChatInfoList> ChatInfoListsDict = new Dictionary<long, ChatInfoList>();
    }
}
namespace ET.Server
{
    [ChildOf(typeof(ChatInfoListsComponent))]
    public class ChatInfoList: Entity,IAwake,IDestroy
    {
        public int Type = 0;

        [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
        public Dictionary<long, ChatInfoForList> ChatInfos= new Dictionary<long, ChatInfoForList>();
    }
}

 3.3 编写发送聊天消息处理类

namespace ET.Server
{
    [FriendOf(typeof(ChatInfoUnitsComponent))]
    [FriendOf(typeof(ChatInfoListsComponent))]
    [FriendOf(typeof(ChatInfoUnit))]
    [FriendOf(typeof(ChatInfoList))]
    [ActorMessageHandler(SceneType.ChatInfo)]
    public class C2Chat_SendChatInfoHandler : AMActorRpcHandler<ChatInfoUnit, C2Chat_SendChatInfo, Chat2C_SendChatInfo>
    {
        protected override async ETTask Run(ChatInfoUnit chatInfoUnit, C2Chat_SendChatInfo request, Chat2C_SendChatInfo response)
        {

            //如果聊天内容为空直接return
            if (string.IsNullOrEmpty(request.Text))
            {
                response.Error = ErrorCode.ERR_ChatMessageEmpty;
                return;
            }

            if (request.ChatType == 4)
            {
                response.Error = 99999999;
                return;
            }
            
            //私聊
            ChatInfoUnitsComponent chatInfoUnitsComponent = chatInfoUnit.DomainScene().GetComponent<ChatInfoUnitsComponent>();
            if (request.ChatType == 5)
            {
                PrivateTalk pt = new PrivateTalk();
                pt.UnitId = chatInfoUnit.UnitId;
                pt.Text = request.Text;
                pt.TimeStamp = TimeHelper.ClientNow();
                chatInfoUnit.PrivateTalks(pt,request.UnitId);
                otherChatInfoUnit.PrivateTalks(pt,chatInfoUnit.UnitId);
            }
            //世界聊天
            else
            {
                ChatInfoListsComponent chatInfoListsComponent = chatInfoUnit.DomainScene().GetComponent<ChatInfoListsComponent>();
                UserCacheProto1 ucp = chatInfoUnit.ToMessage();
                ChatMessage2 cm = new ChatMessage2()
                {
                    ChatType = request.ChatType,
                    ChatDesType = request.ChatDesType,
                    Text = request.Text,
                    Timestamp = TimeHelper.ClientNow()
                };
                
                chatInfoListsComponent.Send(request.ChatType,ucp, cm,chatInfoUnitsComponent.ChatInfoUnitsDict,chatInfoUnit);
            }
           
            
            await ETTask.CompletedTask;
        }
    }
}

ChatInfoUnitSystem处理私聊信息 

public static void PrivateTalks(this ChatInfoUnit self, PrivateTalk pt, long UnitId)
{
    self.PrivateTalkInfo[UnitId].Add(pt);
    if (self.GateSessionActorId > 0 && self.Online == 1)
    {
        ActorMessageSenderComponent.Instance.Send(self.GateSessionActorId, new Chat2C_NoticeChatInfo()
         {
              UserInfo  = self.GetParent<ChatInfoUnitsComponent>().ChatInfoUnitsDict[pt.UnitId].ToMessage(), 
               ChatMessage = new  ChatMessage2(){ChatType= 5,ChatDesType=pt.ChatDesType,Text = pt.Text,Timestamp = pt.TimeStamp},
          });
     }
            
}

ChatInfoListsComponentSystem处理世界聊天信息

public static void Send(this ChatInfoListsComponent self, int type , UserCacheProto1 ucp,ChatMessage2 cm , Dictionary<long, ChatInfoUnit> ChatInfoUnitsDict, ChatInfoUnit chatInfoUnit)
{
     ChatInfoList cil = self.ChatInfoListsDict[id];
     foreach (var otherUnit in ChatInfoUnitsDict)
     {
       ActorMessageSenderComponent.Instance.Send(otherUnit.Value.GateSessionActorId, new Chat2C_NoticeChatInfo()
        {
             UserInfo =ucp, 
             ChatMessage =cm,
        });
      }
}

Chat2C_NoticeChatInfo是服务器发送给客户端的一次性消息,由客户端来处理并展示聊天信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1986626.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux--shell脚本语言—/—终章

一、shell函数 1、shell函数定义格式 参数说明&#xff1a; 1、可以带function fun() 定义&#xff0c;也可以直接fun() 定义,不带任何参数。 2、参数返回&#xff0c;可以显示加&#xff1a;return 返回&#xff0c;如果不加&#xff0c;将以最后一条命令运行结果&#xff…

(20)SSM-MyBatis关系映射

MyBatis关联映射 概述 在实际开发的工程中&#xff0c;经常对出现多表操作&#xff0c;如果常见的根据某条数据的ID去检索数据&#xff08;根据用户查询订单信息&#xff09;&#xff0c;这个时候我们数据库设计的时候就需要使用外键进行关联&#xff0c;那么mybatis在操作这…

推荐4款2024年热门的win10 录屏软件。

如果只是偶尔需要简单地录制一下电脑屏幕&#xff0c;一般大家都会选免费且操作简单的软件&#xff1b;但如果是专业的视频制作&#xff0c;就需要功能强大、支持后期编辑的软件。而下面的这4款软件却能满足以上两种需求&#xff0c;并且能够兼容的系统也很多。 1、福昕专业录屏…

如何提升你的广告创意?

当你有一个好的产品时&#xff0c;你一定会想到用广告投放来推广它。但简单的广告投放是不足以帮助你建立起品牌知名度的。要从众多产品中脱颖而出&#xff0c;还需要独特又有效的广告创意。以下是尤里改为你总结的提升广告创意的办法&#xff0c;电子商务品牌可以着重了解下~ …

没有软件测试经验的计算机毕业生如何准备面试测试工程师这一职位?

古语云&#xff1a;“知己知彼&#xff0c;百战不殆”。 想应聘测试工程师&#xff0c;首先要知道企业需要什么样的测试工程师&#xff0c;需要具备哪些技术。想知道这点并不难&#xff0c;并且有捷径可走&#xff0c;直接去招聘网站中找答案&#xff0c;看各公司的招聘简章即…

opencascade TopoDS、TopoDS_Vertex、TopoDS_Edge、TopoDS_Wire、源码学习

前言 opencascade TopoDS转TopoDS_Vertex opencascade TopoDS转TopoDS_Edge opencascade TopoDS转TopoDS_Wire opencascade TopoDS转TopoDS_Face opencascade TopoDS转TopoDS_Shell opencascade TopoDS转TopoDS_Solid opencascade TopoDS转TopoDS_Compound 提供方法将 TopoDS_…

Pytorch损失函数-torch.nn.NLLLoss()

一、简介 1.1 nn.CrossEntropyLoss 交叉熵损失函数的定义如下&#xff1a; 就是我们预测的概率的对数与标签的乘积&#xff0c;当qk->1的时候&#xff0c;它的损失接近零。 1.2 nn.NLLLoss 官方文档中介绍称&#xff1a; nn.NLLLoss输入是一个对数概率向量和一个目标标…

进阶学习------线程等待

什么是线程等待 线程等待是指在一个多线程程序中&#xff0c;一个线程在继续执行之前需要等待另一个线程完成特定任务或达到某个状态的行为。在编程中&#xff0c;线程等待是一种同步机制&#xff0c;用于协调不同线程之间的执行顺序&#xff0c;确保数据的一致性和避免竞态条…

鸿蒙AI功能开发【拍照识别文字】

拍照识别文字 介绍 本示例通过使用ohos.multimedia.camera (相机管理)和textRecognition&#xff08;文字识别&#xff09;接口来实现识别提取照片内文字的功能。 效果预览 使用说明 1.点击界面下方圆形文字识别图标&#xff0c;弹出文字识别结果信息界面&#xff0c;显示当…

学习大数据DAY32 HTML基础语法和Flask库的使用

目录 HTML 超文本标记语言 Hyper Text Markup Language 上机练习 9 Flask 显示层 UI 前后端结合动态加载列表数据 flask 在 html 中的语法 上机练习 10 HTML 超文本标记语言 Hyper Text Markup Language 1.<html></html>: 根标签 2.<head></head&…

贝塞尔曲线参数方程推导

1.贝塞尔曲线简介 1.1什么是贝塞尔曲线 贝塞尔曲线于 1962 年&#xff0c;由法国工程师皮埃尔贝济埃&#xff08;Pierre Bzier&#xff09;所广泛发表&#xff0c;他运用贝塞尔曲线来为汽车的主体进行设计。 贝塞尔曲线主要用于二维图形应用程序中的数学曲线&#xff0c;曲线…

opencascade TopoDS_Builder 源码学习

opencascade TopoDS_Builder 前言 构建器&#xff08;Builder&#xff09;用于创建拓扑数据结构。它是构建器类层次结构的根。 构建器中包含三组方法&#xff1a; Make 方法用于创建形状&#xff08;Shapes&#xff09;。Add 方法用于将一个形状包含到另一个形状中。Remove…

访问网站显示不安全怎么办?

访问网站时显示“不安全”&#xff0c;针对不同的原因有不同的解决方式&#xff0c;下面是常见的几种原因和对应的解决办法。 1.未启用HTTPS协议 如果网站仅使用HTTP协议&#xff0c;数据传输没加密&#xff0c;因此会被浏览器标记为“不安全”。解决办法是启用HTTPS协议,给…

可观察性与人工智能的结合:解锁数据收集、分析和预测的新领域

随着软件系统变得越来越复杂&#xff0c;可观察性&#xff08;根据系统外部输出了解系统内部状态的能力&#xff09;已成为开发人员和运营团队的一项关键实践。 传统的可观测性方法难以跟上现代应用的规模和复杂性。随着遥测数据量的增加&#xff0c;导航变得成本高昂且复杂。…

【计算机组成原理】各种周期与字长的概念辨析

前言 在计算机组成原理中&#xff0c;我们会在做题时遇到各种周期与字长的概念辨析题&#xff08;非常重要&#xff09;&#xff0c;因此我们再次统一做一个梳理&#xff0c;帮助大家在理解的基础上进行记忆&#xff0c;并附上几道好题辅助理解。 概念讲解 指令周期&#xff…

【轻松掌握】使用Spring-AI轻松访问大模型本地化部署并搭建UI界面访问指南

文章目录 读前必看什么是Spring-AI目前已支持的对接模型本文使用Spring-AI版本构建项目选择必要的依赖配置系统变量 聊天模型API配置文件方式1-使用默认配置方式2-自定义配置配置其他参数使用示例 图像模型API配置文件方式1-使用默认配置方式2-自定义配置配置其他参数使用示例 …

N5 - 使用Gensim库训练word2vec模型

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目录 环境步骤分词训练word2vec模型模型应用计算词汇间的相似度找出不匹配的词汇计算词汇的词频 总结与心得体会 环境 安装gensim和jieba库 pip install gen…

mysql实现MHA

一、什么是MHA 高可用模式下的故障切换&#xff0c;基于主从复制&#xff0c;单点故障和主从复制不能切换的问题&#xff0c;架构需要奇数台&#xff0c;至少需要3台&#xff0c;故障切换过程0-30秒&#xff0c;vip地址&#xff0c;根据vip地址所在的主机&#xff0c;确定主备…

全网最最实用--边缘智能的常见微调方式以及适用场景

文章目录 1. BitFit2. Adapter3. Prompt-Tuning4. Prefix-Tuning5. LoRA (Low-Rank Adaptation)6. QLoRA (Quantized Low-Rank Adaptation)7. LongLoRA总结 1. BitFit https://arxiv.org/abs/2106.10199 主要做法&#xff1a; BitFit&#xff08;Bias Term Fine-Tuning&#…

日撸Java三百行(day15:栈的应用之括号匹配)

目录 一、栈的括号匹配 二、代码实现 1.方法创建 2.数据测试 3.完整的程序代码 总结 一、栈的括号匹配 要完成今天的任务&#xff0c;需要先来了解一下什么是栈的括号匹配。首先&#xff0c;顾名思义&#xff0c;括号匹配就是指将一对括号匹配起来&#xff0c;我们给定一…