Pipeline SFT de Livros
Um sistema completo para converter livros em conjuntos de dados SFT e treinar modelos de transferência de estilo. Esta skill ensina o pipeline desde o ePub bruto até um modelo que escreve na voz de qualquer autor.
Quando Ativar
Ative esta skill quando:
- Construir conjuntos de dados de fine-tuning a partir de obras literárias
- Criar modelos de voz do autor ou transferência de estilo
- Preparar dados de treinamento para o Tinker ou plataformas SFT similares
- Projetar pipelines de segmentação de texto para conteúdo de formato longo
- Treinar modelos pequenos (8B ou menos) com dados limitados
Conceitos Centrais
Os Três Pilares do SFT de Livros
1. Segmentação Inteligente Os chunks de texto devem ser semanticamente coerentes. Interromper no meio de uma frase ensina o modelo a produzir saída fragmentada. Meta: 150-400 palavras por chunk, sempre em limites naturais.
2. Geração Diversa de Instruções Use múltiplos templates de prompt e prompts de sistema para evitar overfitting. Um único estilo de prompt leva à memorização. Use 15+ templates de prompt com 5+ prompts de sistema.
3. Estilo sobre Conteúdo O objetivo é aprender o ritmo e os padrões de vocabulário do autor, não memorizar enredos. Instruções sintéticas descrevem o que acontece sem citar o texto.
Arquitetura do Pipeline
┌─────────────────────────────────────────────────────────────────┐
│ AGENTE ORQUESTRADOR │
│ Coordena fases do pipeline, gerencia estado, lida com falhas │
└──────────────────────┬──────────────────────────────────────────┘
│
┌───────────────┼───────────────┬───────────────┐
▼ ▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ EXTRAÇÃO │ │ SEGMENTAÇÃO │ │ INSTRUÇÃO │ │ CONSTRUTOR │
│ AGENTE │ │ AGENTE │ │ AGENTE │ │ DATASET │
│ ePub→Texto │ │Texto→Chunks │ │ Chunks→ │ │ Pares→ │
│ │ │ 150-400 pal. │ │ Prompts │ │ JSONL │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ TREINAMENTO │ │ VALIDAÇÃO │
│ AGENTE │ │ AGENTE │
│ LoRA no │ │ Detector AI │
│ Tinker │ │ Originalidade│
└──────────────┘ └──────────────┘
Fase 1: Extração de Texto
Regras Críticas
- Sempre prefira ePub em vez de PDF - Erros de OCR tornam-se padrões aprendidos
- Use extração em nível de parágrafo - Extraia das tags
<p>para preservar quebras - Remova material de front/back matter - Direitos autorais e sumário poluem o dataset
# Extrair texto de parágrafos ePub
from epub2 import EPub
from bs4 import BeautifulSoup
def extract_epub(path):
book = EPub(path)
chapters = []
for item in book.flow:
html = book.get_chapter(item.id)
soup = BeautifulSoup(html, 'html.parser')
paragraphs = [p.get_text().strip() for p in soup.find_all('p')]
chapters.append('\n\n'.join(p for p in paragraphs if p))
return '\n\n'.join(chapters)
Fase 2: Segmentação Inteligente
Chunks Menores + Sobreposição
Chunks menores (150-400 palavras) produzem mais exemplos de treinamento e melhor transferência de estilo do que chunks maiores (250-650).
def segment(text, min_words=150, max_words=400):
paragraphs = text.split('\n\n')
chunks, buffer, buffer_words = [], [], 0
for para in paragraphs:
words = len(para.split())
if buffer_words + words > max_words and buffer_words >= min_words:
chunks.append('\n\n'.join(buffer))
# Manter último parágrafo para sobreposição
buffer = [buffer[-1], para] if buffer else [para]
buffer_words = sum(len(p.split()) for p in buffer)
else:
buffer.append(para)
buffer_words += words
if buffer:
chunks.append('\n\n'.join(buffer))
return chunks
Resultados Esperados
Para um livro de 86.000 palavras:
- Método antigo (250-650 palavras): ~150 chunks
- Novo método (150-400 + sobreposição): ~300 chunks
- Com 2 variantes por chunk: 600+ exemplos de treinamento
Fase 3: Geração Diversa de Instruções
O Insight Principal
Usar um único template de prompt causa memorização. Templates diversos ensinam o estilo subjacente.
SYSTEM_PROMPTS = [
"Você é um escritor criativo especialista capaz de emular estilos literários específicos.",
"Você é um escritor literário com profundo conhecimento de estilos clássicos de prosa.",
"Você é um escritor criativo habilidoso em emular vozes autorais distintas.",
"Você escreve prosa que captura a essência da literatura modernista.",
"Você é um escritor talentoso que pode canalizar autores americanos clássicos.",
]
PROMPT_TEMPLATES = [
"Escreva uma passagem no estilo de {author}: {desc}",
"Canalize a voz de {author} para escrever sobre: {desc}",
"No estilo de prosa distinto de {author}, descreva: {desc}",
"Escreva esta cena como {author} teria escrito: {desc}",
"Usando a técnica repetitiva de {author}, descreva: {desc}",
"Capture o ritmo de {author} nesta passagem: {desc}",
"Escreva como {author}: {desc}",
"Na voz de {author}, escreva: {desc}",
"Este é um exercício literário. Escreva como {author}: {desc}",
"Você consegue escrever no estilo de {author}? {desc}",
]
Geração de Instruções
INSTRUCTION_PROMPT = """Descreva o que está acontecendo neste trecho em 2 a 3 frases.
Foco em: personagens presentes, ações, emoções, cenário.
NÃO cite o texto diretamente.
Trecho:
{text}
"""
# Use um LLM rápido e barato (ex: Gemini Flash)
instruction = llm_call(INSTRUCTION_PROMPT.format(text=chunk))
Fase 4: Construção do Dataset
Formato de Mensagem
{
"messages": [
{"role": "system", "content": "Você é um escritor criativo especialista..."},
{"role": "user", "content": "Escreva no estilo de Autor: Descrição da cena..."},
{"role": "assistant", "content": "O texto real do livro do chunk..."}
]
}
Múltiplas Variantes por Chunk
def build_examples(chunk, instruction, author, variants=2):
examples = []
for i in range(variants):
system = SYSTEM_PROMPTS[i % len(SYSTEM_PROMPTS)]
template = PROMPT_TEMPLATES[(chunk.id + i) % len(PROMPT_TEMPLATES)]
user = template.format(author=author, desc=instruction)
examples.append({"messages": [
{"role": "system", "content": system},
{"role": "user", "content": user},
{"role": "assistant", "content": chunk.text}
]})
return examples
Fase 5: Treinamento LoRA no Tinker
Configuração
CONFIG = {
"model_name": "Qwen/Qwen3-8B-Base", # Base, não instruct
"lora_rank": 32, # Adaptador de 352MB
"learning_rate": 5e-4, # Mais alto para LoRA
"batch_size": 4,
"epochs": 3,
}
Por que Modelo Base?
Use modelos base (pré-treinados), não versões instruction-tuned:
- Modelos base são mais maleáveis para novos estilos
- Modelos instruct têm padrões que resistem à sobrescrita
- Estilo é um padrão de baixo nível que modelos base capturam melhor
Loop de Treinamento
import tinker
from tinker import types
training_client = await service_client.create_lora_training_client_async(
base_model="Qwen/Qwen3-8B-Base",
rank=32
)
for epoch in range(3):
for batch in batches:
await training_client.forward_backward_async(batch, loss_fn="cross_entropy")
await training_client.optim_step_async(types.AdamParams(learning_rate=5e-4))
result = await training_client.save_weights_for_sampler_async(name="final")
Fase 6: Validação
Teste de Cenário Moderno
Teste com cenários que não poderiam existir no livro original:
TEST_PROMPTS = [
"Escreva sobre um barista preparando lattes",
"Descreva amantes se comunicando por mensagens de texto",
"Escreva sobre alguém ansioso com as mudanças climáticas",
]
Se o modelo aplicar marcadores de estilo a cenários modernos, ele aprendeu estilo, não conteúdo.
Verificação de Originalidade
# Pesquisar dados de treinamento por frases da saída
grep "frase específica da saída" dataset.jsonl
# Deve retornar: Nenhuma correspondência
Teste com Detector de IA
Teste as saídas com GPTZero, Pangram ou ZeroGPT.
Problemas Conhecidos e Soluções
Vazamento de Nomes de Personagens
Sintoma: O modelo usa nomes de personagens originais em novos cenários. Causa: Diversidade limitada de nomes de um único livro. Solução: Treinar em múltiplos livros ou adicionar exemplos sintéticos.
Modelo Repete Frases Exatas
Sintoma: Saídas contêm frases exatas dos dados de treinamento. Causa: Poucas variações de prompt ou muitos epochs. Solução: Use 15+ templates, limite a 3 epochs.
Saídas Fragmentadas
Sintoma: Frases parecem incompletas. Causa: Segmentação ruim quebrando no meio de um pensamento. Solução: Sempre quebrar em limites de parágrafo.
Diretrizes
- Sempre prefira ePub em vez de PDF - Erros de OCR tornam-se padrões aprendidos
- Nunca quebre no meio de uma frase - Limites devem ser gramaticalmente completos
- Use prompts diversos - 15+ templates, 5+ prompts de sistema
- Use modelos base - Não versões instruct
- Use chunks menores - 150-400 palavras para mais exemplos
- Reserve conjunto de teste - 50 exemplos no mínimo
- Teste em cenários modernos - Comprova transferência de estilo vs memorização
- Verifique originalidade - Pesquise nos dados de treinamento por frases da saída
Resultados Esperados
| Métrica | Valor |
|---|---|
| Exemplos de treinamento | 500-1000 por livro |
| Modelo | Qwen/Qwen3-8B-Base |
| Rank LoRA | 32 |
| Tamanho do adaptador | ~350 MB |
| Tempo de treinamento | ~15 min |
| Redução de perda | 90%+ |
| Sucesso na transferência de estilo | ~50% perfeito |
Estimativa de Custo
| Componente | Custo |
|---|---|
| LLM (geração de instruções) | ~$0.50 |
| Treinamento no Tinker (15 min) | ~$1.50 |
| Total | ~$2.00 |
Integração com Skills de Engenharia de Contexto
Este exemplo aplica várias skills da coleção Agent Skills for Context Engineering:
project-development
O pipeline segue o padrão de arquitetura em estágios e idempotente:
- Adquirir: Extrair texto do ePub
- Preparar: Segmentar em chunks de treinamento
- Processar: Gerar instruções sintéticas
- Analisar: Construir formato de mensagem
- Renderizar: Gerar JSONL compatível com Tinker
- Treinar: LoRA fine-tuning
- Validar: Teste de cenário moderno
Cada fase é retomável e produz artefatos intermediários para depuração.
context-compression
A segmentação é uma forma de compressão de contexto para treinamento. O insight central de context-compression se aplica: a densidade da informação importa mais que a quantidade de informação. Chunks menores e coerentes (150-400 palavras) produzem melhor transferência de estilo do que chunks maiores e diluídos.
A estratégia de dois níveis espelha a avaliação de compressão de contexto:
- Nível 1: Compressão rápida e determinística
- Nível 2: Assistida por LLM para casos extremos
multi-agent-patterns
O pipeline usa o padrão supervisor/orquestrador:
- Orquestrador coordena fases e gerencia estado
- Agentes especializados (Extração, Segmentação, Instrução, Construtor) têm contextos isolados
- Cada agente recebe apenas a informação necessária para sua tarefa
Isso corresponde ao princípio de que subagentes existem principalmente para isolar contexto, não para simular papéis.
evaluation
A validação segue o padrão avaliação de estado final:
- Teste funcional: A saída corresponde aos marcadores de estilo esperados?
- Verificação de originalidade: O conteúdo é genuinamente gerado?
- Validação externa: Pontuações de detectores de IA
O teste de "cenário moderno" é uma forma de avaliação fora da distribuição que prova a generalização.
context-fundamentals
A diversidade de prompts previne o colapso da atenção em padrões únicos. Quando treinado com estruturas de prompt idênticas, o modelo memoriza o mapeamento instrução-resposta. Templates diversos forçam a atenção sobre os próprios padrões de estilo.
Referências
Referências internas:
- Estratégias de Segmentação - Padrões de divisão de texto
- Especificação de Formato Tinker - Estrutura de dados
- Documentação da API Tinker - Referência completa da API
Skills relacionadas da Agent Skills for Context Engineering:
- project-development - Padrões de arquitetura de pipeline
- context-compression - Estratégias de compressão
- multi-agent-patterns - Coordenação de agentes
- evaluation - Frameworks de avaliação
- context-fundamentals - Atenção e densidade de informação
Recursos externos:
- Artigo de Pesquisa - Chakrabarty et al. 2025
- Dataset no Hugging Face
- Estudo de Caso Gertrude Stein - Exemplo completo funcional
Metadados da Skill
Criado: 2025-12-26 Última Atualização: 2025-12-28 Autor: Muratcan Koylan Versão: 2.0.0 Independente: Sim (separada da coleção principal de engenharia de contexto)