主流大模型技术笔记

本文作为笔记,通过阅读论文,记录市面上主流的大模型的技术内容。

大模型预备知识

🔥Llama3

论文:The Llama 3 Herd of Models
llama3相较于以往,数据量提升了,模型规模也提升了,算法架构并没有很复杂,使用的是标准的稠密的transformer模型,模型性能的提升主要得益于数据集的质量和多样性。

llama3表现

  • 表中是llama3基准测试表现,CoT代表回答问题前告诉模型应该怎么做,它和few shot都是llama模型很常用的后训练手段。模型的参数量对其效果的影响还是很大的。

整体概述

llama3架构
模型流程主要分为预训练后训练,预训练是让模型能够学会生成下一个token,相当于学会说话,理解语言;后训练则是让模型能够完成任务,在编码、数学等各类领域当中有提升。
llama3多模态

  • 多模态编码器预训练:为图像和语音分别训练编码器,模型学会视觉内容与自然语言描述之间的关系。语音编码器通过自监督方法训练,该方法屏蔽部分语音输入,并通过离散token表示重建被屏蔽的部分,从而使模型学习语音信号的结构。
  • 视觉适配模块训练:训练一个adapter,将预训练的图像编码器集成到预训练的语言模型中。adapter由一系列交叉注意力层组成,将图像编码器表示输入到语言模型中。adapter模块在文本-图像对上进行训练,使图像表示与语言表示对齐。在训练adapter时,更新图像编码器的参数的同时冻结语言模型的参数。最后还在视频-文本数据对上训练了一个视频adapter模块,使模型能够跨帧聚合信息。
  • 语音适配模块训练:通过一个adapter将语音编码器集成到模型中,将语音编码转换为可以直接输入微调语言模型的token表示。在SFT阶段,adapter模块和编码器的参数共同更新,以实现高质量的语音理解。在训练语音适配模块时,同样冻结语言模型。

数据处理

预训练时对数据做了大量工作,包括但不限于:

  1. 数据提取和清洗,将html通过工具提取内容,对于图像渲染的数学公式等也进行了提取,还发现markdown文本对于训练是有害的,就除去了,还移除了可能有不安全信息的网站;
  2. 数据退火,将质量好但体量小的数据集用于靠后阶段的训练,能够较好地提升模型(类似于考前背题);
  3. 使用启发式算法过滤数据,用模型做质量过滤;
  4. 各种去重

模型架构

Llama 3使用了标准的稠密Transformer架构,相较于llama2,llama3的模型架构上有小改动:

  1. GQA代替MHA。
  2. 多个无关文档同时训练时,标上注意力掩码,在计算注意力时两个文档之间不进行计算。
  3. 扩展词表,使用128K大小的字典,多语言能力提升,但是这方面依然不如GPT4。
  4. 使用旋转位置编码RoPE进行位置编码,RoPE基本频率超参数增加到500,000,这使模型能够更好地支持更长的上下文。

scaling law

scaling law

  • 如图,算力增长时,损失是比较接近线性下降的,意味着用小的模型就可以低成本地预测大的模型的效果如何。
  • 值得注意的是,当模型足够大时(右下角的弧线),曲线更加平滑,意味着此时样本量的影响没有那么大。
  • 基于scaling law,团队最终决定训练一个405B参数的旗舰模型。

训练硬件

四种并行训练方法

  • 为了扩展Llama 3最大模型的训练,团队使用了4D并行方法——结合了四种不同类型的并行方法来分片模型。这种方法有效地将计算任务分布在多个GPU上,并确保每个GPU的模型参数、优化器状态、梯度和激活都能适应其高带宽内存(HBM)。
  1. 张量并行:将单个权重张量分割成多个块并分配到不同的设备上。
  2. 流水线并行:将模型按层垂直分成多个阶段,使得不同的设备可以并行处理完整模型流水线的不同阶段。
  3. 上下文并行:将输入上下文分割成段,减少长序列输入的内存瓶颈。
  4. 完全分片的数据并行(FSDP):将模型、优化器和梯度分片,同时实现数据并行,即在多个GPU上并行处理数据,并在每个训练步骤后同步。

训练配方

  • 预训练Llama 3 405B的配方包括三个主要阶段:(1)初始预训练(2)长上下文预训练(3)退火。
  • 后训练策略的核心是奖励模型语言模型,步骤如下(要按顺序):
    • RM阶段:先在预训练检查点上训练一个奖励模型(RM),它会学习如何对回答(偏好数据)采取次序不同的三个响应——(编辑 > 选择 > 拒绝),偏好数据是人工严格标注的;
    • SFT阶段:使用奖励模型对人工标注的提示词进行拒绝采样(Rejection sampling,RS),即面对多个答案,RM通过评分函数排序这些答案,过滤掉比较差的答案,生成了新的数据,这些数据被用来微调LLM;
    • DPO阶段:使用直接偏好优化(DPO)对SFT模型进行人类偏好对齐。训练时,他们主要使用前几轮对齐中表现最佳模型收集的最新偏好数据,因此训练数据更符合每轮优化的策略模型的分布,DPO效果好过PPO等探索类算法;
    • 最后,对在每个RM、SFT或DPO阶段使用不同版本的数据或超参数进行实验所获得的模型进行加权平均

🔥ChatGLM

论文:ChatGLM1ChatGLM4

🚢ChatGLM1

1代使用的是encoder-decoder架构,也就是seq2seq的思想。

预训练

GLM的核心技术就在于预训练任务的设计。

GLM填空任务

  • 如图,GLM预训练时,在输入文本中,随机删除连续的tokens,模型以自回归的方式从损坏的文本中预测缺失的词,这意味着在预测一个片段中的缺失词时,模型可以访问损坏的文本和之前预测的片段。
  • 为了充分捕捉不同片段之间的相互依赖关系,会随机打乱片段的顺序,类似于排列语言模型。

GLM预训练方案

  • 输入被分成两部分:Part A是缺失的文本,Part B是被遮盖的片段。Part A的词可以相互看到,但不能看到 Part B中的任何词。Part B的词可以看到Part A和Part B中的前置词,但不能看到Part B中的后续词。
  • 为了实现自回归生成,每个片段都用特殊的符号 [START][END] 进行填充。
  • 在GLM中,使用二维位置编码,第一个位置id用来标记Part A中的位置,第二个位置id用来表示跨度内部的相对位置。
  • 上图d部分也展示了A可以互相看到,B能看到完整的A、B的前面部分而看不到B的后面。

模型结构

在原始Transformer模块的基础上进行了一些修改:

  • 重组了LN和残差连接的顺序;
  • 使用单个线性层对输出token进行预测;
  • 激活函数从ReLU换成了GeLUS。

🚢ChatGLM2

主要提升:更长的上下文,更强大的性能,更高效的推理,更开放的协议。

  • 改进:
  1. RoPE替换二维位置编码;
  2. MQA替换MHA;
  3. 完全的decoder-only:不区分Part A/B,1代中Part A是双向注意力(可以看到后文),这代全部token都无法看到后文;
  4. 多目标任务:去掉特殊任务的token。

🚢ChatGLM3

架构与2代一致,整体变化不大,算是一个普通的迭代。

  • 2、3代相较于1代的共同变化:
  1. 位置编码改为从每个GLMBlock一份提升为全局一份;
  2. 词表的大小从ChatGLM的150528缩小为65024,加载更快;
  3. 激活函数改成Swish-1。

🚢ChatGLM4

GLM4整体性能相比GLM3全面提升60%,逼近GPT-4;支持更长上下文;更强的多模态;支持更快推理速度,更多并发,大大降低推理成本;同时GLM-4增强了智能体能力。

GLM4的agent能力

  • GLM-4 实现自主根据用户意图,自动理解、规划复杂指令,自由调用网页浏览器、Code Interpreter代码解释器和多模态文生图大模型,以完成复杂任务。
  • 简单来讲,即只需一个指令,GLM-4会自动分析指令,结合上下文选择决定调用合适的工具。
  • 可以实现文生图、代码解释器、网页浏览、函数调用等工具的使用,还可以一次调用多个工具。

🔥DeepSeek

论文:DeepSeek-v3DeepSeek-R1

DeepSeek-v3改进了transformer内部结构和整体架构,在辅助损失函数等方面也有创新,使用监督微调和强化学习作为后训练手段提升模型性能。而且训练时间、耗费资源和GPT等模型相比都极具优势。

deepseek-v3表现

  • deepseek-v3在编程和数学方面尤为强势,其他方面也相当优秀

DeepSeek-R1是仅基于强化学习,不使用监督学习微调(SFT)的模型,性能强于OpenAI-o1,各方面表现都是最强的。它增加了思考环节,使用蒸馏手段训练了很强的小模型。

deepseek-R1表现

🚢DeepSeek-v3

deepseek-v3核心改进
deepseek-v3对transformer的MLP(前馈网络)和注意力机制进行了改进,得到 DeepSeekMoEMLA

MLA

Multi-head Latent Attention(MLA)是基于transformer的多头注意力机制(MHA)改进得到的。
MLA改进部分

  • 如图所示,MLA在MHA前面增加了一些计算过程(可学习)生成QKV,而不是将输入直接作为QKV。主要是通过低秩联合压缩来减小KV cache的大小,从而提高推理速度。图中阴影部分是需要缓存的内容。
  • 如图kv生成的部分,上一层的输入通过降采样矩阵生成ct,再通过上采样矩阵生成K和V,这意味着KV cache只需要缓存内存占用更小的ct,而不用缓存K、V。
  • 可以看到输入进MHA的k由两个部分拼接而成,左边的是输入特征通过旋转位置向量(RoPE)进行位置编码生成的k(这个k连同ct需要缓存),主要提供位置信息;右边的是通过低秩联合压缩生成的k,主要提供内容信息。
  • Q这边,是输入特征通过降采样矩阵生成ct,ct分别通过上采样和位置编码生成两种q,拼接后获得Q输入MHA。虽然Q不需要缓存,但是可能是为了QK操作的对称性,还是进行了这些操作。
  • 总的来说,MLA增加了计算量,但是降低了内存压力,相当于小的时间换了大的空间。

MoE

混合专家机制(MoE),不同于MLP每个神经元无时无刻都在起作用,MoE是一种稀疏的网络模型。
DeepSeekMoE

  • 网络由多个共享专家(shared experts)和路由专家(routed experts)组成。如图,绿色的共享专家是必定激活的,而蓝色的路由专家是可选择激活的。路由器router负责选择top k个路由专家激活。

MoE机制

  • 公式如上,模块输出h = 输入u(残差连接) + 共享专家输出 + 路由专家输出。g是路由专家的亲合度分数由输入u和路由器的向量e(可学习)求相似度求得,也就是路由器会学习如何根据输入选择最合适的Kr个路由专家进行推理。所以路由专家的输出其实是加权的,g会作为每个路由专家的话语权参与输出的计算。

无辅助损失负载均衡

  • 为了防止某些路由专家过多或者过少地参与,过去会新设置辅助损失来惩罚这种不均的情况,这会降低模型性能、增加计算量。如上图,deepseek采用无辅助损失负载均衡(auxiliary-loss-free load balancing),即在训练过程中,为每个专家添加一个偏置b参与亲合度g的计算。当某个专家被激活时,b会降低来减少下一次激活的可能性,反之亦然。

MTP

Multi-Token Prediction(MTP)可以高效重复利用特征,使得模型一次生成多个token,以提升预测效果。
MTP

  • 如图主模型(main model)是原本的transformer结构,主模型主干部分在输出特征用于预测时,该特征也被输入到MTP(只有一个transformer块)来生成多一个的token,有n个MTP就能生成n+1个token。
  • 损失计算时,所有MTP损失求均值,再加权后参与损失计算即可。
  • 实验表明,MTP策略在绝大多数评估指标上都带来了持续的性能提升。

混合精度框架

混合精度框架

  • 大部分核心密集计算操作(前向、反向传播),均采用FP8精度实现。
  • 而关键操作则保持原有数据格式(BF16 或 FP32),向量层、输出层、MoE 门控模块、标准化运算和注意力运算模块。如此混合精度训练以实现训练效率和数值稳定性的最优平衡。

后训练

  • SFT:对每个训练实例,系统生成两类 SFT 样本,一类是问题与原始答案的直接配对,另一类则引入系统提示词,将其与问题和 R1 答案组合。
  • RL:系统同时采用规则型模型型两种奖励模型,前者用于明确规则的任务(比如写代码、按特定格式回答),可以用规则直接验证,可靠性强;后者则是应对写作等没有标准答案的任务,奖励模型则基于问题和回答的整体性给出评估反馈。
  • RL沿用了V2的群组相对策略优化(GRPO)算法,这种方法不需要与策略模型规模相当的评论家模型,而是通过群组评分估计基线。

🚢DeepSeek-R1

deepseek-R1训练流程
R1的训练主要基于传统强化学习方法,这让模型能够通过思维链CoT的方式进行长思考以生成文本。训练流程大致如上。

  • 用纯RL方法将V3作为基座先训练出了DeepSeek-R1-Zero,没有用到SFT,该模型具有自我思考、验证、反思的能力。这也是为数不多只用RL进行训练的模型。

  • GRPO:R1的强化学习核心算法,亮点是不需要使用critic模型进行评价,更稳定高效,公式是基于PPO算法进行改进的。

  • Zero的提示词:让模型生成的文字带有<think><answer>两部分,也就是xml格式。

  • Zero的奖励:主要就判断模型生成的文本有没有上述格式,以及生成的答案是否正确(比如代码可以通过力扣等去验证)。

  • R1多阶段训练:

    1. 阶段1(冷启动):防止初期RL训练不稳定,使用少量高质量的 CoT 数据进行冷启动,预热模型,数据来自Zero模型生成以及人为筛选。
    2. 阶段2:进行面向推理的强化学习,提升模型在推理任务上的性能。
    3. 阶段3:使用拒绝采样和监督微调,进一步提升模型的综合能力。
    4. 阶段4:再次进行强化学习,使模型在所有场景下都表现良好

Deepseek-R1涌现反思能力

  • 如上图,红色文字反映了R1在训练过程中涌现的反思能力,这并未经过引导。

R1蒸馏qwen和llama

  • 蒸馏:为了获得更高效的小模型,并使其具有 DeekSeek-R1 的推理能力,团队还将R1作为教师模型蒸馏给llama和qwen,效果也不错,超越原模型,以及更大规模的原模型。
  • 同时还发现蒸馏会比直接给小模型做RL更好。因为蒸馏可将「大模型的推理轨迹」直接转移给小模型,小模型只需要模仿大模型相对完备的推理流程,可以在较小训练/推理开销下取得远胜于自身独立强化学习的效果,这也是团队认为R1工作的核心价值。

🔥Qwen

论文:QwenQwen2Qwen2.5Qwen-VLQwen2-VL

Qwen系列
千问系列除了有纯语言模型,还包含了视觉-语言模型Qwen-VL和音频-语言模型Qwen-Audio。团队发布了四个密集模型,参数量分别为0.5B、1.5B、7B和72B,还有一个参数量为57B的混合专家(MoE)模型。

🚢Qwen1

Qwen是使用Transformer的修改版本设计的,具体来说,是采用了LlaMA的架构设计,Qwen对架构的修改包括以下几个方面:

  • 位置编码:使用旋转位置编码RoPE;
  • 偏置:在 QKV 注意力层中添加偏置以增强模型的外推能力;
  • 归一化:使用RMSNorm,是LayerNorm的一种变体,在相同的性能下提高了效率。
  • 激活函数:采用SwiGLU作为激活函数,它是Swish和门控线性单元的组合。初步实验验证,基于GLU的激活函数效果优于基于GELU等其他基线的选项。

Qwen还合并了两种注意力机制:LogN-Scaling, Window Attention。LogN-Scaling调整点积Q和V的因子取决于上下文长度和训练长度的比率,确保注意力值的熵随着上下文长度的增长保持稳定。Window Attention将注意力限制在一个有限的上下文窗口中,避免模型注意力计算的tokens之间不会距离太远。

  • 训练方法上,后训练还是SFT和RLHF齐上。

🚢Qwen2

模型架构

  • Qwen2采用了基于字节级别的字节对编码(byte-level byte-pair encoding)的相同tokenizer。这个tokenizer表现出高效的编码效率,其压缩率优于其他方案,从而增强了Qwen2的多语言处理能力。
  • Qwen2系列基本上是基于Transformer架构的大型语言模型,具有因果掩码的自注意力机制。该系列包括四种规模的密集语言模型和一个MoE模型。
  • 密集语言模型
    • 使用了前面提到的组查询注意力GQA代替MHA。
    • 同时,为了扩展Qwen2的上下文窗口,Qwen2实现了双块注意力(Dual Chunk Attention, DCA),将长序列分割成可管理长度的块。如果输入可以在一个块内处理,DCA会产生与原始注意力机制相同的结果。否则,DCA有助于有效捕捉块内和跨块之间的相对位置信息,从而提升长上下文处理性能。
    • 此外,Qwen2还采用了YARN重新调整注意力权重,以更好地进行长度外推。
    • Qwen2延续了Qwen的SwiGLU激活函数,旋转位置向量(RoPE)进行位置编码,QKV偏置进行注意力处理,以及RMSNorm和预归一化方法以确保训练的稳定性。
  • 专家混合模型
    • Qwen2的MoE模型采用细粒度专家,创建了更小规模的专家,并同时激活更多的专家。
    • 共享专家、路由专家之前提到,大体上是一样的。

qwen2模型规格

  • Qwen2系列包括五种规模的模型,与Qwen1.5模型相比,Qwen2模型每个token的键值(KV)大小显著较低。这一特性使得在长上下文推理任务中内存占用大幅减少。

训练

  • 预训练:
    • Qwen2对数据集进行了质量提升(优化算法过滤数据)和数据扩展(多语言、代码、数学);
    • 还优化了来自不同来源和领域的数据混合以学习近似人类的分布。
    • 为了增强Qwen2的长上下文处理能力,团队在预训练的最后阶段将上下文长度从4,096个token增加到32,768个token。
  • 后训练:
    • 使用SFTRLHF进行后训练,采用协作数据注释自动数据生成来产生数据集。
    • RLHF方面,在离线训练阶段,使用预编译的偏好数据集,通过直接偏好优化最大化y+和y-之间的似然差异(y+是比y-更优的答案)。在在线训练阶段,模型实时迭代优化其性能,利用奖励模型进行即时反馈。

🚢Qwen2.5

Qwen2.5 的关键特点:

  1. 规模更优,引入更多规模的模型如14B、32B;
  2. 数据更优,预训练和后训练数据量有了显著提升;
  3. 使用体验更优,Qwen2 在使用中的关键限制已被克服,包括生成长度从2K tokens提升至8K tokens,更好地支持结构化输入和输出(如表格和JSON),以及更便捷的工具使用。
  • Qwen2.5延续了Qwen2的关键技术,如GQA、SwiGLU激活函数、旋转位置编码RoPE、RMSNorm,为了增强长上下文处理能力,继续使用YARN和双块注意力(DCA)。
  • 在稠密模型的基础上,团队进一步扩展为 MoE 模型架构。

Qwen2.5上下文能力

  • Qwen2.5在秘钥检索任务中达到百分百准确率,显示其超强的上下文能力。为了提升推理速度,团队引入了稀疏注意力机制,这对于提升长上下文处理时的用户体验至关重要。
  • 总的来说,2.5是基于2的一个正常迭代,没有很革命性的新技术,但是得到了很好的效果。

🚢Qwen-VL

架构

  • 架构上,语言部分使用了来自Qwen-7B模型的预训练权重,视觉部分采用了Vision Transformer(ViT)架构,在训练和推理过程中,将输入图像调整到特定的分辨率,然后通过将图像分割成大小为14的图块来处理它们。
  • 位置感知的视觉-语言适配器(Position-aware Vision-Language Adapter):
    • 作用:为了压缩图像token长度,提高图像特征处理效率;
    • 该模块由一个单层的交叉注意力模块构成,使用一组可训练的向量(嵌入)作为Q,使用来自视觉编码器的图像特征作为交叉注意力操作的K;
    • 考虑到图像中位置信息的重要性,作者引入了2D绝对位置编码到交叉注意力机制的查询-键对中。

训练

Qwen-VL训练过程

  1. stage1:预训练,目标是使用大量的图文对数据对齐视觉模块和LLM的模态,这个阶段冻结LLM模块的参数;
  2. stage2:多任务预训练,使用更高质量的图文多任务数据(主要来源自开源VL任务,部分自建数据集),更高的图片像素输入,全参数训练;
  3. stage3:指令微调阶段,这个阶段冻结视觉Encoder模块,使用的数据主要来自大模型Self-Instruction方式自动生成,目标是提升模型的指令遵循和多轮对话能力。

🚢Qwen2-VL

Qwen2-VL架构

  • 架构方面,依然是LLM+视觉编码器结构,但是无adapter。
  • 原生分辨率输入:Qwen2-VL现在可以处理任意分辨率的图像,动态将其转换为可变数量的视觉tokens。为支持此功能,修改了ViT,去除了原始的绝对位置嵌入,并引入了2D-RoPE,以捕捉图像的二维位置信息。
  • 压缩图像token:为减少每幅图像的视觉tokens,在ViT后采用了一个简单的多层感知器(MLP)层,将相邻的2×2个tokens压缩为一个token,并在压缩的视觉tokens的开头和结尾放置特殊的<|vision_start|>和<|vision_end|> tokens。

多模态旋转位置编码

  • 与传统的1D-RoPE(用于LLM)仅能编码一维位置信息不同,M-RoPE有效地建模了多模态输入的位置信息。这通过将原始旋转embedding分解为三个组成部分:时间、高度和宽度来实现。对于文本输入,这些组件使用相同的位置ID,使得M-RoPE在功能上等同于1D-RoPE。 在处理图像时,每个视觉token的时间ID保持不变,而高度和宽度组件则根据token在图像中的位置分配不同的ID。对于视频,视为一系列帧,每帧的时间ID递增,而高度和宽度组件遵循与图像相同的ID分配模式。在输入包含多种模态的情况下,每种模态的位置编号通过将前一模态的最大位置ID +1 来初始化(如图中文本输入的第一个位置编码为4)。M-RoPE不仅增强了位置信息的建模,还减少了图像和视频的位置ID值,使模型在推理时能够推断更长的序列。

  • 训练依然遵循Qwen-VL,采用三阶段训练方法。

🔥Kimi-k1.5

Kimi-k1.5
后训练部分通过SFT、long-CoT SFT、RL、long2short四个阶段让模型具备文本能力、多模态能力、128k超长文能力。

  • long-CoT SFT:让模型具备类o1模型的“先思考后回答”的能力,从 RL prompt 集合里采 prompt,通过提示工程构建了一个小而高质量的 long-CoT warmup 数据集,包含文本和图像输入的经过准确验证的推理路径。
  • RL:和deepseek类似,也是用了on-policy的强化学习策略,kimi在设计奖励函数时引入长度惩罚来缓解模型“过度思考”。
  • long2short:使用 long-CoT 模型来提升 short-CoT 模型能力,包括权重平均、拒绝采样和SFT、强化学习训练等一套流程:
    • 模型合并:通过简单地平均两个模型的权重来合并它们,无需训练即可获得一个新模型。
    • 最短拒绝采样:该方法对同一问题进行 n 次采样(实验中 n=8),并选择最短的正确响应用于监督微调。
    • DPO:利用 long-CoT 模型生成多个响应样本,选择最短的正确解决方案作为正样本,而较长的响应(正确但太长的、错误的)被视为负样本。这些正负样本对构成了用于DPO训练的成对偏好数据。
    • Long2short RL:在标准RL训练阶段之后,选择一个在性能和token效率之间达到最佳平衡的模型作为基础模型,并进行单独的 Long2short RL训练阶段,引入提到过的长度惩罚。

🔥Baichuan2

在模型架构层面,主要还是基于Transformer,改进如下:

  1. Tokenizer:Baichuan 2的词汇表大小从 Baichuan 1的 64,000 扩展到 125,696,使用使用来自 SentencePiece 的字节对编码(BPE),不像 Baichuan 1那样添加虚拟前缀。
  2. Baichuan 2-7B 采用位置编码 RoPE,为 Baichuan 2-13B 采用 ALiBi。
  3. 使用 SwiGLU 激活函数、RMSNorm均方根归一化、AdamW优化器、BF16精度。
  4. 微调是SFT+RLHF。

Baichuan的RLHF

  • 给定一个提示,用不同大小和阶段(SFT,PPO)的 Baichuan 2 模型生成多样化的回应。在训练RM时,只使用由 Baichuan 2 模型族生成的回应。
  • 获得奖励模型之后,使用PPO算法进一步训练语言模型,具体使用了4种模型
  1. actor模型:负责生成回应;
  2. reference模型:用于计算固定参数的KL惩罚;
  3. reward模型:提供整个回应的总体奖励,固定参数;
  4. critic模型:用于学习每个token的值。
  • Copyrights © 2023-2025 LegendLeo Chen
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信