GLM4大模型微调入门实战-命名实体识别(NER)任务

[GLM4]是清华智谱团队最近开源的大语言模型。

以GLM4作为基座大模型,通过指令微调的方式做高精度的命名实体识别(NER),是学习入门LLM微调、建立大模型认知的非常好的任务。

在这里插入图片描述

显存要求相对较高,需要40GB左右。

知识点1:什么是指令微调?

大模型指令微调(Instruction Tuning)是一种针对大型预训练语言模型的微调技术,其核心目的是增强模型理解和执行特定指令的能力,使模型能够根据用户提供的自然语言指令准确、恰当地生成相应的输出或执行相关任务。

指令微调特别关注于提升模型在遵循指令方面的一致性和准确性,从而拓宽模型在各种应用场景中的泛化能力和实用性。

在实际应用中,我的理解是,指令微调更多把LLM看作一个更智能、更强大的传统NLP模型(比如Bert),来实现更高精度的NLP任务。所以这类任务的应用场景覆盖了以往NLP模型的场景,甚至很多团队拿它来标注互联网数据

知识点2:什么是命名实体识别?

命名实体识别 (NER) 是一种NLP技术,主要用于识别和分类文本中提到的重要信息(关键词)。这些实体可以是人名、地名、机构名、日期、时间、货币值等等。 NER 的目标是将文本中的非结构化信息转换为结构化信息,以便计算机能够更容易地理解和处理。

在这里插入图片描述

NER 也是一项非常实用的技术,包括在互联网数据标注、搜索引擎、推荐系统、知识图谱、医疗保健等诸多领域有广泛应用。

1.环境安装

本案例基于Python>=3.8,请在您的计算机上安装好Python,并且有一张英伟达显卡(显存要求并不高,大概10GB左右就可以跑)。

我们需要安装以下这几个Python库,在这之前,请确保你的环境内已安装好了pytorch以及CUDA

swanlab
modelscope
transformers
datasets
peft
accelerate
pandas
tiktoken

一键安装命令:

pip install swanlab modelscope transformers datasets peft pandas accelerate tiktoken

本案例测试于modelscope1.14.0、transformers4.41.2、datasets2.18.0、peft0.11.1、accelerate0.30.1、swanlab0.3.11、tiktoken==0.7.0

2.准备数据集

本案例使用的是HuggingFace上的[chinese_ner_sft]数据集,该数据集主要被用于训练命名实体识别模型。

在这里插入图片描述

chinese_ner_sft由不同来源、不同类型的几十万条数据组成,应该是我见过收录最齐全的中文NER数据集。

这次训练我们不需要用到它的全部数据,只取其中的CCFBDCI数据集(中文命名实体识别算法鲁棒性评测数据集)进行训练,该数据集包含LOC(地点)、GPE(地理)、ORG(组织)和PER(人名)四种实体类型标注,每条数据的例子如下:

{"text": "今天亚太经合组织第十二届部长级会议在这里开幕,中国外交部部长唐家璇、外经贸部部长石广生出席了会议。","entities": [{"start_idx": 23,"end_idx": 25,"entity_text": "中国","entity_label": "GPE","entity_names": ["地缘政治实体", "政治实体", "地理实体", "社会实体"]},{"start_idx": 25,"end_idx": 28,"entity_text": "外交部","entity_label": "ORG","entity_names": ["组织", "团体", "机构"]},{"start_idx": 30,"end_idx": 33,"entity_text": "唐家璇","entity_label": "PER","entity_names": ["人名", "姓名"]}, ...],
"data_source": "CCFBDCI"
}

其中text是输入的文本,entities是文本抽取出的实体。我们的目标是希望微调后的大模型能够根据由text组成的提示词,预测出一个json格式的实体信息:

输入:今天亚太经合组织第十二届部长级会议在这里开幕,中国外交部部长唐家璇、外经贸部部长石广生出席了会议。大模型输出:{"entity_text":"中国", "entity_label":"组织"}{"entity_text":"唐家璇", "entity_label":"人名"}...

现在我们将数据集下载到本地目录。下载方式是前往[chinese_ner_sft - huggingface]下载ccfbdci.jsonl到项目根目录下即可:

在这里插入图片描述

3. 加载模型

这里我们使用modelscope下载GLM4-9b-Chat模型(modelscope在国内,所以直接用下面的代码自动下载即可,不用担心速度和稳定性问题),然后把它加载到Transformers中进行训练:

from modelscope import snapshot_download, AutoTokenizer
from transformers import AutoModelForCausalLM, TrainingArguments, Trainer, DataCollatorForSeq2Seq
import torchmodel_id = "ZhipuAI/glm-4-9b-chat"    
model_dir = "./ZhipuAI/glm-4-9b-chat/"# 在modelscope上下载GLM4模型到本地目录下
model_dir = snapshot_download(model_id, cache_dir="./", revision="master")# Transformers加载模型权重
tokenizer = AutoTokenizer.from_pretrained(model_dir, use_fast=False, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_dir, device_map="auto", torch_dtype=torch.bfloat16, trust_remote_code=True)
model.enable_input_require_grads()  # 开启梯度检查点时,要执行该方法

4. 配置LoRA

from peft import LoraConfig, TaskType, get_peft_modelconfig = LoraConfig(task_type=TaskType.CAUSAL_LM,target_modules=["query_key_value", "dense", "dense_h_to_4h", "activation_func", "dense_4h_to_h"],inference_mode=False,  # 训练模式r=8,  # Lora 秩lora_alpha=32,  # Lora alaph,具体作用参见 Lora 原理lora_dropout=0.1,  # Dropout 比例
)model = get_peft_model(model, config)

5. 配置训练可视化工具

我们使用SwanLab来监控整个训练过程,并评估最终的模型效果。

这里直接使用SwanLab和Transformers的集成来实现:

from swanlab.integration.huggingface import SwanLabCallbackswanlab_callback = SwanLabCallback(...)trainer = Trainer(...callbacks=[swanlab_callback],
)

如果你是第一次使用SwanLab,那么还需要去[swanlab.cn]上注册一个账号,在用户设置页面复制你的API Key,然后在训练开始时粘贴进去即可:

在这里插入图片描述

6. 完整代码

开始训练时的目录结构:

|--- train.py
|--- ccfbdci.jsonl

train.py:

import json
import pandas as pd
import torch
from datasets import Dataset
from modelscope import snapshot_download, AutoTokenizer
from swanlab.integration.huggingface import SwanLabCallback
from peft import LoraConfig, TaskType, get_peft_model
from transformers import AutoModelForCausalLM, TrainingArguments, Trainer, DataCollatorForSeq2Seq
import os
import swanlabdef dataset_jsonl_transfer(origin_path, new_path):"""将原始数据集转换为大模型微调所需数据格式的新数据集"""messages = []# 读取旧的JSONL文件with open(origin_path, "r") as file:for line in file:# 解析每一行的json数据data = json.loads(line)input_text = data["text"]entities = data["entities"]match_names = ["地点", "人名", "地理实体", "组织"]entity_sentence = ""for entity in entities:entity_json = dict(entity)entity_text = entity_json["entity_text"]entity_names = entity_json["entity_names"]for name in entity_names:if name in match_names:entity_label = namebreakentity_sentence += f"""{{"entity_text": "{entity_text}", "entity_label": "{entity_label}"}}"""if entity_sentence == "":entity_sentence = "没有找到任何实体"message = {"instruction": """你是一个文本实体识别领域的专家,你需要从给定的句子中提取 地点; 人名; 地理实体; 组织 实体. 以 json 格式输出, 如 {"entity_text": "南京", "entity_label": "地理实体"} 注意: 1. 输出的每一行都必须是正确的 json 字符串. 2. 找不到任何实体时, 输出"没有找到任何实体". ""","input": f"文本:{input_text}","output": entity_sentence,}messages.append(message)# 保存重构后的JSONL文件with open(new_path, "w", encoding="utf-8") as file:for message in messages:file.write(json.dumps(message, ensure_ascii=False) + "\n")def process_func(example):"""对数据集进行数据预处理,主要用于被dataset.map调用"""MAX_LENGTH = 384 input_ids, attention_mask, labels = [], [], []system_prompt = """你是一个文本实体识别领域的专家,你需要从给定的句子中提取 地点; 人名; 地理实体; 组织 实体. 以 json 格式输出, 如 {"entity_text": "南京", "entity_label": "地理实体"} 注意: 1. 输出的每一行都必须是正确的 json 字符串. 2. 找不到任何实体时, 输出"没有找到任何实体"."""instruction = tokenizer(f"<|system|>\n{system_prompt}<|endoftext|>\n<|user|>\n{example['input']}<|endoftext|>\n<|assistant|>\n",add_special_tokens=False,)response = tokenizer(f"{example['output']}", add_special_tokens=False)input_ids = instruction["input_ids"] + response["input_ids"] + [tokenizer.pad_token_id]attention_mask = (instruction["attention_mask"] + response["attention_mask"] + [1])labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]if len(input_ids) > MAX_LENGTH:  # 做一个截断input_ids = input_ids[:MAX_LENGTH]attention_mask = attention_mask[:MAX_LENGTH]labels = labels[:MAX_LENGTH]return {"input_ids": input_ids, "attention_mask": attention_mask, "labels": labels}   def predict(messages, model, tokenizer):"""对测试集进行模型推理,得到预测结果"""device = "cuda"text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True)model_inputs = tokenizer([text], return_tensors="pt").to(device)generated_ids = model.generate(model_inputs.input_ids,max_new_tokens=512)generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)]response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]print(response)return responsemodel_id = "ZhipuAI/glm-4-9b-chat"    
model_dir = "./ZhipuAI/glm-4-9b-chat/"# 在modelscope上下载GLM4模型到本地目录下
model_dir = snapshot_download(model_id, cache_dir="./", revision="master")# Transformers加载模型权重
tokenizer = AutoTokenizer.from_pretrained(model_dir, use_fast=False, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_dir, device_map="auto", torch_dtype=torch.bfloat16, trust_remote_code=True)
model.enable_input_require_grads()  # 开启梯度检查点时,要执行该方法# 加载、处理数据集和测试集
train_dataset_path = "ccfbdci.jsonl"
train_jsonl_new_path = "ccf_train.jsonl"if not os.path.exists(train_jsonl_new_path):dataset_jsonl_transfer(train_dataset_path, train_jsonl_new_path)# 得到训练集
total_df = pd.read_json(train_jsonl_new_path, lines=True)
train_df = total_df[int(len(total_df) * 0.1):]
train_ds = Dataset.from_pandas(train_df)
train_dataset = train_ds.map(process_func, remove_columns=train_ds.column_names)# 配置LoRA
config = LoraConfig(task_type=TaskType.CAUSAL_LM,target_modules=["query_key_value", "dense", "dense_h_to_4h", "activation_func", "dense_4h_to_h"],inference_mode=False,  # 训练模式r=8,  # Lora 秩lora_alpha=32,  # Lora alaph,具体作用参见 Lora 原理lora_dropout=0.1,  # Dropout 比例
)# 得到被peft包装后的模型
model = get_peft_model(model, config)# 配置Transformers训练参数
args = TrainingArguments(output_dir="./output/GLM4-NER",per_device_train_batch_size=4,per_device_eval_batch_size=4,gradient_accumulation_steps=4,logging_steps=10,num_train_epochs=2,save_steps=100,learning_rate=1e-4,save_on_each_node=True,gradient_checkpointing=True,report_to="none",
)# 设置SwanLab与Transformers的回调
swanlab_callback = SwanLabCallback(project="GLM4-NER-fintune",experiment_name="GLM4-9B-Chat",description="使用智谱GLM4-9B-Chat模型在NER数据集上微调,实现关键实体识别任务。",config={"model": model_id,"model_dir": model_dir,"dataset": "qgyd2021/chinese_ner_sft",},
)# 设置Transformers Trainer
trainer = Trainer(model=model,args=args,train_dataset=train_dataset,data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),callbacks=[swanlab_callback],
)# 开始训练
trainer.train()# 用随机20条数据测试模型
test_df = total_df[:int(len(total_df) * 0.1)].sample(n=20)test_text_list = []
for index, row in test_df.iterrows():instruction = row['instruction']input_value = row['input']messages = [{"role": "system", "content": f"{instruction}"},{"role": "user", "content": f"{input_value}"}]response = predict(messages, model, tokenizer)messages.append({"role": "assistant", "content": f"{response}"})result_text = f"{messages[0]}\n\n{messages[1]}\n\n{messages[2]}"test_text_list.append(swanlab.Text(result_text, caption=response))# 记录测试结果
swanlab.log({"Prediction": test_text_list})
# 关闭SwanLab记录
swanlab.finish()

看到下面的进度条即代表训练开始:

在这里插入图片描述

7.训练结果演示

在SwanLab上查看最终的训练结果:

可以看到在2个epoch之后,微调后的GLM4的loss降低到了不错的水平——当然对于大模型来说,真正的效果评估还得看主观效果。

在这里插入图片描述

可以看到在一些测试样例上,微调后的GLM4能够给出准确的NER结果:

在这里插入图片描述

至此,你已经完成了qwen2指令微调的训练!

8.推理训练好的模型

训好的模型默认被保存在./output/GLM4-NER文件夹下。 推理模型的代码如下:

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModeldef predict(messages, model, tokenizer):device = "cuda"text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)model_inputs = tokenizer([text], return_tensors="pt").to(device)generated_ids = model.generate(model_inputs.input_ids, max_new_tokens=512)generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)]response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]return responsemodel_dir = "./ZhipuAI/glm-4-9b-chat/"
lora_dir = "./output/GLM4-NER/checkpoint-1700"# 加载原下载路径的tokenizer和model
tokenizer = AutoTokenizer.from_pretrained(model_dir, use_fast=False, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_dir, device_map="auto", torch_dtype=torch.bfloat16)# 加载训练好的Lora模型
model = PeftModel.from_pretrained(model, model_id=lora_dir)input_text = "西安电子科技大学的陈志明爱上了隔壁西北工业大学苏春红,他们约定好毕业后去中国的苏州定居。"
test_texts = {"instruction": """你是一个文本实体识别领域的专家,你需要从给定的句子中提取 地点; 人名; 地理实体; 组织 实体. 以 json 格式输出, 如; {"entity_text": "南京", "entity_label": "地理实体"} 注意: 1. 输出的每一行都必须是正确的 json 字符串. 2. 找不到任何实体时, 输出"没有找到任何实体". ""","input": f"文本:{input_text}"
}instruction = test_texts['instruction']
input_value = test_texts['input']messages = [{"role": "system", "content": f"{instruction}"},{"role": "user", "content": f"{input_value}"}
]response = predict(messages, model, tokenizer)
print(response)

输出结果为:

{"entity_text": "西安电子科技大学", "entity_label": "组织"}
{"entity_text": "陈志明", "entity_label": "人名"}
{"entity_text": "西北工业大学", "entity_label": "组织"}
{"entity_text": "苏春红", "entity_label": "人名"}
{"entity_text": "中国", "entity_label": "地理实体"}
{"entity_text": "苏州", "entity_label": "地理实体"}

如何学习AI大模型?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

在这里插入图片描述

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

在这里插入图片描述

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

在这里插入图片描述

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

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

相关文章

Unity之王牌飞行员申请出战

目录 &#x1f4da;一、准备工作 &#x1f4bb;二、飞机的两套控制器 &#x1f3ae;2.1 起飞前 &#x1f579;️2.2 起飞后 &#x1f680;三、实现射击功能 &#x1f4a5;3.1 射击脚本 &#x1f4a5;3.2 爆炸脚本 &#x1f4a5;3.3 爆炸特效脚本 &#x1f6e0;️四、组…

AGE 可比性、相等性、可排序性和等效性

AGE已经对原始类型&#xff08;布尔值、字符串、整数和浮点数&#xff09;和映射的相等性有了良好的语义。此外&#xff0c;Cypher对整数、浮点数和字符串的可比性和可排序性也有很好的语义。然而&#xff0c;处理不同类型的值与Postgres定义的逻辑和openCypher规范存在偏差&am…

Linux_网络编程_TCP

服务器客户端模型&#xff1a; client / server brow / ser b / s http p2p socket——tcp 1、模式 C/S 模式 》服务器/客户端模型 server :socket()-->bind()--->listen()-->accept()-->recv()-->close()client :socket()-->conn…

STM32第九课:STM32-基于标准库的42步进电机的简单I/O控制(附电机教程,看到即赚到)

一&#xff1a;步进电机简介 步进电机又称为脉冲电机&#xff0c;简而言之&#xff0c;就是一步一步前进的电机。基于最基本的电磁铁原理,它是一种可以自由回转的电磁铁,其动作原理是依靠气隙磁导的变化来产生电磁转矩&#xff0c;步进电机的角位移量与输入的脉冲个数严格成正比…

超越单兵作战:多智能体 Multi-Agent System (MAS)

超越单兵作战&#xff1a;多智能体 Multi-Agent System (MAS) Multi-Agent System 是指一个系统中有多个智能体同时工作的情况。在这样的系统中&#xff0c;每个智能体都具有一定程度的自主性&#xff0c;可以独立执行任务、做决定&#xff0c;并且能够与其他智能体进行交互&a…

STM32的Code、RO-data、RW-data、ZI-data和RAM以及flash的关系

对于刚接触stm32编程的同学来说&#xff0c;通常不知道如何选择合适型号的芯片来开发自己的项目&#xff0c;下面就分析一下多大的片内ram以及flash能符合我们项目的需求。 不知道大家有没有注意到&#xff0c;我们的项目每次编译完成后&#xff0c;都会出现这个Program Size&…

亚马逊卖家告别熬夜!批量定时上下架,自动调价

必用能功三个&#xff0c;不限制上传商品。 大家好&#xff0c;今天来讲下这款erp的定时上下架功能。 打开工具这栏选择智能调价&#xff0c;点击添加智能调价选择店铺&#xff0c;选择定时上架的商品添加也可以全部添加。每个商品的价格都是不同的&#xff0c;可以点击保底价…

windows10开启防火墙,增加入站规则后不生效,还是不能访问后端程序

一、背景&#xff1a; 公司护网要求开启防火墙&#xff0c;开启防火墙后&#xff0c;前后端分离的项目调试受影响&#xff0c;于是增加入站规则开放固定的后台服务端口&#xff0c;增加的mysql端口3306和redis端口6379&#xff0c;别人都可以访问&#xff0c;但是程序的端口808…

抖音工具箱功能菜单解析分享

一 支持视频链接 采集/点赞/评论/收藏 二 支持导入 用户id私信 内容自定义 可 关注后私信对方 私信间隔自定义 三 支持多直播间 发言 内容-间隔自定义 五 支持 监听指定用户作品 新发作品 自动 点赞/评论/收藏 六 支持 视频评论实时监控 新发评论自动采集获取 七 智能 暂停…

NLP入门——卷积语言模型的搭建、训练与预测

语言模型建模是针对句子建模&#xff0c;主要分为掩码语言模型和自回归语言模型。 我们从corpus中截取一句话作为例子&#xff0c;这句话是bpe分词后的句子&#xff1a; 1994 年 5 月 17 日 安全 理事会 第 33 77 次 会议 通过 掩码语言模型的主要机制是&#xff1a;例如将33 7…

PostgREST API 安装及基础使用

PostgREST是一个独立的Web服务器&#xff0c;它将PostgreSQL数据库转换为RESTful API。它提供基于基础数据库的结构自定义的API。 PostgREST安装 首先访问Releases PostgREST/postgrest (github.com)&#xff0c;根据安装平台选择下载的源码。比如我现在的设备是Mac但是我的…

删掉此电脑中烦人的百度网盘、WPS、迅雷下载图标(还有导航栏)-win10/11

删掉此电脑的图标 1、首先 搜索 注册表管理器 或者 win R 输入 regedit 2、在红框的地方输入这串路径&#xff08;下2选1&#xff09;&#xff1a; 计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\ HKEY_CURRENT_US…

【C++】使用C++实现基于Socket的通信

在本文中&#xff0c;我们将详细讨论如何使用C实现基于Socket的通信&#xff0c;并设计一个TLV&#xff08;Type-Length-Value&#xff09;协议用于数据交互。TLV协议因其灵活性和可扩展性&#xff0c;在多种通信协议中被广泛使用&#xff0c;特别是在需要动态定义数据结构的场…

【Axure】产品原型如何在谷歌浏览器中打开

作为一名前端开发来说&#xff0c;在拿到产品的原型图后&#xff0c;如何打开&#xff1f;直接用谷歌浏览器打开&#xff0c;是打不开的&#xff0c;需要安装对应的插件。但是谷歌插件市场在不翻墙的情况下&#xff0c;是没有办法直接打开的&#xff0c;分享一种超级简单的方法…

深入解析RocketMQ的名字服务机制:功能、原理与应用

NameServer 是专为 RocketMQ 设计的轻量级名字服务&#xff0c;它的源码非常精简&#xff0c;八个类 &#xff0c;少于 1000 行代码。 这篇文章&#xff0c; 笔者会从基础概念、Broker 发送心跳包、NameServer 维护路由、Zookeeper vs NameServer 四个模块揭秘名字服务的设计精…

电脑怎样连接打印机?详细步骤告诉你!

在现代办公环境中&#xff0c;打印机是必不可少的设备之一。无论是打印文档、图片还是其他资料&#xff0c;连接打印机都是我们日常工作中的基本操作。然而&#xff0c;不同类型的打印机和连接方式可能会让人感到困惑。本文将介绍电脑怎样连接打印机的3种方法&#xff0c;帮助您…

简易限流实现

需求描述 写一个1秒两个的限流工具类&#xff0c;2r/s 使用semaphore 代码实现-类似令牌桶算法 public class LimitHelper {private int maxLimit;private Semaphore semaphore;private int timeoutSeconds;public LimitHelper(int maxLimit, int timeoutSeconds) {this.max…

LNMP搭建Discuz和Wordpress

1、LNMP L:linux操作系统 N&#xff1a;nginx展示前端页面web服务 M&#xff1a;mysql数据库&#xff0c;保存用户和密码&#xff0c;以及论坛相关的内容 P&#xff1a;php动态请求转发的中间件 数据库的作用&#xff1a; 登录时验证用户名和密码 创建用户和密码 发布和…

昇思25天学习打卡营第十七天|文本解码原理--以MindNLP为例

背景 提供免费算力支持&#xff0c;有交流群有值班教师答疑的华为昇思训练营进入第十七天了。 今天是第十七天&#xff0c;从第十天开始&#xff0c;进入了应用实战阶段&#xff0c;前九天都是基础入门阶段&#xff0c;具体的学习内容可以看链接 基础学习部分 昇思25天学习打卡…

Unity发布webgl之后修改StreamingAssets 内的配置文件读取到的还是之前的配置文件的解决方案

问题描述 unity发布webgl之后&#xff0c;修改在StreamingAssets 中的配置信息&#xff0c;修改之后读取的还是之前的配置信息 读取配置文件的代码IEnumerator IE_WebGL_LoadWebSocketServerCopnfig(){var uri new System.Uri(Path.Combine(Application.streamingAssetsPath…