国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

解密Prompt系列6. lora指令微調扣細節(jié)-請冷靜,1個小時真不夠~

這篇具有很好參考價值的文章主要介紹了解密Prompt系列6. lora指令微調扣細節(jié)-請冷靜,1個小時真不夠~。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

上一章介紹了如何基于APE+SELF自動化構建指令微調樣本。這一章咱就把微調跑起來,主要介紹以Lora為首的低參數微調原理,環(huán)境配置,微調代碼,以及大模型訓練中顯存和耗時優(yōu)化的相關技術細節(jié)

標題這樣寫是因為上周突然收到了一周內上線一版chatbo的命令,原因無它領導們都刷到了《一個小時你也可以擁有ChatGPT》,《100美金訓練ChatGPT》,《僅訓練3小時超越ChatGPT》,《人人都可以擁有ChatGPT》。。。領導說人人都有了為啥我沒有呀???!真誠呼吁標題黨們求手下留情,留人一命!于是這里我換個標題來Debuff!Debuff!

看到這里本文最重要的部分已經說完了,累了的小伙伴可以撤退了,五一快樂~

解密Prompt系列6. lora指令微調扣細節(jié)-請冷靜,1個小時真不夠~

低參數微調原理

  • LORA:LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS
  • 原理:INTRINSIC DIMENSIONALITY EXPLAINS THE EFFECTIVENESS
    OF LANGUAGE MODEL FINE-TUNING
  • 前人的肩膀:Adapter: Parameter-Efficient Transfer Learning for NLP

我們之前在解密Prompt系列3. 凍結LM微調Prompt介紹過一些soft-prompt,包括P-Tunning和Prompt-Tunning也屬于低參數微調。這些方案是通過參數拼接的方案引入額外參數。這里介紹另一類方案,同樣是凍結LLM的參數,通過參數相加的方案引入額外參數, 相較soft-prompt最明顯的優(yōu)勢,就是不會占用輸入token的長度。

LoRA的原理比較簡單,原始全量微調其實就是在原始模型參數上通過微調加入增量\(W = W_0+\Delta W\),那我們可以通過凍結原始參數\(W_0\),并且把增量部分通過低秩分解方式進一步降低參數量級\(\Delta W=A*B^T\),原始參數的維度是\(d*d\), 則低秩分解后的參數量級是\(2*r*d\),因為這里的r<<d,因此可以起到大幅降低微調參數量級的效果,如下圖

解密Prompt系列6. lora指令微調扣細節(jié)-請冷靜,1個小時真不夠~

核心代碼如下

## 初始化低秩矩陣A和B
self.lora_A.update(nn.ModuleDict({adapter_name: nn.Linear(self.in_features, r, bias=False)}))
self.lora_B.update(nn.ModuleDict({adapter_name: nn.Linear(r, self.out_features, bias=False)}))
self.scaling[adapter_name] = lora_alpha / r

## 向前計算
result = F.linear(x, transpose(self.weight, self.fan_in_fan_out), bias=self.bias)
result += (
    self.lora_B[self.active_adapter](
        self.lora_A[self.active_adapter](self.lora_dropout[self.active_adapter](x))
    )
    * self.scaling[self.active_adapter]
)

論文測試了在多數場景下適當的LORA微調和全量微調的效果不相上下。一個可能原因是INTRINSIC DIMENSIONALITY論文中提出,雖然語言模型整體參數空間很大,但具體到每個任務其實有各自的隱表征空間(intrisic dimension),這個隱表征空間的維度并不高, 因此在微調過程中加入低秩分解并不一定會影響微調效果。使用LORA微調有以下幾個細節(jié)

  1. 對哪些參數進行微調:基于Transformer結構,LORA只對每層的Self-Attention的部分進行微調,有\(W_q, W_k, W_v, W_O\)四個映射層參數可以進行微調。消融實驗顯示只微調\(W_q\)效果略差,微調\(W_q, W_v\)的效果和微調\(W_q, W_k, W_v, W_O\)的效果相似。需要注意不同模型參數名稱不同,像chatglm對應的參數名稱就是query_key_value
  2. Rank的選?。篟ank的取值作者對比了1-64,效果上Rank在4-8之間最好,再高并沒有效果提升。不過論文的實驗是面向下游單一監(jiān)督任務的,因此在指令微調上根據指令分布的廣度,Rank選擇還是需要在8以上的取值進行測試。
  3. alpha參數:alpha其實是個縮放參數,本質和learning rate相同,所以為了簡化我默認讓alpha=rank,只調整lr,這樣可以簡化超參
  4. 初始化:A和Linear層的權重相同Uniform初始化,B是zero初始化,這樣最初的Lora權重為0。所以Lora參數是從頭學起,并沒有那么容易收斂。

Lora的優(yōu)點很明顯,低參數,適合小樣本場景;可以拔插式的使用,快速針對不同下游任務訓練不同的lora權重;完全沒有推理延時,這個在后面代碼中會提到推理時,可以預先把lora權重merge到原始權重上。

但Lora微調雖好,個人在嘗試中感受到的局限性就是adapter類的微調方案可能更適合下游單一任務類型/生成風格。至于是否適合作為通用指令微調的解決方案,有個問題我也沒有搞懂,就是通用的指令樣本是否真的有統(tǒng)一的低秩空間表征?這個表征又是什么含義?因為指令微調階段的樣本其實是混合的多任務指令樣本,這種情況下lora是否合適,感覺需要更全面的評估(當前出來的眾多LLama們都缺少合理統(tǒng)一全面可比的Evaluation),當前就我們的嘗試情況lora的效果并不及預期。

環(huán)境配置

  • GPU 云服務廠商對比

我用了featurize和攬睿星舟。云服務廠商的選擇主要看是否有jupyter,存儲夠大,下載快,能連git,有高配torch環(huán)境。這兩家在眾多小廠里脫穎而出,4090的卡一個小時也就3塊錢,來來來盆友辛苦把推廣費結一下~

強調下環(huán)境配置,想跑通微調,搞定環(huán)境你就成功了80%!運氣好1分鐘,運氣差1天都在原地打轉

  1. 實例環(huán)境:TRX4090 + py38 + torch2.0 + CUDA12
  2. python環(huán)境:主要坑在transforemrs和peft,幾個相關issue包括:llama tokenizer special token有問題,peft adapter.bin微調不更新,Bug with fan_in_fan_out。我一個不差都踩中了。。。
# 以下配置可能會隨時間變化,出了問題就去issue里面刨吧
# 要相信你不是唯一一個大冤種!
accelerate
appdirs
loralib
bitsandbytes
black
black[jupyter]
datasets
fire
transformers>=4.28.0
git+https://github.com/huggingface/peft.git
sentencepiece
gradio
wandb
cpm-kernel

模型初始化

以下代碼主要整合自alpaca-lora和chatglm-finetune。其實lora微調的代碼本身并不復雜,相反是如何加速大模型訓練,降低顯存占用的一些技巧大家可能不太熟悉。模型初始化代碼如下,get_peft_model會初始化PeftModel把原模型作為base模型,并在各個self-attention層加入lora層,同時改寫模型forward的計算方式。

主要說下load_in_8bit和prepare_model_for_int8_training,這里涉及到2個時間換空間的大模型顯存壓縮技巧。

from peft import get_peft_model, LoraConfig, prepare_model_for_int8_training, set_peft_model_state_dict
from transformers import AutoTokenizer, AutoModel

model = AutoModel.from_pretrained("THUDM/chatglm-6b", load_in_8bit=True, torch_dtype=torch.float16, trust_remote_code=True, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True)
model = prepare_model_for_int8_training(model)

lora_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    inference_mode=False,
    r=8,
    lora_alpha=8,
    lora_dropout=0.05,
)
model = get_peft_model(model, lora_config)
model.config.use_cache = False

模型顯存占用分成兩個部分,一部分是靜態(tài)顯存基本由模型參數量級決定,另一部分是動態(tài)顯存在向前傳播的過程中每個樣本的每個神經元都會計算激活值并存儲,用于向后傳播時的梯度計算,這部分和batchsize以及參數量級相關。以下8bit量化優(yōu)化的是靜態(tài)顯存,而梯度檢查優(yōu)化的是動態(tài)顯存。

1. 8bit Quantization

https://huggingface.co/blog/hf-bitsandbytes-integration

from_pretrained中的load_in_8bit參數是bitsandbytes庫賦予的能力,會把加載模型轉化成混合8bit的量化模型,注意這里的8bit模型量化只用于模型推理,通過量化optimizer state降低訓練時顯存的時8bit優(yōu)化器是另一個功能不要搞混喲~

模型量化本質是對浮點參數進行壓縮的同時,降低壓縮帶來的誤差。 8-bit quantization是把原始FP32(4字節(jié))壓縮到Int8(1字節(jié))也就是1/4的顯存占用。如上加載后會發(fā)現(xiàn)除lora層外的多數層被轉化成int類型如下

解密Prompt系列6. lora指令微調扣細節(jié)-請冷靜,1個小時真不夠~

當然壓縮方式肯定不是直接四舍五入,那樣會帶來巨大的精度壓縮損失。常見的量化方案有absolute-maximum和zero-point,它們的差異只是rescale的方式不同,這里簡單說下absmax,如下

解密Prompt系列6. lora指令微調扣細節(jié)-請冷靜,1個小時真不夠~

先尋找tensor矩陣的絕對值的最大值,并計算最大值到127的縮放因子,然后使用該縮放因子對整個tensor進行縮放后,再round到整數。這樣就把浮點數映射到了INT8,逆向回到float的原理相同。

當然以上的縮放方案依舊存在精度損失,以及當矩陣中存在outlier時,這個精度損失會被放大,例如當tensor中絕大部分取值在1以下,有幾個值在100+,則縮放后,所有1以下的tensor信息都會被round抹去。因此LLM.int8()的實現(xiàn)對outlier做了進一步的優(yōu)化,把outlier和非outlier的矩陣分開計算,再把結果進行合并來降低outlier對精度的影響。

解密Prompt系列6. lora指令微調扣細節(jié)-請冷靜,1個小時真不夠~

prepare_model_for_int8_training是對在Lora微調中使用LLM.int8()進行了適配用來提高訓練的穩(wěn)定性,主要包括

  • layer norm層保留FP32精度
  • 輸出層保留FP32精度保證解碼時隨機sample的差異性

2. gradient checkpoint

https://medium.com/tensorflow/fitting-larger-networks-into-memory-583e3c758ff9

prepare_model_for_int8_training函數還做了一件事就是設置gradient_checkpointing=True,這是另一個時間換空間的技巧。

gradient checkpoint的實現(xiàn)是在向前傳播的過程中使用torch.no_grad()不去存儲中間激活值,降低動態(tài)顯存的占用。而只是保存輸入和激活函數,當進行反向傳播的時候,會重新獲取輸入和激活函數計算激活值用于梯度計算。因此向前傳播會計算兩遍,所以需要更多的訓練時間。

use_cache設置為False,是因為和gradient checkpoint存在沖突。因為use_cache是對解碼速度的優(yōu)化,在解碼器解碼時,存儲每一步輸出的hidden-state用于下一步的輸入,而因為開啟了gradient checkpoint,中間激活值不會存儲,因此use_cahe=False。其實#21737已經加入了參數檢查,這里設置只是為了不輸出warning。

模型訓練

訓練基本和常規(guī)訓練基本相同,代碼如下。主要說下模型存儲和加載以及混合精度訓練

import datasets
from transformers import Trainer, DataCollatorForSeq2Seq

if resume_from_checkpoint:
    lora_weight = torch.load(ckpt_name)
    set_peft_model_state_dict(model, lora_weight)

train_data = datasets.load_from_disk(dataset_path)

class ModifiedTrainer(Trainer):
    def save_model(self, output_dir=None, _internal_call=False):
        # 改寫trainer的save_model,在checkpoint的時候只存lora權重
        from transformers.trainer import TRAINING_ARGS_NAME

        os.makedirs(output_dir, exist_ok=True)
        torch.save(self.args, os.path.join(output_dir, TRAINING_ARGS_NAME))
        saved_params = {
            k: v.to("cpu") for k, v in self.model.named_parameters() if v.requires_grad
        }
        torch.save(saved_params, os.path.join(output_dir, "adapter_model.bin"))
        
trainer = ModifiedTrainer(
    model=model,
    train_dataset=train_data,
        args=transformers.TrainingArguments(
            per_device_train_batch_size=8,
            gradient_accumulation_steps=16,
            num_train_epochs=10,
            learning_rate=3e-4,
            fp16=True,
            logging_steps=10,
            save_steps=200,
            output_dir=output_dir
        ),
    data_collator=DataCollatorForSeq2Seq(
        tokenizer, pad_to_multiple_of=8, return_tensors="pt", padding=True
    ),
)
trainer.train()
model.save_pretrained(train_args.output_dir)

1. 模型的存儲和加載

因為peftModel重寫了原始model的save_pretrained函數,只把lora層的權重進行存儲,因此model.save_pretrained只會存儲lora權重。而trainer的save_model函數沒有做相應的重寫,因此我們重寫下對應的function,避免checkpoint寫入原始模型全部參數。

相應的如果你從ckpt加載lora權重去繼續(xù)訓練的話,也是對PeftModel中的Lora權重進行加載。

2. 混合精度訓練

https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#fp16-training

除了默認的全精度FP32,參數精度還有半精度FP16,以及BF16和TF32。最常用也是這里使用的是FP16的混合精度。

解密Prompt系列6. lora指令微調扣細節(jié)-請冷靜,1個小時真不夠~

實現(xiàn)原理是并非所有變量都需要全精度存儲,如果把部分中間變量轉化成半精度,則計算效率會大幅提升,加上一些GPU對FP16計算做了優(yōu)化,吞吐上比全精度會快2~5倍。

不過只使用半精度訓練同樣會帶來量化誤差,主要包括:數據溢出因為半精度比全精度的范圍更小,訓練到后期因為梯度越來越小可能會下溢出;舍入誤差梯度變小后,因為精度有限,導致梯度更新被四舍五入,更新了個寂寞。

為了解決以上的問題引入了混合精度訓練。簡單來說就是向前傳遞時,模型權重、激活值和梯度都使用FP16進行存儲,同時會拷貝一份模型權重以FP32存儲,向后傳播optimizer更新時會更新FP32的參數。因此混合精度訓練并不會節(jié)省內存,只會提高模型訓練速度。

模型推理

推理有兩個方案,一個和訓練相同,直接加入Lora層,不過會增加推理延時因為多了lora層的計算,適合線下測評用,如下

from peft import PeftModel
from transformers import AutoModel, AutoTokenizer

model = AutoModel.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True, load_in_8bit=True, device_map='auto')
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True)
model = PeftModel.from_pretrained(model, "./lora_ckpt")
model.half().to(device)
model.eval()

另一個沒有推理延時的方案,是先把lora權重和原始模型權重進行合并,把合并后的參數存儲成新的bin文件,然后和加載常規(guī)模型一樣加載合并后的模型參數進行推理。權重合并的代碼如下

tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True)
# when merging disable int8
model = AutoModel.from_pretrained(
    "THUDM/chatglm-6b", load_in_8bit=False, torch_dtype=torch.float16,
    trust_remote_code=True, device_map={"": "cpu"},
)
## 用來檢查權重是否合并成功,合并成功weight會改變
first_weight = model.base_model.layers[0].attention.query_key_value.weight
first_weight_old = first_weight.clone()

# 返回的不是新的模型,而是在原始模型上加了adapter層
lora_model = PeftModel.from_pretrained(
    model,
    "./lora_ckpt",
    device_map={"": "cpu"},
    torch_dtype=torch.float16,
)
# 報錯:A*B shape mismatch,大概率是get_peft_model錯誤修改了peft_config里面的fan_in_fan_out參數,某個peft的revision有這個bug
lora_model = lora_model.merge_and_unload()
lora_model.train(False)

# 報錯:大概率peft訓練有問題,檢查adapter.bin大小
assert not torch.allclose(first_weight_old, first_weight), 'Weight Should Change after Lora Merge'

# lora模型權重把原模型權重加了prefix,這里移除恢復原始key
deloreanized_sd = {
    k.replace("base_model.model.", ""): v
    for k, v in lora_model.state_dict().items()
    if "lora" not in k
}
# 保存合并后的模型權重
lora_model.save_pretrained(output_dir, state_dict=deloreanized_sd)

更多Prompt相關論文·教程,開源數據·模型,以及AIGC相關玩法戳這里DecryptPrompt


Reference文章來源地址http://www.zghlxwxcb.cn/news/detail-429031.html

  1. https://blog.csdn.net/anycall201/article/details/129959567
  2. 蘇劍林. (Jun. 20, 2022). 《Ladder Side-Tuning:預訓練模型的“過墻梯” 》[Blog post]. Retrieved from https://kexue.fm/archives/9138
  3. 蘇劍林. (Apr. 17, 2023). 《梯度視角下的LoRA:簡介、分析、猜測及推廣 》[Blog post]. Retrieved from https://kexue.fm/archives/9590
    4.https://github.com/huggingface/blog/blob/main/notebooks/HuggingFace_int8_demo.ipynb
  4. ChatGLM-Finetune
  5. Alpaca-lora

到了這里,關于解密Prompt系列6. lora指令微調扣細節(jié)-請冷靜,1個小時真不夠~的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 解密prompt系列5. APE+SELF=自動化指令集構建代碼實現(xiàn)

    解密prompt系列5. APE+SELF=自動化指令集構建代碼實現(xiàn)

    上一章我們介紹了不同的指令微調方案, 這一章我們介紹如何降低指令數據集的人工標注成本!這樣每個人都可以構建自己的專屬指令集, 哈哈當然我也在造數據集進行時~ 介紹兩種方案SELF Instruct和Automatic Prompt Engineer,前者是基于多樣的種子指令,利用大模型的上下文和指令

    2023年04月10日
    瀏覽(26)
  • 基于LLAMA-7B的lora中文指令微調

    基于LLAMA-7B的lora中文指令微調

    前言: 系統(tǒng):ubuntu18.04 顯卡:GTX3090 - 24G (慘呀,上次還是A100,現(xiàn)在只有3090了~) (本文旨在快速實現(xiàn)基于llama-7b的中文指令微調) 咱們還是用lit-llama(環(huán)境安裝過程見上篇博客) 地址:https://github.com/Lightning-AI/lit-llama 模型下載 在huggingface上搜索\\\"llama chinese\\\",我們選以下這

    2024年02月12日
    瀏覽(23)
  • 【Midjourney】Midjourney 的 Prompt 指令類型 ( 畫風指令 | 人物細節(jié)指令 | 燈光鏡頭指令 | 藝術家風格指令 )

    【Midjourney】Midjourney 的 Prompt 指令類型 ( 畫風指令 | 人物細節(jié)指令 | 燈光鏡頭指令 | 藝術家風格指令 )

    在 Midjourney 中 , 使用簡單的指令 , 如幾個單詞 , 如果不添加其它詳細的指令 或 參數 , 生成的圖像隨機性很大 , 無法獲取預期的圖像 ; 更詳細的 Prompt 提示詞描述包括 : 畫風指令 人物細節(jié) 燈光鏡頭 藝術家風格 參數設置 常用的 畫風指令 / 繪圖風格 : 超現(xiàn)實主義 : hype

    2024年02月05日
    瀏覽(32)
  • 快速訓練自己的大語言模型:基于LLAMA-7B的lora指令微調

    快速訓練自己的大語言模型:基于LLAMA-7B的lora指令微調

    前言: 系統(tǒng):ubuntu 18.04 顯卡:A100-80G(蹭的,嘿嘿~) (本次主要記錄如何快速進行大模型的指令微調) 地址:https://github.com/Lightning-AI/lit-llama 切換到工程目錄 使用pip安裝依賴庫 (當然,這里可能會遇到網絡問題,安裝不了lightning) 可使用以下方式安裝: 下載lightning工程

    2024年02月11日
    瀏覽(25)
  • [NLP]LLM---大模型指令微調中的“Prompt”

    [NLP]LLM---大模型指令微調中的“Prompt”

    大家有沒有分析過 prompt對模型訓練或者推理的影響?之前推理的時候,發(fā)現(xiàn)不加訓練的時候prompt,直接輸入模型性能會變差的,這個倒是可以理解。假如不加prompt直接訓練,是不是測試的時候不加prompt也可以?還有一個就是多輪prompt和單輪prompt怎么構造的問題?好多模型訓練

    2024年02月09日
    瀏覽(20)
  • 【ChatGLM_02】LangChain知識庫+Lora微調chatglm2-6b模型+提示詞Prompt的使用原則

    【ChatGLM_02】LangChain知識庫+Lora微調chatglm2-6b模型+提示詞Prompt的使用原則

    運行l(wèi)angchain-ChatGLM-master下面的webui.py文件 (1) 配置知識庫 新建知識庫 向知識庫當中添加文件 支持上傳的數據格式:word、pdf、excel、csv、txt、文件夾等。但是此處我試了一下 (2) 文檔數據測試 word文檔測試: (3) 知識庫測試模式 知識庫測試只會返回輸入內容在當前知識庫當中的

    2024年02月14日
    瀏覽(24)
  • LLMs:LLaMA Efficient Tuning(一款可高效微調【全參數/LoRA/QLoRA】主流大模型【ChatGLM2/LLaMA2/Baichuan等】的高效工具【預訓練+指令監(jiān)督微調+

    LLMs:LLaMA Efficient Tuning(一款可高效微調【全參數/LoRA/QLoRA】主流大模型【ChatGLM2/LLaMA2/Baichuan等】的高效工具【預訓練+指令監(jiān)督微調+

    LLMs:LLaMA Efficient Tuning(一款可高效微調【全參數/LoRA/QLoRA】主流大模型【ChatGLM-2/LLaMA-2/Baichuan等】的高效工具【預訓練+指令監(jiān)督微調+獎勵模型訓練+PPO 訓練+DPO 訓練】)的簡介、安裝、使用方法之詳細攻略 目錄 相關文章 LLMs之ChatGLM:ChatGLM Efficient Tuning(一款高效微調ChatGLM-6B/Ch

    2024年02月09日
    瀏覽(34)
  • llama-factory SFT 系列教程 (四),lora sft 微調后,使用vllm加速推理

    llama-factory SFT 系列教程 (四),lora sft 微調后,使用vllm加速推理

    llama-factory SFT系列教程 (一),大模型 API 部署與使用 llama-factory SFT系列教程 (二),大模型在自定義數據集 lora 訓練與部署 llama-factory SFT系列教程 (三),chatglm3-6B 命名實體識別實戰(zhàn) llama-factory SFT 系列教程 (四),lora sft 微調后,使用vllm加速推理 llama-factory 提供了 vllm API 部署,但筆

    2024年04月27日
    瀏覽(20)
  • 解密Prompt系列10. 思維鏈COT原理探究

    解密Prompt系列10. 思維鏈COT原理探究

    前一章思維鏈基礎和進階玩法我們介紹了如何寫Chain-of-thought Prompt來激活生成逐步推理,并提高模型解決復雜問題的能力,這一章我們追本溯源,討論下COT的哪些元素是提升模型表現(xiàn)的核心? 要進行因果分析,需要把思維鏈中的不同元素拆解開來,然后通過控制變量實驗,來

    2024年02月11日
    瀏覽(23)
  • 分布式 - 服務器Nginx:一小時入門系列之 rewrite 指令

    1. rewrite 指令語法 nginx的rewrite指令用于重寫URL,可以將一個URL重寫為另一個URL。它的語法如下: 其中,regex是一個正則表達式,用于匹配需要重寫的URL;replacement是重寫后的URL;flag是可選的標志,用于控制重寫的行為。flag 的常見取值為 last 和 break,都是用于控制重寫規(guī)則執(zhí)

    2024年02月11日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包