Spaces:
Running on Zero
Running on Zero
File size: 5,179 Bytes
562df32 8764c67 | 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 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | import spaces
@spaces.GPU
def _zerogpu_noop():
# ZeroGPU exige uma função decorada; o app roda todo em CPU.
return None
"""Explorador estático do piloto de injeção de prompt (resultados agregados).
Os números vêm de dados/*.csv, copiados de results/SUMMARY.md do pacote
llm-injection-pilot, lidos como texto. Nada é recalculado aqui. Só mudam o
separador decimal (ponto para vírgula) e o formato do intervalo.
"""
from pathlib import Path
import gradio as gr
import pandas as pd
DADOS = Path(__file__).parent / "dados"
def _ler(nome):
return pd.read_csv(DADOS / nome, dtype=str, keep_default_na=False)
def _virgula(s):
return str(s).replace(".", ",")
def _ic(s):
# "[70.9, 92.9]" vira "70,9 a 92,9"
return _virgula(s.strip("[]").replace(", ", " a "))
def tabela_principal(arquivo, n_rotulo):
d = _ler(arquivo)
return pd.DataFrame(
{
"Modelo": d["cfg"],
"Condição do prompt de sistema": d["condition"].map(
{"baseline": "padrão", "hardened": "reforçado"}
),
"Sucessos": d["k"] + " de " + d["n"],
"ASR (%)": d["asr_%"].map(_virgula),
"IC 95% Wilson (%)": d["ic95"].map(_ic),
}
).rename(columns={"Sucessos": n_rotulo})
def tabela_t0():
return tabela_principal("ic_t0.csv", "Sucessos (40 ataques)")
def tabela_t07():
return tabela_principal("ic_t07.csv", "Sucessos (120 gerações)")
def tabela_criterios(temp="0"):
d = _ler("asr_por_categoria.csv")
d = d[d["temp"] == temp]
return pd.DataFrame(
{
"Modelo": d["cfg"],
"Condição": d["condition"].map({"baseline": "padrão", "hardened": "reforçado"}),
"Categoria": d["category"].map({"direct": "direto", "indirect": "indireto"}),
"n": d["n"],
"Critério principal, casamento normalizado (%)": d["asr_principal"].map(_virgula),
"String exata (%)": d["asr_exact_str"].map(_virgula),
}
).reset_index(drop=True)
def filtrar_criterios(temp, modelo):
t = tabela_criterios("0" if temp == "T=0" else "0.7")
if modelo != "Todos":
t = t[t["Modelo"] == modelo]
return t.reset_index(drop=True)
MODELOS = ["Todos"] + sorted(_ler("ic_t0.csv")["cfg"].unique().tolist())
TEXTO_TOPO = """
# Piloto de injeção de prompt em dois modelos pequenos (CPU): resultados agregados
Este Space mostra só números agregados de um piloto pequeno e exploratório. Os ataques
e os textos dos prompts de ataque não são exibidos aqui.
"""
TEXTO_T0 = """
## Número principal: temperatura 0 (decodificação gulosa)
ASR é a taxa de ataque bem-sucedido, pelo critério principal (casamento normalizado),
sobre os 40 ataques por modelo e condição (16 diretos e 24 indiretos). Os dois modelos
não se comparam entre si.
"""
TEXTO_T07 = """
## Confirmação: temperatura 0,7 (3 seeds)
São 120 gerações por modelo e condição, que correspondem aos mesmos 40 ataques repetidos
em 3 seeds. As gerações não são independentes, então os intervalos abaixo ficam otimistas.
Use esta tabela como confirmação do T=0, não como número principal.
"""
TEXTO_CRITERIO = """
## Critério principal ao lado da string exata
O critério de sucesso foi corrigido depois de eu ver os resultados. A coluna de string
exata é o critério original e fica ao lado para a diferença ficar visível. Valores em
porcentagem, por categoria, como estão em results/SUMMARY.md.
"""
TEXTO_RESSALVAS = """
## Ressalvas
- Piloto pequeno e exploratório: 40 ataques por modelo e condição.
- Os ataques são próprios, escritos para este piloto. Não são um benchmark publicado.
- O critério de sucesso foi corrigido depois de ver os resultados. A string exata original
está na tabela de critérios.
- Os dois modelos não se comparam entre si: tamanho e quantização diferentes (1,7B em Q8_0
contra 3B em Q4_K_M) e amostra pequena.
- Reforçar o prompt de sistema não mudou o total em T=0 nos dois modelos. Com esta amostra
não há diferença detectável, e isso não quer dizer que o reforço não funcione.
- Não é réplica do INFUSE e não se compara com os números dele: benchmark, juiz e modelos
são outros.
- Execução em CPU, modo sem raciocínio (/no_think), 256 tokens no máximo por resposta.
- Nenhuma conclusão sobre a segurança de modelo algum.
"""
with gr.Blocks(title="Piloto de injeção de prompt: explorador") as demo:
gr.Markdown(TEXTO_TOPO)
gr.Markdown(TEXTO_T0)
gr.Dataframe(value=tabela_t0(), interactive=False, wrap=True)
gr.Markdown(TEXTO_T07)
gr.Dataframe(value=tabela_t07(), interactive=False, wrap=True)
gr.Markdown(TEXTO_CRITERIO)
with gr.Row():
sel_t = gr.Radio(["T=0", "T=0,7"], value="T=0", label="Temperatura")
sel_m = gr.Dropdown(MODELOS, value="Todos", label="Modelo")
saida = gr.Dataframe(value=filtrar_criterios("T=0", "Todos"), interactive=False, wrap=True)
sel_t.change(filtrar_criterios, [sel_t, sel_m], saida)
sel_m.change(filtrar_criterios, [sel_t, sel_m], saida)
gr.Markdown(TEXTO_RESSALVAS)
if __name__ == "__main__":
demo.launch()
|