Spaces:
Paused
Paused
| # aduc_framework/engineers/prompt_engine.py | |
| # | |
| # Copyright (C) August 4, 2025 Carlos Rodrigues dos Santos | |
| # | |
| # Versão 3.0.0 (Provider-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 é ciente do provedor (Llama, Gemini, etc.) e aplica os | |
| # templates de formatação apenas quando necessário (ex: para o Llama), | |
| # usando um prompt genérico direto para outros (ex: Gemini). | |
| 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 | |
| no provedor de LLM ativo e na presença de imagens na requisição. | |
| """ | |
| def __init__(self): | |
| """ | |
| Inicializa o PromptEngine em um estado "em espera". O provedor | |
| e os templates são carregados posteriormente pelo Composer. | |
| """ | |
| self.provider: str | None = None | |
| self.model_map_name: str = "llama_3_2_vision" # Padrão para Llama | |
| self.template_with_image: str | None = None | |
| self.template_text_only: str | None = None | |
| logger.info("PromptEngine inicializado (aguardando configuração do provedor pelo Composer).") | |
| 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(): | |
| 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 set_provider(self, provider: str): | |
| """ | |
| Configura o provedor de LLM ativo (ex: 'llama_multimodal', 'gemini') | |
| e carrega os templates de formatação específicos, se necessário. | |
| Este método é chamado pelo Composer durante sua inicialização. | |
| """ | |
| if self.provider == provider: | |
| return # Evita recarregamentos desnecessários | |
| self.provider = provider | |
| logger.info(f"PromptEngine: Provedor de LLM definido como '{self.provider}'.") | |
| # Carrega os templates específicos do Llama apenas se ele for o provedor. | |
| # Para o Gemini, nenhum template é necessário, então os atributos permanecem None. | |
| if self.provider == 'llama_multimodal': | |
| logger.info(f"Carregando templates para o mapa de modelo '{self.model_map_name}'...") | |
| self.template_with_image = self._load_model_template(self.model_map_name, "image_template.txt") | |
| self.template_text_only = self._load_model_template(self.model_map_name, "text_template.txt") | |
| else: | |
| self.template_with_image = None | |
| self.template_text_only = None | |
| 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, | |
| mas somente se o provedor ativo (Llama) exigir. Para provedores como o | |
| Gemini, retorna o prompt genérico sem modificação. | |
| 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. | |
| """ | |
| if self.provider is None: | |
| raise RuntimeError("PromptEngine: O provedor não foi definido. Chame set_provider() antes de usar.") | |
| # --- LÓGICA CONDICIONAL --- | |
| # Se o provedor for Gemini, ele usa o "prompt padrão genérico" sem modificação. | |
| if self.provider == 'gemini': | |
| logger.debug("PROMPT ENGINE (Gemini): Retornando prompt genérico sem aplicar template.") | |
| return generic_prompt_content | |
| # A lógica original do Llama é executada para o provedor padrão ('llama_multimodal') | |
| logger.debug(f"--- PROMPT ENGINE ({self.provider}): INICIANDO TRADUÇÃO (Imagem: {has_image}) ---") | |
| template = self.template_with_image if has_image else self.template_text_only | |
| if not template: | |
| raise RuntimeError(f"PromptEngine: Template para o provedor '{self.provider}' não foi carregado corretamente.") | |
| 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 ENGINE ({self.provider}): 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 instância é criada vazia e será configurada dinamicamente pelo Composer. | |
| prompt_engine_singleton = PromptEngine() |