Proeycto de images-worker creado
This commit is contained in:
114
mvp/image-worker/src/pipeline/pipeline.service.ts
Normal file
114
mvp/image-worker/src/pipeline/pipeline.service.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { PerfilCompletoDto } from '../webhook/webhook.dto';
|
||||
import { PromptBuilderService } from './prompt-builder.service';
|
||||
import { ImageGeneratorService } from './image-generator.service';
|
||||
import { SupervisorService } from './supervisor.service';
|
||||
import { ReformixService } from '../reformix/reformix.service';
|
||||
|
||||
interface ZonaRender {
|
||||
zona: string;
|
||||
imagen: string;
|
||||
score: number;
|
||||
aprobada: boolean;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class PipelineService {
|
||||
private readonly logger = new Logger(PipelineService.name);
|
||||
private readonly maxRetries: number;
|
||||
private readonly minScore: number;
|
||||
|
||||
constructor(
|
||||
private readonly config: ConfigService,
|
||||
private readonly promptBuilder: PromptBuilderService,
|
||||
private readonly imageGenerator: ImageGeneratorService,
|
||||
private readonly supervisor: SupervisorService,
|
||||
private readonly reformix: ReformixService,
|
||||
) {
|
||||
this.maxRetries = this.config.get<number>('MAX_RETRIES', 2);
|
||||
this.minScore = this.config.get<number>('SUPERVISOR_MIN_SCORE', 70);
|
||||
}
|
||||
|
||||
async procesarLead(dto: PerfilCompletoDto): Promise<void> {
|
||||
const { leadId, reforma, zonas } = dto;
|
||||
const zonasConFotos = zonas.filter((z) => z.fotos.antes.length > 0);
|
||||
const zonasSaltadas = zonas.filter((z) => z.fotos.antes.length === 0);
|
||||
|
||||
this.logger.log(`[${leadId}] Iniciando pipeline para ${zonasConFotos.length} zonas`);
|
||||
|
||||
for (const z of zonasSaltadas) {
|
||||
this.logger.log(`[${leadId}] Zona ${z.zona}: sin fotos "antes", saltando`);
|
||||
}
|
||||
|
||||
const renders: ZonaRender[] = [];
|
||||
|
||||
for (const zona of zonasConFotos) {
|
||||
try {
|
||||
const render = await this.procesarZona(leadId, zona.zona, reforma, zona.notas, zona.fotos.antes[0]);
|
||||
renders.push(render);
|
||||
} catch (err: any) {
|
||||
this.logger.error(`[${leadId}] Zona ${zona.zona}: error fatal: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (renders.length === 0) {
|
||||
this.logger.warn(`[${leadId}] No se generaron renders para ninguna zona`);
|
||||
return;
|
||||
}
|
||||
|
||||
const items = renders.map((r) => ({
|
||||
zona: r.zona,
|
||||
imagen: r.imagen,
|
||||
}));
|
||||
|
||||
const ok = await this.reformix.entregarRenders(leadId, items);
|
||||
if (ok) {
|
||||
this.logger.log(`[${leadId}] Renders entregados correctamente (${renders.length} zonas)`);
|
||||
} else {
|
||||
this.logger.error(`[${leadId}] Error entregando renders a la app principal`);
|
||||
}
|
||||
}
|
||||
|
||||
private async procesarZona(
|
||||
leadId: string,
|
||||
zona: string,
|
||||
reforma: PerfilCompletoDto['reforma'],
|
||||
notas: string[],
|
||||
fotoAntes: string,
|
||||
): Promise<ZonaRender> {
|
||||
const prompt = await this.promptBuilder.generarPrompt(reforma.tipo, reforma.m2Suelo, reforma.calidad, notas);
|
||||
this.logger.log(`[${leadId}] Zona ${zona}: prompt generado`);
|
||||
|
||||
let ultimaImagen: string | null = null;
|
||||
|
||||
for (let intento = 0; intento <= this.maxRetries; intento++) {
|
||||
if (intento > 0) {
|
||||
this.logger.log(`[${leadId}] Zona ${zona}: reintento ${intento} de ${this.maxRetries}`);
|
||||
}
|
||||
|
||||
const imagen = await this.imageGenerator.generarRender(prompt, fotoAntes);
|
||||
ultimaImagen = imagen;
|
||||
this.logger.log(`[${leadId}] Zona ${zona}: imagen generada`);
|
||||
|
||||
const resultado = await this.supervisor.supervisar(
|
||||
reforma.tipo,
|
||||
reforma.m2Suelo,
|
||||
reforma.calidad,
|
||||
notas,
|
||||
fotoAntes,
|
||||
imagen,
|
||||
);
|
||||
|
||||
const aprobada = resultado.aprobado && resultado.score >= this.minScore;
|
||||
this.logger.log(`[${leadId}] Zona ${zona}: ${aprobada ? 'aprobada' : 'rechazada'} (score: ${resultado.score}) - ${resultado.motivo}`);
|
||||
|
||||
if (aprobada) {
|
||||
return { zona, imagen, score: resultado.score, aprobada: true };
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.warn(`[${leadId}] Zona ${zona}: usando ultimo render pese a no superar validacion`);
|
||||
return { zona, imagen: ultimaImagen!, score: 0, aprobada: false };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user