ishandutta2007awesome-masked-language-modeling

2026年08月11日 | 来源:
信息源:

📋 多平台草稿预览 (12平台差异化改编)

遮蔽语言模型:当AI学会“猜词”,一场NLP的静默革命正在发生

想象一下,你拿到一篇文章,其中20%的词汇被涂黑。你不仅需要猜出这些词,还要在猜测过程中理解整篇文章的语义、语法和上下文——这就是遮蔽语言模型(Masked Language Modeling)的核心训练范式。这项看似简单的“填空”技术,正是GPT、BERT等大模型背后的基石,也是AI从“语法正确”走向“语义理解”的关键一跃。

想象一下,你拿到一篇文章,其中20%的词汇被涂黑。你不仅需要猜出这些词,还要在猜测过程中理解整篇文章的语义、语法和上下文——这就是遮蔽语言模型(Masked Language Modeling)的核心训练范式。这项看似简单的“填空”技术,正是GPT、BERT等大模型背后的基石,也是AI从“语法正确”走向“语义理解”的关键一跃。

从“预测下一个词”到“还原被遮蔽的词”

在深度学习统治NLP之前,语言模型的主流范式是“自回归”——从左到右逐词预测。这种模式像极了我们小时候的“接龙游戏”:给定前文,预测下一个词。但它的致命缺陷在于:模型只能利用左侧的上下文信息,无法同时参考右侧语境。这就像一个只看得见过去、看不见未来的旅人,在语言迷宫中摸索前行。

2018年,BERT(Bidirectional Encoder Representations from Transformers)的诞生彻底改变了这一局面。它的核心创新正是遮蔽语言建模:随机将输入文本中15%的token替换为[MASK]标记,然后训练模型根据双向上下文预测这些被遮蔽的词。这个看似简单的改动,让模型第一次能够同时利用左右两侧的语境信息,实现了真正的“双向理解”。

技术原理:一场精心设计的“猜词游戏”

让我们深入技术细节。遮蔽语言模型的训练过程包含三个关键步骤:

1. 动态遮蔽策略

并非所有token都同等重要。研究者们设计了一套精妙的遮蔽策略:80%的概率用[MASK]替换,10%的概率用随机词替换,10%的概率保持不变。这种“以假乱真”的策略迫使模型不依赖特定位置的固定词,而是真正理解上下文语义。

2. 双向Transformer编码器

与GPT的因果注意力不同,遮蔽语言模型使用双向注意力机制。每个token都能“看到”序列中的所有其他token(包括被遮蔽的位置),这要求模型必须在完整语境中推断缺失信息。

3. 预训练+微调范式

遮蔽语言模型首先在海量无标注语料上进行预训练,学习通用语言知识;然后在特定下游任务(如情感分析、命名实体识别)上进行微调。这种“先通识教育,再专业训练”的模式,让模型具备了极强的迁移学习能力。

下面是一个简单的PyTorch代码示例,展示如何使用HuggingFace的transformers库微调一个遮蔽语言模型:

from transformers import BertTokenizer, BertForMaskedLM, DataCollatorForLanguageModeling
from transformers import Trainer, TrainingArguments
import torch

# 加载预训练模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForMaskedLM.from_pretrained('bert-base-uncased')

# 准备训练数据
texts = ["The quick brown fox jumps over the lazy dog.", 
         "Artificial intelligence is transforming the world."]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# 创建数据整理器,自动应用遮蔽策略
data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer,
    mlm=True,
    mlm_probability=0.15
)

# 设置训练参数
training_args = TrainingArguments(
    output_dir="./mlm_finetuned",
    num_train_epochs=3,
    per_device_train_batch_size=8,
    save_steps=500,
)

# 创建Trainer并开始训练
trainer = Trainer(
    model=model,
    args=training_args,
    data_collator=data_collator,
    train_dataset=inputs['input_ids'],
)

trainer.train()

从“猜词”到“理解”:MLM的深远影响

遮蔽语言模型的影响远不止于提升NLP任务的准确率。它带来了一场认知层面的革命:

1. 上下文感知的表示学习

传统词向量(如Word2Vec)为每个词分配固定向量,无法处理一词多义。而MLM训练的模型能为每个token生成动态的上下文表示——在“苹果公司”和“苹果很甜”中,“苹果”的向量表示截然不同。这种动态性让模型真正理解语言的使用场景。

2. 跨任务泛化能力

通过遮蔽语言建模预训练的模型,在自然语言推理、问答、文本分类等众多下游任务上表现卓越。2023年的一项研究表明,基于MLM的模型在零样本场景下的表现比传统方法提升了约23%,这意味着模型不仅“记住了知识”,更“理解了语义”。

3. 多模态扩展

MLM的范式已被扩展到视觉-语言领域。例如,BERT的变体模型VL-BERT和UniLM通过遮蔽图像区域或文本片段,学习跨模态的语义对齐。这种“多模态遮蔽”正在推动AI从纯文本理解走向多感官融合。

<svg viewBox="0 0 800 400" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" style="stop-color:#667eea;stop-opacity:0.1" />
      <stop offset="100%" style="stop-color:#764ba2;stop-opacity:0.1" />
    </linearGradient>
    <linearGradient id="lineGrad" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:#667eea" />
      <stop offset="100%" style="stop-color:#764ba2" />
    </linearGradient>
  </defs>
  
  <rect width="800" height="400" fill="url(#bgGrad)" rx="15"/>
  
  <!-- Title -->
  <text x="400" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#2d3748">
    Masked Language Model Training Pipeline
  </text>
  
  <!-- Input text -->
  <rect x="50" y="80" width="200" height="50" rx="8" fill="#667eea" opacity="0.8"/>
  <text x="150" y="110" text-anchor="middle" font-family="monospace" font-size="14" fill="white">
    Original Text
  </text>
  
  <!-- Masking step -->
  <rect x="300" y="80" width="200" height="50" rx="8" fill="#764ba2" opacity="0.8"/>
  <text x="400" y="105" text-anchor="middle" font-family="monospace" font-size="13" fill="white">
    "The [MASK] fox"
  </text>
  <text x="400" y="122" text-anchor="middle" font-family="Arial" font-size="11" fill="#e2e8f0">
    15% tokens masked
  </text>
  
  <!-- Model -->
  <rect x="550" y="80" width="200" height="50" rx="8" fill="#48bb78" opacity="0.8"/>
  <text x="650" y="105" text-anchor="middle" font-family="Arial" font-size="14" fill="white">
    BERT Encoder
  </text>
  <text x="650" y="122" text-anchor="middle" font-family="Arial" font-size="11" fill="#f0fff4">
    Bidirectional Attention
  </text>
  
  <!-- Arrows between steps -->
  <defs>
    <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
      <polygon points="0 0, 10 3.5, 0 7" fill="#4a5568"/>
    </marker>
  </defs>
  
  <line x1="250" y1="105" x2="295" y2="105" stroke="#4a5568" stroke-width="2" marker-end="url(#arrowhead)"/>
  <line x1="500" y1="105" x2="545" y2="105" stroke="#4a5568" stroke-width="2" marker-end="url(#arrowhead)"/>
  
  <!-- Output prediction -->
  <rect x="300" y="200" width="200" height="50" rx="8" fill="#ed8936" opacity="0.8"/>
  <text x="400" y="225" text-anchor="middle" font-family="monospace" font-size="13" fill="white">
    Predict: "quick"
  </text>
  <text x="400" y="242" text-anchor="middle" font-family="Arial" font-size="11" fill="#fffaf0">
    Softmax over vocab
  </text>
  
  <line x1="650" y1="130" x2="650" y2="170" stroke="#4a5568" stroke-width="2"/>
  <line x1="650" y1="170" x2="400" y2="195" stroke="#4a5568" stroke-width="2" marker-end="url(#arrowhead)"/>
  
  <!-- Loss -->
  <rect x="550" y="200" width="200" height="50" rx="8" fill="#f56565" opacity="0.8"/>
  <text x="650" y="225" text-anchor="middle" font-family="Arial" font-size="14" fill="white">
    Cross-Entropy Loss
  </text>
  <text x="650" y="242" text-anchor="middle" font-family="Arial" font-size="11" fill="#fff5f5">
    Compare with original
  </text>
  
  <line x1="500" y1="225" x2="545" y2="225" stroke="#4a5568" stroke-width="2" marker-end="url(#arrowhead)"/>
  
  <!-- Iteration loop -->
  <path d="M 400 250 L 400 300 L 650 300 L 650 255" fill="none" stroke="#4a5568" stroke-width="2" stroke-dasharray="5,5" marker-end="url(#arrowhead)"/>
  <text x="525" y="320" text-anchor="middle" font-family="Arial" font-size="12" fill="#718096">
    Iterative Training Loop
  </text>
  
  <!-- Application -->
  <rect x="250" y="345" width="300" height="40" rx="8" fill="#4299e1" opacity="0.7"/>
  <text x="400" y="370" text-anchor="middle" font-family="Arial" font-size="13" fill="white">
    Fine-tune on Downstream Tasks
  </text>
  
  <line x1="400" y1="300" x2="400" y2="340" stroke="#4a5568" stroke-width="2" marker-end="url(#arrowhead)"/>
</svg>

前沿进展与争议

尽管遮蔽语言模型取得了巨大成功,但它并非没有争议。批评者指出:

  • 计算开销:与自回归模型相比,MLM需要更多的训练资源,因为每个训练样本都包含多个遮蔽位置需要预测。
  • 训练-推理不匹配:预训练时使用[MASK]标记,但下游任务中不会出现该标记,这种不一致可能影响模型性能。
  • 长文本处理:MLM对长序列的处理能力有限,因为双向注意力机制的计算复杂度是输入长度的平方。

针对这些问题,研究者们提出了多种改进方案。例如,ELECTRA使用“替换token检测”替代遮蔽预测,大幅提升训练效率;XLNet通过排列语言建模结合了自回归和双向上下文优势;而T5则将MLM统一为“文本到文本”的生成框架。

未来展望:超越“填空”的智能

遮蔽语言模型的意义不仅在于技术本身,更在于它揭示了AI理解语言的一种可能路径:理解源于预测,预测促进理解。当我们让AI不断猜测缺失的信息,它实际上在建构对世界的内部模型——这正是认知科学中“预测加工理论”的核心观点。

随着模型规模持续扩大(如GPT-4、PaLM-2),遮蔽语言建模正在与指令微调、人类反馈强化学习等技术融合,催生出更强大的AI系统。但无论如何演进,“让机器学会猜词”这一简单而深刻的思想,都将作为大语言模型发展史上的重要里程碑而被铭记。



排版建议:
  • 标题字号 18px,加粗
  • 正文 15px,#333333
  • 引用块 #888888 14px
  • 代码块使用深色背景
  • 段落间距 1.75 倍行距
  • 图片居中,宽度 100%

https://github.com/ishandutta2007/Awesome-Masked-Language-Modeling

标签:#机器学习, #自然语言处理, #大语言模型

知乎回答


问题:如何看待 遮蔽语言模型:当AI学会“猜词”,一场NLP的静默革命正在发生?


想象一下,你拿到一篇文章,其中20%的词汇被涂黑。你不仅需要猜出这些词,还要在猜测过程中理解整篇文章的语义、语法和上下文——这就是遮蔽语言模型(Masked Language Modeling)的核心训练范式。这项看似简单的“填空”技术,正是GPT、BERT等大模型背后的基石,也是AI从“语法正确”走向“语义理解”的关键一跃。

想象一下,你拿到一篇文章,其中20%的词汇被涂黑。你不仅需要猜出这些词,还要在猜测过程中理解整篇文章的语义、语法和上下文——这就是遮蔽语言模型(Masked Language Modeling)的核心训练范式。这项看似简单的“填空”技术,正是GPT、BERT等大模型背后的基石,也是AI从“语法正确”走向“语义理解”的关键一跃。

从“预测下一个词”到“还原被遮蔽的词”

在深度学习统治NLP之前,语言模型的主流范式是“自回归”——从左到右逐词预测。这种模式像极了我们小时候的“接龙游戏”:给定前文,预测下一个词。但它的致命缺陷在于:模型只能利用左侧的上下文信息,无法同时参考右侧语境。这就像一个只看得见过去、看不见未来的旅人,在语言迷宫中摸索前行。

2018年,BERT(Bidirectional Encoder Representations from Transformers)的诞生彻底改变了这一局面。它的核心创新正是遮蔽语言建模:随机将输入文本中15%的token替换为[MASK]标记,然后训练模型根据双向上下文预测这些被遮蔽的词。这个看似简单的改动,让模型第一次能够同时利用左右两侧的语境信息,实现了真正的“双向理解”。

技术原理:一场精心设计的“猜词游戏”

让我们深入技术细节。遮蔽语言模型的训练过程包含三个关键步骤:

1. 动态遮蔽策略

并非所有token都同等重要。研究者们设计了一套精妙的遮蔽策略:80%的概率用[MASK]替换,10%的概率用随机词替换,10%的概率保持不变。这种“以假乱真”的策略迫使模型不依赖特定位置的固定词,而是真正理解上下文语义。

2. 双向Transformer编码器

与GPT的因果注意力不同,遮蔽语言模型使用双向注意力机制。每个token都能“看到”序列中的所有其他token(包括被遮蔽的位置),这要求模型必须在完整语境中推断缺失信息。

3. 预训练+微调范式

遮蔽语言模型首先在海量无标注语料上进行预训练,学习通用语言知识;然后在特定下游任务(如情感分析、命名实体识别)上进行微调。这种“先通识教育,再专业训练”的模式,让模型具备了极强的迁移学习能力。

下面是一个简单的PyTorch代码示例,展示如何使用HuggingFace的transformers库微调一个遮蔽语言模型:

from transformers import BertTokenizer, BertForMaskedLM, DataCollatorForLanguageModeling
from transformers import Trainer, TrainingArguments
import torch

# 加载预训练模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForMaskedLM.from_pretrained('bert-base-uncased')

# 准备训练数据
texts = ["The quick brown fox jumps over the lazy dog.", 
         "Artificial intelligence is transforming the world."]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# 创建数据整理器,自动应用遮蔽策略
data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer,
    mlm=True,
    mlm_probability=0.15
)

# 设置训练参数
training_args = TrainingArguments(
    output_dir="./mlm_finetuned",
    num_train_epochs=3,
    per_device_train_batch_size=8,
    save_steps=500,
)

# 创建Trainer并开始训练
trainer = Trainer(
    model=model,
    args=training_args,
    data_collator=data_collator,
    train_dataset=inputs['input_ids'],
)

trainer.train()

从“猜词”到“理解”:MLM的深远影响

遮蔽语言模型的影响远不止于提升NLP任务的准确率。它带来了一场认知层面的革命:

1. 上下文感知的表示学习

传统词向量(如Word2Vec)为每个词分配固定向量,无法处理一词多义。而MLM训练的模型能为每个token生成动态的上下文表示——在“苹果公司”和“苹果很甜”中,“苹果”的向量表示截然不同。这种动态性让模型真正理解语言的使用场景。

2. 跨任务泛化能力

通过遮蔽语言建模预训练的模型,在自然语言推理、问答、文本分类等众多下游任务上表现卓越。2023年的一项研究表明,基于MLM的模型在零样本场景下的表现比传统方法提升了约23%,这意味着模型不仅“记住了知识”,更“理解了语义”。

3. 多模态扩展

MLM的范式已被扩展到视觉-语言领域。例如,BERT的变体模型VL-BERT和UniLM通过遮蔽图像区域或文本片段,学习跨模态的语义对齐。这种“多模态遮蔽”正在推动AI从纯文本理解走向多感官融合。

<svg viewBox="0 0 800 400" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" style="stop-color:#667eea;stop-opacity:0.1" />
      <stop offset="100%" style="stop-color:#764ba2;stop-opacity:0.1" />
    </linearGradient>
    <linearGradient id="lineGrad" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:#667eea" />
      <stop offset="100%" style="stop-color:#764ba2" />
    </linearGradient>
  </defs>
  
  <rect width="800" height="400" fill="url(#bgGrad)" rx="15"/>
  
  <!-- Title -->
  <text x="400" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#2d3748">
    Masked Language Model Training Pipeline
  </text>
  
  <!-- Input text -->
  <rect x="50" y="80" width="200" height="50" rx="8" fill="#667eea" opacity="0.8"/>
  <text x="150" y="110" text-anchor="middle" font-family="monospace" font-size="14" fill="white">
    Original Text
  </text>
  
  <!-- Masking step -->
  <rect x="300" y="80" width="200" height="50" rx="8" fill="#764ba2" opacity="0.8"/>
  <text x="400" y="105" text-anchor="middle" font-family="monospace" font-size="13" fill="white">
    "The [MASK] fox"
  </text>
  <text x="400" y="122" text-anchor="middle" font-family="Arial" font-size="11" fill="#e2e8f0">
    15% tokens masked
  </text>
  
  <!-- Model -->
  <rect x="550" y="80" width="200" height="50" rx="8" fill="#48bb78" opacity="0.8"/>
  <text x="650" y="105" text-anchor="middle" font-family="Arial" font-size="14" fill="white">
    BERT Encoder
  </text>
  <text x="650" y="122" text-anchor="middle" font-family="Arial" font-size="11" fill="#f0fff4">
    Bidirectional Attention
  </text>
  
  <!-- Arrows between steps -->
  <defs>
    <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
      <polygon points="0 0, 10 3.5, 0 7" fill="#4a5568"/>
    </marker>
  </defs>
  
  <line x1="250" y1="105" x2="295" y2="105" stroke="#4a5568" stroke-width="2" marker-end="url(#arrowhead)"/>
  <line x1="500" y1="105" x2="545" y2="105" stroke="#4a5568" stroke-width="2" marker-end="url(#arrowhead)"/>
  
  <!-- Output prediction -->
  <rect x="300" y="200" width="200" height="50" rx="8" fill="#ed8936" opacity="0.8"/>
  <text x="400" y="225" text-anchor="middle" font-family="monospace" font-size="13" fill="white">
    Predict: "quick"
  </text>
  <text x="400" y="242" text-anchor="middle" font-family="Arial" font-size="11" fill="#fffaf0">
    Softmax over vocab
  </text>
  
  <line x1="650" y1="130" x2="650" y2="170" stroke="#4a5568" stroke-width="2"/>
  <line x1="650" y1="170" x2="400" y2="195" stroke="#4a5568" stroke-width="2" marker-end="url(#arrowhead)"/>
  
  <!-- Loss -->
  <rect x="550" y="200" width="200" height="50" rx="8" fill="#f56565" opacity="0.8"/>
  <text x="650" y="225" text-anchor="middle" font-family="Arial" font-size="14" fill="white">
    Cross-Entropy Loss
  </text>
  <text x="650" y="242" text-anchor="middle" font-family="Arial" font-size="11" fill="#fff5f5">
    Compare with original
  </text>
  
  <line x1="500" y1="225" x2="545" y2="225" stroke="#4a5568" stroke-width="2" marker-end="url(#arrowhead)"/>
  
  <!-- Iteration loop -->
  <path d="M 400 250 L 400 300 L 650 300 L 650 255" fill="none" stroke="#4a5568" stroke-width="2" stroke-dasharray="5,5" marker-end="url(#arrowhead)"/>
  <text x="525" y="320" text-anchor="middle" font-family="Arial" font-size="12" fill="#718096">
    Iterative Training Loop
  </text>
  
  <!-- Application -->
  <rect x="250" y="345" width="300" height="40" rx="8" fill="#4299e1" opacity="0.7"/>
  <text x="400" y="370" text-anchor="middle" font-family="Arial" font-size="13" fill="white">
    Fine-tune on Downstream Tasks
  </text>
  
  <line x1="400" y1="300" x2="400" y2="340" stroke="#4a5568" stroke-width="2" marker-end="url(#arrowhead)"/>
</svg>

前沿进展与争议

尽管遮蔽语言模型取得了巨大成功,但它并非没有争议。批评者指出:

  • 计算开销:与自回归模型相比,MLM需要更多的训练资源,因为每个训练样本都包含多个遮蔽位置需要预测。
  • 训练-推理不匹配:预训练时使用[MASK]标记,但下游任务中不会出现该标记,这种不一致可能影响模型性能。
  • 长文本处理:MLM对长序列的处理能力有限,因为双向注意力机制的计算复杂度是输入长度的平方。

针对这些问题,研究者们提出了多种改进方案。例如,ELECTRA使用“替换token检测”替代遮蔽预测,大幅提升训练效率;XLNet通过排列语言建模结合了自回归和双向上下文优势;而T5则将MLM统一为“文本到文本”的生成框架。

未来展望:超越“填空”的智能

遮蔽语言模型的意义不仅在于技术本身,更在于它揭示了AI理解语言的一种可能路径:理解源于预测,预测促进理解。当我们让AI不断猜测缺失的信息,它实际上在建构对世界的内部模型——这正是认知科学中“预测加工理论”的核心观点。

随着模型规模持续扩大(如GPT-4、PaLM-2),遮蔽语言建模正在与指令微调、人类反馈强化学习等技术融合,催生出更强大的AI系统。但无论如何演进,“让机器学会猜词”这一简单而深刻的思想,都将作为大语言模型发展史上的重要里程碑而被铭记。



总结:

这个事件/技术的核心价值在于它推动了一个重要方向的发展。作为从业者/关注者,我们既要看到短期的影响,也要理解其长期意义。


https://github.com/ishandutta2007/Awesome-Masked-Language-Modeling

原文链接:https://github.com/ishandutta2007/Awesome-Masked-Language-Modeling

抖音口播脚本

时长:60秒以内


【开场 Hook(0-5秒)】

想象一下,你拿到一篇文章,其中20%的词汇被涂黑。你不仅需要猜出这些词,还要在猜测过程中理解整篇文章的语义、语法和上下文——这就是遮蔽语言模型(Masked Language Modeling)的核心训练范式。这项看似简单的“填空”技术,正是GPT、BERT等大模型背后的基石,也是AI从“语法正确”走向“语义理解”的关键一跃。


【核心内容(5-45秒)】

遮蔽语言模型:当AI学会“猜词”,一场NLP的静默革命正在发生

(根据文章正文提炼 3-5 个关键点,口语化表达)

【结尾引导(45-60秒)】

如果你觉得有用,点赞收藏,评论区告诉我你的看法!


拍摄建议:
  • 竖屏 9:16
  • 表情自然,语速适中
  • 关键信息配文字弹幕
  • 背景音乐:科技感电子乐

小红书笔记


遮蔽语言模型:当AI学会“猜词”,一场NLP的静默革命正在发生 🔥

想象一下,你拿到一篇文章,其中20%的词汇被涂黑。你不仅需要猜出这些词,还要在猜测过程中理解整篇文章的语义、语法和上下文——这就是遮蔽语言模型(Masked Language Modeling)的核心训练范式。这项看似简单的“填空”技术,正是GPT、BERT等大模型背后的基石,也是AI从“语法正确”走向“语义理解”的关键一跃。


💡 关键信息:

  • 来源:GitHub Trending
  • 更多详情见完整文章

##机器学习 ##自然语言处理 ##大语言模型

#科技资讯 #前沿技术

🚀 多平台发布

点击「复制」获取平台专属文案,到各平台编辑器(App/网页)粘贴即可发布。
有密钥的 4 个平台(微信服务号 / 头条 / 百家号 / 微博)可自动发布,密钥填好后自动点亮。

平台状态操作
💬 公众号🔑 待配置密钥
🤔 知乎📋 手动复制
🎵 抖音📋 手动复制
📕 小红书📋 手动复制