diff --git a/README.md b/README.md index 7bdfe76..76dc5ad 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,7 @@ O primeiro build leva alguns minutos (PyTorch); os seguintes reaproveitam o cach - [`notebooks/dados/01_eda.ipynb`](notebooks/dados/01_eda.ipynb): análise exploratória e as figuras dos slides (`docs/figuras/`). - [`docs/bpmn/`](docs/bpmn/): processo em BPMN 2.0. - [`genai/FORMATO_JSON.md`](genai/FORMATO_JSON.md) e [`genai/REGRAS_PARECER.md`](genai/REGRAS_PARECER.md): contrato e regras do parecer. +- [`genai/avaliacao/`](genai/avaliacao/CRITERIOS.md): critérios, os 20 casos de avaliação e os resultados do parecer (prompts v2 a v4), com a revisão humana da v4. - [`docs/ROTEIRO_DEMO.md`](docs/ROTEIRO_DEMO.md): roteiro da demo, plano B e perguntas prováveis. - [`infra/`](infra/README.md): o mesmo ambiente em Terraform (provider Docker, local, sem custo). - [`skills/`](skills/README.md): guia do projeto por setor (estrutura, ambiente, dados, modelo, juro justo, parecer, API, painel, governança). @@ -168,4 +169,5 @@ Cada frente registra aqui como usou assistentes de IA (agentic coding) e como re - **Dados:** os scripts de carga, os esquemas SQL e a documentação foram escritos com apoio do Claude e revisados e testados pelo responsável da frente. - **App e infraestrutura:** a integração da API com o `prever()`, as telas do painel e os testes foram feitos com apoio do Claude, a partir dos protótipos do grupo e dos contratos (`FORMATO_JSON.md`, `REGRAS_PARECER.md`). A responsável revisou o código e conferiu o resultado com testes automáticos e rodando as telas. -- **Modelo e GenAI:** a completar por cada frente. +- **Modelo:** a completar pela frente. +- **GenAI:** o código do parecer, os prompts e os documentos da frente foram escritos com apoio do Claude, guiado pelos guias da frente em `skills/regras_negocio/` ([`normas_rag`](skills/regras_negocio/normas_rag/SKILL.md), [`parecer_genai`](skills/regras_negocio/parecer_genai/SKILL.md) e [`avaliacao_parecer`](skills/regras_negocio/avaliacao_parecer/SKILL.md)) e pelos contratos (`FORMATO_JSON.md`, `REGRAS_PARECER.md`). As propostas maiores (template, cadeia em LangChain, prompts v3 e v4) também passaram pela revisão de uma segunda IA. A responsável leu cada mudança antes de aplicá-la e conferiu o resultado com os testes automáticos (`tests/genai/`), a avaliação dos 20 casos e a revisão humana dos pareceres (`genai/avaliacao/`). diff --git a/skills/README.md b/skills/README.md index 4bcf0b8..87f8628 100644 --- a/skills/README.md +++ b/skills/README.md @@ -12,7 +12,7 @@ Esta pasta descreve o projeto **por setor**, para que uma IA (ou uma pessoa nova Marcadores usados: **[PRONTO]** já existe e funciona · **[EM ANDAMENTO]** alguém está fazendo (nome entre parênteses) · **[PENDENTE]** ainda não começou · **[A DECIDIR]** depende de decisão do grupo (o texto diz a escolha padrão). -Atualizado em **06/11/2026**, a partir do repositório nessa data. +Atualizado em **06/11/2026**, a partir do repositório nessa data. Skills da GenAI (`normas_rag`, `parecer_genai`, `avaliacao_parecer`) atualizadas em **10/11/2026**. ## Mapa @@ -29,7 +29,9 @@ skills/ ├── modelo_risco/ variáveis, XGBoost, calibração, métricas, faixas, revisão manual, SHAP ├── juro_justo/ fluxo de caixa, convenção nominal, LGD, margem, incerteza, situação do preço ├── contratos_dados/ formatos JSON entre as frentes (prever, parecer, API, carteira) - ├── parecer_genai/ regras do parecer, RAG, prompt, LLM, checagem e template + ├── normas_rag/ normas brasileiras, divisão em trechos, indexação no pgvector e busca + ├── parecer_genai/ regras do parecer, prompt, cadeia com o Gemini, conferência e template + ├── avaliacao_parecer/ os 20 casos, critérios, métricas e revisão humana do parecer ├── auditoria_carteira/ lote da carteira, equidade, backtest, ROI e segmentação ├── api/ FastAPI: rotas, schemas e conversões └── painel/ Streamlit: telas, blocos, design e decisão do analista @@ -38,7 +40,7 @@ skills/ ## Ordem de leitura - **Para entender o projeto:** `visao-geral` → `regras_negocio/governanca` → `regras_negocio/contratos_dados`. -- **Para construir do zero:** `estrutura-projeto` → `boas-praticas-python` → `ambiente-e-infra` → `dados` → `modelo_risco` → `juro_justo` → `contratos_dados` → `parecer_genai` → `api` → `painel` → `auditoria_carteira`. +- **Para construir do zero:** `estrutura-projeto` → `boas-praticas-python` → `ambiente-e-infra` → `dados` → `modelo_risco` → `juro_justo` → `contratos_dados` → `normas_rag` → `parecer_genai` → `avaliacao_parecer` → `api` → `painel` → `auditoria_carteira`. - **Para mexer em um setor:** leia o `SKILL.md` dele, os setores em "Leia antes" e, sempre, `governanca` e `contratos_dados`. ## Como usar com uma IA diff --git a/skills/regras_negocio/avaliacao_parecer/SKILL.md b/skills/regras_negocio/avaliacao_parecer/SKILL.md new file mode 100644 index 0000000..fa314c7 --- /dev/null +++ b/skills/regras_negocio/avaliacao_parecer/SKILL.md @@ -0,0 +1,46 @@ +--- +name: auditor-avaliacao-parecer +description: Use para avaliar o parecer do Auditor de Preço Justo antes de trocar o prompt, o modelo do Gemini ou a busca — os 20 casos, critérios definidos antes dos resultados, avaliar.py, métricas por código, revisão humana e comparação entre versões. +--- + +# Avaliação do parecer + +> Leia antes: `regras_negocio/parecer_genai`, `regras_negocio/normas_rag`. Dono: Maria (GenAI). Critérios: `genai/avaliacao/CRITERIOS.md` (definidos **antes** dos resultados). + +## Objetivo + +Medir se o parecer é **certo, fiel às normas e claro** antes de qualquer mudança chegar à demo, e registrar cada versão para comparar. + +## Arquivos + +`genai/avaliacao/CRITERIOS.md`, `montar_casos.py` (monta os casos e as normas aceitas por situação), `casos_avaliacao.json`, `avaliar.py`, `resultados__.json` e `.md` (v2, v3 e v4); `tests/genai/test_avaliacao.py`. + +## Regras + +20 casos: 5 acima, 4 abaixo, 4 dentro, 2 revisão manual, 5 difíceis (motivo com gênero, número extremo, trecho irrelevante, revisão manual prevalecendo, país no rótulo). Critérios: recuperação no top 3 (meta ≥ 80%; a busca v1 atingiu 8/10 e a v4, 16/16), fidelidade, consistência numérica (por código), citação correta, alucinação (meta zero na demo), regras, clareza (1–5). Cada caso rodado 2 vezes. + +- Rodar (com o banco indexado e a chave): `python -m genai.avaliacao.avaliar`, que grava `resultados__.json` e `.md`; `--relatorio` refaz o `.md` a partir do JSON da versão e do modelo atuais. +- **Atenção:** rodar de novo ou usar `--relatorio` **reescreve o `.md` do zero e apaga a revisão humana**. Antes, faça o commit da revisão; numa versão já revisada, não rode de novo com o mesmo prompt e modelo. +- As normas aceitas por situação ficam em `montar_casos.py` e só mudam **antes** de rodar uma versão. +- Métricas por código além dos critérios: fonte específica por situação (sem contar a LGPD art. 20, que entra em todos os casos), citações da LGPD art. 20, recusas por palavra e por artigo. +- Resultado da v4 (09/11): recomendação 40/40, sem palavra proibida 40/40, mesma resposta nas 2 rodadas 16/20, fonte específica 8/8 no caso "abaixo" e 1/9 no "acima" (as normas tratam de transparência, não de teto de juros). Revisão humana (10/11, 17 pareceres): fidelidade 17/17, alucinação 0/17, citação correta 7/8, clareza média 3,6. As duas quedas para o template (C13 na v3, C03 na v4) foram timeouts do Gemini. +- Na v4, "fontes dentro das normas aceitas" dá 32/33 por causa do C03: ele citou o CDC art. 54-D, II corretamente (sim na revisão humana), mas esse artigo não estava entre as normas aceitas do caso "acima". A métrica está certa: ela mede o gabarito definido antes de rodar, não se a citação está correta. +- Os casos e as normas aceitas **não mudam depois de rodar** uma versão: mudar o gabarito depois do resultado invalida a comparação. Os casos com país no rótulo ("Estônia") ficam como estão: testam se o código retira o país. +- A revisão humana é do **texto original do LLM**, antes dos ajustes de estilo; não reavaliar com os ajustes e dizer que o modelo melhorou. +- Relatar a fonte específica **por situação**: no caso "dentro" não há problema a apontar, e no "acima" muitas vezes não há norma pertinente (o sistema prefere não citar a citar errado). + +## Como construir + +1. Banco indexado (`regras_negocio/normas_rag`), `DATABASE_URL` e `GOOGLE_API_KEY` definidos. +2. Antes de rodar uma versão nova, decidir e registrar se as normas aceitas mudam (`montar_casos.py`). +3. `python -m genai.avaliacao.avaliar` (cerca de 5 a 10 minutos: há uma pausa de 4 s entre as chamadas, configurável por `PAUSA_ENTRE_CHAMADAS`, para não estourar o limite do plano gratuito do Gemini). +4. Preencher a revisão humana no `.md` (fidelidade, citação correta, alucinação, clareza 1–5), com legenda, resumo e observações logo abaixo da tabela. +5. Comparar com a versão anterior e anotar o motivo da próxima versão nas notas do prompt. + +## Pronto quando + +O `.md` da versão tem as métricas por código e a revisão humana preenchida; recomendação certa e "sem palavra proibida" em 100%; alucinação zero na revisão humana; `tests/genai/test_avaliacao.py` passa. + +## Estado em 10/11/2026 + +- **[PRONTO]** critérios, 20 casos, `avaliar.py` com `--relatorio`, avaliações v2, v3 e v4, revisão humana da v4. diff --git a/skills/regras_negocio/normas_rag/SKILL.md b/skills/regras_negocio/normas_rag/SKILL.md new file mode 100644 index 0000000..f7dc64c --- /dev/null +++ b/skills/regras_negocio/normas_rag/SKILL.md @@ -0,0 +1,48 @@ +--- +name: auditor-normas-rag +description: Use para incluir, trocar ou reindexar as normas do parecer do Auditor de Preço Justo e para mexer na busca (RAG) — fontes oficiais, divisão em trechos, trecho_id, embeddings multilíngues, tabela trechos_normas no pgvector, perguntas de busca por situação e pergunta de governança. +--- + +# Normas e busca (RAG) + +> Leia antes: `regras_negocio/governanca`. Depois: `regras_negocio/parecer_genai` (quem usa os trechos) e `regras_negocio/avaliacao_parecer` (como medir a busca). Dono: Maria (GenAI). Código: `genai/src/dividir.py`, `indexar.py`, `testar_busca.py`, `cadeia.py` (`buscar_trechos`, `carregar_modelo_embeddings`). + +## Objetivo + +Guardar as normas brasileiras em trechos pesquisáveis e, para cada contrato, **trazer os trechos que podem sustentar o parecer**. A busca nunca decide nada: só entrega trechos ao LLM, que cita apenas o que recebeu. + +## Arquivos + +`genai/normas/*.md` + `FONTES.md`; `genai/src/dividir.py` (`dividir_normas`), `indexar.py` (cria a extensão e a tabela, grava os 91 trechos), `testar_busca.py` (10 perguntas de resposta conhecida); `buscar_trechos` em `genai/src/cadeia.py`; `genai/avaliacao/resultado_busca_v1*.txt`. + +## Regras + +- Normas em `genai/normas/`, copiadas de fonte oficial e limpas (sem anotações, revogados ou vetados), com `FONTES.md` (arquivo, norma, artigos, URL, data de acesso): + - `lgpd.md` Lei 13.709/2018, arts. 5º, 6º, 7º, 11, 12, 20 + - `cdc.md` Lei 8.078/1990, arts. 2º, 3º, 4º, 6º, 30, 31, 39, 42, 42-A, 46, 47, 52, 54, 54-A a 54-D, 54-F, 54-G, 104-A a 104-C + - `cet.md` Res. CMN 4.881/2020, arts. 1º a 9º + - `credito_oferta.md` Res. CMN 5.004/2022, arts. 1º a 9º + - `ref.md` Relatório de Estabilidade Financeira do BC (maio/2026), seção 2.1 e apêndice, dividido por parágrafo +- **Divisão:** um trecho por artigo; longos quebrados entre incisos/parágrafos (`TAMANHO_MAXIMO = 1000`, sobra < `TAMANHO_MINIMO = 300` junta à anterior, repete `TAMANHO_CAPUT = 150` caracteres do caput). +- **`trecho_id`:** `-art-` (`cdc-art6-1`, `cdc-art54b-1`, `lgpd-art20-1`); REF `ref-p-1`. O inciso vai no campo `artigo` da fonte ("art. 6º, III"). +- **Indexação:** `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2` (384 dimensões) na tabela `trechos_normas` do pgvector. +- **Busca (`buscar_trechos`):** uma pergunta fixa por situação (`PERGUNTAS_BUSCA`) traz os **4** trechos mais próximos (`QUANTOS_TRECHOS`), mais **1** trecho da pergunta de governança (`PERGUNTA_GOVERNANCA`, revisão de decisões automatizadas, que traz a LGPD art. 20), sem repetir trecho. Cada trecho tem `norma`, `artigo`, `trecho_id`, `texto`. Sem banco → segue sem trechos (o parecer sai sem fontes, nunca falha). +- O LLM cita só o que recebeu. Sem trecho pertinente → `fontes: []`; a tela mostra "Não encontrei base normativa para este caso." +- **Não direcionar** a busca do caso "acima" para o CDC art. 39 (ele está indexado, mas a pergunta evita): o texto começa com "práticas abusivas", e o LLM tenderia a copiar a palavra proibida. Três trechos indexados têm palavras proibidas no texto da lei (`cdc-art6-1`, `lgpd-art6-2`, `lgpd-art20-1` § 2º): o prompt pede para não copiá-las. +- Uma norma nova só entra com fonte oficial registrada no `FONTES.md`; depois, reindexar e rodar o `testar_busca.py` de novo. O `indexar.py` apaga a tabela e grava todos os trechos de novo (não há indexação parcial), o que leva poucos segundos depois que o modelo foi baixado. + +## Como construir + +1. Copiar a norma da fonte oficial para `genai/normas/.md`, limpa, e registrar no `FONTES.md`. +2. `python genai/src/dividir.py` para conferir os trechos (contagem por norma e tamanhos). +3. Com o banco no ar e `DATABASE_URL` definida: `python genai/src/indexar.py` (na 1ª vez baixa o modelo de embeddings, ~470 MB). No ambiente da demo, o `iniciar.ps1` faz este passo. +4. `python genai/src/testar_busca.py`: meta de **8 de 10** perguntas com o artigo certo entre os 3 primeiros. +5. Mudou uma pergunta de busca? Rodar a avaliação do parecer (`regras_negocio/avaliacao_parecer`) e comparar a recuperação. + +## Pronto quando + +`indexar.py` grava **91 trechos** (CDC 37, LGPD 17, REF 17, Res. 4.881 9, Res. 5.004 11); `testar_busca.py` acerta pelo menos 8 de 10 (a v1 acertou 8/10); na avaliação, a recuperação fica em pelo menos 80% (na v4: 16/16). Os testes de `buscar_trechos` em `tests/genai/` passam (busca sem banco devolve lista vazia; a pergunta de governança não repete trecho). + +## Estado em 10/11/2026 + +- **[PRONTO]** normas, `FONTES.md`, divisão, indexação, busca v1 (8/10), pergunta de governança (v3), indexação automática no `iniciar.ps1`. diff --git a/skills/regras_negocio/parecer_genai/SKILL.md b/skills/regras_negocio/parecer_genai/SKILL.md index f88dced..0fbcecb 100644 --- a/skills/regras_negocio/parecer_genai/SKILL.md +++ b/skills/regras_negocio/parecer_genai/SKILL.md @@ -1,11 +1,11 @@ --- name: auditor-parecer-genai -description: Use para construir ou alterar o parecer automatizado do Auditor de Preço Justo — quem decide o quê, linguagem, números, recomendação escolhida pelo código, RAG sobre normas brasileiras com pgvector, prompt versionado, chamada ao Gemini, checagem por código, template de reserva e avaliação. +description: Use para construir ou alterar o parecer automatizado do Auditor de Preço Justo — quem decide o quê, linguagem, números, recomendação escolhida pelo código, prompt versionado, cadeia LCEL com o Gemini, conferência por código, ajustes de estilo e template de reserva. Normas e busca ficam em normas_rag; avaliação em avaliacao_parecer. --- # Parecer com GenAI -> Leia antes: `regras_negocio/governanca`, `regras_negocio/contratos_dados`. Dono: Maria (GenAI). Documentos do dono: `genai/REGRAS_PARECER.md` (v1.3), `genai/FORMATO_JSON.md` (v1.4). +> Leia antes: `regras_negocio/governanca`, `regras_negocio/contratos_dados`. Junto: `regras_negocio/normas_rag` (busca) e `regras_negocio/avaliacao_parecer` (avaliação). Dono: Maria (GenAI). Documentos do dono: `genai/REGRAS_PARECER.md` (v1.7), `genai/FORMATO_JSON.md` (v1.5). ## Objetivo @@ -13,14 +13,14 @@ Transformar a saída do `prever()` num **parecer curto, em português, apoiado e ## Arquivos -`genai/normas/*.md` + `FONTES.md`; `genai/src/dividir.py`, `indexar.py`, `testar_busca.py`, `checagem.py` (pydantic + `conferir_parecer`), `template.py` (`montar_template`, `escolher_recomendacao`), `prompt.py` (`montar_mensagens`), `testar_llm.py`; `genai/prompts/parecer_v1.md`; `genai/avaliacao/`; `tests/genai/`. +`genai/src/checagem.py` (pydantic, `conferir_parecer`, `ajustar_resposta`, formatação dos números), `template.py` (`montar_template`, `escolher_recomendacao`), `prompt.py` (`montar_mensagens`, `VERSAO_PROMPT`), `cadeia.py` (`gerar_parecer`, `buscar_trechos`, `carregar_modelo_embeddings`), `testar_llm.py`; `genai/prompts/parecer_v1.md` a `parecer_v4.md`; `tests/genai/`. As normas e a busca estão em `normas_rag`; a avaliação, em `avaliacao_parecer`. ## Quem decide o quê | Quem | Faz | |---|---| | `prever()` | todos os números e a marcação de revisão manual | -| Código da cadeia | escolhe a recomendação, decide LLM × template, formata números, busca normas, confere o resultado, escreve `contexto_mercado` | +| Código da cadeia | escolhe a recomendação, decide LLM × template, formata números, busca normas, confere o resultado, faz os ajustes de estilo, escreve `contexto_mercado` | | **LLM** | **só escreve**: resumo, pontos de atenção, texto da recomendação, escolha das fontes entre os trechos recebidos | | Analista | decisão final; só ele encaminha ao compliance | @@ -40,53 +40,58 @@ Transformar a saída do `prever()` num **parecer curto, em português, apoiado e - PT-BR, frases curtas, sem jargão. Resumo ≤ 2 frases; ≤ 3 pontos de atenção. Modo hipotético: "se este contrato fosse de um banco brasileiro". A recomendação **sempre termina** com "A decisão final é do analista." - Usar "indício", "ponto de atenção", "recomenda-se revisar", "recomenda-se encaminhar ao compliance". Palavras proibidas em `governanca`, regra 4 (regex `PALAVRAS_PROIBIDAS`; "discriminar" no sentido de detalhar é permitido). - Fatores pelo `rotulo`, nunca pelo nome técnico. -- Só podem aparecer: PD, juro cobrado, juro justo, mínimo e máximo da margem (e a faixa). O LLM **copia** os números já formatados ("24,9% ao ano"); não recalcula, não arredonda, não calcula diferenças. Campo `null` nunca é citado. Todo número do texto entra em `numeros_citados` com o valor exato. +- Só podem aparecer: PD, juro cobrado, juro justo, mínimo e máximo da margem (e a faixa). O LLM **copia** os números já formatados ("24,9% ao ano (nominal)"); não recalcula, não arredonda, não calcula diferenças. Campo `null` nunca é citado. Todo número do texto entra em `numeros_citados` com o valor exato. +- Juros com **1 casa decimal**; com **2** quando dois juros diferentes ficariam iguais com 1 casa (ex.: 30,56% e 30,58%, que virariam "30,6% abaixo de 30,6%"). Vale para o prompt e para o template (`casas_decimais`). +- Unidade: `UNIDADE_JURO = "ao ano (nominal)"` (mensal = anual ÷ 12, como o Bondora e o `prever()`). - Não falar de CET, tarifas, encargos ou média de mercado. **Números do REF nunca aparecem** no parecer (v1.3): os trechos do REF só explicam a composição do custo do crédito. +- A média de mercado do BC vai só em `contexto_mercado`, uma **frase fixa escrita pelo código** (série 20742, efetiva, convertida para nominal: 12 × ((1 + e)^(1/12) − 1)); o LLM nunca a escreve. Sem o dado (antes de 03/2011) → `null`. +- Nenhuma regra do prompt nomeia um artigo de lei (v4): na v3, o exemplo "art. 6º, III" virou alucinação. ## Ética e privacidade - Nada de identificador ao LLM (nem `contrato_id`, nem `versao_modelo`); o código reinsere. -- Gênero, idade e país nunca aparecem; `motivos_permitidos()` filtra motivos sensíveis antes do prompt. +- Gênero, idade e país nunca aparecem; `motivos_permitidos()` filtra motivos sensíveis antes do prompt e tira o país entre parênteses dos rótulos (ex.: "score de crédito (Estônia)"). -## RAG +## Normas e busca -- Normas em `genai/normas/`, copiadas de fonte oficial e limpas (sem anotações, revogados ou vetados), com `FONTES.md` (arquivo, norma, artigos, URL, data de acesso): - - `lgpd.md` Lei 13.709/2018, arts. 5º, 6º, 7º, 11, 12, 20 - - `cdc.md` Lei 8.078/1990, arts. 2º, 3º, 4º, 6º, 30, 31, 39, 42, 42-A, 46, 47, 52, 54, 54-A a 54-D, 54-F, 54-G, 104-A a 104-C - - `cet.md` Res. CMN 4.881/2020, arts. 1º a 9º - - `credito_oferta.md` Res. CMN 5.004/2022, arts. 1º a 9º - - `ref.md` Relatório de Estabilidade Financeira do BC (maio/2026), seção 2.1 e apêndice, dividido por parágrafo -- **Divisão:** um trecho por artigo; longos quebrados entre incisos/parágrafos (`TAMANHO_MAXIMO = 1000`, sobra < `TAMANHO_MINIMO = 300` junta à anterior, repete `TAMANHO_CAPUT = 150` caracteres do caput). -- **`trecho_id`:** `-art-` (`cdc-art6-1`, `cdc-art54b-1`, `lgpd-art20-1`); REF `ref-p-1`. O inciso vai no campo `artigo` da fonte ("art. 6º, III"). -- **Indexação:** `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2` (384 dimensões) na tabela `trechos_normas` do pgvector. -- **Busca:** top 3–5 trechos com `norma`, `artigo`, `trecho_id`, `texto`. O LLM cita só o que recebeu. Sem trecho pertinente → `fontes: []`; a tela mostra "Não encontrei base normativa para este caso." +Detalhes em `regras_negocio/normas_rag`. O que importa aqui: a cadeia recebe até 5 trechos (`norma`, `artigo`, `trecho_id`, `texto`); o LLM cita só o que recebeu; sem trecho pertinente → `fontes: []`, e a tela mostra "Não encontrei base normativa para este caso." Sem banco, o parecer sai sem fontes e nunca falha. ## Prompt e LLM - Prompt versionado em `genai/prompts/parecer_vN.md`; `prompt.py` lê só as seções "Mensagem do sistema" e "Mensagem do usuário" e preenche `{situacao}`, `{recomendacao}`, `{faixa}`, `{numeros}`, `{fatores}`, `{trechos}`. Qualquer mudança de regra = novo arquivo, com o motivo anotado nas notas. -- LLM: **Gemini** via `google-genai`, chave `GOOGLE_API_KEY` no `.env`, **saída estruturada** no formato `RespostaLLM`. Timeout de **20 s**. -- `gerar_parecer(saida_prever) -> Parecer`: valida a entrada → escolhe a recomendação → revisão manual? template : (busca → prompt → LLM → `conferir_parecer`) → falhou? template → preenche `contrato_id`, `recomendacao`, `origem`, `versao_prompt`, `gerado_em` (−03:00). +- Versão atual: **`parecer_v4`** (`VERSAO_PROMPT` em `prompt.py`). A v1, a v2 e a v3 continuam no repositório; o motivo de cada versão está nas notas do arquivo. +- LLM: **Gemini** (`MODELO_LLM`, padrão `gemini-3.5-flash-lite`; plano B `gemini-3.1-flash-lite`) via **LangChain** (`langchain-google-genai`, `ChatGoogleGenerativeAI.with_structured_output`), chave `GOOGLE_API_KEY` no `.env`, **saída estruturada** num esquema plano (`_RespostaGemini`: o Gemini não aceita dicionário livre) convertida para `RespostaLLM`. **10 s por tentativa** (mínimo aceito pelo Gemini), **2 tentativas** (a 2ª só em erro temporário, como 503). +- **Cadeia LCEL, fixa, sem agente e sem memória:** `busca_normas | monta_prompt | gemini | conferencia` (`RunnableLambda`). Cada parecer depende só do contrato. Sem LangChain instalado, `_CadeiaSemLangChain` roda os mesmos passos em ordem. Os imports do LangChain e do `sentence-transformers` ficam dentro das funções, para o CI testar sem torch. +- `gerar_parecer(saida_prever) -> dict`: valida a entrada → escolhe a recomendação → revisão manual? template : cadeia → erro ou conferência reprovada? template : ajustes de estilo → preenche `contrato_id`, `recomendacao`, `origem`, `versao_prompt`, `gerado_em` (−03:00), `contexto_mercado`. **Nunca lança exceção.** +- A API carrega o modelo de embeddings na subida (`carregar_modelo_embeddings()`), para a 1ª busca não demorar. ## Checagem (`conferir_parecer`) -Entrada válida (`EntradaPrever`; inválida → revisão manual) · resposta válida (`RespostaLLM`) · cada valor de `numeros_citados` igual ao da entrada e cada número do texto ligado a um valor recebido (tolerância **0,051 pp**) · todo `trecho_id` entre os recuperados · nenhuma palavra proibida · nenhum atributo sensível · tamanho do resumo e dos pontos. **Qualquer falha → template.** +Entrada válida (`EntradaPrever`; inválida → revisão manual) · resposta válida (`RespostaLLM`) · cada valor de `numeros_citados` igual ao da entrada e cada número do texto ligado a um valor recebido (tolerância **0,051 pp**) · todo `trecho_id` entre os recuperados · **artigos** (v4): o artigo de cada fonte é o do próprio trecho, e todo "art. N" do texto é o artigo de um trecho recuperado (compara número e letra, ignora inciso; o REF não tem artigo; "Lei nº" e "Resolução" não contam) · nenhuma palavra proibida · nenhum atributo sensível · tamanho do resumo e dos pontos. **Qualquer falha → template.** + +## Ajustes de estilo (`ajustar_resposta`, depois da conferência) + +Só rodam **depois** que a conferência aprova, que sempre vê a resposta original do LLM. **Só tiram, nunca acrescentam**, e não mandam para o template: +- pontos de atenção que começam com "Recomenda-se" saem; frases do resumo que começam assim saem se sobrar outra frase (duas versões do prompt não resolveram a repetição); +- a LGPD art. 20 sai das fontes quando o texto não fala de revisão de decisão automatizada (citação decorativa). + +O que foi ajustado vai para o log. As métricas da avaliação medem o LLM **antes** desses ajustes. ## Template de reserva -Usado em revisão manual, falha da API, timeout > 20 s, JSON inválido ou checagem reprovada. Texto só com faixa, situação, números formatados e até 3 rótulos de motivos (em revisão manual, só o juro cobrado). `origem: "template"`, `versao_prompt: "template_v1"`, `fontes: []`, mesma recomendação da tabela, fuso −03:00. +Usado em revisão manual, falha da API, timeout (2 tentativas de 10 s), JSON inválido ou conferência reprovada. Texto só com faixa, situação, números formatados e até 3 rótulos de motivos (em revisão manual, só o juro cobrado). `origem: "template"`, `versao_prompt: "template_v1"`, `fontes: []`, mesma recomendação da tabela, fuso −03:00. -## Avaliação (`genai/avaliacao/CRITERIOS.md`, critérios definidos **antes** dos resultados) +## Avaliação -20 casos: 5 acima, 4 abaixo, 4 dentro, 2 revisão manual, 5 difíceis (motivo com gênero, número extremo, trecho irrelevante). Critérios: recuperação no top 3 (meta ≥ 80%; a busca v1 atinge 8/10), fidelidade, consistência numérica (por código), citação correta, alucinação (meta zero na demo), regras, clareza (1–5). Cada caso rodado 2 vezes. +Antes de trocar o prompt, o modelo ou a busca, rodar a avaliação dos 20 casos (`regras_negocio/avaliacao_parecer`). Na v4: recomendação 40/40, sem palavra proibida 40/40, alucinação 0/17 na revisão humana. ## Pronto quando -`tests/genai/` passa: `test_checagem`, `test_conferencia` (números, fontes, tamanho), `test_regras` (palavras e atributos), `test_template` (recomendação por situação, sem LLM em revisão manual), `test_prompt`. A avaliação dos 20 casos está registrada. +`tests/genai/` passa (164 testes em 10/11, sem internet e sem banco: o LLM e a busca são trocados por versões falsas): `test_checagem`, `test_conferencia` (números, fontes, tamanho), `test_regras` (palavras e atributos), `test_template` (recomendação por situação, sem LLM em revisão manual), `test_prompt`, `test_cadeia` e `test_cadeia_langchain` (cadeia, fallback e LCEL), `test_avaliacao`, `test_ajustes_v2`, `test_v3`, `test_v4` (checagem de artigos), `test_ajustes_finais`. A avaliação está registrada (`regras_negocio/avaliacao_parecer`). -## Estado em 06/11/2026 +## Estado em 10/11/2026 -- **[PRONTO]** normas, divisão, indexação, busca v1, checagem, template, prompt v1 + `montar_mensagens`, teste da chave do Gemini. -- **[EM ANDAMENTO] (Maria, até 08/11)** `gerar_parecer()`; avaliação dos 20 casos. -- **[EM ANDAMENTO] (Maria + Yasmin)** `contexto_mercado` (ver `contratos_dados`, seção 3). -- **[A DECIDIR]** `REGRAS_PARECER.md` v1.3 aguardando o grupo; saída do `FORMATO_JSON.md` aguardando a Yasmin. -- Integração: a API hoje chama `montar_template` em `_parecer()`; trocar por `gerar_parecer()` é uma linha (ver `regras_negocio/api`). +- **[PRONTO]** checagem (com artigos), ajustes de estilo, template, prompts v1 a v4, `gerar_parecer()` em cadeia LCEL, `contexto_mercado`. Normas e busca: ver `normas_rag`; avaliação: ver `avaliacao_parecer`. +- **[PRONTO]** integração: a API chama `gerar_parecer()` e carrega o modelo de embeddings na subida; `iniciar.ps1` indexa as normas. +- **[A DECIDIR]** `REGRAS_PARECER.md` v1.7 e `FORMATO_JSON.md` v1.5 aguardando o ok do grupo. +- **[PENDENTE] (Maria, até 14/11)** cache dos pareceres dos casos da demo (`docs/ROTEIRO_DEMO.md`). diff --git a/skills/visao-geral/SKILL.md b/skills/visao-geral/SKILL.md index 949cc56..c1a1061 100644 --- a/skills/visao-geral/SKILL.md +++ b/skills/visao-geral/SKILL.md @@ -27,8 +27,8 @@ Contrato (formulário do painel ou carteira) → modelo de risco: PD + faixa A–E + motivos SHAP (regras_negocio/modelo_risco) → juro justo por fluxo de caixa + margem de incerteza (regras_negocio/juro_justo) → situação do preço: acima / abaixo / dentro / revisão manual - → busca das normas (RAG, pgvector) (regras_negocio/parecer_genai) - → parecer em JSON (LLM; ou template de reserva) + → busca das normas (RAG, pgvector) (regras_negocio/normas_rag) + → parecer em JSON (LLM; ou template de reserva) (regras_negocio/parecer_genai) → checagem dos números e das regras do parecer por código → painel do analista (Streamlit) (regras_negocio/painel) → decisão humana registrada: manter / revisar / compliance @@ -43,7 +43,7 @@ Em paralelo, um **processo em lote** pontua a carteira inteira, estima a diferen | Dados | pandas, pandera, PostgreSQL 16, SQLAlchemy 2, psycopg2 | | Vetores | pgvector, extensão no **mesmo** PostgreSQL (imagem `pgvector/pgvector:pg16`) | | Modelo | scikit-learn, XGBoost, SHAP, scipy (brentq), joblib | -| Parecer | Gemini (`google-genai`), sentence-transformers multilíngue, prompts versionados em Markdown | +| Parecer | LangChain (chain LCEL), Gemini (`langchain-google-genai`), sentence-transformers multilíngue, prompts versionados em Markdown | | Serviço e app | FastAPI + uvicorn, Streamlit | | Infra e qualidade | Docker + Docker Compose, pytest, GitHub Actions | | Linguagem | Python 3.14 (ver `ambiente-e-infra`) | @@ -54,7 +54,7 @@ Em paralelo, um **processo em lote** pontua a carteira inteira, estima a diferen |---|---|---| | Dados e processo | Marcos | `dados`, BPMN, `docs/qualidade_dados.md`, glossário, tabela de decisões | | Modelo e juro justo | Samuel | `modelo_risco`, `juro_justo`, `auditoria_carteira` (lote), `DECISOES.md` | -| GenAI | Maria | `parecer_genai`, `FORMATO_JSON.md`, `REGRAS_PARECER.md` | +| GenAI | Maria | `normas_rag`, `parecer_genai`, `avaliacao_parecer`, `FORMATO_JSON.md`, `REGRAS_PARECER.md` | | App e infraestrutura | Yasmin | `api`, `painel`, `ambiente-e-infra`, vídeo da demo | **Contratos entre frentes só mudam com aviso a todas** (ver `regras_negocio/contratos_dados`).