Capítulo 8 — Programação II
Mapa da aula
Aula 08 publicada. Mapa, exemplo, EX022.
flowchart TD
N0["8.1 Módulos e responsabilidades"]
N1["8.2 JSON e arquivos"]
N2["8.3 Pacotes e arquivos de modelo"]
N3["8.4 Testes adversariais"]
N4["8.6b Testes que protegem o analisador"]
N5["Síntese"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Exemplo resolvido"]
EX --> Q["Exercício EX022"]
Desenho lógico
flowchart LR
N0["8.1 Módulos e responsabilidades"]
N1["8.2 JSON e arquivos"]
N2["8.3 Pacotes e arquivos de modelo"]
N3["8.4 Testes adversariais"]
N4["8.6b Testes que protegem o analisador"]
N5["Síntese"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX022"]
[8.1 Módulos e responsabilidades]
|
v
[8.2 JSON e arquivos]
|
v
[8.3 Pacotes e arquivos de modelo]
|
v
[8.4 Testes adversariais]
|
v
[8.6b Testes que protegem o analisador]
|
v
[Síntese]
|
v
[Exemplo resolvido] --> [Exercício EX022]
Objetivos de aprendizagem
Você vai (1) organizar programas em módulos e funções com responsabilidades claras; (2) usar JSON e arquivos com segurança; (3) gerenciar pacotes de terceiros e arquivos de modelo com verificações de integridade; e (4) escrever testes que incluam casos adversariais.
8.1 Módulos e responsabilidades
Divida os programas de modo que cada parte tenha uma única tarefa. Numa aplicação com LLM: tratamento de entradas, recuperação, chamada ao modelo, verificação de política, execução de ferramentas, registro em log. Manter a verificação de política em seu próprio módulo pequeno permite revisá-la e testá-la independentemente do modelo. A separação também limita o dano: se o módulo de recuperação for manipulado para devolver um documento hostil, a verificação de política continua decidindo de forma independente se alguma chamada de ferramenta resultante é permitida. No Ask Lumen, as verificações de marcação que Rina escreveu no capítulo de programação ficam num módulo assim, com testes que rodam a cada mudança. Um revisor consegue ler o módulo inteiro em poucos minutos.
8.2 JSON e arquivos
Analise dados estruturados com analisadores estritos (json.loads) e valide campos, tipos e intervalos. Rejeite campos desconhecidos. Nunca use eval sobre dados. Quando se pede ao modelo que produza JSON, valide-o da mesma forma, porque o modelo pode produzir saídas malformadas ou manipuladas. No Ask Lumen, pede-se ao modelo que devolva uma marcação em JSON com um código de clínica, uma data e um identificador de paciente. O analisador rejeita qualquer campo extra, como uma instrução para cancelar outras consultas, e qualquer valor fora dos intervalos permitidos. Uma resposta malformada leva a uma mensagem educada de falha para o paciente, nunca a uma ação parcial.
8.3 Pacotes e arquivos de modelo
Instale pacotes de fontes confiáveis, com versões fixadas. Arquivos de modelo são riscos parecidos com código: alguns formatos de serialização podem executar código ao serem carregados. Verifique o hash SHA-256 de um arquivo contra um manifesto confiável antes de carregá-lo; o laboratório detecta adulterações dessa forma.
"""Lab H: integrity of model artefacts with SHA-256 manifests (stdlib only).
Creates synthetic 'artefact' bytes, records a manifest, then detects a
one-byte tampering and a swapped file. No real models are involved."""
import hashlib, json
files = {"model.bin": bytes(range(256)) * 40, "tokenizer.json": b'{"vocab": ["a", "b"]}',
"config.yaml": b"layers: 4\nheads: 8\n"}
manifest = {n: hashlib.sha256(b).hexdigest() for n, b in files.items()}
print(json.dumps({k: v[:16] for k, v in manifest.items()}, indent=1))
received = dict(files)
tampered = bytearray(received["model.bin"]); tampered[5000] ^= 1
received["model.bin"] = bytes(tampered)
received["config.yaml"] = b"layers: 4\nheads: 8\ntrust_remote_code: true\n"
for n, b in sorted(received.items()):
ok = hashlib.sha256(b).hexdigest() == manifest[n]
print(f"{n:15s} {'OK' if ok else 'MISMATCH'}")
Saída esperada:
{
"model.bin": "e96760a87768717b",
"tokenizer.json": "f63d2ddabc61f2d9",
"config.yaml": "e5bbb570ca0fcb87"
}
config.yaml MISMATCH
model.bin MISMATCH
tokenizer.json OK
No Lab H, um único bit invertido em model.bin e uma linha acrescentada em config.yaml mudam os respectivos hashes, enquanto o tokenizer.json intocado continua correspondendo. O manifesto precisa vir de uma fonte confiável, como a versão assinada do fornecedor, ou um atacante que altera um arquivo poderia alterar também o manifesto.
8.4 Testes adversariais
Acrescente testes que tentem quebrar seu código: entradas grandes demais, tipos errados, cadeias que parecem injeção, pedidos de dados de outros usuários. Mantenha-os permanentemente na suíte de testes. No analisador de marcações, os testes adversariais incluem uma data escrita por extenso, um identificador de paciente que pertence a outra pessoa, um código de clínica com espaços no final e uma saída do modelo contendo duas marcações. Cada teste registra a rejeição esperada. Uma vez acrescentados, esses testes protegem contra regressões: uma mudança posterior que afrouxe por acidente uma verificação falha na hora, antes de chegar aos pacientes.
8.5 Exemplo resolvido (caso sintético da LCH)
O fornecedor do DocSort enviou um modelo atualizado. A verificação de integridade de Rina comparou o hash com o manifesto assinado do fornecedor e encontrou uma divergência no arquivo de configuração. A investigação mostrou que um terceirizado havia editado o arquivo para ativar um modo de depuração que registrava o texto completo das cartas. A mudança foi revertida, e a LCH passou a exigir que toda mudança de modelo chegasse pelo processo de versões assinadas. O modo de depuração corresponde, em espírito, à linha de configuração adulterada do Lab H: uma pequena mudança de texto com grande efeito sobre a privacidade.
8.6 Erros e limites
Três erros são comuns: lógica de política misturada ao texto do prompt; carregar arquivos de modelo sem verificação de integridade; e testes apenas com entradas benignas. Uma política escrita no prompt pode ser contornada por uma mensagem habilidosa, enquanto uma política em código não pode. Carregar arquivos de modelo sem verificar hashes teria deixado o modo de depuração do terceirizado chegar à produção na LCH. Testes apenas com entradas benignas passam mesmo quando o analisador aceita saídas perigosas; o arquivo de testes hostis do analisador de marcações existe precisamente para evitar isso, e cresce a cada incidente.
8.6b Testes que protegem o analisador
O módulo que transforma a saída do modelo num pedido de marcação é o código mais relevante para a segurança no Ask Lumen, porque uma resposta malformada ou manipulada poderia cancelar a consulta errada. A LCH mantém um arquivo de testes com saídas hostis — campos extras, datas erradas, dois identificadores de consulta — e toda mudança no analisador precisa passar por ele antes da integração. Cada saída hostil do arquivo vem de uma falha real ou de um achado de revisão, então o arquivo registra o histórico de ataques ao analisador, além de protegê-lo contra eles. Quando aparece um novo tipo de falha, um teste para ela é acrescentado antes da correção.
Exercícios
- EX022 — Leitura do laboratório. Quais arquivos falham na verificação de hash do laboratório e por quê? Rubrica: 3 = model.bin e config.yaml, ambos alterados; 2 = um; 1 = vago; 0 = errado.
- EX023 — Validação de JSON. Liste quatro verificações para o JSON de marcação produzido pelo modelo. Rubrica: 3 = JSON válido, só campos permitidos, tipos, intervalos/titularidade; 2 = três; 1 = uma ou duas; 0 = nenhuma.
- EX024 — Modo de depuração. Por que a mudança para o modo de depuração era um problema de segurança? Rubrica: 3 = registrava dados de saúde sensíveis, ampliando a exposição; mudança não autorizada; 2 = parcial; 1 = vago; 0 = errado.
Síntese
Programas estruturados, análise estrita, dependências verificadas e testes adversariais tornam as aplicações de IA mais difíceis de quebrar e mais fáceis de confiar.
Continue estudando — capítulo 08 de 40
← Capítulo 07 (rascunho) · Índice de capítulos do curso · Capítulo 09 (rascunho) →