Pular para conteúdo

Prompt Registry

O Prompt Registry é a camada usada para registrar e versionar prompts estruturados do SotuHire.

Na v0.10.0, a primeira implementação está em:

  • modules/ai/prompt_spec.py;
  • modules/ai/prompt_registry.py;
  • modules/ai/prompt_loader.py.

Objetivo

Centralizar todos os prompts de IA para evitar chamadas soltas espalhadas pelo código.

Problema atual

Sem registry, cada módulo tende a montar seu próprio prompt. Isso dificulta:

  • versionamento;
  • testes;
  • auditoria;
  • troca de provider;
  • validação de schema;
  • comparação entre versões;
  • reprodutibilidade de análises.

Modelo implementado

@dataclass(frozen=True)
class PromptSpec:
    prompt_id: str
    version: str
    system_prompt: str
    user_template: str
    output_schema: type[BaseModel]
    temperature: float = 0.1
    mode: str = "structured_extraction"
    max_retries: int = 1
    context_policy: str = "minimum_necessary"
    evaluation_suite: str = "golden"
    golden_cases: tuple[str, ...] = ()
    failure_modes: tuple[str, ...] = (...)
    providers_tested: tuple[str, ...] = ("local",)
    baseline_status: str = "pending"

Interface implementada

class PromptRegistry:
    def get(self, prompt_id: str, version: str | None = None) -> PromptSpec:
        ...

    def render_user_prompt(self, prompt_id: str, payload: dict) -> str:
        ...

    def output_schema(self, prompt_id: str, version: str | None = None) -> type[BaseModel]:
        ...

Prompts registrados inicialmente

  • resume_extraction_v1;
  • job_extraction_multi_domain_v1;
  • domain_classification_v1;
  • github_repo_analysis_v2;
  • match_analysis_evidence_based_v1;
  • ats_analysis_v1;
  • resume_tailor_v1;
  • career_advice_v1;
  • source_import_enrichment_v1;
  • job_radar_match_explanation_v1;
  • job_wishlist_builder_v1;
  • profile_items_extractor_v1;
  • profile_lattes_extractor_v1;
  • public_exam_notice_extractor_v1.
  • github_profile_analysis_v1;
  • portfolio_gap_analysis_v1.

Os 16 prompts de produção pertencem a um único AiTask. career_advice_v1 passou a ter consumidor seguro em modules/ai/guidance.py; não há prompt de produção órfão. Documentos conceituais fora do registry não são tratados como prompts ativos.

Conteúdo interpolado é delimitado como não confiável e recebe uma system policy comum contra prompt injection. Cada tarefa declara providers, structured output, fallback, finalidade de contexto, política sensível, suíte e métricas padrão.

O prompt do Radar explica evidências e lacunas, mas não altera score final.

job_wishlist_builder_v1 transforma texto livre em rascunho de wishlist do Radar. Ele deve retornar JSON validado, exigir revisão humana e não inventar formação, experiência, certificação, registro profissional, licença, empresa, salário ou requisito. O prompt é multiárea e não assume que a pessoa é de tecnologia, usa GitHub, procura CLT ou possui experiência formal.

profile_items_extractor_v1 extrai itens universais de perfil a partir de texto colado pelo usuário. Ele sempre retorna drafts com confirmed_by_user=false, preserva evidência, separa baixa confiança de fato confirmado e não inclui segredos, cookies, tokens ou API keys.

profile_lattes_extractor_v1 extrai evidências acadêmicas/Lattes como candidatos de ProfileItem. Ele não inventa publicação, DOI, ORCID, instituição, orientador, vínculo, prêmio ou titulação. Tudo continua com confirmed_by_user=false até confirmação explícita no Perfil Profissional Universal.

public_exam_notice_extractor_v1 estrutura editais, concursos e chamadas públicas como rascunhos revisáveis. Ele não inventa órgão, banca, datas, taxa, salário, requisitos ou conteúdo programático e não substitui o edital oficial.

Dados salvos por execução

Cada execução de prompt deve registrar:

{
  "prompt_id": "resume_extraction_v1",
  "prompt_version": "1.0.0",
  "provider": "gemini",
  "model": "configured-model",
  "input_hash": "sha256",
  "schema_version": "1.0.0",
  "created_at": "timestamp",
  "status": "success | fallback | failed",
  "confidence": 0.0
}

Regras

  • Nunca chamar provider direto de módulo de negócio.
  • Sempre validar saída.
  • Sempre versionar prompt.
  • Sempre salvar prompt_id e prompt_version quando houver resultado persistido.
  • Sempre marcar fallback quando IA falhar.
  • Nunca confiar em score calculado apenas pela IA quando houver engine determinística.

Relação com providers

O registry não deve depender de Gemini diretamente.

Ele deve funcionar com qualquer provider compatível com texto e JSON estruturado.

Na v1.9.4, o runtime selecionado pode ser Gemini ou OpenAI, sempre pelo backend local e pelo modelo salvo em Configurações de IA. Fluxos com fallback determinístico devem retornar provider_used, requested_provider, analysis_mode e warnings quando a IA externa falhar.

Critérios de pronto

  • Todos os prompts carregados por ID.
  • Schemas Pydantic vinculados.
  • JSON inválido tratado pelo JSON Guard.
  • Fallback documentado.
  • Testes unitários para pelo menos três prompts.
  • Fixtures cobrindo múltiplas áreas.