通过源码了解ChatGPT原理和核心流程

ChatGPT

ChatGPT,全称为Chat Generative Pre-trained Transformer, ChatGPT是一种基于Transformer预训练语言模型

想象一下,你有一个超级聪明的朋友,名叫ChatGPT。ChatGPT能够阅读和理解大量的书籍、文章和网页等各种材料。它读得越多,就越聪明。

ChatGPT记忆力非常惊人,不仅能记住读过的每个词内容, 还能理解这些词之间的关联和模式。比如,如果你问它一本小说的主要情节,它不仅能告诉你情节,还能分析人物性格,甚至预测故事可能的结局。

ChatGPT详细原理和训练过程非常复杂,并涉及到大量的工程技术、分布式计算以及大规模数据处理。OpenAI也没有公开完整训练的源代码。

有个开源版本的ChatGPT OpenChatKit(github.com/togethercom...)

下面是一个简化版的流程并给出部分Python伪代码来说明关键步骤。

1.数据收集

  • ChatGPT收集大量的公开的文本数据,包括网页、新闻、书籍、对话和代码等。
  • 同时, 分析网络上的热点话题和流行文化,以了解最新的语言模式和表达方式。
  • 数据越大、越多样化,模型生成的自然语言文本就越好。
arduino 复制代码
def collect_data():
    raw_text_data = []
    
    # 使用爬虫或者其他手段抓取数据
    for webpage in web_crawler():
        raw_text_data.append(webpage.text)

    cleaned_data = [clean_text(text) for text in raw_text_data]
    
    return cleaned_data_

2.数据清洗

去除HTML标签、特殊字符等, 帮助模型更好地理解输入的文本,并提高生成的文本的质量。

ini 复制代码
def clean_text(text):
    # 实际清理可能包括很多操作
    cleaned = re.sub('<.*?>', '', text)  # 移除HTML标签
    cleaned = ''.join(c for c in cleaned if c.isprintable())  # 只保留可打印字符
    return cleaned

3. 数据预处理

实际预处理还会包括去除噪声、标准化词汇、构建词汇表等步骤,最终生成数据集(词汇表).

ini 复制代码
def preprocess_data(cleaned_data, tokenizer):
    input_ids, attention_masks = [], []

    for text in cleaned_data:
        '''
        1. 分词:将输入的文本分割成单词或子词。
        2. 添加特殊标记:可能会添加一些特殊的标记或标识符,用于表示文本的开头和结尾,或者用于区分不同的部分。
        3. 编码:将单词或子词映射到特定的编码或索引。
        4. 添加其他信息:可能会添加一些额外的信息,例如词的位置、词性标记等。
        '''
        encoded = tokenizer.encode_plus(
            text,
            add_special_tokens=True,
            max_length=tokenizer.model_max_length,
            padding='max_length',
            truncation=True,
            return_tensors='pt'
        )
        input_ids.append(encoded['input_ids'])
        attention_masks.append(encoded['attention_mask'])

    dataset = torch.utils.data.TensorDataset(torch.cat(input_ids), torch.cat(attention_masks))

    # 返回数据集
    return dataset

4.训练

生成最终的模型

ini 复制代码
def train(dataset, optimizer):
    # 初始化训练模型和配置
    config = transformers.GPT2Config.from_pretrained('gpt2')
    # 创建模型实例
    model = GPT2LMHeadModel(config)

    # 将模型移动到指定的设备上进行训练,如 GPU。
    device = "cuda" # 或者 "cuda:0" 等具体的 GPU 索引
    model.to(device)

    # 在每个epoch中,对数据集的多个批次进行处理,计算损失,并根据损失的梯度来更新模型的参数,以逐步改进模型的性能
    for epoch in range(num_epochs):
        for batch in dataloader:
            inputs, masks = batch
            inputs, masks = inputs.to(device), masks.to(device)
            
            outputs = model(inputs, masks)
            loss = compute_loss(outputs, targets)  # 根据实际情况定义损失函数
            
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        
    trainer = Trainer(
        model=model,
        args=training_args,
        train_dataset=dataset,
    )
    trainer.train()

5. 微调

对模型进行微调以适应特定任务, 进一步提高模型在特定领域的性能和表现。

ruby 复制代码
def fine_tune_on_task(model, task_data):
    # 更新训练参数以适应微调任务
    training_args.num_train_epochs = 3  # 示例:减少预训练时长
    trainer = Trainer(model, train_dataset=task_data)

    # 执行微调
    trainer.train()
    # 返回新的模型
    return model

class ChatGPTTransformerEncoder:
    def __init__(self, config):
        self.encoder = GPT2Model(config)

    def encode(self, input_ids, attention_mask):
        # 输入ids经过嵌入层、位置编码后送入多层Transformer编码器
        encoded_output = self.encoder(input_ids=input_ids, attention_mask=attention_mask)
        
        # 最后一层Transformer编码器的输出作为上下文向量
        context_vector = encoded_output.last_hidden_state[:, 0, :]  # 取第一个Token(通常是[CLS])的向量
        
        return context_vector, encoded_output.attentions  # 返回上下文向量及各层注意力权重

6. 接受并处理prompt(提示词)

将文本prompt转换为模型所需的input_ids和attention_mask。 参数:

  • prompt: 输入的文本提示
  • max_length: 模型的最大prompt序列长度
ini 复制代码
def process_prompt(prompt, max_length=512):
    # 对prompt进行编码
    encoding = tokenizer.encode_plus(
        prompt,
        add_special_tokens=True,  # 添加特殊token(如[CLS]和[SEP])
        max_length=max_length,
        padding='max_length',  # 若长度不足,则填充到最大长度
        truncation=True,  # 若长度超过,则截断至最大长度
        return_tensors='pt'  # 返回PyTorch张量格式
    )

    # 提取必要的部分
    input_ids = encoding['input_ids']
    attention_mask = encoding['attention_mask']

    return input_ids, attention_mask

7. Transformer编码阶段

ini 复制代码
def transformer_encode(input_ids, attention_mask):
    # 初始化编码器
    config = transformers.GPT2Config.from_pretrained('gpt2')
    encoder = ChatGPTTransformerEncoder(config)

    # 返回上下文向量及各层注意力权重
    context_vector, attentions = encoder.encode(input_ids, attention_mask)_

8. Transformer解码并生成回答

ini 复制代码
def transformer_decode(input_ids, attention_mask, max_length=512):
    # 使用预训练好的完整GPT模型进行解码生成
    model = GPT2LMHeadModel.from_pretrained('gpt2')
    tokenizer = transformers.GPT2Tokenizer.from_pretrained('gpt2')

    output = model.generate(
        input_ids=input_ids,
        max_length=max_length,
        pad_token_id=model.config.eos_token_id,
        no_repeat_ngram_size=3,  # 控制生成不重复n-gram
        do_sample=False,  # 开启或关闭采样生成
        temperature=1.0,  # 控制生成随机性
        top_p=1.0,  # 设置top-p采样策略(此处设置为1代表使用概率最高的token)
        eos_token_id=model.config.eos_token_id,  # 指定结束符ID
        num_return_sequences=1,  # 返回单个序列
        truncation=True  # 开启截断
    )

    # 解码生成最终用户看到的文本
    responseText = tokenizer.decode(output[0], skip_special_tokens=True)
    return responseText
相关推荐
aiguangyuan3 小时前
使用LSTM进行情感分类:原理与实现剖析
人工智能·python·nlp
孟健3 小时前
OpenClaw 2.6 调教实录:从崩溃 4671 次到省 50% token
aigc·openai·ai编程
小小张说故事3 小时前
BeautifulSoup:Python网页解析的优雅利器
后端·爬虫·python
luoluoal3 小时前
基于python的医疗领域用户问答的意图识别算法研究(源码+文档)
python
Shi_haoliu3 小时前
python安装操作流程-FastAPI + PostgreSQL简单流程
python·postgresql·fastapi
ZH15455891313 小时前
Flutter for OpenHarmony Python学习助手实战:API接口开发的实现
python·学习·flutter
小宋10213 小时前
Java 项目结构 vs Python 项目结构:如何快速搭一个可跑项目
java·开发语言·python
一晌小贪欢4 小时前
Python 爬虫进阶:如何利用反射机制破解常见反爬策略
开发语言·爬虫·python·python爬虫·数据爬虫·爬虫python
躺平大鹅4 小时前
5个实用Python小脚本,新手也能轻松实现(附完整代码)
python