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