feat: flag forcar_do_zero para treinar do zero ignorando modelo atual

Permite disparar treino com yolov8n limpo (sem fine-tuning) sem apagar
o cerebro.pt em produção, que continua servindo o /detectar normalmente
enquanto o novo treino roda.
This commit is contained in:
Davi Dias
2026-07-02 19:23:51 -03:00
parent 5f489ecb9e
commit a990e6b618
+14 -4
View File
@@ -83,11 +83,20 @@ def carregar_modelo_do_s3(ambiente: str):
return MODELOS_CARREGADOS[ambiente] return MODELOS_CARREGADOS[ambiente]
def _executar_treino_sync(ambiente: str, pular_triagem: bool) -> dict: def _executar_treino_sync(ambiente: str, pular_triagem: bool, forcar_do_zero: bool = False) -> dict:
"""Execução síncrona do treino — chamada em background thread.""" """Execução síncrona do treino — chamada em background thread."""
prefix_novos = f"treinamento/{ambiente}/novos-treinamentos/" prefix_novos = f"treinamento/{ambiente}/novos-treinamentos/"
objs = s3.list_objects_v2(Bucket=BUCKET, Prefix=prefix_novos) objs = s3.list_objects_v2(Bucket=BUCKET, Prefix=prefix_novos)
if forcar_do_zero:
# Ignora o cerebro.pt atual só para efeito de treino — o arquivo em
# modelos/{ambiente}/atual/cerebro.pt não é tocado, então o /detectar
# em produção continua servindo normalmente enquanto este treino roda.
log_print(f"Treino do zero forçado para '{ambiente}' — ignorando modelo atual.")
modelo_base = YOLO('yolov8n.pt')
is_fine_tuning = False
pular_triagem = True # sem modelo próprio confiável, triagem não faz sentido
else:
# Tenta carregar modelo atual do S3; se não existir, usa YOLO genérico (primeiro treino) # Tenta carregar modelo atual do S3; se não existir, usa YOLO genérico (primeiro treino)
try: try:
modelo_base = carregar_modelo_do_s3(ambiente) modelo_base = carregar_modelo_do_s3(ambiente)
@@ -198,12 +207,12 @@ def _executar_treino_sync(ambiente: str, pular_triagem: bool) -> dict:
return {"status": "vazio"} return {"status": "vazio"}
def _treinar_bg(ambiente: str, pular_triagem: bool): def _treinar_bg(ambiente: str, pular_triagem: bool, forcar_do_zero: bool = False):
global _treinamento_status global _treinamento_status
with _status_lock: with _status_lock:
_training_logs.clear() _training_logs.clear()
try: try:
resultado = _executar_treino_sync(ambiente, pular_triagem) resultado = _executar_treino_sync(ambiente, pular_triagem, forcar_do_zero)
with _status_lock: with _status_lock:
if resultado["status"] == "sucesso": if resultado["status"] == "sucesso":
_treinamento_status = { _treinamento_status = {
@@ -256,9 +265,10 @@ async def treinar(dados: dict):
raise HTTPException(status_code=409, detail="Treinamento já em andamento") raise HTTPException(status_code=409, detail="Treinamento já em andamento")
ambiente = dados.get("ambiente", "gondola") ambiente = dados.get("ambiente", "gondola")
pular_triagem = dados.get("pular_triagem", False) pular_triagem = dados.get("pular_triagem", False)
forcar_do_zero = dados.get("forcar_do_zero", False)
_treinamento_status = {"status": "running", "ambiente": ambiente, "versao": None, "detalhe": None} _treinamento_status = {"status": "running", "ambiente": ambiente, "versao": None, "detalhe": None}
threading.Thread(target=_treinar_bg, args=(ambiente, pular_triagem), daemon=True).start() threading.Thread(target=_treinar_bg, args=(ambiente, pular_triagem, forcar_do_zero), daemon=True).start()
return {"status": "iniciado", "ambiente": ambiente} return {"status": "iniciado", "ambiente": ambiente}