File size: 4,239 Bytes
6090b73
 
 
 
e897ba2
 
 
 
 
 
6090b73
 
 
e897ba2
6090b73
 
 
 
 
e897ba2
 
 
6090b73
 
e897ba2
 
 
 
 
 
 
6090b73
e897ba2
 
 
 
 
 
6090b73
 
e897ba2
 
 
 
 
6090b73
e897ba2
 
 
6090b73
 
 
e897ba2
6090b73
e897ba2
 
 
 
 
 
 
 
 
6090b73
e897ba2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6090b73
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# aduc_framework/engineers/prompt_engine.py
#
# Copyright (C) August 4, 2025  Carlos Rodrigues dos Santos
#
# Versão 2.0.0 (Context-Aware Prompt Translator)
#
# O PromptEngine atua como o tradutor entre a lógica de tarefa agnóstica
# do Composer e o formato de prompt específico exigido por um LLM.
# Esta versão é consciente do contexto, sabendo diferenciar entre
# prompts que requerem contexto visual (imagens) e os que são apenas texto.

import logging
from pathlib import Path
from typing import Dict

logger = logging.getLogger(__name__)

class PromptEngine:
    """
    O PromptEngine traduz prompts genéricos para o formato específico do
    modelo de linguagem alvo. Ele seleciona o template correto com base
    na presença de imagens na requisição.
    """
    def __init__(self, model_map_name: str):
        """
        Inicializa o PromptEngine carregando os templates específicos do modelo.

        Args:
            model_map_name (str): O nome do diretório do mapa do modelo em 
                                  'aduc_framework/prompts/model_maps/'.
        """
        self.model_map_name = model_map_name
        
        # Carrega os dois templates essenciais: um para prompts com imagens
        # e outro para prompts que contêm apenas texto.
        self.template_with_image = self._load_model_template(model_map_name, "image_template.txt")
        self.template_text_only = self._load_model_template(model_map_name, "text_template.txt")
        
        logger.info(f"PromptEngine inicializado com o mapa de modelo '{model_map_name}'.")

    def _load_model_template(self, map_name: str, template_file: str) -> str:
        """
        Carrega um arquivo de template de um mapa de modelo específico.
        """
        map_path = Path(__file__).resolve().parent.parent / "prompts" / "model_maps" / map_name / template_file
        if not map_path.is_file():
            # Este é um erro crítico de configuração, então levantamos uma exceção clara.
            raise FileNotFoundError(f"Template de modelo '{template_file}' não encontrado no mapa '{map_name}' em: {map_path}")
        
        with open(map_path, 'r', encoding='utf-8') as f:
            return f.read()

    def translate(self, generic_prompt_content: str, has_image: bool) -> str:
        """
        Envolve o conteúdo do prompt genérico com o template específico do modelo,
        escolhendo o template correto com base na presença de uma imagem.

        Args:
            generic_prompt_content (str): O conteúdo do prompt agnóstico gerado pelo Composer.
            has_image (bool): Sinaliza se a tarefa atual inclui um contexto visual.

        Returns:
            str: O prompt final, formatado e pronto para ser enviado ao LLM.
        """
        logger.debug(f"--- PROMPT ENGINE: INICIANDO TRADUÇÃO (Imagem: {has_image}) ---")
        logger.debug(f"PROMPT GENÉRICO RECEBIDO:\n---\n{generic_prompt_content[:500]}...\n---")
        
        # Seleciona o "mapa" correto com base no contexto
        if has_image:
            template = self.template_with_image
            logger.debug("Usando o template de modelo com imagem.")
        else:
            template = self.template_text_only
            logger.debug("Usando o template de modelo apenas de texto.")
        
        try:
            # Insere o conteúdo genérico dentro do template específico do modelo
            final_prompt = template.format(generic_prompt_content=generic_prompt_content)
            logger.debug(f"PROMPT FINAL (TRADUZIDO) GERADO:\n---\n{final_prompt}\n---")
            logger.debug("--- PROMPT ENGINE: TRADUÇÃO CONCLUÍDA ---")
            return final_prompt
        except KeyError as e:
            logger.error(f"PROMPT ENGINE: Erro de chave durante a tradução! Chave não encontrada: {e}", exc_info=True)
            logger.error("Verifique se o template do modelo contém apenas o placeholder '{generic_prompt_content}'.")
            raise e

# --- Instância Singleton ---
# A seleção do mapa de modelo é feita aqui. No futuro, isso poderia ser
# lido do arquivo de configuração `config.yaml` para maior flexibilidade.
prompt_engine_singleton = PromptEngine(model_map_name="llama_3_2_vision")