AI智能体研发之路-模型篇(二):DeepSeek-V2-Chat 训练与推理实战

简介: AI智能体研发之路-模型篇(二):DeepSeek-V2-Chat 训练与推理实战

一、引言

5月6日私募基金幻方发布DeepSeek-V2,千亿级模型,每百万Tokens仅需1元-2元。5月15日,字节发布白菜价的豆包大模型,5月21日阿里、百度相机大幅下调甚至免费开放自家商用模型接口,大模型价格战正式打响。而被誉为大模型价格屠夫的“DeepSeek-V2”到底是怎么个事儿,是否可以进行训练和推理,今天我们来展开讲一讲。

二、模型简介

2.1 DeepSeek V2模型概述

DeepSeek V2(Moe)是一个基于专家网络(MoE)的大语言模型,是DeepSeek LLM(dense)的升级版本。

  • 主要特点:训练经济、推理高效。
  • 模型尺寸:236B,其中激活参数21B。
  • 上下文长度:128K
  • 相较于他的前一代DeepSeek LLM(67B),节省了42.5%的训练成本,减少了93.3%的KV缓存,最大生成吞吐量提升至5.76倍。

  • 采用8.1万亿个token的多样化高质量预料预训练,在进行全面的预训练之后,进行监督微调(SFT)以及强化学习(RL),充分发挥模型性能。
  • 官方于5月16日发布了可消费级显卡部署的lite版模型:DeepSeek-V2-Lite,总参数16B,激活函数2.4B,上下文长度32K,降低用户私有化部署成本。

  • 中文评测集效果对比(官方发布,仅供参考):  

  •  各大厂商价格战之前的商用接口价格对比(2024.5.6)

就是因为这么一张价格对比表,开启了国产大模型价格之战,“砸我饭碗,都别吃了!”

2.2 DeepSeek V2模型架构

DeepSeek-V2针对attention机制和MoE网络进行创新,保证经济的训练和高效的推理:

  • 对于注意力,设计了MLA(多头潜在注意力),它利用低秩键值联合压缩来消除推理时键值缓存的瓶颈,从而支持高效的推理。
  • 对于前馈网络(FFN),采用 DeepSeekMoE 架构,这是一种高性能 MoE 架构,能够以更低的成本训练更强大的模型。

模型结构配置(configuration_deepseek.py),这里对涉及网络结构的每个参数进行中文说明。

from transformers.configuration_utils import PretrainedConfig
from transformers.utils import logging
 
logger = logging.get_logger(__name__)
 
DEEPSEEK_PRETRAINED_CONFIG_ARCHIVE_MAP = {}
class DeepseekV2Config(PretrainedConfig):
 
    model_type = "deepseek_v2"
    keys_to_ignore_at_inference = ["past_key_values"]
 
    def __init__(
        self,
        vocab_size=102400,#深度模型词汇量,默认102400
        hidden_size=4096,#隐层的维度,默认4096
        intermediate_size=11008,#MLP的维度,默认11008
        moe_intermediate_size = 1407,#MOE的维度,默认1407
        num_hidden_layers=30,#在transformer decoder中隐层的数量,默认30
        num_attention_heads=32,#在transformer decoder中每个多头注意力层的头数,默认32
        num_key_value_heads=32,
        #用于实现分组查询注意力的 key_value 头的数量
        #如果`num_key_value_heads=num_attention_heads`,模型将使用多头注意力(MHA),
        #如果`num_key_value_heads=1 时,模型将使用多查询注意 (MQA),否则将使用 GQA。
        #当将多头检查点转换为 GQA 检查点,应构造每个组键和值头。意思是meanpooling该组内的所有original heads
        #详细说明见(https://arxiv.org/pdf/2305.13245.pdf)
        #默认num_key_value_heads=num_attention_heads
        n_shared_experts = None,#moe共享专家数,为None代表dense model稠密模型
        n_routed_experts = None,#moe路由专家数,为None代表dense model稠密模型
        ep_size = 1,
        routed_scaling_factor = 1.0,#路由专家的缩放因子,
        kv_lora_rank = 512,
        q_lora_rank = 1536,
        qk_rope_head_dim = 64,
        v_head_dim = 128,
        qk_nope_head_dim = 128,
        topk_method = 'gready',#moe网络中路由门控的topk选择方法,默认为贪心算法
        n_group = None,#路由专家的组数,默认为None不分组
        topk_group = None,#每个token选中的组数(对于每个 token,确保选中的专家仅在 `topk_group` 组内)
        num_experts_per_tok = None,#选定专家的数量,无表示密集模型
        moe_layer_freq = 1,#MoE 层的频率:每“moe_layer_freq - 1”密集层有一个专家层
        first_k_dense_replace = 0,#浅层中的密集层数(embed->dense->dense->...->dense->moe->moe...->lm_head)。
        norm_topk_prob = False,#是否标准化已路由专家的权重。
        scoring_func = 'softmax',#计算专家权重的方法,默认softmax
        aux_loss_alpha = 0.001,#辅助损失系数。
        seq_aux = True,#是否计算每个单独样本的辅助损失。
        hidden_act="silu",#decoder中非线性激活函数,默认为silu
        max_position_embeddings=2048,#该模型可能用到的最大序列长度,默认为2048,这个参数直接影响模型上下文长度。如果太短,在应用中设置较长的system prompt会让对话被截断。
        initializer_range=0.02,#用于初始化所有权重矩阵的 truncated_normal_initializer 的标准差
        rms_norm_eps=1e-6,#均方根归一化层使用的 epsilon,用于处理浮点数比较时的误差或精度问题,通常是个很小的值。
        use_cache=True,模型是否应该返回最后的key value注意力的值(并非所有模型都使用)。仅当 `config.is_decoder=True` 才有意义
        pad_token_id=None,#填充的token id
        bos_token_id=100000,#token流开始的id,默认为100000
        eos_token_id=100001,#token流结束的id,默认为100001
        pretraining_tp=1,#实验性功能。预训练期间使用的张量并行度等级。此值是确保预训练结果的精确再现性是必要的。
        tie_word_embeddings=False,#是否绑定词嵌入
        rope_theta=10000.0,#RoPE 嵌入的基期,默认为10000
        rope_scaling=None,#包含 RoPE 嵌入的缩放配置的字典。目前支持两种缩放策略:线性和动态。它们的缩放因子必须是大于 1 的浮点数。预期格式为`{"type": 策略名称,"factor": 缩放因子}`。使用此标志时,不要更新`max_position_embeddings` 达到预期的新最大值。
        attention_bias=False,#在自注意力期间是否在查询、键、值和输出投影层中使用偏差,默认False
        attention_dropout=0.0,#注意力概率的丢失率。
        **kwargs,
    ):
        self.vocab_size = vocab_size
        self.max_position_embeddings = max_position_embeddings
        self.hidden_size = hidden_size
        self.intermediate_size = intermediate_size
        self.moe_intermediate_size = moe_intermediate_size
        self.num_hidden_layers = num_hidden_layers
        self.num_attention_heads = num_attention_heads
        self.n_shared_experts = n_shared_experts
        self.n_routed_experts = n_routed_experts
        self.ep_size = ep_size
        self.routed_scaling_factor = routed_scaling_factor
        self.kv_lora_rank = kv_lora_rank
        self.q_lora_rank = q_lora_rank
        self.qk_rope_head_dim = qk_rope_head_dim
        self.v_head_dim = v_head_dim
        self.qk_nope_head_dim = qk_nope_head_dim
        self.topk_method = topk_method
        self.n_group = n_group
        self.topk_group = topk_group
        self.num_experts_per_tok = num_experts_per_tok
        self.moe_layer_freq = moe_layer_freq
        self.first_k_dense_replace = first_k_dense_replace
        self.norm_topk_prob = norm_topk_prob
        self.scoring_func = scoring_func
        self.aux_loss_alpha = aux_loss_alpha
        self.seq_aux = seq_aux
        # for backward compatibility
        if num_key_value_heads is None:
            num_key_value_heads = num_attention_heads
 
        self.num_key_value_heads = num_key_value_heads
        self.hidden_act = hidden_act
        self.initializer_range = initializer_range
        self.rms_norm_eps = rms_norm_eps
        self.pretraining_tp = pretraining_tp
        self.use_cache = use_cache
        self.rope_theta = rope_theta
        self.rope_scaling = rope_scaling
        self.attention_bias = attention_bias
        self.attention_dropout = attention_dropout
 
        super().__init__(
            pad_token_id=pad_token_id,
            bos_token_id=bos_token_id,
            eos_token_id=eos_token_id,
            tie_word_embeddings=tie_word_embeddings,
            **kwargs,
        )
  • vocab_size=102400,#词库大小,默认102400,作为参考qwen-72B为152064
  • hidden_size=4096,#隐层的维度,默认4096
  • intermediate_size=11008,#MLP的维度,默认11008
  • moe_intermediate_size = 1407,#MOE的维度,默认1407
  • num_hidden_layers=30,#在transformer decoder中隐层的数量,默认30
  • num_attention_heads=32,#在transformer decoder中每个多头注意力层的头数,默认32,作为参考,qwen-72B为80,baichuan2-13B为40
  • num_key_value_heads=32,
  • #用于实现分组查询注意力的 key_value 头的数量
  • #如果`num_key_value_heads=num_attention_heads`,模型将使用多头注意力(MHA),
  • #如果`num_key_value_heads=1 时,模型将使用多查询注意 (MQA),否则将使用 GQA。
  • #当将多头检查点转换为 GQA 检查点,应构造每个组键和值头。意思是meanpooling该组内的所有original heads
  • #详细说明见(https://arxiv.org/pdf/2305.13245.pdf)
  • #默认num_key_value_heads=num_attention_heads
  • n_shared_experts = None,#moe共享专家数,为None代表dense model稠密模型
  • n_routed_experts = None,#moe路由专家数,为None代表dense model稠密模型
  • ep_size = 1,
  • routed_scaling_factor = 1.0,#路由专家的缩放因子,
  • kv_lora_rank = 512,kv lora矩阵的秩,默认为512
  • q_lora_rank = 1536,q lora矩阵的秩,默认为1536
  • qk_rope_head_dim = 64,qk rope矩阵头维度,默认为64
  • v_head_dim = 128,v矩阵头维度,默认为128
  • qk_nope_head_dim = 128,qk nope矩阵头维度,默认为128
  • topk_method = 'gready',#moe网络中路由门控的topk选择方法,默认为贪心算法
  • n_group = None,#路由专家的组数,默认为None不分组
  • topk_group = None,#每个token选中的组数(对于每个 token,确保选中的专家仅在 `topk_group` 组内)
  • num_experts_per_tok = None,#选定专家的数量,无表示密集模型
  • moe_layer_freq = 1,#MoE 层的频率:每“moe_layer_freq - 1”密集层有一个专家层
  • first_k_dense_replace = 0,#浅层中的密集层数(embed->dense->dense->...->dense->moe->moe...->lm_head)。
  • norm_topk_prob = False,#是否标准化已路由专家的权重。
  • scoring_func = 'softmax',#计算专家权重的方法,默认softmax
  • aux_loss_alpha = 0.001,#辅助损失系数。
  • seq_aux = True,#是否计算每个单独样本的辅助损失。
  • hidden_act="silu",#decoder中非线性激活函数,默认为silu
  • max_position_embeddings=2048,#该模型可能用到的最大序列长度,默认为2048,这个参数直接影响模型上下文长度。如果太短,在应用中设置较长的system prompt会让对话被截断。
  • initializer_range=0.02,#用于初始化所有权重矩阵的 truncated_normal_initializer 的标准差
  • rms_norm_eps=1e-6,#均方根归一化层使用的 epsilon,用于处理浮点数比较时的误差或精度问题,通常是个很小的值。
  • use_cache=True,模型是否应该返回最后的key value注意力的值(并非所有模型都使用)。仅当 `config.is_decoder=True` 才有意义
  • pad_token_id=None,#填充的token id
  • bos_token_id=100000,#token流开始的id,默认为100000
  • eos_token_id=100001,#token流结束的id,默认为100001
  • pretraining_tp=1,#实验性功能。预训练期间使用的张量并行度等级。此值是确保预训练结果的精确再现性是必要的。
  • tie_word_embeddings=False,#是否绑定词嵌入
  • rope_theta=10000.0,#ROPE旋转位置编码里theta的空间,qwen-72B为1000000。ROPE是一种位置编码算法,通过优化的矩阵乘法方式为Q/K引入位置信息,使得token能够在Attention计算中感知到相对位置信息。
  • rope_scaling=None,#包含 RoPE 嵌入的缩放配置的字典。目前支持两种缩放策略:线性和动态。它们的缩放因子必须是大于 1 的浮点数。预期格式为`{"type": 策略名称,"factor": 缩放因子}`。使用此标志时,不要更新`max_position_embeddings` 达到预期的新最大值。
  • attention_bias=False,#在自注意力期间是否在查询、键、值和输出投影层中使用偏差,默认False
  • attention_dropout=0.0,#注意力概率的丢失率。

Tips:

之前在做深度学习推荐系统的时候,也经常接触到attention机制和MoE专家网络这两个模型网络,采用attention机制学习item或user序列的潜在关系,采用MoE专家网络做推荐系统中多场景/多目标网络的主模型,较为知名的有MMoE网络和PLE网络,通过共享多个专家网络,提升模型的多场景/多目标的关联学习能力。

三、训练与推理

3.1 DeepSeek V2模型训练

由于机器资源限制,这里基于QLoRA指令微调(SFT)DeepSeek V2的lite版(DeepSeek-V2-Lite-Chat),使用之前文章介绍的LLaMA-Factory框架。

国内网络环境下LLaMA-Factory部署:AI智能体研发之路-模型训练篇(一):大模型训练框架LLaMA-Factory在国内网络环境下的安装、部署及使用_llama训练框架-CSDN博客

SFT训练启动代码:

CUDA_VISIBLE_DEVICES=1 llamafactory-cli train \
    --stage sft \
    --do_train True \
    --model_name_or_path deepseek-ai/deepseek-moe-16b-chat \
    --finetuning_type lora \
    --quantization_bit 4 \
    --template deepseek \
    --flash_attn auto \
    --dataset_dir data \
    --dataset oaast_sft_zh \
    --cutoff_len 4096 \
    --learning_rate 5e-05 \
    --num_train_epochs 5.0 \
    --max_samples 100000 \
    --per_device_train_batch_size 2 \
    --gradient_accumulation_steps 8 \
    --lr_scheduler_type cosine \
    --max_grad_norm 1.0 \
    --logging_steps 5 \
    --save_steps 100 \
    --warmup_steps 0 \
    --optim adamw_torch \
    --packing False \
    --report_to none \
    --output_dir saves/DeepSeek-MoE-16B-Chat/lora/train_2024-05-23-deepseek-v2 \
    --fp16 True \
    --lora_rank 16 \
    --lora_alpha 16 \
    --lora_dropout 0 \
    --lora_target q_proj,v_proj \
    --plot_loss True

其中:

  • quantization_bit = 4 ,int4量化,sft根据惯例fp16训练大概需要模型尺寸*2的GPU,int4需要模型尺寸*0.75的GPU,这里是16B,int4大概需要16*0.75=12G的GPU资源,如果fp16需要32G,对于V100显卡,单卡32G基本很难启动。
  • template = deepseek,template采用deepseek的,LLaMA Factory框架针对当下国内外主流模型都进行了template适配,训练和推理记得设置。
  • cutoff_len = 4096,上下文长度这里先设置4096,对于agent开发,特别是较长的system prompt,这里一定要尽量大,至少要4096。
  • per_device_train_batch_size = 2,每个设备训练的batich size,这里设置为2,不要太大
  • gradient_accumulation_steps = 8,

启动后,webui、docker logs或者save目录中的running_logs日志文件可以查看日志状态。

deepseek v2的SFT微调训练启动后要加载很久,需要确保服务器资源充足,并且要有足够的耐心。

对于以上参数,5轮迭代需要7小时12分钟,耐心等待叭。

训练完毕后,可以看到loss明显收敛,各位可以通过调整自己的数据样本集训练私有化模型。

3.2 DeepSeek V2模型推理

这里采用LLaMA Factory WebUI的chat部分进行模型推理测试,由于资源限制智能采用int4量化后进行推理测试,大概占用了12G显存。框架支持RoPE插值方法,可以配置线性插值和动态插值,以及支持flashattn2加速和unsloth加速。

从对话效果来看,int4的模型还是存在一定幻觉,比如问“你支持工具调用嘛”,模型回答“支持工具调用,但不具备调用工具的能力”。逻辑上产生错误。

但在个人实际工作中,官方完整版的deepseek-v2-chat(236B)还是非常好用的,对于agent的开发,回复效果上强于gpt3.5,回复速度上快于gpt4.0。接入dify平台上直接就可以使用,由于采用OpenAI兼容的API规范,配置和使用过程都很流畅。最重要的是,真便宜!测试用了6万token才花费了0.07元!

如何部署Dify智能体开发平台可参考之前的文章:AI智能体研发之路-工程篇(二):Dify智能体开发平台一键部署_dify 接入 天气预报

四、总结

本文首先针对deepseek-v2-chat这个大模型价格屠夫的模型特点和技术架构进行介绍,之后以LLaMA-factory为训练和推理框架,进行SFT微调训练和推理测试。

deepseek-v2-chat巧妙的将attention注意力机制和MoE网络架构与大模型相结合,通过模型算法与架构的升级,提升了推理和训练效率,最终呈现的就是成本的优化和商业市场价值的转化。是一个典型的通过技术创新直接创造商业价值的案例。respect。

如果认为文章现在或未来可以帮助到你,辛苦关注、点赞、收藏噢,您的鼓励是我持续创作的动力!

目录
相关文章
|
10天前
|
机器学习/深度学习 人工智能 自然语言处理
当语言遇见智慧火花:GPT家族历代模型大起底,带你见证从平凡到卓越的AI进化奇迹!
【10月更文挑战第6天】随着自然语言处理技术的进步,GPT系列模型(Generative Pre-trained Transformers)成为该领域的明星。从GPT-1的开创性工作,到GPT-2在规模与性能上的突破,再到拥有1750亿参数的GPT-3及其无需微调即可执行多种NLP任务的能力,以及社区驱动的GPT-NeoX,这些模型不断进化。虽然它们展现出强大的语言理解和生成能力,但也存在如生成错误信息或偏见等问题。本文将对比分析各代GPT模型的特点,并通过示例代码展示其部分功能。
44 2
|
3天前
|
人工智能 自然语言处理
从迷茫到精通:揭秘模型微调如何助你轻松驾驭AI新热点,解锁预训练模型的无限潜能!
【10月更文挑战第13天】本文通过简单的问题解答形式,结合示例代码,详细介绍了模型微调的全流程。从选择预训练模型、准备新任务数据集、设置微调参数,到进行微调训练和评估调优,帮助读者全面理解模型微调的技术细节和应用场景。
19 6
|
2天前
|
机器学习/深度学习 人工智能 并行计算
"震撼!CLIP模型:OpenAI的跨模态奇迹,让图像与文字共舞,解锁AI理解新纪元!"
【10月更文挑战第14天】CLIP是由OpenAI在2021年推出的一种图像和文本联合表示学习模型,通过对比学习方法预训练,能有效理解图像与文本的关系。该模型由图像编码器和文本编码器组成,分别处理图像和文本数据,通过共享向量空间实现信息融合。CLIP利用大规模图像-文本对数据集进行训练,能够实现zero-shot图像分类、文本-图像检索等多种任务,展现出强大的跨模态理解能力。
11 2
|
10天前
|
人工智能 自然语言处理 安全
【通义】AI视界|Adobe推出文生视频AI模型,迎战OpenAI和Meta
本文精选了过去24小时内的重要科技新闻,包括微软人工智能副总裁跳槽至OpenAI、Adobe推出文本生成视频的AI模型、Meta取消高端头显转而开发超轻量设备、谷歌与核能公司合作为数据中心供电,以及英伟达股价创下新高,市值接近3.4万亿美元。这些动态展示了科技行业的快速发展和激烈竞争。点击链接或扫描二维码获取更多资讯。
|
8天前
|
机器学习/深度学习 人工智能 TensorFlow
解锁AI潜力:让开源模型在私有环境绽放——手把手教你搭建专属智能服务,保障数据安全与性能优化的秘密攻略
【10月更文挑战第8天】本文介绍了如何将开源的机器学习模型(如TensorFlow下的MobileNet)进行私有化部署,包括环境准备、模型获取与转换、启动TensorFlow Serving服务及验证部署效果等步骤,适用于希望保护用户数据并优化服务性能的企业。
23 4
|
8天前
|
人工智能 算法 决策智能
面向软件工程的AI智能体最新进展,复旦、南洋理工、UIUC联合发布全面综述
【10月更文挑战第9天】近年来,基于大型语言模型(LLM)的智能体在软件工程领域展现出显著成效。复旦大学、南洋理工大学和伊利诺伊大学厄巴纳-香槟分校的研究人员联合发布综述,分析了106篇论文,探讨了这些智能体在需求工程、代码生成、静态代码检查、测试、调试及端到端软件开发中的应用。尽管表现出色,但这些智能体仍面临复杂性、性能瓶颈和人机协作等挑战。
19 1
|
8天前
|
机器学习/深度学习 人工智能 自然语言处理
揭开模型微调Fine-Tuning的神秘面纱:如何在预训练基础上巧妙调整,解锁定制AI解决方案的秘密武器
【10月更文挑战第8天】模型微调是在预训练模型基础上,利用特定领域数据进一步训练,以优化模型在特定任务上的表现。此方法广泛应用于自然语言处理和计算机视觉等领域,通过调整预训练模型的部分或全部参数,结合适当的正则化手段,有效提升模型性能。例如,使用Hugging Face的Transformers库对BERT模型进行微调,以改善文本匹配任务的准确率。
20 1
|
10天前
|
机器学习/深度学习 数据采集 人工智能
【紧跟AI浪潮】深度剖析:如何在大模型时代精准捕获用户心声——提高召回率的实战秘籍
【10月更文挑战第5天】在深度学习领域,大型模型常面临召回率不足的问题,尤其在信息检索和推荐系统中尤为关键。本文通过具体代码示例,介绍如何提升大模型召回率。首先,利用Pandas进行数据预处理,如清洗和特征工程;其次,选择合适的模型架构,如使用PyTorch构建推荐系统;再者,优化训练策略,采用合适的损失函数及正则化技术;此外,选择恰当的评估指标,如召回率和F1分数;最后,通过后处理优化结果展示。以上方法不仅提升召回率,还增强了模型整体性能。
37 0
|
2月前
|
存储 人工智能
|
14天前
|
Python 机器学习/深度学习 人工智能
手把手教你从零开始构建并训练你的第一个强化学习智能体:深入浅出Agent项目实战,带你体验编程与AI结合的乐趣
【10月更文挑战第1天】本文通过构建一个简单的强化学习环境,演示了如何创建和训练智能体以完成特定任务。我们使用Python、OpenAI Gym和PyTorch搭建了一个基础的智能体,使其学会在CartPole-v1环境中保持杆子不倒。文中详细介绍了环境设置、神经网络构建及训练过程。此实战案例有助于理解智能体的工作原理及基本训练方法,为更复杂应用奠定基础。首先需安装必要库: ```bash pip install gym torch ``` 接着定义环境并与之交互,实现智能体的训练。通过多个回合的试错学习,智能体逐步优化其策略。这一过程虽从基础做起,但为后续研究提供了良好起点。
51 4
手把手教你从零开始构建并训练你的第一个强化学习智能体:深入浅出Agent项目实战,带你体验编程与AI结合的乐趣