Sistema de agentes do zero|INEMA.CLUB-PRO

Aula 4 · 15 min

Instruções e memória: quem ele é e o que lembra de você

Cada conversa começa do zero, a não ser que o harness entregue duas coisas antes do pedido: as instruções (quem o agente é e como age) e a memória (o que ele já sabe de você). As duas ficam em arquivos de texto que você abre e edita.

Começar a aula
Caderno aberto ao lado de uma caixa de fichas, com uma mão robótica guardando uma ficha.

Nesta aula você vai

  1. 1A mensagem de sistema: instruções que valem sempre
  2. 2Memória em arquivo, com a ferramenta lembrar
  3. 3Por que guardar não é o mesmo que usar

Objetivo: pôr as instruções em instrucoes.md e a memória em memoria.json, e ver um fato sobreviver de uma conversa para a outra.

01O que vai na conversa antes do seu pedido

Clique em cada peça.

Clique em cada bloco do diagrama para ver o que ele faz.

02Os arquivos da aula 4

Rode dentro de agente-do-zero/. O cp traz o agente.py da aula 4 e o instrucoes.md.

Arquivo · kit/instrucoes.md
Você é o assistente pessoal do dono. Responda em português, em no máximo 3 frases.
Use as ferramentas quando o pedido for sobre arquivos ou sobre algo para guardar.
Quando o dono disser "lembre que...", chame a ferramenta lembrar com o fato.
Se uma ferramenta responder "recusado", diga ao dono o motivo e não tente de outro jeito.
Nunca invente o conteúdo de um arquivo: leia antes de responder.
Arquivo · kit/aula4/agente.py
#!/usr/bin/env python3
"""Agente do zero (aula 4): + instruções num arquivo e memória que fica entre uma conversa e outra."""
import json, os, sys, urllib.request

MODELO = os.environ.get("MODELO", "llama3.2")
URL = os.environ.get("OLLAMA_URL", "http://localhost:11434") + "/api/chat"
PASTA = os.path.realpath("trabalho")
MEMORIA = "memoria.json"
MAX_RODADAS = 5


def cerebro(mensagens, ferramentas):
    corpo = {"model": MODELO, "messages": mensagens, "tools": ferramentas, "stream": False, "think": False,
             "options": {"temperature": 0, "seed": 1}}
    pedido = urllib.request.Request(URL, json.dumps(corpo).encode(), {"Content-Type": "application/json"})
    with urllib.request.urlopen(pedido, timeout=600) as r:
        return json.loads(r.read())["message"]


def memorias():
    return json.load(open(MEMORIA)) if os.path.exists(MEMORIA) else []


def ler_arquivo(nome):
    with open(os.path.join(PASTA, nome)) as f:      # ainda sem trava: ela entra na aula 5
        return f.read()


def lembrar(fato):
    json.dump(memorias() + [fato], open(MEMORIA, "w"), ensure_ascii=False)
    return f"guardado: {fato}"


FERRAMENTAS = {"ler_arquivo": ler_arquivo, "lembrar": lembrar}
DESCRICOES = [
    {"type": "function", "function": {"name": "ler_arquivo", "description": "Lê um arquivo da pasta de trabalho.",
     "parameters": {"type": "object", "properties": {"nome": {"type": "string"}}, "required": ["nome"]}}},
    {"type": "function", "function": {"name": "lembrar", "description": "Guarda um fato sobre o dono para sempre.",
     "parameters": {"type": "object", "properties": {"fato": {"type": "string"}}, "required": ["fato"]}}},
]


def responder(pedido, mostrar=print):
    instrucoes = open("instrucoes.md").read()
    lembrancas = "\n".join(f"- {m}" for m in memorias()) or "(nada ainda)"
    mensagens = [{"role": "system", "content": f"{instrucoes}\n\nO que você sabe do dono:\n{lembrancas}"},
                 {"role": "user", "content": pedido}]
    for rodada in range(MAX_RODADAS):
        msg = cerebro(mensagens, DESCRICOES)
        mensagens.append(msg)
        if not msg.get("tool_calls"):
            return msg.get("content", ""), rodada + 1
        for chamada in msg["tool_calls"]:
            nome, args = chamada["function"]["name"], chamada["function"].get("arguments") or {}
            try:
                saida = FERRAMENTAS[nome](**args)
            except Exception as erro:
                saida = f"recusado: {erro}"
            mostrar(f"[ferramenta] {nome} {json.dumps(args, ensure_ascii=False)} -> {saida[:80]}")
            mensagens.append({"role": "tool", "content": saida})
    return "Parei: cheguei ao limite de rodadas.", MAX_RODADAS


if __name__ == "__main__":
    os.makedirs(PASTA, exist_ok=True)
    resposta, rodadas = responder(" ".join(sys.argv[1:]))
    print(f"{resposta}\n({rodadas} rodada(s))")
Terminal · guardar e perguntar depois
cd ~/agente-do-zero
cp ~/agentes-do-zero-v72/kit/aula4/agente.py ~/agentes-do-zero-v72/kit/instrucoes.md .
python3 agente.py "lembre que meu cachorro se chama Thor"
cat memoria.json; echo
python3 agente.py "qual o nome do meu cachorro?"
Exemplo do repositório
[ferramenta] lembrar {"fato": "Seu cachorro se chama Thor"} -> guardado: Seu cachorro se chama Thor
Você tem um cachorro chamado Thor. Posso ajudar com algo mais relacionado a ele?
(2 rodada(s))
["Seu cachorro se chama Thor"]
[ferramenta] ler_arquivo {"nome": "Thor"} -> recusado: [Errno 2] No such file or directory: '~/agente-do-zero/t
Desculpe, não consegui encontrar o nome do seu cachorro no arquivo. Você pode me dizer o nome do seu cachorro, Thor?
(2 rodada(s))

O fato foi guardado (está no memoria.json) e foi entregue ao modelo na segunda conversa. Mesmo assim o llama3.2 foi procurar um arquivo chamado "Thor" e disse que não achou. Guardar funcionou; usar, não. Você vai medir isso na aula 6 e tentar consertar na aula 7.

03Prática: o agente com a sua cara

Faça na ordem.

E1 · Um fato que fica

10 min

Diga ao agente um fato seu ("lembre que meu time é o Grêmio") e abra o memoria.json.

Pronto quando: o memoria.json tem o seu fato e continua lá depois de fechar e abrir o terminal.

E2 · Mude o jeito dele

10 min

Edite a primeira linha do instrucoes.md com nano instrucoes.md (por exemplo, "responda em uma frase só") e repita python3 agente.py "leia notas.txt e diga a hora da reunião".

Pronto quando: a resposta mudou de forma (mais curta, por exemplo) sem você alterar o agente.py. Se o modelo pequeno não obedecer de primeira, tudo bem: é isso que a aula 6 vai medir.

04Teste o que aprendeu

A explicação aparece depois da sua resposta.

Pergunta 1 de 3

Onde ficam as instruções do agente nesta versão?

05Resumo da aula

Instruçõesinstrucoes.md: quem ele é e como age.
Memóriamemoria.json + ferramenta lembrar.
Guardar ≠ usarO fato chegou ao modelo e ele não usou. Medir mostra.
Aula anteriorPróxima aula