File size: 3,270 Bytes
1e18736
 
 
 
 
 
 
 
 
0b9aac3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7e35e16
0b9aac3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import spaces


@spaces.GPU
def _zerogpu_noop():
    # ZeroGPU exige uma função decorada; o app roda todo em CPU.
    return None


"""Explorador da amostra rotulada de nl2bash-pt (200 linhas, seed 42)."""
from pathlib import Path

import gradio as gr
import pandas as pd

DADOS = Path(__file__).parent / "dados"
FONTES = ["nl2bash", "nl2sh-alfa"]
CLASSES = ["OK", "ERRO_LEVE", "ERRO_GRAVE"]
COLUNAS = {
    "en": "Original (inglês)",
    "pt": "Tradução",
    "comando": "Comando",
    "classe": "Classe",
}


def carregar():
    return pd.read_csv(DADOS / "amostra_rotulada.csv", dtype=str, keep_default_na=False)


def numeros_do_arquivo():
    """Linhas de resultados.txt até antes das colunas de validação, sem alteração."""
    linhas = (DADOS / "resultados.txt").read_text(encoding="utf-8").splitlines()
    fim = next(i for i, l in enumerate(linhas) if l.startswith("is_valid="))
    return "\n".join(linhas[:fim])


def filtrar(fontes, classes, df=None):
    d = carregar() if df is None else df
    d = d[d["fonte"].isin(fontes) & d["classe"].isin(classes)]
    return d[list(COLUNAS)].rename(columns=COLUNAS).reset_index(drop=True)


def contagem(fontes, classes):
    return f"{len(filtrar(fontes, classes))} de 200 linhas"


TOPO = """
# nl2bash-pt: explorador da medição de erro de tradução

Abaixo, o texto de `resultados.txt` exatamente como saiu da análise. Os percentuais e os
intervalos de Wilson (IC 95%) usam ponto decimal, como no arquivo. Em resumo: 52 de 200 linhas
(26,0%) com erro grave, IC 95% Wilson de 20,4% a 32,5%.
"""

METODO = """
## Como a medição foi feita

- A amostra tem 200 linhas aleatórias do split train, com seed 42 (`random_state=42`).
- Os rótulos (OK, ERRO_LEVE, ERRO_GRAVE) são automatizados, sem revisão linha a linha.
- A fronteira entre erro leve e erro grave é subjetiva. Traduzir literais de arquivo, caminho,
  string ou flag foi contado como grave, e um critério mais brando reduziria a taxa de grave.
- A amostra não diz nada sobre cada linha individual: o rótulo de uma linha pode estar errado.

## Licença e créditos

Licença do dataset: cc-by-4.0 (linhas de tldr-pages). Avisos MIT de NL2Bash e NL2SH-ALFA mantidos.

- NL2Bash (Lin et al., LREC 2018): https://github.com/TellinaTool/nl2bash. Dados em MIT.
- NL2SH-ALFA (MIT-ALFA, NAACL 2025): https://huggingface.co/datasets/westenfelder/NL2SH-ALFA.
  Licença MIT declarada. O NL2SH-ALFA agrega fontes com licenças diversas, entre elas
  tldr-pages (CC BY 4.0, com atribuição obrigatória) e fontes sem licença declarada. Não foi
  possível determinar quais linhas vieram de qual fonte.
"""

with gr.Blocks(title="nl2bash-pt: explorador") as demo:
    gr.Markdown(TOPO)
    gr.Code(value=numeros_do_arquivo(), language=None, interactive=False, label="resultados.txt")
    gr.Markdown(METODO)
    with gr.Row():
        f = gr.CheckboxGroup(FONTES, value=FONTES, label="Fonte")
        c = gr.CheckboxGroup(CLASSES, value=CLASSES, label="Classe")
    n = gr.Markdown(contagem(FONTES, CLASSES))
    t = gr.Dataframe(value=filtrar(FONTES, CLASSES), interactive=False, wrap=True)
    for comp in (f, c):
        comp.change(filtrar, [f, c], t)
        comp.change(contagem, [f, c], n)

if __name__ == "__main__":
    demo.launch()