The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

Replicabilidade ponta-a-ponta — do codebook ao relatório de método

Esta vignette demonstra o pipeline completo de análise de conteúdo qualitativa assistida por LLM, com foco na replicabilidade: cada decisão metodológica é documentada de forma que outro pesquisador possa reproduzir a análise apenas com o codebook em YAML e o relatório gerado por ac_qual_report().

A demonstração usa dados sintéticos (ac_qual_code() requer chave de LLM paga); a estrutura, formatos e sequência são idênticos a uma rodada real.

O pipeline em 6 etapas

  1. Coleta — corpus real ou fabricado
  2. Codebook — instrumento analítico (ac_qual_codebook)
  3. Classificação — LLM com live view (ac_qual_code(live = ...))
  4. Amostragem para revisãoac_qual_sample()
  5. Confiabilidade inter-codificadorac_qual_reliability()
  6. Relatório de métodoac_qual_report()

1. Corpus

Corpus fabricado de 12 pronunciamentos com posição declarada (favor/contra/neutro) — em uso real, este data.frame viria de ac_fetch_camara(), ac_fetch_senado() ou de importação de PDFs.

df <- data.frame(
  doc_id = paste0("d", sprintf("%02d", 1:12)),
  text = c(
    "Apoio integralmente esta reforma que simplifica o sistema tributario.",
    "Sou favoravel a proposta: reduz distorcoes historicas do setor.",
    "Voto sim com plena adesao: precisamos modernizar a estrutura fiscal.",
    "Aprovo a reforma tributaria, e uma conquista para o desenvolvimento.",
    "Rejeito esta proposta, e um retrocesso para os trabalhadores.",
    "Voto contra: a reforma prejudica os mais pobres e as pequenas empresas.",
    "Sou contrario a essa proposta, ela beneficia apenas grandes corporacoes.",
    "Nao apoio o texto atual, precisa de revisao profunda antes da votacao.",
    "O texto substitutivo altera o artigo 145 da Constituicao Federal.",
    "O relatorio incorporou 47 emendas apresentadas em plenario.",
    "A comissao aprovou o parecer com 15 votos a favor e 8 contra.",
    "O projeto seguira para votacao na proxima sessao ordinaria."
  ),
  partido = c("PT","PSD","PL","MDB","PSOL","PT","PDT","PSOL",
              "MDB","PSDB","PL","MDB"),
  stringsAsFactors = FALSE
)

corpus <- ac_corpus(df)
#> New names:
#> • `doc_id` -> `doc_id...1`
#> • `doc_id` -> `doc_id...3`
corpus
#> 
#> ── Corpus acR ──────────────────────────────────────────────────────────────────
#> • Documentos: 12
#> • Metadados: 2 colunas
#> • Idioma: "pt"
#> # A tibble: 12 × 4
#>   doc_id...1 text                                             doc_id...3 partido
#>   <chr>      <chr>                                            <chr>      <chr>  
#> 1 doc_1      Apoio integralmente esta reforma que simplifica… d01        PT     
#> 2 doc_2      Sou favoravel a proposta: reduz distorcoes hist… d02        PSD    
#> 3 doc_3      Voto sim com plena adesao: precisamos moderniza… d03        PL     
#> 4 doc_4      Aprovo a reforma tributaria, e uma conquista pa… d04        MDB    
#> 5 doc_5      Rejeito esta proposta, e um retrocesso para os … d05        PSOL   
#> 6 doc_6      Voto contra: a reforma prejudica os mais pobres… d06        PT     
#> # ℹ 6 more rows

2. Codebook

O codebook é o instrumento central. Aqui usamos três categorias (favor, contra, neutro/técnico) com definições operacionais e exemplos positivos e negativos para desambiguar categorias vizinhas.

cb <- ac_qual_codebook(
  name         = "posicao_reforma_tributaria",
  instructions = paste(
    "Classifique a posicao do parlamentar sobre a reforma tributaria",
    "com base no discurso apresentado."
  ),
  categories = list(
    favor = list(
      definition   = "Apoio explicito a aprovacao da reforma tributaria.",
      examples_pos = c("Sou a favor desta reforma que simplifica o sistema."),
      examples_neg = c("O texto altera o artigo 145 da Constituicao Federal."),
      weight       = 1
    ),
    contra = list(
      definition   = "Oposicao explicita a reforma, com argumentos de rejeicao.",
      examples_pos = c("Voto contra: prejudica os trabalhadores."),
      examples_neg = c("Precisa de ajustes antes da votacao."),
      weight       = 1.2  # categoria com mais dificuldade retorica
    ),
    neutro = list(
      definition   = "Discurso tecnico ou processual, sem posicionamento claro.",
      examples_pos = c("O relatorio incorporou emendas apresentadas."),
      examples_neg = c("Sou totalmente contra esta proposta.")
    )
  ),
  lang = "pt"
)

cb
#> 
#> ── Codebook acR: "posicao_reforma_tributaria" ──────────────────────────────────
#> • Modo: "manual"
#> • Categorias (3): "favor", "contra", and "neutro"
#> • Multilabel: FALSE
#> • Idioma: "pt"
#> • Criado em: 29/07/2026 12:32
#> 
#> Instrução geral:
#> Classifique a posicao do parlamentar sobre a reforma tributaria com base no
#> discurso apresentado.
#> 
#> Categorias:
#> • "favor": Apoio explicito a aprovacao da reforma tributaria.
#> Ex+: Sou a favor desta reforma que simplifica o sistema.
#> • "contra" [peso: 1.2]: Oposicao explicita a reforma, com argumentos de
#> rejeicao.
#> Ex+: Voto contra: prejudica os trabalhadores.
#> • "neutro": Discurso tecnico ou processual, sem posicionamento claro.
#> Ex+: O relatorio incorporou emendas apresentadas.

Salvar o codebook em YAML permite versionamento em Git e retomada da análise em outra sessão:

arquivo_cb <- tempfile(fileext = ".yaml")
ac_qual_save_codebook(cb, path = arquivo_cb)
#> ✅ Codebook salvo em
#> '/var/folders/wr/lsgxp5bj5vd2jgq9ybg24ng00000gn/T//RtmpRcfHsp/file24683602c854.yaml'
cat("Codebook salvo em:", arquivo_cb, "\n")
#> Codebook salvo em: /var/folders/wr/lsgxp5bj5vd2jgq9ybg24ng00000gn/T//RtmpRcfHsp/file24683602c854.yaml

3. Classificação com live view

Em uma rodada real, o comando seria:

library(ellmer)
chat <- chat_anthropic(model = "claude-sonnet-4-5")

resultado <- ac_qual_code(
  corpus        = corpus,
  codebook      = cb,
  chat          = chat,
  k_consistency = 3,           # 3 rodadas de self-consistency
  reasoning     = TRUE,        # pede raciocinio estruturado
  live          = "terminal"   # ver o LLM classificando ao vivo
)

Com live = "terminal", cada documento aparece na hora:

1/12 | =>                    8% | ETA 45s | d01 -> favor  (conf 1.00) "Apoio integralmente..."
2/12 | ==>                  17% | ETA 40s | d02 -> favor  (conf 1.00) "Sou favoravel a..."
3/12 | ====>                25% | ETA 35s | d03 -> favor  (conf 0.67) "Voto sim com conviccao..."
...

Para esta vignette, simulamos o resultado que o LLM retornaria (formato idêntico ao real):

set.seed(42)
resultado <- tibble::tibble(
  doc_id = df$doc_id,
  categoria = c(rep("favor", 4), rep("contra", 4), rep("neutro", 4)),
  confidence_score = c(1.00, 1.00, 0.67, 1.00,
                       1.00, 1.00, 1.00, 0.67,
                       1.00, 1.00, 0.67, 1.00),
  reasoning = c(
    "Apoio explicito com 'apoio integralmente'.",
    "Uso do adjetivo 'favoravel' e 'reduz distorcoes'.",
    "Voto declarado, mas ambivalente entre favor e neutro.",
    "'Aprovo' e 'conquista' marcam adesao.",
    "'Rejeito' e 'retrocesso' marcam oposicao.",
    "'Voto contra' e argumento distributivo.",
    "'Sou contrario' com justificativa.",
    "'Nao apoio' + pede revisao (borderline neutro/contra).",
    "Descreve alteracao normativa sem posicionar.",
    "Descreve processo legislativo.",
    "Numeros do resultado, sem opiniao. Borderline.",
    "Encaminhamento processual."
  )
)
resultado
#> # A tibble: 12 × 4
#>    doc_id categoria confidence_score reasoning                                  
#>    <chr>  <chr>                <dbl> <chr>                                      
#>  1 d01    favor                 1    Apoio explicito com 'apoio integralmente'. 
#>  2 d02    favor                 1    Uso do adjetivo 'favoravel' e 'reduz disto…
#>  3 d03    favor                 0.67 Voto declarado, mas ambivalente entre favo…
#>  4 d04    favor                 1    'Aprovo' e 'conquista' marcam adesao.      
#>  5 d05    contra                1    'Rejeito' e 'retrocesso' marcam oposicao.  
#>  6 d06    contra                1    'Voto contra' e argumento distributivo.    
#>  7 d07    contra                1    'Sou contrario' com justificativa.         
#>  8 d08    contra                0.67 'Nao apoio' + pede revisao (borderline neu…
#>  9 d09    neutro                1    Descreve alteracao normativa sem posiciona…
#> 10 d10    neutro                1    Descreve processo legislativo.             
#> 11 d11    neutro                0.67 Numeros do resultado, sem opiniao. Borderl…
#> 12 d12    neutro                1    Encaminhamento processual.

Distribuição dos resultados:

resultado |>
  dplyr::count(categoria) |>
  dplyr::mutate(pct = round(100 * n / sum(n), 1))
#> # A tibble: 3 × 3
#>   categoria     n   pct
#>   <chr>     <int> <dbl>
#> 1 contra        4  33.3
#> 2 favor         4  33.3
#> 3 neutro        4  33.3

Casos com baixa confiança (candidatos prioritários para revisão humana):

resultado |>
  dplyr::filter(confidence_score < 1.0) |>
  dplyr::select(doc_id, categoria, confidence_score, reasoning)
#> # A tibble: 3 × 4
#>   doc_id categoria confidence_score reasoning                                   
#>   <chr>  <chr>                <dbl> <chr>                                       
#> 1 d03    favor                 0.67 Voto declarado, mas ambivalente entre favor…
#> 2 d08    contra                0.67 'Nao apoio' + pede revisao (borderline neut…
#> 3 d11    neutro                0.67 Numeros do resultado, sem opiniao. Borderli…

4. Amostra para revisão humana

ac_qual_sample(strategy = "uncertainty") prioriza documentos com menor confidence_score — foca o esforço humano onde o LLM mais errou.

amostra <- ac_qual_sample(
  resultado,
  n        = 4,
  strategy = "uncertainty"
)
#> ℹ Amostra de 4 documentos selecionada (estratégia: "uncertainty").
#> ℹ Use `ac_qual_export_for_review()` para exportar para Excel.
amostra |> dplyr::select(doc_id, categoria, confidence_score, sample_reason)
#> # A tibble: 4 × 4
#>   doc_id categoria confidence_score sample_reason                
#>   <chr>  <chr>                <dbl> <chr>                        
#> 1 d03    favor                 0.67 uncertainty (confidence=0.67)
#> 2 d08    contra                0.67 uncertainty (confidence=0.67)
#> 3 d11    neutro                0.67 uncertainty (confidence=0.67)
#> 4 d01    favor                 1    uncertainty (confidence=1)

Em uma rodada real, você exportaria essa amostra para Excel, um codificador humano preencheria a coluna categoria_humano, e o resultado seria reimportado:

ac_qual_export_for_review(amostra, path = "revisao.xlsx", corpus = corpus)
# ... revisor humano preenche a coluna categoria_humano no Excel ...
revisado <- ac_qual_import_human("revisao.xlsx")

5. Confiabilidade inter-codificador

Simulamos a revisão humana (com 1 discordância em 12) e calculamos as métricas de concordância — no artigo, essas métricas aparecem na seção de método:

humano <- tibble::tibble(
  doc_id    = resultado$doc_id,
  categoria = c(rep("favor", 4), rep("contra", 4),
                "neutro","neutro","favor","neutro")  # 1 discordancia
)

irr <- ac_qual_reliability(
  llm       = resultado,
  human     = humano,
  bootstrap = 100L
)
#> Calculando confiabilidade em 12 documentos comuns...
#> Warning in irr::kripp.alpha(mat, method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> Warning in irr::kripp.alpha(rbind(l, h), method = "nominal"): NAs introduced by
#> coercion
#> ℹ Interpretação baseada em Landis & Koch (1977) e Gwet (2014).
#> ℹ IC 95% via bootstrap (n = 100).
irr
#> # A tibble: 4 × 5
#>   metric             estimate ci_lower ci_upper interpretation                  
#>   <chr>                 <dbl>    <dbl>    <dbl> <chr>                           
#> 1 percent_agreement     0.917    0.75         1 excelente (>= 90%)              
#> 2 krippendorff_alpha    0.880    0.584        1 quase perfeita (Landis & Koch, …
#> 3 gwet_ac1              0.875    0.629        1 quase perfeita (Landis & Koch, …
#> 4 f1_macro              0.915    0.625        1 quase perfeita (Landis & Koch, …

6. Relatório de método — replicabilidade automática

Aqui está o coração desta vignette: ac_qual_report() empacota tudo — codebook, config LLM, distribuição de resultados, métricas de IRR — em um documento único, pronto para anexar como material suplementar de um artigo.

arquivo_md <- tempfile(pattern = "relatorio-", fileext = ".md")

ac_qual_report(
  coded       = resultado,
  codebook    = cb,
  reliability = irr,
  chat        = "anthropic/claude-sonnet-4-5",  # ou objeto Chat
  title       = "Classificacao de posicionamento na reforma tributaria",
  author      = "Silva, A.; Souza, B.",
  method      = "Corpus de 12 pronunciamentos parlamentares (2023-2024).",
  format      = "md",
  path        = arquivo_md,
  lang        = "pt"
)
#> Warning: Unknown or uninitialised column: `metrics`.
#> ✔ Relatorio salvo em
#>   '/var/folders/wr/lsgxp5bj5vd2jgq9ybg24ng00000gn/T//RtmpRcfHsp/relatorio-24686522bb8b.md'

Primeiras 40 linhas do relatório gerado:

cat(head(readLines(arquivo_md), 40), sep = "\n")
#> # Classificacao de posicionamento na reforma tributaria
#> 
#> - **Gerado em:** 2026-07-29 12:32:05 -03
#> - **Versao do acR:** 0.3.2
#> - **Autor(es):** Silva, A.; Souza, B.
#> - **Metodo:** Corpus de 12 pronunciamentos parlamentares (2023-2024).
#> 
#> ## 1. Visao geral
#> 
#> Este relatorio documenta as decisoes metodologicas da rodada de codificacao qualitativa assistida por LLM, seguindo as recomendacoes de Krippendorff (2018) sobre replicabilidade em analise de conteudo e as boas praticas de Gilardi et al. (2023) para uso de LLMs em anotacao de textos.
#> 
#> ## 2. Codebook
#> 
#> | Nome | posicao_reforma_tributaria |
#> |---|---|
#> | Idioma        | `pt` |
#> | Modo        | `manual` |
#> | Multilabel  | `FALSE` |
#> | Criado em     | 2026-07-29 12:32:04 |
#> 
#> **Instrucoes ao codificador:**
#> 
#> > Classifique a posicao do parlamentar sobre a reforma tributaria com base no discurso apresentado.
#> 
#> ### Categorias
#> 
#> #### `favor`
#> 
#> **Definicao:** Apoio explicito a aprovacao da reforma tributaria.
#> 
#> **Exemplos positivos:**
#> - Sou a favor desta reforma que simplifica o sistema.
#> 
#> **Exemplos negativos:**
#> - O texto altera o artigo 145 da Constituicao Federal.
#> 
#> #### `contra`
#> 
#> **Definicao:** Oposicao explicita a reforma, com argumentos de rejeicao.

O relatório completo cobre 8 seções: metadados, codebook completo, histórico de modificações, configuração da LLM, distribuição de resultados, confiabilidade (com IC 95%), referências metodológicas e sugestão de citação.

Para gerar em HTML autocontido (com CSS embutido, pronto para publicação web):

ac_qual_report(
  coded       = resultado,
  codebook    = cb,
  reliability = irr,
  format      = "html",
  path        = "apendice_metodo.html",
  lang        = "pt"      # ou "en" para submissao internacional
)

Fluxo completo em 6 linhas

Recapitulando toda a vignette em código executável:

library(acR); library(ellmer)
corpus    <- ac_corpus(meu_data_frame)
cb        <- ac_qual_codebook(name = "...", instructions = "...", categories = list(...))
resultado <- ac_qual_code(corpus, cb, chat = chat_anthropic("..."), live = "terminal")
amostra   <- ac_qual_sample(resultado, n = 30, strategy = "uncertainty")
# ... revisao humana ...
irr       <- ac_qual_reliability(llm = resultado, human = revisado)
ac_qual_report(resultado, cb, reliability = irr, path = "metodo.md")

Seis funções principais, um pipeline reproduzível, um relatório automático — do texto bruto ao apêndice metodológico do artigo.

Referências

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.