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()