9 月 25 日 Meta 发布了 Llama 3.2,包括 11B 和 90B 的视觉语言模型。

前排提示,文末有大模型AGI-CSDN独家资料包哦!

Llama 3技术剖析与部署

相较于Llama2, Llama3的改变其实并不是太大。 Tokenizer变成了128K的词表,使用了GQA,不在是原来的只在Llama2-70B里使用了。所以说,最大的改变就是词表与GQA。然后在训练上变化比较大,参数变大了,400B的还没放出来。但它的训练是变化很大的。训练数据明显比过去多,15T的token数差不多是Llama2的四倍多,而且这个数据的质量明显要高呢。

新的数据过滤器,幻觉、NSFW、语义重复、分类这些都有提高或者新增。

预训练的数据也在变好,再加上适当的优化技术。

所以真的结构上的改变是GQA。

那看一下GQA是咋回事吧。 一切的改进都是针对Transformer的QKV这块来的。

在这里插入图片描述

原始的是这样的,每一个QKV的计算都是分别进行的,这样QKV的计算其实要有大量的计算。基本上是一个下面的计算

在这里插入图片描述

考虑到这样一个大的计算会有非常大的计算量,于是把这个Attention拆成了小块,然后连接在一起。也就是下面的MHA其实也是一种优化,但是很明显,在LLM变成极大后,这个东西还要再优化,因为它还是消耗了太大的计算量。

在这里插入图片描述

于是最早有人想优化成MQA那种,就是一个K、一个V对应所有的Q,这种方式确实很容易扩大QKV的参数规模,同时非常有效的减少KV缓存。但是因为这个参数它太共同了,所以后期要在FFN那块增加相应的参数才成。效果也没有证明好了。

于是又有了更优的版本:GQA,所有的优化都是“中庸”嘛,中不偏,庸不易。

于是GQA呢,是简单的把MHA分成几组,每组共用一个就好了。从Llama2-70b,还有Llama3全系来看呢,GQA这个确实是在性能与KV缓存的显存占用上获得了很好的平衡。

谈到这儿,你有没有发现现在讲Llama3,其实是有很多基础的东西,如attention, mha, ffn一类的东西,你可能有些模糊了呢?我非常建议有举的人都去听听由知乎知学堂开设的这门AI大模型公开课,课程带你学习GPT背后的技术原理,LangChain、Fine-tune技术,从理论实践,到深度讲解,带你全程体验微调过程,定制属于自己的大模型。课上还能直接对话AI技术大佬,现场答疑,非常不错。这样你能掌握一套更全面的知识了。

既然这套东西没有什么大的改动,那我们就看看怎么用吧。

通常我们可以这样认为 Prompt是要优先RAG,RAG是要优先微调Finetune的。我们就从部署一个Llama3开始吧。看看怎么用Prompt,再怎么用RAG,再怎么微调Finetune它。

模型基本使用方法

这次我们搞个接地气的,直接用一个大家想不到的模型:中国联通AI创新中心微调的“Unichat-llama3-Chinese-8B”,看看联通的实力如何。毕竟我们用中文更容易看到效果。

运行代码很简单:

import transformers
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

model_id = "UnicomLLM/Unichat-llama3-Chinese-8B" #可以是本地路径

pipeline = transformers.pipeline(
    "text-generation",
    model=model_id,
    model_kwargs={"torch_dtype": torch.bfloat16},
    device="cuda",
)

messages = [
    {"role": "system", "content": "A chat between a curious user and an artificial intelligence assistant.The assistant gives helpful, detailed, and polite answers to the user's questions."},
    {"role": "user", "content": "你是谁"},
]
prompt = pipeline.tokenizer.apply_chat_template(
      messages,
      tokenize=False,
      add_generation_prompt=True
)
terminators = [
      pipeline.tokenizer.eos_token_id,
      pipeline.tokenizer.convert_tokens_to_ids("<|eot_id|>")
]
outputs = pipeline(
        prompt,
        max_new_tokens=2048,
        eos_token_id=terminators,
        do_sample=False,
        temperature=0.6,
        top_p=1,
        repetition_penalty=1.05
)
print(outputs[0]["generated_text"][len(prompt):])

理论上你就能运行了,如果不缺支持库(24G显存的运行会顺畅些)

Rag

这事吧,其实也不难,现在的框架已经很丰富了。我们举个例子吧。

通常langchain rag的流程如下

在这里插入图片描述
代码吧,搞一份供参考吧:

from langchain.llms.base import LLM
from typing import Any, List, Optional
from langchain.callbacks.manager import CallbackManagerForLLMRun
from transformers import AutoTokenizer, AutoModelForCausalLM, RagTokenizer, RagRetriever, RagSequenceForGeneration
import torch

class LLaMA3_LLM(LLM):
    tokenizer: AutoTokenizer = None
    model: AutoModelForCausalLM = None
    rag_tokenizer: RagTokenizer = None
    rag_retriever: RagRetriever = None
    rag_generator: RagSequenceForGeneration = None
        
    def __init__(self, mode_name_or_path :str, rag_name_or_path: str):

        super().__init__()
        print("正在从本地加载模型和RAG组件...")
        self.tokenizer = AutoTokenizer.from_pretrained(mode_name_or_path, use_fast=False)
        self.model = AutoModelForCausalLM.from_pretrained(mode_name_or_path, torch_dtype=torch.bfloat16, device_map="auto")
        self.tokenizer.pad_token = self.tokenizer.eos_token
        
        # 初始化RAG组件
        self.rag_tokenizer = RagTokenizer.from_pretrained(rag_name_or_path)
        self.rag_retriever = RagRetriever.from_pretrained(rag_name_or_path)
        self.rag_generator = RagSequenceForGeneration.from_pretrained(rag_name_or_path)
        
        print("完成本地模型和RAG组件的加载")

    def bulid_input(self, prompt, history=[]):
        user_format='user\n\n{content}'
        assistant_format='assistant\n\n{content}'
        history.append({'role':'user','content':prompt})
        prompt_str = ''
        # 拼接历史对话
        for item in history:
            if item['role']=='user':
                prompt_str+=user_format.format(content=item['content'])
            else:
                prompt_str+=assistant_format.format(content=item['content'])
        return prompt_str
    
    def _call(self, prompt : str, stop: Optional[List[str]] = None,
                run_manager: Optional[CallbackManagerForLLMRun] = None,
                **kwargs: Any):

        input_str = self.bulid_input(prompt=prompt)
        input_ids = self.tokenizer.encode(input_str, add_special_tokens=False, return_tensors='pt').to(self.model.device)
        
        # 使用RAG模型进行检索
        with torch.no_grad():
            retrieved = self.rag_retriever(input_str, return_tensors="pt")
            generated = self.rag_generator(input_ids=retrieved['retrieved_indices'], attention_mask=retrieved['retrieved_attention_mask'])
        
        # 检查是否成功生成了回复
        if generated is None:
            return "Sorry, I couldn't generate a response."
        
        outputs = generated.sequences.tolist()[0][len(input_ids[0]):]
        response = self.tokenizer.decode(outputs).strip().replace('', "").replace('assistant\n\n', '').strip()
        return response
        
    @property
    def _llm_type(self) -> str:
        return "LLaMA3_LLM"
        
from LLM import LLaMA3_LLM
llm = LLaMA3_LLM(mode_name_or_path = "/root/autodl-tmp/LLM-Research/Meta-Llama-3-8B-Instruct")
llm("你是谁")

微调

微调这事,其实主要还是看数据,太少了你也不要有太大期望。不过参考代码还是可以给一下。

首先你的数据是这样的(多个重复):

{
  "instruction": "回答以下用户问题,仅输出答案。",
  "input": "1+1等于几?",
  "output": "2"
}

然后代码差不多是这样的(这次从modelscope下载, 期望你能知道安装相应的库)

import torch
from modelscope import snapshot_download, AutoModel, AutoTokenizer
import os

model_dir = snapshot_download('LLM-Research/Meta-Llama-3-8B-Instruct', cache_dir='/root/autodl-tmp', revision='master')

def process_func(example):
    MAX_LENGTH = 384    # Llama分词器会将一个中文字切分为多个token,因此需要放开一些最大长度,保证数据的完整性
    input_ids, attention_mask, labels = [], [], []
    instruction = tokenizer(f"<|start_header_id|>user<|end_header_id|>\n\n{example['instruction'] + example['input']}<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n\n", add_special_tokens=False)  # add_special_tokens 不在开头加 special_tokens
    response = tokenizer(f"{example['output']}<|eot_id|>", add_special_tokens=False)
    input_ids = instruction["input_ids"] + response["input_ids"] + [tokenizer.pad_token_id]
    attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1]  # 因为eos token咱们也是要关注的所以 补充为1
    labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]
    if len(input_ids) > MAX_LENGTH:  # 做一个截断
        input_ids = input_ids[:MAX_LENGTH]
        attention_mask = attention_mask[:MAX_LENGTH]
        labels = labels[:MAX_LENGTH]
    return {
        "input_ids": input_ids,
        "attention_mask": attention_mask,
        "labels": labels
    }
    
    tokenizer = AutoTokenizer.from_pretrained('/root/autodl-tmp/LLM-Research/Meta-Llama-3-8B-Instruct', use_fast=False, trust_remote_code=True)

model = AutoModelForCausalLM.from_pretrained('/root/autodl-tmp/LLM-Research/Meta-Llama-3-8B-Instruct', device_map="auto",torch_dtype=torch.bfloat16)

config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
    inference_mode=False, # 训练模式
    r=8, # Lora 秩
    lora_alpha=32, # Lora alaph,具体作用参见 Lora 原理
    lora_dropout=0.1# Dropout 比例
)

args = TrainingArguments(
    output_dir="./output/llama3",
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,
    logging_steps=10,
    num_train_epochs=3,
    save_steps=100,
    learning_rate=1e-4,
    save_on_each_node=True,
    gradient_checkpointing=True
)

trainer = Trainer(
    model=model,
    args=args,
    train_dataset=tokenized_id,
    data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),
)
trainer.train()

lora_path='./llama3_lora'
trainer.model.save_pretrained(lora_path)
tokenizer.save_pretrained(lora_path)

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
from peft import PeftModel

mode_path = '/root/autodl-tmp/LLM-Research/Meta-Llama-3-8B-Instruct'
lora_path = './llama3_lora' # lora权重路径

# 加载tokenizer
tokenizer = AutoTokenizer.from_pretrained(mode_path)

# 加载模型
model = AutoModelForCausalLM.from_pretrained(mode_path, device_map="auto",torch_dtype=torch.bfloat16)

# 加载lora权重
model = PeftModel.from_pretrained(model, model_id=lora_path, config=config)

prompt = "你是谁?"
messages = [
    # {"role": "system", "content": "现在你要扮演皇帝身边的女人--甄嬛"},
    {"role": "user", "content": prompt}
]

text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)

model_inputs = tokenizer([text], return_tensors="pt").to('cuda')

generated_ids = model.generate(
    model_inputs.input_ids,
    max_new_tokens=512,
    eos_token_id=tokenizer.encode('<|eot_id|>')[0]
)
generated_ids = [
    output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]

response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

print(response)

多模态训练

可能还要等等,现在的llama3官方还没有提供400B的那个多模态版本。不过GitHub上有个llama-multimodal-vqa的项目,大概的方向是这样的,用一个CLIP把图像编码成了Token,再用Llama3训练一下。但是结果真的不太成啊。还是等官方400b吧。

在这里插入图片描述

读者福利:如果大家对大模型感兴趣,这套大模型学习资料一定对你有用

对于0基础小白入门:

如果你是零基础小白,想快速入门大模型是可以考虑的。

一方面是学习时间相对较短,学习内容更全面更集中。
二方面是可以根据这些资料规划好学习计划和方向。

包括:大模型学习线路汇总、学习阶段,大模型实战案例,大模型学习视频,人工智能、机器学习、大模型书籍PDF。带你从零基础系统性的学好大模型!

😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

👉AI大模型学习路线汇总👈

大模型学习路线图,整体分为7个大的阶段:(全套教程文末领取哈)

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

👉大模型实战案例👈

光学理论是没用的,要学会跟着一起做,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

在这里插入图片描述

👉大模型视频和PDF合集👈

观看零基础学习书籍和视频,看书籍和视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
在这里插入图片描述
在这里插入图片描述

👉学会后的收获:👈

• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

👉获取方式:

😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐