Найти в Дзене
Обо всем по немногу.

Создание Кастомной Модели GPT с PyQt6 и Hugging Face Transformers

Введение В области обработки естественного языка (NLP) модели на основе архитектуры GPT (Generative Pretrained Transformer) стали основой для множества приложений, включая генерацию текста, чат-боты и перевод. В данной статье мы рассмотрим, как создать графическое интерфейсное приложение с использованием PyQt6 для настройки и создания кастомной модели GPT с использованием библиотеки transformers от Hugging Face. Обзор проекта Этот скрипт реализует интерфейс на PyQt6, который позволяет пользователю настроить параметры модели GPT и запустить процесс её создания. Приложение поддерживает загрузку уже существующего токенизатора и настройку модели через GUI. Процесс создания модели осуществляется в отдельном потоке, чтобы приложение оставалось отзывчивым. Описание основных компонентов Как работает приложение? Основные шаги в процессе создания модели Заключение Этот скрипт представляет собой мощный инструмент для пользователей, которым необходимо гибко и быстро настраивать и создавать кастомн

Введение

В области обработки естественного языка (NLP) модели на основе архитектуры GPT (Generative Pretrained Transformer) стали основой для множества приложений, включая генерацию текста, чат-боты и перевод. В данной статье мы рассмотрим, как создать графическое интерфейсное приложение с использованием PyQt6 для настройки и создания кастомной модели GPT с использованием библиотеки transformers от Hugging Face.

Обзор проекта

Этот скрипт реализует интерфейс на PyQt6, который позволяет пользователю настроить параметры модели GPT и запустить процесс её создания. Приложение поддерживает загрузку уже существующего токенизатора и настройку модели через GUI. Процесс создания модели осуществляется в отдельном потоке, чтобы приложение оставалось отзывчивым.

Описание основных компонентов

  1. Основные элементы интерфейсаПриложение разделено на две основные вкладки:Создание модели: Вкладка отображает процесс создания модели и обновляет статус на каждом шаге. В завершение пользователю предлагается закрыть приложение.
    Настройки: Эта вкладка позволяет пользователю настроить параметры модели, такие как количество слоев, количество голов внимания, размер эмбеддингов и другие критические параметры.
  2. Потоковая обработкаСоздание модели выполняется в отдельном потоке (ModelThread), чтобы основной интерфейс оставался интерактивным. Это предотвращает "замораживание" приложения во время долгих вычислительных операций.

Как работает приложение?

  • Создание пользовательского интерфейса
    Основной класс MainWindow наследует QMainWindow и содержит метод initUI, который инициализирует элементы интерфейса. Приложение имеет две вкладки: одну для настройки параметров и другую для отображения процесса создания модели.
  • Настройка параметров модели
    Вкладка "Настройки" (createSettingsTab) предоставляет пользователю возможность ввести параметры модели GPT, такие как путь к токенизатору, количество слоев, размер эмбеддингов и другие. Эти параметры затем используются для конфигурации модели.
  • Процесс создания модели
    Когда пользователь нажимает на кнопку "Начать создание модели", параметры модели передаются в поток ModelThread. Этот поток загружает токенизатор, создает конфигурацию модели GPT, используя заданные параметры, и сохраняет модель и токенизатор в указанной директории.
  • Обновление статуса
    Поток отправляет сигналы в основной интерфейс для обновления текста в QTextEdit, что позволяет пользователю следить за прогрессом создания модели. После завершения процесса кнопка "Выход" становится активной, позволяя пользователю закрыть приложение.

Основные шаги в процессе создания модели

  1. Загрузка токенизатора
    Сначала поток загружает токенизатор из указанного пути, используя метод GPT2Tokenizer.from_pretrained.
  2. Создание конфигурации модели
    Используя предоставленные параметры, поток создает объект конфигурации модели GPT2 (GPT2Config), который включает все основные настройки, такие как количество слоев, размер эмбеддингов, количество голов внимания и т.д.
  3. Создание и сохранение модели
    На основе созданной конфигурации поток создает модель GPT2 (GPT2LMHeadModel) и сохраняет её вместе с токенизатором в указанной пользователем директории.

Заключение

Этот скрипт представляет собой мощный инструмент для пользователей, которым необходимо гибко и быстро настраивать и создавать кастомные модели GPT. Благодаря простому и удобному интерфейсу на PyQt6, пользователи могут легко настроить все необходимые параметры модели и запустить процесс её создания, при этом приложение остаётся отзывчивым и предоставляет информацию о текущем прогрессе. Этот подход особенно полезен для исследователей и разработчиков, работающих в области NLP, которые хотят экспериментировать с различными конфигурациями моделей GPT.

Сам скрипт:

import sys

import os

from PyQt6.QtWidgets import QApplication, QMainWindow, QTextEdit, QPushButton, QLabel, QLineEdit, QVBoxLayout, QWidget, QFormLayout, QTabWidget

from PyQt6.QtCore import QThread, pyqtSignal

from transformers import GPT2Tokenizer, GPT2Config, GPT2LMHeadModel

class ModelThread(QThread):

update_text_signal = pyqtSignal(str)

model_saved_signal = pyqtSignal()

def __init__(self, config):

super().__init__()

self.config = config

def run(self):

if not os.path.exists(self.config['tokenizer_path']):

self.update_text_signal.emit(f"Путь к токенизатору не существует: {self.config['tokenizer_path']}")

return

self.update_text_signal.emit("Загружаем предварительно созданный токенизатор")

tokenizer = GPT2Tokenizer.from_pretrained(self.config['tokenizer_path'])

self.update_text_signal.emit("Создаем конфигурацию модели с нужными параметрами")

model_config = GPT2Config(

vocab_size=tokenizer.vocab_size,

n_layer=self.config['n_layer'],

n_head=self.config['n_head'],

n_embd=self.config['n_embd'],

intermediate_size=self.config['intermediate_size'],

hidden_size=self.config['hidden_size'],

max_position_embeddings=self.config['max_position_embeddings'],

num_attention_heads=self.config['num_attention_heads'],

gradient_checkpointing=self.config['gradient_checkpointing'],

bos_token_id=tokenizer.bos_token_id,

eos_token_id=tokenizer.eos_token_id,

pad_token_id=tokenizer.pad_token_id,

sep_token_id=tokenizer.sep_token_id,

activation_function=self.config['activation_function'],

initializer_range=self.config['initializer_range'],

layer_norm_eps=self.config['layer_norm_eps'],

scale_attn_by_inverse_layer_idx=self.config['scale_attn_by_inverse_layer_idx'],

reorder_and_upcast_attn=self.config['reorder_and_upcast_attn']

)

self.update_text_signal.emit("Создаем модель на основе заданной конфигурации")

model = GPT2LMHeadModel(config=model_config)

model.resize_token_embeddings(len(tokenizer))

self.update_text_signal.emit("Модель создана.")

self.update_text_signal.emit("Сохраняем модель и токенизатор.")

model.save_pretrained(self.config['model_save_path'])

tokenizer.save_pretrained(self.config['model_save_path'])

self.update_text_signal.emit("Модель и токенизатор сохранены.")

self.model_saved_signal.emit()

class MainWindow(QMainWindow):

def __init__(self):

super().__init__()

self.setWindowTitle("Создание модели GPT")

self.setGeometry(100, 100, 600, 400)

self.initUI()

def initUI(self):

self.tabs = QTabWidget(self)

self.setCentralWidget(self.tabs)

self.createModelTab()

self.createSettingsTab()

self.model_thread = None

def createModelTab(self):

self.modelTab = QWidget()

self.tabs.addTab(self.modelTab, "Создание модели")

layout = QVBoxLayout()

self.text_edit = QTextEdit(self)

self.text_edit.setReadOnly(True)

self.exit_button = QPushButton("Выход", self)

self.exit_button.setEnabled(False)

self.exit_button.clicked.connect(self.close)

layout.addWidget(self.text_edit)

layout.addWidget(self.exit_button)

self.modelTab.setLayout(layout)

def createSettingsTab(self):

self.settingsTab = QWidget()

self.tabs.addTab(self.settingsTab, "Настройки")

layout = QFormLayout()

self.tokenizerPathEdit = QLineEdit("D:/GPT_pro/token")

self.modelSavePathEdit = QLineEdit("D:/GPT_pro/model")

self.nLayerEdit = QLineEdit("22")

self.nHeadEdit = QLineEdit("32")

self.nEmbdEdit = QLineEdit("2048")

self.intermediateSizeEdit = QLineEdit("3072")

self.hiddenSizeEdit = QLineEdit("1536")

self.maxPositionEmbeddingsEdit = QLineEdit("3072")

self.numAttentionHeadsEdit = QLineEdit("32")

self.gradientCheckpointingEdit = QLineEdit("True")

self.activationFunctionEdit = QLineEdit("gelu_new")

self.initializerRangeEdit = QLineEdit("0.02")

self.layerNormEpsEdit = QLineEdit("1e-5")

self.scaleAttnByInverseLayerIdxEdit = QLineEdit("True")

self.reorderAndUpcastAttnEdit = QLineEdit("True")

layout.addRow("Путь к токенизатору:", self.tokenizerPathEdit)

layout.addRow("Путь сохранения модели:", self.modelSavePathEdit)

layout.addRow("Количество слоев:", self.nLayerEdit)

layout.addRow("Количество голов:", self.nHeadEdit)

layout.addRow("Размер эмбеддингов:", self.nEmbdEdit)

layout.addRow("Промежуточный размер:", self.intermediateSizeEdit)

layout.addRow("Скрытый размер:", self.hiddenSizeEdit)

layout.addRow("Макс. позиционные эмбеддинги:", self.maxPositionEmbeddingsEdit)

layout.addRow("Количество голов внимания:", self.numAttentionHeadsEdit)

layout.addRow("Контроль градиентов:", self.gradientCheckpointingEdit)

layout.addRow("Функция активации:", self.activationFunctionEdit)

layout.addRow("Диапазон инициализации:", self.initializerRangeEdit)

layout.addRow("Эпсилон нормализации слоев:", self.layerNormEpsEdit)

layout.addRow("Масштабировать внимание по индексу слоя:", self.scaleAttnByInverseLayerIdxEdit)

layout.addRow("Перестроить и увеличивать внимание:", self.reorderAndUpcastAttnEdit)

self.start_button = QPushButton("Начать создание модели")

self.start_button.clicked.connect(self.start_model_creation)

layout.addWidget(self.start_button)

self.settingsTab.setLayout(layout)

def start_model_creation(self):

config = {

'tokenizer_path': self.tokenizerPathEdit.text(),

'model_save_path': self.modelSavePathEdit.text(),

'n_layer': int(self.nLayerEdit.text()),

'n_head': int(self.nHeadEdit.text()),

'n_embd': int(self.nEmbdEdit.text()),

'intermediate_size': int(self.intermediateSizeEdit.text()),

'hidden_size': int(self.hiddenSizeEdit.text()),

'max_position_embeddings': int(self.maxPositionEmbeddingsEdit.text()),

'num_attention_heads': int(self.numAttentionHeadsEdit.text()),

'gradient_checkpointing': self.gradientCheckpointingEdit.text().lower() == 'true',

'activation_function': self.activationFunctionEdit.text(),

'initializer_range': float(self.initializerRangeEdit.text()),

'layer_norm_eps': float(self.layerNormEpsEdit.text()),

'scale_attn_by_inverse_layer_idx': self.scaleAttnByInverseLayerIdxEdit.text().lower() == 'true',

'reorder_and_upcast_attn': self.reorderAndUpcastAttnEdit.text().lower() == 'true'

}

self.model_thread = ModelThread(config)

self.model_thread.update_text_signal.connect(self.update_text)

self.model_thread.model_saved_signal.connect(self.enable_exit_button)

self.model_thread.start()

def update_text(self, text):

self.text_edit.append(text)

def enable_exit_button(self):

self.exit_button.setEnabled(True)

if __name__ == "__main__":

app = QApplication(sys.argv)

window = MainWindow()

window.show()

sys.exit(app.exec())