Sistema de revisão editorial para .docx e .pdf, com interface em Streamlit, orquestração por agentes, autocorreções seguras e exportação de comentários no DOCX.
O projeto foi desenhado para:
- receber um documento editorial;
- extrair o conteúdo em blocos estruturais;
- enviar cada trecho só para os agentes compatíveis;
- filtrar falso positivo depois da resposta da LLM;
- aplicar automaticamente só os ajustes formais e seguros;
- exportar um
.docxcomentado e um relatório.json.
python -m pip install -e .O arquivo principal de configuração é .env.example.
Copie para .env na raiz do repositório e ajuste o provider desejado.
LLM_PROVIDER=openai
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o-miniLLM_PROVIDER=ollama
OLLAMA_BASE_URL=http://localhost:11434/v1
OLLAMA_MODEL=llama3.1:8b
OLLAMA_API_KEY=ollamaLLM_PROVIDER=openai_compatible
LLM_BASE_URL=http://servidor-interno/v1
LLM_MODEL=nome-do-modelo
# LLM_API_KEY=token-opcional- Arquivo para uso normal: .env.example e depois
.envna raiz. - Lógica de provider/modelo/base URL: llm.py.
- Exibição da configuração na interface: streamlit_app.py.
Na prática:
- para trocar só provider, modelo e URL, edite
.env; - para mudar a lógica de fallback entre
openai,ollamaeopenai_compatible, edite llm.py. - em
openai_compatible, a chave pode ficar ausente quando o endpoint interno/local não exigir autenticação; a fábrica aplica um fallback interno apenas se o cliente precisar.
Interface:
streamlit run streamlit_app.pyLinha de comando:
PYTHONPATH=src python -m editorial_docx "testes/arquivo.docx"<nome>_output.docx<nome>_output.relatorio.json
Para entrada PDF, a saída principal é o relatório JSON com referência de página e bloco.
flowchart TD
A["Entrada do documento"] --> B["Carga do arquivo"]
B --> C["Extração de blocos e metadados"]
C --> D["Classificação estrutural"]
D --> E["Construção de seções"]
E --> F["Seleção de escopo por agente"]
F --> G["Execução em lotes"]
G --> H["Parse do JSON dos agentes"]
H --> I["Filtros pós-agente"]
I --> J["Autocorreções seguras"]
J --> K["Consolidação e ancoragem de comentários"]
K --> L["Exportação do DOCX e relatório JSON"]
O sistema aceita:
.docx.pdf
Entrada via CLI: main.py
Entrada via interface: streamlit_app.py
Em document_loader.py, o sistema:
- carrega o arquivo;
- extrai blocos textuais;
- cria referências por bloco;
- monta uma visão inicial das seções.
Para DOCX, a extração fina fica em docx_utils.py.
Cada bloco recebe um tipo, por exemplo:
headingparagraphcaptiontable_celllist_itemreference_entryreference_headingdirect_quote
Essa etapa combina:
- quantidade de caracteres;
- estilo do Word;
- presença de numeração;
- posição no documento;
- contexto vizinho;
- heurísticas textuais.
Os headings reais são usados para:
- delimitar seções;
- melhorar o recorte estrutural;
- evitar que expressões internas do corpo sejam tratadas como título.
Em graph_chat.py, cada agente recebe só os blocos compatíveis com sua responsabilidade.
Essa etapa é uma das mais importantes do sistema, porque reduz ruído antes mesmo da LLM responder.
Os blocos selecionados são agrupados em lotes que preservam:
- índice global;
- texto;
- tipo estrutural;
- referência do bloco;
- perfil do documento;
- contexto auxiliar de normas e tarefas.
Os agentes respondem em JSON conforme schemas.py.
Cada comentário pode conter:
categorymessageparagraph_indexissue_excerptsuggested_fixauto_applyformat_spec
Em graph_chat.py, os comentários passam por validação de escopo e segurança.
Exemplos de bloqueio atual:
- comentário estrutural sobre menção de seção no meio de um parágrafo;
- comentário de título em legenda de tabela ou gráfico;
- comentário de
tabelas_figurassobre falta de fonte ancorado emtable_cell; - comentário de referência fora de
reference_entryoureference_heading; - comentário tipográfico que tenta mexer em conteúdo textual;
- sugestão com
issue_excerptidêntico àsuggested_fix.
Só entram em autocorreção quando a mudança é formal, verificável e não muda informação.
Exemplos:
- normalização mecânica de título já existente;
- padronização mecânica de identificador de tabela/figura;
- fonte, tamanho, alinhamento, recuo e espaçamento;
- ajustes mecânicos seguros em referência, sem completar conteúdo ausente.
Na exportação do DOCX:
- comentários do mesmo parágrafo podem ser consolidados;
- quando os problemas estão em trechos muito diferentes, eles são separados;
- o sistema tenta ancorar no
issue_excerpt; - o trecho ancorado recebe destaque amarelo;
- ajustes
auto_applyficam silenciosos e não viram comentário visível.
O sistema exporta:
- relatório JSON com comentários visíveis;
- DOCX comentado;
- DOCX já com autoajustes aplicados quando cabível.
A ordem atual está em prompt.py:
AGENT_ORDER = [
"metadados",
"sinopse_abstract",
"gramatica_ortografia",
"tabelas_figuras",
"referencias",
"estrutura",
"tipografia",
]Para mudar a ordem, edite prompt.py.
Prompt: metadados.md
Vê:
- capa;
- falsa folha;
- blocos editoriais iniciais;
- placeholders explícitos.
Responsabilidade:
- revisar título, autoria, afiliação, dados editoriais e campos preliminares;
- detectar ausência ou duplicidade de metadados visíveis;
- evitar placeholders esquecidos.
Não deve fazer:
- comentar corpo analítico como se fosse metadado;
- atuar em tabela, referência ou citação como se fosse capa.
Prompt: sinopse_abstract.md
Vê:
SINOPSE;ABSTRACT;Palavras-chave;Keywords;JEL.
Responsabilidade:
- revisar forma do resumo;
- cobrar parágrafo único quando aplicável;
- cobrar justificação;
- revisar formatação de palavras-chave e keywords;
- verificar presença e consistência do
JELnos blocos PT/EN.
Não deve fazer:
- comentar corpo analítico só porque parece resumo;
- sair dessas seções.
Prompt: gramatica_ortografia.md
Vê:
- qualquer bloco do documento, desde que haja erro linguístico objetivo.
Responsabilidade:
- revisar ortografia, acentuação, pontuação, concordância, crase e regência;
- agir só quando houver erro linguístico comprovável;
- preservar sentido e tom do texto.
Não deve fazer:
- reescrita estilística disfarçada;
- “trocar seis por meia dúzia”;
- repetir o original como sugestão;
- opinar sobre estrutura ou conteúdo editorial.
Prompt: tabelas_figuras.md
Vê:
caption;- contexto vizinho de tabelas, quadros, gráficos e figuras.
Responsabilidade:
- revisar identificador, subtítulo, fonte, elaboração, unidade e nota;
- verificar posicionamento editorial correto desses componentes;
- permitir autoapply só em normalização mecânica segura do identificador já existente.
Não deve fazer:
- usar
table_cellpara inferir falta de fonte, subtítulo ou identificador; - inserir
Fonte:dentro da legenda; - cobrar fonte/subtítulo fora de
caption.
Prompt: referencias.md
Vê:
reference_entry;reference_heading.
Responsabilidade:
- revisar consistência bibliográfica sustentada por texto visível;
- apontar problemas de pontuação, ordem e composição quando houver base no trecho;
- usar as normas locais do projeto como apoio.
Não deve fazer:
- inventar ano, DOI, paginação, editora, URL ou título faltante;
- tratar caixa alta como erro por padrão;
- atuar fora do bloco de referências.
Prompt: estrutura.md
Vê:
heading;- títulos reais e blocos estruturalmente inequívocos.
Responsabilidade:
- revisar hierarquia, ordem, duplicidade estrutural, título real e numeração real;
- permitir autoapply só para normalização mecânica de título já existente.
Não deve fazer:
- agir sobre menção de seção dentro de parágrafo;
- transformar expressão interna do corpo em subtítulo;
- tratar
Tabela,Figura,Gráfico,QuadroouImagemcomo seção; - ancorar sugestão de título fora de
headingreal.
Prompt: tipografia.md
Vê:
- blocos formais compatíveis com autoaplicação segura;
- principalmente
heading,captione trechos estruturados de abertura.
Responsabilidade:
- revisar fonte, tamanho, negrito, itálico, alinhamento, recuo, espaçamento e entrelinha;
- aplicar automaticamente ajustes formais seguros no DOCX exportado.
Não deve fazer:
- sugerir capitalização editorial;
- alterar conteúdo textual;
- atuar em
reference_entry; - aparecer como comentário visível quando for autoaplicado.
Prompt: coordenador.md
Responsabilidade:
- resumir os achados finais;
- apresentar uma visão agregada ao usuário;
- não reexecutar a revisão.
O sistema usa arquivos locais em:
Esses arquivos alimentam principalmente:
tipografiaestruturatabelas_figurasreferencias
- streamlit_app.py: interface, painel de correção e download.
- graph_chat.py: escopo, filtros, batches e coordenação dos agentes.
- docx_utils.py: extração estrutural do DOCX, autoajustes e comentários no Word.
- document_loader.py: carga de DOCX/PDF e montagem das seções.
- llm.py: escolha do provider, modelo e base URL.
- prompt.py: ordem dos agentes, prompts e contexto auxiliar.
- test_graph_chat.py: regressões do pipeline editorial.
pytest -qtipografiaé silencioso quando autoaplica;estruturanão roda em modo global;referenciasetabelas_figurastêm filtros fortes de escopo;gramatica_ortografiaestá mais amplo, mas filtrado por erro objetivo;- o sistema suporta
openai,ollamaeopenai_compatiblepela mesma fábrica em llm.py.