akra35567 commited on
Commit
cab3d70
·
1 Parent(s): 64b4ab9

Update modules/treinamento.py

Browse files
Files changed (1) hide show
  1. modules/treinamento.py +58 -69
modules/treinamento.py CHANGED
@@ -1,33 +1,33 @@
1
- # modules/treinamento.py — TREINO LORA ANGOLANO AUTOMÁTICO + EMBEDDINGS (ÉPICO!)
2
  import json
3
  import os
4
  import threading
5
  import time
6
  from loguru import logger
7
  from sentence_transformers import SentenceTransformer
8
- from peft import LoraConfig, get_peft_model, prepare_model_for_int8_training
9
  from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer
10
  from torch.utils.data import Dataset
 
11
  from .database import Database
12
 
13
  # PASTAS
14
  FINETUNED_PATH = "/home/user/data/finetuned_hermes"
15
  DATA_PATH = f"{FINETUNED_PATH}/dataset.jsonl"
16
  EMBEDDINGS_PATH = f"{FINETUNED_PATH}/embeddings.jsonl"
17
- LORA_PATH = f"{FINETUNED_PATH}/lora_angolano"
18
 
19
  os.makedirs(FINETUNED_PATH, exist_ok=True)
20
  os.makedirs(LORA_PATH, exist_ok=True)
21
 
22
- # MODELOS
23
- EMBEDDING_MODEL = SentenceTransformer("intfloat/multilingual-e5-large") # MELHOR PARA PORTUGUÊS/ANGOLANO
24
- TOKENIZER = None
25
- MODEL = None
26
 
27
- # LOCK PARA THREADS
28
  _lock = threading.Lock()
 
29
 
30
- class AngolanoDataset(Dataset):
31
  def __init__(self, data):
32
  self.data = data
33
 
@@ -36,31 +36,29 @@ class AngolanoDataset(Dataset):
36
 
37
  def __getitem__(self, idx):
38
  item = self.data[idx]
39
- text = f"<s>[INST] {item['user']} [/INST] {item['assistant']}</s>"
40
- encoded = TOKENIZER(text, truncation=True, max_length=2048, padding="max_length")
41
  encoded["labels"] = encoded["input_ids"].copy()
42
  return {k: torch.tensor(v) for k, v in encoded.items()}
43
 
44
- class Treinamento:
45
  def __init__(self, db: Database):
46
  self.db = db
47
- self.dataset = []
48
  self._carregar_dataset()
49
- logger.info("TREINAMENTO ANGOLANO ATIVO → EMBEDDINGS + LORA A CADA 4H!")
50
-
51
- # Inicia treino periódico
52
  threading.Thread(target=self._treino_periodico, daemon=True).start()
53
 
54
  def _carregar_dataset(self):
 
55
  if os.path.exists(DATA_PATH):
56
  with open(DATA_PATH, "r", encoding="utf-8") as f:
57
- self.dataset = [json.loads(line) for line in f]
58
- logger.info(f"{len(self.dataset)} interações carregadas para treino!")
59
 
60
  def registrar_interacao(self, usuario, mensagem, resposta, numero='', **kwargs):
61
  self.db.salvar_mensagem(usuario, mensagem, resposta, numero)
62
  self._salvar_roleplay(mensagem, resposta)
63
- self._salvar_embedding(mensagem, resposta)
64
 
65
  def _salvar_roleplay(self, msg, resp):
66
  entry = {"user": msg, "assistant": resp}
@@ -68,87 +66,78 @@ class Treinamento:
68
  json.dump(entry, f, ensure_ascii=False)
69
  f.write("\n")
70
  with _lock:
71
- self.dataset.append(entry)
72
 
73
- def _salvar_embedding(self, msg, resp):
74
  try:
75
- emb_msg = EMBEDDING_MODEL.encode(msg, normalize_embeddings=True).tolist()
76
- emb_resp = EMBEDDING_MODEL.encode(resp, normalize_embeddings=True).tolist()
77
- entry = {"msg": msg, "resp": resp, "emb_msg": emb_msg, "emb_resp": emb_resp}
78
  with open(EMBEDDINGS_PATH, "a", encoding="utf-8") as f:
79
  json.dump(entry, f, ensure_ascii=False)
80
  f.write("\n")
81
- logger.debug("Embedding salvo com sucesso!")
82
- except Exception as e:
83
- logger.error(f"Erro no embedding: {e}")
84
 
85
  def _treino_periodico(self):
86
- global TOKENIZER, MODEL
87
  while True:
88
- time.sleep(4 * 3600) # A CADA 4 HORAS
89
- if len(self.dataset) < 10:
90
- logger.info("Poucos dados ainda... esperando mais kandandos!")
91
  continue
92
 
93
- logger.info("INICIANDO TREINO LORA ANGOLANO AUTOMÁTICO!")
94
  try:
95
- # Carrega tokenizer e modelo base (só na primeira vez)
96
- if TOKENIZER is None:
97
- TOKENIZER = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf", use_fast=True)
 
98
  TOKENIZER.pad_token = TOKENIZER.eos_token
99
 
100
- if MODEL is None:
101
- MODEL = AutoModelForCausalLM.from_pretrained(
102
- "meta-llama/Llama-2-7b-hf",
103
- load_in_8bit=True,
104
- device_map="auto"
105
- )
106
- MODEL = prepare_model_for_int8_training(MODEL)
107
 
108
- # Config LoRA
109
  lora_config = LoraConfig(
110
- r=16,
111
- lora_alpha=32,
112
  target_modules=["q_proj", "v_proj"],
113
  lora_dropout=0.05,
114
  bias="none",
115
  task_type="CAUSAL_LM"
116
  )
117
- model_peft = get_peft_model(MODEL, lora_config)
118
 
119
- # Dataset
120
- train_dataset = AngolanoDataset(self.dataset[-500:]) # últimas 500 interações
121
 
122
- # Treino
123
- training_args = TrainingArguments(
124
  output_dir=LORA_PATH,
125
- per_device_train_batch_size=2,
126
  gradient_accumulation_steps=4,
127
- num_train_epochs=3,
128
  learning_rate=2e-4,
129
  fp16=True,
130
- logging_steps=10,
131
- save_steps=50,
132
- save_total_limit=2,
133
  report_to=[],
134
- disable_tqdm=False
135
- )
136
-
137
- trainer = Trainer(
138
- model=model_peft,
139
- args=training_args,
140
- train_dataset=train_dataset,
141
- tokenizer=TOKENIZER
142
  )
143
 
 
144
  trainer.train()
145
  trainer.save_model(LORA_PATH)
146
- logger.info("LORA ANGOLANO TREINADO E SALVO! SOTAQUE MAIS FORTE QUE NUNCA!")
147
 
148
- # Converte para GGUF (opcional, se quiser usar direto no llama.cpp)
149
- os.system(f"python -m llama_cpp.convert --outfile {FINETUNED_PATH}/adapter_model.gguf --model {LORA_PATH}")
 
 
 
 
150
 
151
  except Exception as e:
152
- logger.error(f"Erro no treino: {e}")
153
- import traceback
154
- logger.error(traceback.format_exc())
 
1
+ # modules/treinamento.py — TREINO LEVE (30s) + EMBEDDINGS RÁPIDOS + LORA ANGOLANO
2
  import json
3
  import os
4
  import threading
5
  import time
6
  from loguru import logger
7
  from sentence_transformers import SentenceTransformer
8
+ from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
9
  from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer
10
  from torch.utils.data import Dataset
11
+ import torch
12
  from .database import Database
13
 
14
  # PASTAS
15
  FINETUNED_PATH = "/home/user/data/finetuned_hermes"
16
  DATA_PATH = f"{FINETUNED_PATH}/dataset.jsonl"
17
  EMBEDDINGS_PATH = f"{FINETUNED_PATH}/embeddings.jsonl"
18
+ LORA_PATH = f"{FINETUNED_PATH}/lora_leve"
19
 
20
  os.makedirs(FINETUNED_PATH, exist_ok=True)
21
  os.makedirs(LORA_PATH, exist_ok=True)
22
 
23
+ # EMBEDDING LEVE E RÁPIDO (300MB)
24
+ EMBEDDING_MODEL = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
 
 
25
 
26
+ # LOCK
27
  _lock = threading.Lock()
28
+ _dataset = []
29
 
30
+ class LeveDataset(Dataset):
31
  def __init__(self, data):
32
  self.data = data
33
 
 
36
 
37
  def __getitem__(self, idx):
38
  item = self.data[idx]
39
+ text = f"<|im_start|>user\n{item['user']}<|im_end|>\n<|im_start|>assistant\n{item['assistant']}<|im_end|>"
40
+ encoded = TOKENIZER(text, truncation=True, max_length=512, padding="max_length")
41
  encoded["labels"] = encoded["input_ids"].copy()
42
  return {k: torch.tensor(v) for k, v in encoded.items()}
43
 
44
+ class TreinamentoLeve:
45
  def __init__(self, db: Database):
46
  self.db = db
 
47
  self._carregar_dataset()
48
+ logger.info("TREINAMENTO LEVE ATIVO → LORA A CADA 30 MIN + EMBEDDINGS RÁPIDOS!")
 
 
49
  threading.Thread(target=self._treino_periodico, daemon=True).start()
50
 
51
  def _carregar_dataset(self):
52
+ global _dataset
53
  if os.path.exists(DATA_PATH):
54
  with open(DATA_PATH, "r", encoding="utf-8") as f:
55
+ _dataset = [json.loads(line) for line in f]
56
+ logger.info(f"{len(_dataset)} kandandos carregados!")
57
 
58
  def registrar_interacao(self, usuario, mensagem, resposta, numero='', **kwargs):
59
  self.db.salvar_mensagem(usuario, mensagem, resposta, numero)
60
  self._salvar_roleplay(mensagem, resposta)
61
+ self._salvar_embedding_leve(mensagem, resposta)
62
 
63
  def _salvar_roleplay(self, msg, resp):
64
  entry = {"user": msg, "assistant": resp}
 
66
  json.dump(entry, f, ensure_ascii=False)
67
  f.write("\n")
68
  with _lock:
69
+ _dataset.append(entry)
70
 
71
+ def _salvar_embedding_leve(self, msg, resp):
72
  try:
73
+ emb = EMBEDDING_MODEL.encode(f"{msg} {resp}", normalize_embeddings=True).tolist()
74
+ entry = {"text": f"{msg} -> {resp}", "emb": emb}
 
75
  with open(EMBEDDINGS_PATH, "a", encoding="utf-8") as f:
76
  json.dump(entry, f, ensure_ascii=False)
77
  f.write("\n")
78
+ except: pass
 
 
79
 
80
  def _treino_periodico(self):
 
81
  while True:
82
+ time.sleep(30 * 60) # A CADA 30 MINUTOS
83
+ if len(_dataset) < 5:
 
84
  continue
85
 
86
+ logger.info("INICIANDO TUNE LEVE (30s) → LORA ANGOLANO!")
87
  try:
88
+ # Tokenizer (só uma vez)
89
+ global TOKENIZER
90
+ if 'TOKENIZER' not in globals():
91
+ TOKENIZER = AutoTokenizer.from_pretrained("NousResearch/OpenHermes-2.5-Mistral-7B", use_fast=True)
92
  TOKENIZER.pad_token = TOKENIZER.eos_token
93
 
94
+ # Modelo em 4bit (LEVE!)
95
+ model = AutoModelForCausalLM.from_pretrained(
96
+ "NousResearch/OpenHermes-2.5-Mistral-7B",
97
+ load_in_4bit=True,
98
+ device_map="auto"
99
+ )
100
+ model = prepare_model_for_kbit_training(model)
101
 
102
+ # LoRA leve
103
  lora_config = LoraConfig(
104
+ r=8,
105
+ lora_alpha=16,
106
  target_modules=["q_proj", "v_proj"],
107
  lora_dropout=0.05,
108
  bias="none",
109
  task_type="CAUSAL_LM"
110
  )
111
+ model = get_peft_model(model, lora_config)
112
 
113
+ # Dataset (últimas 50 interações)
114
+ dataset = LeveDataset(_dataset[-50:])
115
 
116
+ # Treino RÁPIDO
117
+ args = TrainingArguments(
118
  output_dir=LORA_PATH,
119
+ per_device_train_batch_size=1,
120
  gradient_accumulation_steps=4,
121
+ num_train_epochs=1,
122
  learning_rate=2e-4,
123
  fp16=True,
124
+ logging_steps=5,
125
+ save_steps=10,
126
+ save_total_limit=1,
127
  report_to=[],
128
+ disable_tqdm=True
 
 
 
 
 
 
 
129
  )
130
 
131
+ trainer = Trainer(model=model, args=args, train_dataset=dataset)
132
  trainer.train()
133
  trainer.save_model(LORA_PATH)
 
134
 
135
+ # Converte pra GGUF leve
136
+ os.system(f"python -m llama_cpp.convert --outfile {FINETUNED_PATH}/lora_leve.gguf --model {LORA_PATH} --quantize q4_k_m")
137
+
138
+ logger.info("LORA LEVE TREINADO EM 30s! SOTAQUE ANGOLANO + FORTE!")
139
+ del model, trainer
140
+ torch.cuda.empty_cache()
141
 
142
  except Exception as e:
143
+ logger.error(f"Erro no tune leve: {e}")