Skip to content

[draft] Add reference app to markup reference. #30

Draft
gitnnolabs wants to merge 7 commits into
scieloorg:mainfrom
gitnnolabs:feature/scielo-tools-19
Draft

[draft] Add reference app to markup reference. #30
gitnnolabs wants to merge 7 commits into
scieloorg:mainfrom
gitnnolabs:feature/scielo-tools-19

Conversation

@gitnnolabs

Copy link
Copy Markdown
Collaborator

Marcação de referências com IA (infra, prompt e API REST)

O que esse PR faz?

Entrega a capacidade de marcar citações bibliográficas (texto livre → JSON estruturado → XML JATS/SPS) no SciELO Tools, usando modelo local via Ollama (sem API comercial de IA), com:

  1. infraestrutura Docker para o serviço Ollama, no futuro iremos ter uma app IA podendo escolher outros modelos veja o PR: [scielo-tools-18] Adicionar app ia #25;
  2. estratégia de prompt few-shot(instruções para a IA vários exemplos (tipicamente 3–10+)) alinhada ao SPS: https://docs.google.com/document/d/1GTv4Inc2LS_AXY-ToHT3HmO66UT0VAHWJNOIqzBNSgA/edit?tab=t.0#heading=h.2upcpyuv6r4o;
  3. exposição da marcação como API REST do SciELO Tools (JWT), consumindo a API HTTP do Ollama(por hora) como infra de IA;
  4. reaproveitamento de reference/data_utils.py (conversão JSON→JATS e orquestração), proveniente da implementação anterior do Edgar.
  5. Também foi adicionado um .mdc para orientar a IA no momento de desenvolvimento da marcação das referencias
  6. Existe uma inteligência se em caso da referencia já existir é reutilizando sem a necessidade de utilizar novamente a IA para fazer a marcação da referência
  7. Ainda não foi possível testar com uma máquina com GPU, já que estamos com problemas no nosso servidor para instalação do Ollama.
  8. Estamos com 100% de testes, porém ainda é necessário testes com arquivos .docx em uma máquina com GPU, em caso contrário é muito demorado.

Detalhe das três partes e dos testes com IA abaixo.


Parte 1 — Infraestrutura: container Ollama

O Compose local (local.yml) passa a incluir o serviço ollama (ollama/ollama:latest), com:

Item Detalhe
Porta 11434:11434
Volume ollama_data/root/.ollama (persiste o modelo entre restarts)
Dependência django, celeryworker e celerybeat dependem de ollama
Modelo padrão llama3.2:3b (REFERENCE_MODEL) pode ser alterado para máquina com menos capacidade de processamento (sem GPU)
URL no stack REFERENCE_URL=http://ollama:11434 (hostname Docker ou um endereço de um privedor de IA podendo ser o SciELO para parceiros da rede SciELO)

Operação típica:

docker compose -f local.yml up -d
make ollama_pull          # ollama pull llama3.2:3b dentro do container

IMPORTANTE: O Django não carrega GGUF in-process (llama-cpp-python removido deste fluxo). A inferência fica no processo Ollama; a aplicação só fala HTTP (POST {REFERENCE_URL}/api/chat), isso evita que tenhamos uma arquivo grande no repositório.

Em ambientes SciELO (intranet/servidor) o mesmo protocolo serve: basta apontar REFERENCE_URL para o endpoint Ollama institucional (e opcionalmente REFERENCE_TOKEN). Em maquinas sem GPU/RAM suficiente, o Compose local pode ser omitido e a URL remota usada.
Atende aos casos em que não é possível ter máquinas com GPU:

Variáveis relevantes (.envs / settings):

  • REFERENCE_ENABLED — liga/desliga a marcação via Llama
  • REFERENCE_URL — base URL Ollama (http://ollama:11434 ou URL SciELO)
  • REFERENCE_MODEL — ex. llama3.2:3b
  • REFERENCE_TIMEOUT — timeout HTTP (default 300s)
  • REFERENCE_TOKEN — Bearer opcional para Ollama protegido

Parte 2 — Estratégia de utilização do prompt

A marcação não depende de fine-tuning: usa prompt de sistema + exemplos few-shot + schema JSON, definidos em reference/prompts.py e enviados pelo reference/providers/http.py.

Peça Função
Mensagem system Obriga resposta somente JSON; enumera @publication-type SPS (journal, book, data, software, legal-doc, …); regras de título/source por tipo; autores pessoa vs collab; DOI nu; no máximo uma URI
Pares user/assistant Exemplos concretos (artigo, capítulo/proceedings, dataset SciELO Data, pacote R, decreto) para ancorar o formato
RESPONSE_FORMAT Schema json_object passado ao Ollama (format), reduzindo saída fora do contrato
Parâmetros temperature=0.0, top_p=0.1 — favorece estabilidade na avaliação

O que significa role em reference/prompts.py

A lista MESSAGES é o histórico de chat enviado ao Ollama (POST …/api/chat). Cada item tem role + content — o papel de quem “fala” naquela mensagem:

role Função
system Instruções fixas: responder só em JSON, tipos SPS (reftype), quando usar {"is_reference": false} (figuras, tabelas, títulos de secção), regras de autores/DOI/etc.
user Entrada de exemplo (texto de citação ou legenda de figura).
assistant Resposta esperada a esse exemplo (JSON bibliográfico ou skip).

Os pares user / assistant são few-shot: ensinam o formato pelo exemplo. Em runtime, Provider.run() copia MESSAGES e acrescenta um novo user com a linha a marcar; o modelo responde como assistant (JSON).

Fluxo resumido do prompt: system (regras) → exemplos few-shot → user (texto atual) → resposta JSON do modelo.

Fluxo:

  1. mark_reference / mark_references montam o provider com MESSAGES + RESPONSE_FORMAT.
  2. O texto da citação entra como última mensagem user.
  3. O modelo devolve JSON (reftype, authors, title, source, …).
  4. data_utils.get_xml / build_ref_list transformam JSON em <element-citation> / <ref-list> SPS.

A evolução do prompt é o principal alavanca de qualidade: os testes golden (@pytest.mark.llama) medem o efeito de mudanças no prompt ou no modelo.


Parte 3 — Ollama como backend; SciELO Tools como API REST

duas camadas de API:

  1. API do Ollama (interna ao stack ou ao serviço SciELO de modelos)

    • Cliente: reference/providers/http.py
    • Contrato: POST {REFERENCE_URL}/api/chat com model, messages, format, options, stream=false
    • Resposta normalizada para o formato esperado por marking (choices[].message.content)
  2. API REST do SciELO Tools (produto para editores, integrações e outros apps)

    • ViewSet: reference/api/v1/views.py
    • Router: config/api_router.pyPOST /api/v1/reference/
    • Autenticação: JWT (e Session no admin)
    • Entradas: lista/bloco de referências em JSON, ou upload DOCX (…/reference/docx/)
    • Saídas: type=json (estruturado), type=xml / type=jats (ref-list com mixed-citation + element-citation)

Assim, sistemas editoriais externos não precisam falar com o Ollama diretamente: usam a API REST autenticada do SciELO Tools; a plataforma abstrai modelo, prompt, persistência e formato SPS.


Legado — data_utils (implementação anterior do Edgar)

O módulo reference/data_utils.py concentra a lógica herdada / adaptada do desenvolvimento anterior (Edgar), em especial:

  • normalização e resolução de referências (resolve_references_result, get_reference);
  • conversão do JSON marcado para XML JATS (get_xml<element-citation> com person-group, pub-id, páginas, ext-link, date-in-citation, etc.);
  • montagem do <ref-list> SPS (build_ref_list);
  • integração com modelos Reference / ElementCitation e checksum do texto.

Neste PR, o data_utils deixa de depender de um app ia genérico e passa a consumir a marcação do próprio app reference (mark_references + provider HTTP Ollama), mantendo o contrato de saída JATS/SPS alinhado aos Critérios SciELO.


Testes com IA (Ollama / Llama)

A suíte distingue testes determinísticos (CI / make test) de avaliação com modelo real (make test-llama).

O que roda no CI / default

make test
# pytest -m "not llama"
  • Stubs/mocks do provider HTTP (HttpProviderStub, monkeypatch).
  • Cobertura de data_utils, serializers, views, parsing DOCX, get_xml com JSON fixo.
  • test_eval_corpus_aligned: garante alinhamento do corpus
    reference/fixtures/references.txtreferences.xml (103 pares).
  • Marker llama excluído — não chama Ollama no pipeline padrão.

O que é avaliação com IA

make test-llama
# pytest -m llama reference/tests/test_references.py

Requisitos: stack com Ollama no ar, modelo puxado (make ollama_pull), REFERENCE_URL apontando para o serviço.

Teste O que valida
test_eval_llama_json_matches_golden Para cada citação do corpus, o JSON do Llama bate com campos-chave JATS (reftype, autores, título, source, DOI, volume, páginas, URI, …)
test_eval_llama_jats_matches_golden O mesmo fluxo via get_xml + build_ref_list, comparando <element-citation> gerado ao golden

Notas para o revisor:

  • A saída do LLM não é 100% determinística; falhas pontuais por campo podem ocorrer até o prompt/modelo estabilizarem.
  • A completa (~103 chamadas) é lenta — por isso fica ´fora do make test é necessário rodarmos esses teste em uma máquina com GPU.
  • Objetivo de produto (RCT): amostragem com alta precisão em referências; estes testes são o instrumento de medição local.

Onde a revisão poderia começar?

  1. local.yml — serviço ollama e volume
  2. reference/providers/http.py — cliente POST /api/chat
  3. reference/prompts.py — system + few-shot + schema
  4. reference/api/v1/views.py — API REST SciELO (json / jats / docx)
  5. reference/data_utils.py — JSON → JATS / ref-list (legado Edgar)
  6. reference/tests/test_references.py — corpus alinhado + @pytest.mark.llama

Como este poderia ser testado manualmente?

  1. Subir o stack: docker compose -f local.yml up -d
  2. Baixar o modelo: make ollama_pull
  3. Confirmar envs (ex. .envs/.local/.django):
    REFERENCE_ENABLED=true, REFERENCE_URL=http://ollama:11434, REFERENCE_MODEL=llama3.2:3b
  4. Testes sem IA: make test
  5. Testes com IA: make test-llama é muito lento e precisa de revisão já que não foi possível rodar em uma máquina com GPU.
  6. API REST (JWT):
    eval "$(make bearer_token JWT_USERNAME=user JWT_PASSWORD=pass)"
    curl -X POST http://localhost:8000/api/v1/reference/ \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"type":"jats","references":["Bachman S et al. 2011. Supporting Red List threat assessments. ZooKeys 150:117-126. DOI: https://doi.org/10.3897/zookeys.150.2109"]}'
  7. Confirmar na resposta um ref_list com <mixed-citation> e <element-citation publication-type="journal">.

Algum cenário de contexto que queira dar?

  • Princípio do projeto: IA local (Ollama); humano revisa; XML SPS é o registro.
  • O mesmo REFERENCE_URL serve (Compose) ou endpoint Ollama como o SciELO sendo o provedor de IA.
  • data_utils preserva o investimento já feito na conversão JATS; o PR troca a fonte da marcação (HTTP Ollama) sem reescrever o gerador SPS do zero.
  • Remoção / desacoplamento do app ia genérico (quando no âmbito do ramo) evita provedores cloud e concentra o fluxo de referências no app reference.

Screenshots

Uso no admin, pós enviar um arquivo .docx:

Screenshot 2026-07-21 at 08 02 48 Screenshot 2026-07-21 at 08 06 42 Screenshot 2026-07-21 at 08 06 58

Uso da API no DRF Django:

Screenshot 2026-07-21 at 08 03 59 Screenshot 2026-07-21 at 08 10 26

Quais são tickets relevantes?

Tíquete: #19

Referências

O que ainda falta?

  1. Precisa no futuro ligar a app de IA para que tenhamos mais modelos disponíveis
  2. É necessário realizar mais testes e coleta de evidências
  3. Gerar mais teste com as referencias de um .docx e compara com o XML marcado

Segurança da informação (NSI.04)

Seção obrigatória. Marque as opções aplicáveis e justifique quando necessário. Referência: NSI.04 - Norma de Desenvolvimento Seguro.

Este PR manipula dados sensíveis ou pessoais (LGPD)?

  • Sim — descreva os controles de proteção aplicados (criptografia, mascaramento, anonimização, etc.):
  • Não

Este PR altera autenticação, autorização, controle de acesso ou gerenciamento de sessão?

  • Sim — descreva o que mudou e por quê:
  • Não

Este PR introduz, atualiza ou remove dependências de terceiros?

  • Sim — as novas dependências foram verificadas no SBOM/Trivy sem vulnerabilidades críticas/altas em aberto?
    • Verificado e aprovado
    • Pendente / vulnerabilidade aceita com justificativa:
  • Não

Este PR foi validado pelo pipeline de segurança (SonarQube / Trivy)?

  • Sim — link do job:
  • Não aplicável a este PR (justifique):

Este PR concatena, monta ou executa comandos SQL, HTML ou JavaScript a partir de entrada externa?

  • Sim — confirme que há sanitização/parametrização (prepared statements, escaping, etc.):
  • Não

Este PR expõe novos endpoints, telas ou serviços?

  • Sim — HTTPS obrigatório está garantido e o acesso segue o princípio de menor privilégio?
  • Não

Algum segredo, senha, chave ou token está sendo adicionado ao código-fonte?

  • Não, nenhum segredo foi commitado
  • Sim (bloquear merge e corrigir antes de prosseguir)

gitnnolabs and others added 2 commits July 21, 2026 07:15
Co-authored-by: Cursor <cursoragent@cursor.com>
@gitnnolabs gitnnolabs self-assigned this Jul 21, 2026
@gitnnolabs gitnnolabs added the enhancement New feature or request label Jul 21, 2026
@gitnnolabs

Copy link
Copy Markdown
Collaborator Author

@robertatakenaka ainda está em draft — estou ajustando a máquina com GPU e a infra para reunir evidências mais consistentes no PR.

Também quero deixar uma versão disponível com um tempo aceitável de marcação no ambiente de homologação: https://tools-hml.scielo.org/

Envia o few-shot uma vez por lote (REFERENCE_BATCH_SIZE) em vez de
por linha; fallback 1-a-1 se a resposta do lote for inválida.
…ew-shot uma vez por lote (REFERENCE_BATCH_SIZE) e limita

Envia o few-shot uma vez por lote (REFERENCE_BATCH_SIZE) e limita
o contexto Ollama via options.num_ctx (REFERENCE_NUM_CTX=8192).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant