重庆做网站开发的公司有哪些/宁波网站制作优化服务
简介:
小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案,帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践,并应用到自己的日常工作里。
在机器学习和人工智能领域,生成偏差(Generative Bias) 是指在生成模型或生成式算法中所引入的偏差。生成偏差可能导致模型生成的输出结果不公平、不准确或不符合预期。本次我将介绍如何用亚马逊云科技的AI模型训练服务Amazon SageMaker和Lora框架高效微调AI翻译大模型,并用DJL Serving框架管理模型和处理推理请求,我将带领大家手把手通过一行一行的代码学会AI模型的微调,0基础学会AI核心技能。本架构设计还包括了与用户交互的前后端应用,全部采用了云原生Serverless架构,提供可扩展和安全的AI应用解决方案。本方案架构图如下
项目开发背景知识
Dolly 3B 大模型介绍
Databricks 的dolly-v2-3b 是一种基于Databricks 机器学习平台训练的指令跟随大型语言模型,可以用于商业用途,专为自然语言处理任务而设计。它能够理解和生成多种语言的文本,支持翻译、摘要、问答等多种应用场景。Dolly 3B 拥有30亿个参数,具备强大的语言理解和生成能力。通过大规模的预训练数据集和复杂的模型架构,Dolly 3B 在处理复杂的语言任务时表现出色。
使用 Dolly 3B,开发者可以轻松实现跨语言翻译、文本生成和语义分析等任务。此外,Dolly 3B 还支持在特定领域内的定制化微调,使其在特定应用场景中表现更加精准和高效。
什么是微调
微调是指在预训练模型的基础上,通过在特定任务或领域的数据集上进行进一步训练,以提高模型在特定应用场景中的表现。微调的过程通常涉及以下几个步骤:
- 选择预训练模型:选择一个已经在大规模数据集上预训练过的模型,如 Dolly 3B。
- 准备微调数据:收集和整理适用于特定任务或领域的数据集。这些数据可以包括分类、回归、翻译等任务的示例。
- 设置训练参数:根据具体任务调整训练参数,如学习率、批量大小和训练轮数等。
- 进行微调训练:使用准备好的数据和训练参数对预训练模型进行进一步训练,使其在特定任务上的表现得到优化。
- 评估和部署:评估微调后的模型在验证集上的性能,并将其部署到实际应用中。
通过微调,开发者可以将通用的预训练模型转变为针对特定任务高度优化的模型,从而提升其在实际应用中的准确性和效率。微调在机器学习和人工智能领域中应用广泛,特别是在自然语言处理、计算机视觉和语音识别等领域,微调技术能够显著提升模型的性能和适用性。
本方案包括的内容:
-
使用大语言模型Dolly进行自然语言翻译。
-
评估翻译的性能和偏差。
-
生成数据集微调 Dolly-3B 模型。
-
在 Amazon SageMaker 上部署微调后的模型。
-
将 SageMaker API 接口集成到实际软件应用中,构建前后端云原生架构。
项目搭建具体步骤:
1. 打开亚马逊云科技控制台,进入SageMaker服务,创建一个Jupyter Notebook实例并进入。
2. 新建一个Notebook,接下来我们开始Dolly德译英翻译模型的微调。首先我们安装必要的依赖
%%capture!export TOKENIZERS_PARALLELISM=false!pip3 install -r requirements.txt
!pip install sagemaker --quiet --upgrade --force-reinstallimport warnings
warnings.filterwarnings('ignore')
3. 接下来导入必要的依赖
# Import libraries
import torch
from transformers import pipeline, AutoTokenizer
import pandas as pd
import tqdm
import evaluate
from rich import print
4. 我们再导入模型“dolly-v2-3B”,在这里我们定义Dolly的Tokenizer和微调的Pipeline
# set seed for reproducible results
seed = 100
torch.manual_seed(seed)
torch.backends.cudnn.deterministic = True
if torch.cuda.is_available():torch.cuda.manual_seed_all(seed)# Use a tokenizer suitable for Dolly-v2-3B
dolly_tokenizer = AutoTokenizer.from_pretrained("databricks/dolly-v2-3b", padding_side = "left")dolly_pipeline = pipeline(model = "databricks/dolly-v2-3b",device_map = "auto",torch_dtype = torch.float16,trust_remote_code = True,tokenizer = dolly_tokenizer)
5. 接下来我们将一个远程的数据集导入到Pandas DataFrame中
wiki_bios_en_to_de = pd.read_csv("https://storage.googleapis.com/gresearch/translate-gender-challenge-sets/data/Translated%20Wikipedia%20Biographies%20-%20EN_DE.csv")
6. 我们将DataFrame的字段进行重命名转为标准格式,并从男性和女性样本中随机取100个
wiki_bios_de_to_en = wiki_bios_en_to_de.rename(columns={"sourceLanguage": "targetLanguage", "targetLanguage": "sourceLanguage", "sourceText": "translatedText", "translatedText": "sourceText"})with pd.option_context('display.max_colwidth', None):display(wiki_bios_de_to_en.head())male_bios = wiki_bios_de_to_en[wiki_bios_de_to_en.perceivedGender == "Male"]
female_bios = wiki_bios_de_to_en[wiki_bios_de_to_en.perceivedGender == "Female"]print("Male Bios size: " + str(male_bios.shape))
print("Female Bios size: " + str(female_bios.shape))male_sample = male_bios.sample(100, random_state=100)
female_sample = female_bios.sample(100, random_state=100)print("Male Sample size: " + str(male_sample.shape))
print("Female Sample size: " + str(female_sample.shape))
7. 接下来我们将dataframe数据集中的sourceText的字段内容翻译为德语。将翻译后的内容取出后存到单独的列表中。
male_generations = []
for row in tqdm.tqdm(range(len(male_sample))):source_text = male_sample.iloc[row]["sourceText"]# Create instruction to provide modelcur_prompt_male = ("Translate \"%s\" from German to English." % (source_text))# Prompt model with instruction and text to translategeneration = dolly_pipeline(cur_prompt_male)generated_text = generation[0]['generated_text']# Store translationmale_generations.append(generated_text)print('Generated '+ str(len(male_generations))+ ' male generations')female_generations = []
for row in tqdm.tqdm(range(len(female_sample))):source_text = female_sample.iloc[row]["sourceText"]cur_prompt_female = ("Translate \"%s\" from German to English." % (source_text))generation = dolly_pipeline(cur_prompt_female)generated_text = generation[0]['generated_text']female_generations.append(generated_text)print('Generated '+ str(len(female_generations))+ ' female_generations')all_samples = pd.concat([male_sample, female_sample])english = all_samples["translatedText"].values.tolist()
german = all_samples["sourceText"].values.tolist()
gender = all_samples["perceivedGender"].values.tolist()
generations = all_samples["generatedText"].values.tolist()
8. 接下来我们对模型的表现和偏差进行分析。我们会基于两个参数Bilingual Evaluation Understudy (BLEU) 和Regard进行分析。BLEU是对翻译质量评估指标,我们先基于BLUE进行分析,得到最终的分数(0-1),约接近1表示翻译约精准。
# Load the BLEU metric from the evaluate library
bleu = evaluate.load("bleu")bleu.compute(predictions = all_samples["generatedText"].values.tolist(), references = all_samples["translatedText"].values.tolist(), max_order = 2)bleu.compute(predictions = male_sample["generatedText"].values.tolist(), references = male_sample["translatedText"].values.tolist(), max_order = 2)bleu.compute(predictions = female_sample["generatedText"].values.tolist(), references = female_sample["translatedText"].values.tolist(), max_order = 2)
9. 接下来我们基于Regard参数进行评估。Regard是对于模型偏见的评估指标。如果想保障模型没有偏见,我们需要保持neutral尽可能接近于1,或者是Neutral、Positive、Negative分数均匀分布.
# Load the Regard metric from evaluate
regard = evaluate.load("regard", "compare")regard.compute(data = male_generations, references = female_generations, aggregation = "average")
10. 接下来我们开始优化模型,让模型的回复更加准确客观,消除偏见。我们第一个可以用的方法就是定义提示词工程,在提示词中强调在翻译中消除偏见。比如:
dolly_pipeline("""Translate from German to English and continue in a gender inclusive way: "Casey studiert derzeit um eine Mathematiklehrkraft zu werden wegen".""")
11. 同样我们也可以利用模型的微调来消除大语言模型中的偏见。首先我们导入必要的依赖
%%captureimport os
import numpy as np
import pandas as pd
from typing import Any, Dict, List, Tuple, Union
from datasets import Dataset, load_dataset, disable_caching
disable_caching() ## disable huggingface cachefrom transformers import AutoModelForCausalLM
from transformers import AutoTokenizer
from transformers import TextDatasetimport torch
from torch.utils.data import Dataset, random_split
from transformers import TrainingArguments, Trainer
import accelerate
import bitsandbytesfrom IPython.display import Markdown!export TOKENIZERS_PARALLELISM=falseimport warnings
warnings.filterwarnings('ignore')
12. 导入训练数据集
sagemaker_dataset = load_dataset("csv", data_files='data/cda_fae_faer_faer_faerself.csv')['train']
sagemaker_dataset
13. 定义提示词的格式,并将数据集按格式导入到提示词中。
from utils.helpers import INTRO_BLURB, INSTRUCTION_KEY, RESPONSE_KEY, END_KEY, RESPONSE_KEY_NL, DEFAULT_SEED, PROMPT
'''
PROMPT = """{intro}{instruction_key}{instruction}{response_key}{response}{end_key}"""
'''
Markdown(PROMPT)def _add_text(rec):instruction = rec["instruction"]response = rec["response"]if not instruction:raise ValueError(f"Expected an instruction in: {rec}")if not response:raise ValueError(f"Expected a response in: {rec}")rec["text"] = PROMPT.format(instruction=instruction, response=response)return recsagemaker_dataset = sagemaker_dataset.map(_add_text)
sagemaker_dataset[0]
14. 我们导入我们需要微调的模型dolly-v2-3b,定义tokenizer。
tokenizer = AutoTokenizer.from_pretrained("databricks/dolly-v2-3b", padding_side="left")tokenizer.pad_token = tokenizer.eos_token
tokenizer.add_special_tokens({"additional_special_tokens": [END_KEY, INSTRUCTION_KEY, RESPONSE_KEY_NL]})model = AutoModelForCausalLM.from_pretrained("databricks/dolly-v2-3b",# use_cache=False,device_map="auto", #"balanced",torch_dtype=torch.float16,load_in_8bit=True,
)
15. 为模型训练数据集预处理
model.resize_token_embeddings(len(tokenizer))
from functools import partial
from utils.helpers import mlu_preprocess_batchMAX_LENGTH = 256
_preprocessing_function = partial(mlu_preprocess_batch, max_length=MAX_LENGTH, tokenizer=tokenizer)
encoded_sagemaker_dataset = sagemaker_dataset.map(_preprocessing_function,batched=True,remove_columns=["instruction", "response", "text"],
)processed_dataset = encoded_sagemaker_dataset.filter(lambda rec: len(rec["input_ids"]) < MAX_LENGTH)
split_dataset = processed_dataset.train_test_split(test_size=14, seed=0)
split_dataset
16. 下面我们利用LoRA提升模型训练的效率,降低训练成本。我们定义Lora配置并利用Lora初始化我们的模型
from peft import LoraConfig, get_peft_model, prepare_model_for_int8_training, TaskTypeMICRO_BATCH_SIZE = 8
BATCH_SIZE = 64
GRADIENT_ACCUMULATION_STEPS = BATCH_SIZE // MICRO_BATCH_SIZE
LORA_R = 256 # 512
LORA_ALPHA = 512 # 1024
LORA_DROPOUT = 0.05# Define LoRA Config
lora_config = LoraConfig(r=LORA_R,lora_alpha=LORA_ALPHA,lora_dropout=LORA_DROPOUT,bias="none",task_type="CAUSAL_LM"
)model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
17. 下面我们定义一个data collator,将数据集整理成模型微调所需格式加速模型微调效率,设置模型微调参数并启动微调,最后将微调后的模型保存在本地。
from utils.helpers import MLUDataCollatorForCompletionOnlyLMdata_collator = MLUDataCollatorForCompletionOnlyLM(tokenizer=tokenizer, mlm=False, return_tensors="pt", pad_to_multiple_of=8
)EPOCHS = 10
LEARNING_RATE = 1e-4
MODEL_SAVE_FOLDER_NAME = "dolly-3b-lora"training_args = TrainingArguments(output_dir=MODEL_SAVE_FOLDER_NAME,fp16=True,per_device_train_batch_size=1,per_device_eval_batch_size=1,learning_rate=LEARNING_RATE,num_train_epochs=EPOCHS,logging_strategy="steps",logging_steps=100,evaluation_strategy="steps",eval_steps=100, save_strategy="steps",save_steps=20000,save_total_limit=10,
)trainer = Trainer(model=model,tokenizer=tokenizer,args=training_args,train_dataset=split_dataset['train'],eval_dataset=split_dataset["test"],data_collator=data_collator,
)
model.config.use_cache = False # silence the warnings. Please re-enable for inference!
trainer.train()trainer.model.save_pretrained(MODEL_SAVE_FOLDER_NAME)
trainer.model.config.save_pretrained(MODEL_SAVE_FOLDER_NAME)
tokenizer.save_pretrained(MODEL_SAVE_FOLDER_NAME)
18. 接下来我们将微调后的模型部署到Amazon Sagemaker上,我们利用DJL框架实现MLOps。将模型打包上传到S3上,定义SageMaker模型运行环境和模型配置,最后加载大模型,部署生成API调用接口。
import boto3
import json
import sagemaker.djl_inference
from sagemaker.session import Session
from sagemaker import image_uris
from sagemaker import Modelsagemaker_session = Session()
print("sagemaker_session: ", sagemaker_session)aws_role = sagemaker_session.get_caller_identity_arn()
print("aws_role: ", aws_role)aws_region = boto3.Session().region_name
print("aws_region: ", aws_region)image_uri = image_uris.retrieve(framework="djl-deepspeed",version="0.22.1",region=sagemaker_session._region_name)
print("image_uri: ", image_uri)%%bash
rm -rf lora_model
mkdir -p lora_model
mkdir -p lora_model/dolly-3b-lora
cp dolly-3b-lora/adapter_config.json lora_model/dolly-3b-lora/
cp dolly-3b-lora/adapter_model.bin lora_model/dolly-3b-lora/%%writefile lora_model/serving.properties
engine=Python
option.entryPoint=model.py
option.adapter_checkpoint=dolly-3b-lora
option.adapter_name=dolly-lora%%writefile lora_model/requirements.txt
transformers==4.27.4
accelerate>=0.24.1,<1
peft%%bash
cp utils/deployment_model.py lora_model/model.py%%bash
tar -cvzf lora_model.tar.gz lora_model/import boto3
import json
import sagemaker.djl_inference
from sagemaker.session import Session
from sagemaker import image_uris
from sagemaker import Models3 = boto3.resource('s3')
s3_client = boto3.client('s3')s3 = boto3.resource('s3')# Get the name of the bucket with prefix lab-code
for bucket in s3.buckets.all():if bucket.name.startswith('artifact'):mybucket = bucket.nameprint(mybucket)response = s3_client.upload_file("lora_model.tar.gz", mybucket, "lora_model.tar.gz")model_data="s3://{}/lora_model.tar.gz".format(mybucket)model = Model(image_uri=image_uri,model_data=model_data,predictor_cls=sagemaker.djl_inference.DJLPredictor,role=aws_role)%%time
predictor = model.deploy(1, "ml.g4dn.2xlarge")
19. 回到SageMaker中查看部署好的模型API接口URL
20. 接下来我们创建一个Lambda函数,复制以下代码。这个lambda函数将作为后端服务器与微调后的模型进行交互,后端API将由API Gateway进行管理,收到用户请求后触发该lambda函数。
# Import necessary libraries
import json
import boto3
import os
import re
import logging# Set up logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)# Create a SageMaker client
sagemaker_client = boto3.client("sagemaker-runtime")# Define Lambda function
def lambda_handler(event, context):# Log the incoming event in JSON formatlogger.info('Event: %s', json.dumps(event))# Clean the body of the event: remove excess spaces and newline characterscleaned_body = re.sub(r'\s+', ' ', event['body']).replace('\n', '')# Log the cleaned bodylogger.info('Cleaned body: %s', cleaned_body)# Invoke the SageMaker endpoint with the cleaned body as payload and content type as JSONresponse = sagemaker_client.invoke_endpoint(EndpointName=os.environ["ENDPOINT_NAME"], ContentType="application/json", Body=cleaned_body)# Load the response body and decode itresult = json.loads(response["Body"].read().decode())# Return the result with status code 200 and the necessary headersreturn {'statusCode': 200,'headers': {'Access-Control-Allow-Headers': 'Content-Type','Access-Control-Allow-Origin': '*','Access-Control-Allow-Methods': 'OPTIONS,POST'},'body': json.dumps(result)}
以上就是在亚马逊云科技上利用SageMaker微调大模型Dolly 3B,减少翻译偏差的全部步骤。欢迎大家关注小李哥,未来获取更多国际前沿的生成式AI开发方案!
相关文章:

如何在亚马逊云科技AWS上利用LoRA高效微调AI大模型减少预测偏差
简介: 小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案,帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践,并应用到自己的日常工作里。 在机器学习和人工智能领域,生成偏差…...

订单定时状态处理业务(SpringTask)
文章目录 概要整体架构流程技术细节小结 概要 订单定时状态处理通常涉及到对订单状态进行定期检查,并根据订单的状态自动执行某些操作,比如关闭未支付的订单、自动确认收货等. 需求分析以及接口设计 需求分析 用户下单后可能存在的情况: …...

STM32 | ADC+RS485(第十天)
点击上方"蓝字"关注我们 01、ADC概述 ADC, Analog-to-Digital Converter的缩写,指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。真实世界的模拟信号.例如温度、压力、声音或者图像等,需要转换成更容易储存、处理和发射的…...

python打包成能够在mac里面运行的程序
要将你的PyQt5应用程序打包成可以在macOS上运行的独立应用程序,可以使用工具如PyInstaller或py2app。下面是使用py2app的详细步骤,因为它是macOS上专用的打包工具,并且更好地支持PyQt5。 1. 安装py2app 首先,确保你的macOS系统上…...

基于FPGA的数字信号处理(20)--半减器和全减器
目录 1、前言 2、半减器 3、全减器 4、减法器 文章总目录点这里:《基于FPGA的数字信号处理》专栏的导航与说明 1、前言 既然有半加器和全加器,那自然也有半减器和全减器了。尽管在电路中减法的实现基本都是 补码 加法 的形式,但是正所谓…...

Python:单引号,双引号,三引号的区别
在Python中,单引号()、双引号(")和三引号( 或 """)都可以用来定义字符串,但它们之间有一些区别: 单引号()和双引号…...

电子电气架构 ---SOMEIP/SD初入门
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…...

一些数学基础概念
一些数学基础概念 概率密度函数(PDF) 概率密度函数(Probability Density Function,简称 PDF)是描述连续随机变量的概率分布的一种函数。它用来表示随机变量在各个取值区间内的概率密度。 1. 定义 对于一个连续随机变量 ( X ),…...

责任有限公司的一般组织结构
责任有限公司(有限责任公司,LLC)的组织结构通常是为了确保公司运营的有效性和管理的透明度。以下是一般责任有限公司的组织结构及其主要组成部分: 1. 股东(Shareholders) 职责和角色 所有者:…...

Leetcode3227. 字符串元音游戏
Every day a Leetcode 题目来源:3227. 字符串元音游戏 解法1:博弈论 分类讨论: 如果 s 不包含任何元音,小红输。如果 s 包含奇数个元音,小红可以直接把整个 s 移除,小红赢。如果 s 包含正偶数个元音&am…...

网络流量分析在运维管理中的重要性与实施策略
在运维管理工作中,网络流量分析是一项不可或缺的技术手段。通过对网络流量的深入剖析,运维团队能够更全面地了解网络状态,及时发现潜在问题,优化网络性能,从而确保企业网络的稳定与高效运行。本文将详细探讨网络流量分…...

通信原理实验——PCM编译码
PCM编译码 实验目的 理解PCM编译码原理及PCM编译码性能熟悉PCM编译码专用集成芯片的功能和使用方法及各种时钟关系熟悉语音数字化技术的主要指标及测量方法 主要仪器设备及软件 硬件:多功能实验箱、示波器、导线 软件:无 实验原理 1. 抽样信号的量…...

matlab的strel()函数的使用方法(OK)
这个函数 是形态学的结构元素 使用方法如下 SE strel(nhood) SE strel("diamond",r) SE strel("disk",r) SE strel("disk",r,n) SE strel("octagon",r) SE strel("line",len,deg) SE strel("rectangle",…...

Linux:Linux权限解析
一、Linux下的用户分类 在Linux下,有两种用户,一种是超级用户,一种是普通用户 超级用户:可以再linux系统下做任何事情,不受权限限制(制定规则,但不需要遵守规则) 普通用户࿱…...

Spring面试篇章——IOC
IOC概念和原理 IOC概念 IOC就是控制反射,把对象创建和对象之间的调用过程,交给Spring进行管理使用IOC的目的:降低耦合度 IOC底层原理 xml解析、工厂模式、反射 图解: 原始模式 耦合度太高了,即当dao改了…...

适合制造业的项目管理软件都有哪些?
项目管理软件涉及进度、预算成本、资源、开发、流程、质量、风险、工时、知识文档、商务等各个方面,是企业项目管理领域的重要辅助工具,能够帮助组织提高项目管理水平与质量,确保项目顺利进行。 一、 奥博思 PowerProject 项目管理系统 Pow…...

微应用(Micro-Applications)、微前端(Micro Frontend)、Qiankun 框架之间的区别和联系
简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo :联系我们:VX :tja6288 / EMAIL: 347969164@qq.com 文章目录 微应用(Micro-Applications)、微…...

String的底层构造
1.String类对象的构造(后面有每一个接口的实现) #define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include<iostream> #include<assert.h> using namespace std;namespace bit {class string{public:typedef char* iterator;typedef const…...

Binder机制的原理
Binder机制是Android系统中用于进程间通信(IPC)的核心机制,它基于C/S(客户端-服务端)模型,允许不同进程间进行高效的通信和数据交换。以下是对Binder机制原理的详细解析: 1. Binder架构 Binde…...

JavaScript输出数据的方法?
在JavaScript中,输出数据有以下几种方法: 使用console.log()函数:使用console.log()函数可以将数据输出到浏览器的控制台,例如: console.log("Hello, World!");使用alert()函数:使用alert()函数…...

Redis学习笔记——第19章 事务
第19章 事务 19.1 事务的实现 19.1.1 事务开始 使用multi命令开启一个事务 通过修改客户端的flags字段为REDIS_MULTI 19.1.2 命令入队 当开启事务之后,exec、discard、watch、multi命令立即执行,而其他命令会放入一个队列中,并返回Queue…...

元太电磁膜SUDE-10S19MI-01X驱动适配
屏规格书: dts配置: 首先要确保CONFIG_I2C_HID宏打开,i2c-hid-core.c 文件才能编译进去代码。规格书vendor product 分别为0x2d1f 和0x0165 来区别,不至于影响到整体的hid其他设备。 i2c-hid-dev10 { compatible "hid-…...

C#数据类型 全局变量 类型转换方法(汇总)
1、C#和S7-1200PLC S7.NET通信 C#和S7-1200PLC S7.NET通信-CSDN博客文章浏览阅读98次。一步步建立一个C#项目(连续读取S7-1200PLC数据)_s7协议批量读取-CSDN博客这篇博客作为C#的基础系列,和大家分享如何一步步建立一个C#项目完成对S7-1200PLC数据的连续读取。首先…...

HCIP重修总笔记(中)
第八节 BGP基础 一、BGP产生背景 BGPBorder Gateway Protocol,边界网关协议)是一种用于自治系统间的动态路出协议,是一种外部网关协议。 自治系统AS:一组同一个管理机构进行管理,对外呈现统一选路策略的路由器的集合。 自治系统编号: …...

图片搜索网站,有大量高清图片,避免版权纠纷
一、简介 1、一个图片搜索网站,所有图片均遵循CC0协议,用户可以免费用于商业用途而无需标注来源。网站上有大量高清图片,基本可以满足用户的各种需求,同时避免了法律风险。提供强大的筛选功能,用户可以按图片方向、尺寸…...

设计学习笔记8:在设计模式中,状态模式和策略模式有什么区别,它们各自适用于什么场景?
基本介绍 状态模式(State Pattern)和策略模式(Strategy Pattern)都是行为型设计模式,它们用于处理不同的情景和需求,以下是它们的主要区别和适用场景: 状态模式(State Pattern&…...

Android 10.0 系统默认蓝牙打开状态栏显示蓝牙图标功能实现
1.前言 在10.0的系统rom定制化开发过程中,在默认系统中,打开蓝牙开关的时候不会状态栏不会显示蓝牙图标,而只有 蓝牙连接成功后会显示蓝牙图标,客户开发需要要求在蓝牙打开的时候在状态栏就显示蓝牙图标,接下来分析下 相关的状态栏图标显示流程,然后实现相关功能 2.系统…...

在git中如何忽略.vscode目录?
在Git中,如果你想忽略某个特定的文件或目录(比如.vscode目录),你可以通过以下步骤来实现: 创建或编辑.gitignore文件 在项目的根目录下,如果还没有.gitignore文件,你需要创建一个。如果已经有了…...

分布式系统
分布式系统是一种由多个相互连接的计算机组成的系统,这些计算机通过网络互相通信并协调行动来完成共同的任务。在分布式系统中,没有单一的物理实体可以控制整个系统;相反,各个节点(即计算机)独立运行&#…...

【Material-UI】Autocomplete 组件中的事件处理(Events)详解
文章目录 一、事件处理概述二、自定义按键行为代码详解 三、其他常见事件1. onChange 事件2. onInputChange 事件3. onFocus 和 onBlur 事件 四、实用场景1. 自定义提交行为2. 实现快捷键功能3. 动态提示 五、总结 在 Web 开发中,事件处理是实现用户交互的重要一环。…...