Przejdź do głównej zawartości

Eksploruj dane w trwałym kernelu

Ten poradnik pokazuje, jak sprawić, by agent wczytał coś kosztownego raz, a potem zadał temu kilka pytań, zamiast płacić za wczytanie przy każdym pytaniu.

Narzędzie eval uruchamia trwały interpreter. Zmienne, importy i wczytane dane przetrwają między wywołaniami.

Jednorazowe python -c płaci za przygotowanie przy każdym pytaniu. Wczytanie ramki danych kosztuje sekundy i sto megabajtów, a narysowanie jej wykresu — milisekundy. Gdy każde pytanie kosztuje tyle, co wczytanie, agent zadaje mniej pytań, niż powinien — a każda odpowiedź wraca jako tekst, który musi potem parsować od nowa.

Wczytaj data/runs.csv i podaj mi czas trwania p95 według agenta.

import pandas as pd
runs = pd.read_csv("data/runs.csv")
len(runs)

Ostatnie wyrażenie jest zwracane tak, jak robi to notatnik, więc len(runs) podaje liczbę wierszy bez print.

Potem, w osobnym wywołaniu:

runs.groupby("agent")["duration_ms"].quantile(0.95).sort_values()

runs wciąż jest wczytane. Ramka pandas wraca wyrenderowana jako tabela, a nie jako repr.

import matplotlib.pyplot as plt
runs.groupby("agent")["duration_ms"].mean().plot.bar()

Wykresy są przechwytywane po wykonaniu komórki i zwracane jako obrazy, które renderuje transkrypt. Wykres widzisz Ty — widzi go też agent.

Wykresy są zamykane po przechwyceniu. Nieodebrany wykres zostałby narysowany i wysłany ponownie także przez następną komórkę, więc pięciokomórkowa sesja emitowałaby pierwszy wykres pięć razy.

Są one przepisywane na zwykły kod, zamiast kończyć się błędem:

Co wpiszesz Co się dzieje
%pip install x Uruchamia pip, a następnie czyści pamięć podręczną modułów, aby kolejny import już go widział
%cd path os.chdir
!command Przechwycony podproces
%%bash Reszta komórki jako skrypt powłoki
%%timeit 1000 pomierzonych uruchomień

To właśnie usunięcie z pamięci podręcznej przy %pip ma znaczenie: instalacja w działającym interpreterze nic nie daje modułowi, który został już zaimportowany, więc bez tego wersja, którą właśnie zainstalowano, nie jest tą działającą.

paths = tool("find", {"pattern": "**/*.dart", "path": "lib"})
for path in paths.splitlines()[:100]:
contents = tool("read", {"path": path})
...

tool(name, args) wchodzi z powrotem do rejestru narzędzi samego agenta. Dzięki temu komórka może rozdzielić pracę na ponad sto plików albo delegować przez task, bez wydawania przez model tury na każdy element.

Wywołanie przez most wstrzymuje limit czasu komórki na czas swojego trwania. Budżet mierzy bezczynność, a nie czas zegarowy — komórka, która rozdziela pracę na subagentów i czeka cztery minuty, nie zawiesiła się, a zabicie jej w połowie rozdzielania utraciłoby stan całego kernela.

eval(code: "…", reset: true, description: "Start a clean interpreter")

Odrzuca interpreter i uruchamia czysty. Wszystko, co zostało wczytane, przepada — i właśnie o to chodzi.

W odizolowanym środowisku rozmowy, gdy rozmowa je ma; w przeciwnym razie na hoście.

Trwały interpreter sterowany przez model czytający niezaufane repozytorium to dokładnie ten przypadek, dla którego istnieje wykonywanie wyłącznie w odizolowanym środowisku: jednorazowe wywołanie bash przynajmniej się kończy, a kernel to powłoka, która pamięta.

Nie uruchamia przy tym odizolowanego środowiska — ta sama zasada, która powstrzymuje kartę riga przed automatycznym startem. Jeśli chcesz, aby kernel działał w odizolowanym środowisku, najpierw otwórz powłokę rozmowy. Zobacz Daj agentowi maszynę do testów.

  • Jedna komórka naraz na kernel. Dwie komórki ścigające się w jednym interpreterze to dwie połówki dwóch programów przeplatane w jednej przestrzeni nazw.
  • Wynik jest ograniczany. Komórka w pętli print zostaje obcięta, zamiast wypełnić okno kontekstu.
  • Cztery obrazy na komórkę. Pętla rysująca może emitować wykres przy każdej iteracji, a każdy obraz to duży stały koszt w żądaniu, które go niesie.
  • Kernel ginie razem z uruchomieniem. Kernel wciąż trzymający ramkę danych po zakończeniu rozmowy to wyciek.