Integrando um Tokenizer Personalizado no Llama-Factory: Um Guia Prático

Integrando um Tokenizer Personalizado no Llama-Factory: Um Guia Prático

No desenvolvimento de modelos de linguagem para domínios especializados, um tokenizador genérico frequentemente falha ao lidar com terminologia específica. Termos como "acordo de recompra" em finanças ou "neurotransmissor" na medicina podem ser fragmentados de maneiras que perdem o significado semântico crucial. A solução é treinar e integrar um tokenizador customizado, e o Llama-Factory oferece um caminho direto para essa integração.

O Llama-Factory possui uma lógica de carregamento específica para tokenizadores. Se o parâmetro tokenizer_name_or_path for explicitamente definido no arquivo de configuração YAML, o framework carregará o tokenizador a partir desse caminho. Caso contrário, ele herda o tokenizador padrão do diretório do modelo especificado em model_name_or_path. Esta separação permite combinar diferentes backbones de modelos com tokenizadores otimizdaos para tarefas específicas.

Passo 1: Treinando o Tokenizador para o Seu Domínio

Utilizando a biblioteca tokenizers da Hugging Face, é possível construir um tokenizador BPE ou WordPiece a partir de um corpus específico. O código abaixo demonstra o treinamento de um novo tokenizador BPE, com nomes de variáveis e estrutura ligeiramente alterados:

from tokenizers import Tokenizer, models, pre_tokenizers, trainers

# Instanciando um modelo BPE vazio
domain_tokenizer = Tokenizer(models.BPE())
domain_tokenizer.pre_tokenizer = pre_tokenizers.Whitespace()

# Configurando o treinador com parâmetros ajustados
bpe_trainer = trainers.BpeTrainer(
    vocab_size=30000,
    min_frequency=3,
    special_tokens=["<pad>", "<unk>", "<sep>", "<cls>", "<mask>", "<domain_start>", "<domain_end>"]
)

# Lista de arquivos de texto do corpus
corpus_files = ["./data/technical_corpus.txt"]
domain_tokenizer.train(corpus_files, bpe_trainer)

# Salvando a estrutura completa do tokenizador
output_directory = "./trained_tokenizer"
domain_tokenizer.save(f"{output_directory}/tokenizer.json")</domain_end></domain_start></mask></cls></sep></unk></pad>

Para que seja reconhecido pelo ecossistema Hugging Face, o diretório de saída deve incluir, além do tokenizer.json, os arquivos de configuração tokenizer_config.json e special_tokens_map.json.

Passo 2: Configuração do Llama-Factory para Usar o Novo Tokenizador

No arquivo de configuração YAML do treinamento, aponte explicitamente para o diretório do seu tokenizador treinado. Um ponto crucial é definir overwrite_cache: true. Isso força o Llama-Factory a reprocessar o conjunto de dados com a nova lógica de tokenização, ignorando quaisquer caches antigos que possam conter IDs gerados pelo tokenizador antigo.

# treinamento_config.yaml
model_name_or_path: "caminho/para/o/modelo_base"
tokenizer_name_or_path: "./trained_tokenizer" # Caminho para seu tokenizador customizado

dataset: "meu_dataset_especializado"
template: "chatml"
max_seq_length: 2048

finetuning_type: "lora"
lora_rank: 32
lora_alpha: 64
lora_dropout: 0.05

learning_rate: 1e-4
num_train_epochs: 2
gradient_accumulation_steps: 4
per_device_train_batch_size: 2
output_dir: "./resultados_finetuning"

# Configuração essencial ao mudar o tokenizador
overwrite_cache: true

Passo 3: Sincronizando o Vocabulário com o Modelo

Ao adicionar novos tokens ao tokenizador, a camada de embedding do modelo precisa ser redimensionada para acomodar esses novos IDs. O Llama-Factory realiza essa verificação automaticamente no início do treinamento, mas é uma boa prática validá-lo manualmente. O código a seguir demonstra como carregar o modelo e o tokenizador, adicionar tokens novos e ajustar as embeddings:

from transformers import AutoModelForCausalLM, AutoTokenizer

# Carregar o modelo base
model = AutoModelForCausalLM.from_pretrained("caminho/para/o/modelo_base")
# Carregar seu tokenizador treinado
custom_tokenizer = AutoTokenizer.from_pretrained("./trained_tokenizer")

# Adicionar tokens específicos do domínio, se não estiverem no vocabulário
new_domain_tokens = ["<formula>", "<cita>", "<refer>"]
num_added = custom_tokenizer.add_tokens(new_domain_tokens)

# Redimensionar a camada de embeddings do modelo
if num_added > 0:
    model.resize_token_embeddings(len(custom_tokenizer))
    print(f"Vocabulário expandido em {num_added} tokens. Novo tamanho: {len(custom_tokenizer)}")

# Agora, o modelo e o tokenizador estão sincronizados para o treinamento</refer></cita></formula>

Garantir que len(custom_tokenizer) seja igual a model.config.vocab_size após o redimensionamento é fundamental para evitar erros de índice durante o treinamento.

Soluções para Problemas Comuns

Erro "token not in vocabulary" na inferência: Isso geralmente ocorre quando o modelo treinado é carregado com o tokenizador padrão. Certifique-se de que o diretório do modelo salvo pelo Llama-Factory contenha todos os arquivos do tokenizador customizado e que o código de inferência aponte para ele.

Desempenho abaixo do esperado: Um aumento drástico no tamanho do vocabulário (ex: >10% do original) pode levar a embeddings esparsas e treinamento instável. Considere usar um vocabulário menor ou aplicar uma pré-treinamento adaptativo ao domínio (DAPT) antes do fine-tuning.

Cache desatualizado: Se o loss de treinamento parece anormalmante alto logo no início, verifique se a opção overwrite_cache foi habilitada. O cache antigo contém sequências codificadas de maneira incorreta para o novo tokenizador.

Tags: Llama-Factory Tokenizer Hugging Face Transformers Fine-tuning Processamento de Linguagem Natural

Publicado em 6-4 20:44 por Thomas