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.