Meta-inżynieria systemów AI: od trace’ów do lepszej pamięci
Tłumaczenie automatyczne
Ten artykuł został automatycznie przetłumaczony z angielskiego oryginału.
Ten artykuł otwiera cykl Meta-Engineering AI Systems — sześcioczęściowy przewodnik po inżynierii AI w pętli zamkniętej: wykorzystywaniu agentów do badania awarii, testowania zmian i używania wyników do ulepszania systemów AI.
Zachowanie aplikacji AI zależy od czegoś więcej niż tylko od jej modelu. Na to, co się dzieje, wpływają prompty, wyszukane informacje, przechowywana pamięć, narzędzia i kod aplikacji. Gdy odpowiedź jest błędna, kilka zmian może wyglądać wiarygodnie. Problem inżynieryjny polega na ustaleniu, która zmiana pomaga, ile kosztuje i co jeszcze może zepsuć.
Termin meta-inżynieria oznacza tu projektowanie samego procesu ulepszania: jakie dowody widzi agent, co może zmienić, jak testujemy jego propozycje i kto decyduje o ich przyjęciu. Pętla zamknięta opisuje sposób, w jaki ten proces uczy się na eksperymentach. Każdy wynik wpływa na to, co wypróbujemy lub wykorzystamy dalej — także wtedy, gdy proponowana zmiana zakończy się niepowodzeniem.
Pracę tę możemy automatyzować etapami. Człowiek może wskazać dokładne zmiany do przetestowania, zdefiniować zbiór dozwolonych alternatyw dla algorytmu wyszukiwania albo przekazać wybór kolejnej propozycji agentowi LLM. Runner testuje każdego kandydata i zachowuje dowody na potrzeby kolejnej decyzji. Ten cykl skupia się na włączaniu agentów w ten proces przy zachowaniu jawnej kontroli nad wykonaniem, ewaluacją i przyjęciem zmian.
Przewodnim pytaniem wszystkich sześciu części jest to, jak dużo tej pracy możemy delegować agentowi, zachowując wiarygodność dowodów i decyzji o przyjęciu zmiany. Zaczniemy od zmapowania całego systemu, a następnie zbudujemy małą, działającą wersję opartą na pamięci agenta.
Co zamyka pętlę
Trzeba mieć na uwadze dwie różne pętle. W aplikacji agenta pętla runtime wybiera działanie, wywołuje narzędzie, obserwuje wynik i kontynuuje bieżące zadanie użytkownika. Pętla ulepszania działa między kolejnymi wersjami tej aplikacji. Bada zachowanie zakończonych uruchomień i testuje zmiany, które mają poprawić późniejsze uruchomienia.
Pętla ulepszania zaczyna się od dowodu: błędnej odpowiedzi, niepożądanej zmiany stanu, nadmiernego kosztu albo innej obserwowalnej awarii. Trace rejestruje kroki prowadzące do tego wyniku. Proposer wybiera kandydata — konkretną wersję zmiany. Runner uruchamia kandydata na zdefiniowanych zadaniach, a ewaluator sprawdza wynikowe zachowanie względem wymagań. W opisanym tu eksperymencie proposerem jest agent LLM:
Ewaluacja dostarcza informacji do decyzji, ale nie autoryzuje samej siebie. Ktoś musi zdecydować, czy zmierzona korzyść uzasadnia przyjęcie zmiany, uwzględniając jej wpływ na koszt, uprawnienia i inne wymagane zachowania. W tym cyklu zaczynamy od recenzenta-człowieka. Proposer może zasugerować zmianę, ale nie może przepisać kontroli, zwiększyć własnego budżetu ani przyznać sobie zgody.
Istnieją dwie ścieżki powrotne. Historia eksperymentów zasila kolejne propozycje, także wtedy, gdy kandydat zostanie odrzucony. Jeśli kandydat zostanie zatwierdzony i przyjęty, jego zachowanie dostarcza nowych dowodów z użycia. Odwracalność zmiany ma znaczenie, gdy te dowody zaprzeczają pierwotnemu eksperymentowi. Zapisanie wyniku to tylko jeden krok; pętla zamyka się wtedy, gdy dowody zmieniają to, co wypróbujemy lub wykorzystamy dalej.
Ulepszanym elementem jest target. Może nim być polityka pamięci, pipeline wyszukiwania, kod wyboru narzędzi albo program składający kontekst modelu. Inną możliwą interwencją jest trenowanie modelu. Pętla może działać przy stałych wagach modelu: agent może ulepszać otaczający program bez trenowania modelu. To pierwsze demo zawiera już zewnętrznego agenta LLM. W kolejnych częściach wzmocnimy ewaluator i sprawdzimy, czy agentic search jest wart swojego kosztu w porównaniu z prostszymi metodami.
Wybierz, jak dużą część wyszukiwania delegować
Załóżmy, że już wiesz, co chcesz wypróbować: porównać dwa modele w kroku ekstrakcji albo przetestować progi pamięci 0.6, 0.7 i 0.8. Możesz samodzielnie dostarczyć te wybory i zautomatyzować wykonanie, scoring oraz raportowanie. Po zapoznaniu się z wynikami wybierasz kolejny eksperyment. Pętla sprzężenia zwrotnego działa nawet wtedy, gdy system nie wymyślił kandydatów samodzielnie.
Używam czterech trybów roboczych, aby uwidocznić ten podział. Rysunek pokazuje jeden ze sposobów stopniowego delegowania projektowania eksperymentów: zacząć od dokładnych wyborów modeli, pozwolić systemowi przeszukiwać ustawienia i zatwierdzone komponenty albo poprosić agenta o zbadanie awarii i wybór kolejnego eksperymentu. Człowiek określa mniej elementów każdej próby, nadal ustalając jednak reguły wyszukiwania.
Nazwy trybów opisują praktyczne układy dla tego cyklu, a nie standardową branżową skalę autonomii. To, co może się zmienić, i to, kto wybiera zmianę, to odrębne decyzje. Przykłady przestrzeni wyszukiwania w Optunie łączą wybór modelu z zakresami parametrów. Wyszukiwanie pipeline’ów w scikit-learn porównuje alternatywne komponenty za pomocą zwykłego grid search. Sama wymiana komponentu nie czyni więc procesu bardziej agentic. Szerokości na rysunku ilustrują podział pracy w tych przykładach; nie są zmierzonym udziałem kontroli ani wysiłku.
Agent-led investigation opisuje sposób wyboru kolejnej próby. Agent odczytuje awarie i wcześniejsze wyniki, proponuje zmianę i dostosowuje się po teście. Jest to zgodne z rozróżnieniem przedstawionym w workflow i wzorcach agentów Anthropic: zdefiniowany proces może automatyzować wykonanie, natomiast agent kieruje kolejnymi krokami na podstawie informacji zwrotnej. Możliwe są również metody hybrydowe: MIPROv2 w DSPy wykorzystuje model do proponowania instrukcji, a Bayesian optimization do wyszukiwania ich kombinacji. Stałe porównanie modeli nie wymaga proposera LLM; jego wyniki wchodzą do pętli sprzężenia zwrotnego, gdy kierują kolejnym eksperymentem lub wersją systemu.
Uprawnienia do proponowania, wykonywania i przyjmowania zmian pozostają rozdzielone. Agent może przygotować zmianę do zatwierdzenia przed każdym uruchomieniem albo bez nadzoru testować dozwolone zmiany, podczas gdy człowiek ocenia ich przyjęcie. Lista zatwierdzonych komponentów nadal wymaga kompatybilnych implementacji; uprawnienie do wyboru adaptera nie obejmuje uprawnienia do jego napisania. W każdym trybie agent pozostaje w granicach dozwolonych zmian, stałych kontroli i budżetu i nie może sam przyznać sobie zgody na wdrożenie. Delegowanie większej części pracy nadal pozostawia miejsce na nadzór: badanie wdrożonych agentów przeprowadzone przez Anthropic opisuje, jak użytkownicy przechodzą od zatwierdzania pojedynczych działań do monitorowania i interweniowania.
Wszystkie tryby mogą korzystać z tego samego rejestru eksperymentów: zapisu każdej podjętej próby zmiany. Zachowaj kandydata i jego rodzica, dokładną zmianę i informację, kto ją dostarczył, wersje testów i środowiska, wynik, koszt oraz każdą awarię lub odrzucenie. Dzięki tej historii człowiek może przekazać kolejną propozycję agentowi — albo odebrać mu tę rolę — bez utraty dowodów. Wyniki z różnych wersji testów nadal trzeba rozróżniać.
To demo łączy wyszukiwanie konfiguracji z badaniem prowadzonym przez agenta. Definiujemy pięć ustawień, testy, budżet i regułę wyboru. Agent wybiera wartości oraz kolejną hipotezę na podstawie informacji zwrotnej; Python automatycznie uruchamia testy. Przegląd wdrożenia przez człowieka pozostaje oddzielny. Repozytorium akceptuje również JSON kandydata dostarczony przez człowieka za pomocą lab evaluate. Przeglądy modeli, adaptery komponentów i kod pisany przez agenta to szersze opcje projektowe na późniejsze części, a nie zaimplementowane tryby tego demo pamięci.
Dlaczego warto badać to teraz
Zasada sprzężenia zwrotnego jest znana z inżynierii. Interesują mnie najnowsze prace, które umieszczają agentów kodujących wewnątrz procesu badania i eksperymentowania. Dostarczają konkretnych implementacji do analizy, zamiast wymagać założenia, że autonomiczne ulepszanie zadziała.
autoresearch Karpathy’ego definiuje zwięzły eksperyment: zmodyfikować program treningowy, uruchomić go przy stałym budżecie czasu treningu, sprawdzić wynik walidacji i zapisać, czy próba została zachowana, odrzucona czy zakończyła się awarią. Instrukcje oddzielają edytowalny plik treningowy od stałego kodu ewaluacji. To rozdzielenie sprawia, że proponowana praca i kryterium sukcesu są możliwe do przeanalizowania.
Meta-Harness, preprint z marca 2026 roku, bada inny target: kod sterujący tym, jakie informacje aplikacja LLM przechowuje, wyszukuje i prezentuje swojemu modelowi. Proposer może przez system plików analizować źródła, wyniki i trace’y wcześniejszych kandydatów. Historia eksperymentów staje się materiałem roboczym do kolejnego badania.
Projekty te motywują pytanie inżynieryjne tego cyklu: gdy agent potrafi badać i proponować zmiany, co musi zrobić otaczający go system, aby eksperymenty były użyteczne? Sama większa liczba prób nie ustanawia lepszych decyzji. Słaby ewaluator może nagradzać szkodliwą zmianę, a proces wyszukiwania może wielokrotnie wykorzystywać tę słabość. Sprawdzimy wartość propozycji agentowych względem prostszych alternatyw, zamiast z góry zakładać ich przewagę.
Jak sześć części zbuduje jeden system
Artykuły rozwiną jeden skumulowany projekt towarzyszący. Każda część podejmuje pytanie pozostawione przez poprzedni eksperyment i dodaje mechanizm potrzebny do jego zbadania.
| Część | Pytanie | Co dodaje do tego samego systemu |
|---|---|---|
| 1. Od trace’ów do lepszej pamięci | Czy możemy przekształcić awarię w ulepszenie możliwe do zrecenzowania? | Narzędzie pamięci, proposer LLM, ograniczone eksperymenty, informacje zwrotne i zachowane dowody. |
| 2. Sprawmy, by dało się to oceniać | Czy ewaluator rozpoznaje użyteczne zmiany, także pozorne sukcesy powodujące szkody? | Silniejsza ewaluacja, celowo wywołane fałszywe sukcesy i kontrole tego, co wyniki rzeczywiście ustanawiają. |
| 3. Harness ulepszania | Które elementy możemy ponownie wykorzystać dla różnych targetów i trybów pracy? | Wspólne wykonanie, historia i uprawnienia dla proposerów ludzkich, klasycznych i LLM. |
| 4. Porównanie strategii wyszukiwania | Jak dużą część pracy związanej z propozycjami warto delegować agentowi? | Porównania z wyszukiwaniem ludzkim i klasycznym przy wyrównanych budżetach i dozwolonych zmianach. |
| 5. Ulepszanie z gwarancjami | Jakie dowody wystarczą, aby przyjąć pozornego zwycięzcę? | Głębsze testy adversarial, etapowe przyjmowanie i mechanizmy rollbacku. |
| 6. Od historii do danych treningowych | Czy zrecenzowane eksperymenty mogą ulepszyć komponent uczony? | Mały eksperyment z weryfikatorem lub trenowaniem polityki, testowany względem prostszych napraw. |
Kontrole prywatności i przegląd człowieka należą do pierwszej wersji. Część 5 wzmocni tę ochronę, gdy proposer zyska większe możliwości. Podobnie część 6 zbada możliwe wykorzystanie zgromadzonych dowodów; każda wcześniejsza część musi pozostać użyteczna bez trenowania nowego modelu.
Daj zewnętrznemu agentowi mały, możliwy do przeanalizowania target
Wyobraź sobie asystenta, który pamięta dane konta Ady. 1 stycznia dowiaduje się, że mieszka ona w Berlinie. 3 stycznia dowiaduje się o przeprowadzce do Paryża obowiązującej od 10 stycznia. Zapytany o jej miasto 5 stycznia, odpowiada „Paryż”.
Pamięć zawiera oba fakty. Reguła wyszukiwania preferuje ten otrzymany niedawno, nie sprawdzając, od kiedy staje się ważny. To konkretna awaria, którą może zbadać agent ulepszający.
Targetem jest celowo tylko narzędzie pamięci, a nie kompletny asystent. Otrzymuje przygotowane fakty, zapisuje je lub odrzuca i wyszukuje wartość na potrzeby pytania. Jego zapis, obsługa dat, wyszukiwanie i wybór odpowiedzi są zwykłym kodem Python. Ekstrakcję z rozmowy i generowanie odpowiedzi w języku naturalnym pozostawiamy poza eksperymentem, aby móc ustalić, co faktycznie zmieniła dana reguła.
LLM znajduje się w zewnętrznej pętli eksperymentu Python. Agent otrzymuje wyniki testów, decyduje, które ustawienia zmienić, i dostaje z powrotem kolejny wynik. Zarejestrowane kampanie wykorzystywały rzeczywisty model do wyboru tych zmian.
Taki podział pozwala testować pętlę inżynieryjną bez wprowadzania drugiego źródła zachowania modelowego wewnątrz narzędzia pamięci. W większej aplikacji obie pętle mogłyby korzystać z modeli. Tutaj jeden LLM wystarcza, aby uczynić proces ulepszania agentowym. Inny LLM może pełnić tę samą rolę proposera; jego propozycje muszą przestrzegać tego samego schematu i przechodzić te same kontrole.
Przeanalizuj eksperyment
Repozytorium towarzyszące na GitHubie zawiera zewnętrznego agenta, narzędzie pamięci, testy i zwięzłe raporty z trzech rzeczywistych kampanii LLM. Kompletne żądania, odpowiedzi i trace’y są dostępne w archiwum dowodów z sumami kontrolnymi. Raport eksperymentu śledzi proponowane zmiany, ich zmierzone wyniki i każdą decyzję o zakończeniu. W dalszej części artykułu użyjemy repozytorium do uruchomienia świeżej kampanii.
Zrozum jeden test, zanim odczytasz wynik
Scenariusz to jedna kompletna historia testowa. Zdarzenie to jedna akcja wysłana do narzędzia pamięci: zapis, zapytanie lub usunięcie. Scenariusz przyszłej przeprowadzki ma cztery zdarzenia:
- Zapisz
city = Berlin, obowiązujące od 1 stycznia. - Zapisz
city = Paris, otrzymane 3 stycznia, ale obowiązujące od 10 stycznia. - Zapytaj o miasto 5 stycznia. Oczekuj Berlina.
- Zapytaj o miasto 12 stycznia. Oczekuj Paryża.
Dane wejściowe są już ustrukturyzowane. Na przykład fakt dotyczący Paryża identyfikuje właściciela (north workspace, użytkownik ada), podmiot (account), właściwość (city), wartość (Paris) i datę obowiązywania. Ciągi Berlin i Paris pochodzą z danych testowych, a nie z modelu generującego wspomnienia na podstawie rozmowy.
Confidence to dostarczony wynik używany do podjęcia decyzji o zapisaniu proponowanego faktu. Writer porównuje go z min_confidence. Propozycja delivery = courier z wynikiem 0.4 jest odrzucana przy bazowym progu 0.7, ale zapisywana przy progu 0.2. Autor testu dostarcza ten wynik; nie jest to zmierzone prawdopodobieństwo poprawności propozycji. Oceniamy, jak reguła zapisu obsługuje te wyniki, a nie to, czy model potrafi je wiarygodnie szacować.
Każdy scenariusz zaczyna się od pustej listy rekordów pamięci w Pythonie. Zaakceptowane aktualizacje zamykają okres ważności poprzedniej wartości i dołączają nowy rekord. Po dwóch zapisach dotyczących miasta rekordy opisują:
| Wartość | Otrzymano | Ważne od | Ważne do |
|---|---|---|---|
| Berlin | 1 stycznia | 1 stycznia | 10 stycznia, wyłącznie |
| Paryż | 3 stycznia | 10 stycznia | Brak daty końcowej |
Funkcja odpowiedzi zwraca pierwszy wyszukany rekord pasujący do żądanej właściwości. Ewaluator porównuje tę wartość z oczekiwaną odpowiedzią. Kompletny scenariusz przechodzi tylko wtedy, gdy każda odpowiedź jest poprawna i każda mająca zastosowanie kontrola reguł danych przechodzi pomyślnie. Usuwanie, izolacja właściciela i zabronione zapisy mają jawne kontrole obok jakości odpowiedzi.
Testy przekazują identyfikatory właścicieli bezpośrednio; to demo nie ma systemu uwierzytelniania. Rzeczywista usługa musi pobierać te identyfikatory z uwierzytelnionego żądania. Odrzucenie danych jawnie oznaczonych jako instrukcja również nie demonstruje wykrywania instrukcji ukrytych w zwykłym tekście.
Nadaj pamięci schemat
Fakty również potrzebują własnych reguł. Wzorcem, w którym schematy zarządzają przechowywanym stanem i jego cyklem życia, jest Schema-Guided Agent Memory (SGAM). Tutaj demonstrujemy jego mały fragment: typowane fakty, własność, odwołania do źródeł, przedziały obowiązywania i usuwanie. Późniejszy schemat SGR będzie określał, co może proponować zewnętrzny agent; ten schemat pamięci określa, co narzędzie może przechowywać.
Rekord Paryża po drugim zapisie zawiera:
{
"tenant": "north",
"user": "ada",
"entity": "account",
"key": "city",
"value": "Paris",
"confidence": 0.95,
"source": "user",
"valid_from": "2026-01-10",
"schema_version": 1,
"memory_type": "fact",
"id": "m002",
"source_event_id": "future-move:event-2",
"observed_at": "2026-01-03",
"valid_to": null,
"supersedes_memory_id": "m001"
}
source_event_id wskazuje zdarzenie, które dostarczyło informację o Paryżu. supersedes_memory_id łączy Paryż z rekordem Berlina, m001. schema_version: 1 identyfikuje format rekordu; nie oznacza to, że program może automatycznie migrować stare dane.
MemoryRecord i Memory.write() wymuszają ten format. Brak odwołań do źródła, niepoprawne daty i zniekształcone pola są odrzucane, zanim zmieni się przechowywana historia. Zamknięty przedział musi kończyć się po swoim początku. Berlin może kończyć się 10 stycznia, a Paryż zaczynać tego samego dnia; żaden rekord nie ma pustego przedziału.
Załóżmy, że kolejny zapis brzmi Rzym, również obowiązujący od 10 stycznia. Writer odrzuca ten konflikt i pozostawia Paryż bez zmian. Drugi fakt dotyczący Paryża dla tej samej daty po prostu ponownie wykorzystuje rekord. Aktualizacja z wcześniejszą datą obowiązywania również zostaje odrzucona: ten mały writer nie rekonstruuje historii napływającej z opóźnieniem. Są to stałe polityki, których zewnętrzny agent nie może zmienić. Jego ustawienie deduplicate steruje powtarzanymi potwierdzeniami z późniejszą datą obowiązywania.
Bazowa wersja nadal celowo ignoruje filtry podmiotu i daty podczas odczytu. Przechowuje poprawne rekordy, ale może wybrać niewłaściwy. To błąd, który przekazujemy agentowi do naprawy. Izolacja właściciela obowiązuje dla każdej konfiguracji, a usunięcie usuwa wszystkie wersje żądanej właściwości w ramach podmiotu danego właściciela.
To demonstracja tych reguł SGAM w pamięci. Nie ma trwałej bazy danych, usługi retencji ani systemu migracji. Oddzielne testy regresyjne writera sprawdzają odrzucone zapisy i granice przedziałów; nie są dodatkowymi scenariuszami w wyniku kampanii obejmującej 20 historii.
Pozwól agentowi wybrać zmianę
Kampania to jedna próba ulepszenia pierwotnej konfiguracji, rozpoczynająca się od świeżej historii agenta. Iteracja to jedno wywołanie, w którym agent proponuje zmianę albo decyduje się zakończyć. Kolejna iteracja otrzymuje informacje zwrotne z wcześniejszych.
Kampania zaczyna się od uruchomienia wyłącznie konfiguracji bazowej. Przechodzi ona 13 z 20 scenariuszy. Następnie przekazujemy agentowi:
- bieżące ustawienia i ich znaczenie;
- pomiary konfiguracji bazowej;
- trace’y nieudanych scenariuszy, odrzuconych zapisów i powtarzanych potwierdzeń;
- zmiany, które agent może proponować;
- wcześniejsze propozycje i ich wyniki, jeśli takie istnieją.
Pierwsze żądanie nie zawiera gotowych ulepszonych konfiguracji. Repozytorium ma również cztery ręcznie przygotowane konfiguracje służące do wyjaśnienia mechaniki pamięci, ale działający agent nie rozpoczyna od tych odpowiedzi.
Agent może zmieniać pięć ustawień istniejącego narzędzia:
| Ustawienie | Skutek zmiany |
|---|---|
min_confidence | Zmienia minimalny dostarczony wynik wymagany do zapisania faktu. |
filter_entity | Ogranicza wyszukiwanie do żądanego podmiotu, na przykład domu zamiast pracy. |
time_aware | Ogranicza wyszukiwanie do faktów ważnych w żądanej dacie. |
deduplicate | Ponownie wykorzystuje identyczny aktywny fakt zamiast zapisywać kolejne potwierdzenie. |
top_k | Określa, ile rekordów zostanie wybranych przed zapakowaniem kontekstu odpowiedzi. |
Propozycja może zmienić najwyżej dwa ustawienia. Wartości liczbowe mają ograniczenia: confidence od 0 do 1, a top_k od 1 do 8. Kontrakt rejestruje dozwolone zmiany konfiguracji narzędzia; schemat agenta i walidator dodają reguły propozycji.
W tym procesie agent nie ma narzędzi powłoki ani systemu plików. Nie może edytować Pythona, oczekiwanych odpowiedzi, izolacji właściciela, zachowania usuwania, schematu pamięci, obsługi konfliktów, scoringu, budżetów ani uprawnień do wdrożenia. Jego wyjście to dane, które Python może zaakceptować lub odrzucić. To mały eksperyment konfiguracyjny, a nie sandbox dla dowolnego kodu pisanego przez agenta.
Niech każda propozycja będzie rekordem decyzji SGR
Wykorzystuję Schema-Guided Reasoning, aby uczynić decyzję możliwą do przeanalizowania. Każda odpowiedź modelu ma te same pola:
| Pole | Co czytelnik powinien móc sprawdzić |
|---|---|
observations | Który dostarczony scenariusz i event uzasadniają proponowaną zmianę? |
hypothesis | Jaka reguła wydaje się powodować problem? |
predicted_effect | Co powinno się poprawić po przetestowaniu zmiany? |
action | Czy agent proponuje zmianę, czy kończy działanie? |
patch | Które dozwolone ustawienia powinny się zmienić? |
Żądanie OpenAI Responses wykorzystuje ścisły JSON Schema wygenerowany z modeli Pydantic. Obiekty odrzucają dodatkowe pola, a każde pole patcha jest wymagane, ale może mieć wartość null oznaczającą „pozostaw to ustawienie bez zmian”. Structured Outputs ogranicza kształt odpowiedzi. Python nadal sprawdza, czy odwołania istnieją, wartości są dozwolone, a proponowana konfiguracja nie była już testowana.
Schemat nie dowodzi poprawności hipotezy ani nie ujawnia wewnętrznego rozumowania modelu. Są to zwięzłe rekordy decyzji, które możemy sprawdzać względem dowodów.
W pierwszej zarejestrowanej iteracji agent zidentyfikował wyszukiwanie między podmiotami oraz zwracanie faktów poza ich przedziałem obowiązywania. Jego rzeczywista odpowiedź proponowała następujący patch:
{
"min_confidence": null,
"filter_entity": true,
"time_aware": true,
"deduplicate": null,
"top_k": null
}
Te dwa ustawienia zostały wybrane przez model. Runner dostarczył identyfikator rodzica i przypisał identyfikator kandydata; model nie mógł przekierować zmiany do dowolnego rodzica ani pliku.
Prześledź zmianę w Pythonie
Zarówno konfiguracja bazowa, jak i nowa przechowują te same rekordy Berlina i Paryża. Proponowana zmiana wpływa na to, które rekordy wyszukiwanie może brać pod uwagę.
W Memory.query() te przełączniki aktywują dwa filtry:
if self.config.filter_entity:
eligible = [r for r in eligible if r["entity"] == event["entity"]]
if self.config.time_aware:
eligible = [r for r in eligible if valid_at(r, event["as_of"])]
Kontrola obowiązywania obejmuje datę początkową, ale wyklucza datę końcową:
def valid_at(item: dict, at: str) -> bool:
return item["valid_from"] <= at and (
item["valid_to"] is None or at < item["valid_to"]
)
Daty używają YYYY-MM-DD, więc ich kolejność tekstowa odpowiada kolejności kalendarzowej. W pytaniu dotyczącym 5 stycznia Paryż zostaje wykluczony, ponieważ staje się ważny 10 stycznia. Berlin pozostaje dostępny. W pytaniu dotyczącym 12 stycznia Paryż jest ważny, a Berlin ma status historyczny.
Python uruchamia proponowaną konfigurację na wszystkich 20 historiach. Ta pierwsza zmiana zwiększa sukces z 13/20 do 19/20, przy przejściu wszystkich zaimplementowanych twardych kontroli. Zmienia ona dwa filtry jednocześnie, więc wzrost w całym zestawie mierzy ich łączny efekt. Trace miasta wskazuje, co filtr daty zrobił w tym konkretnym przypadku.
Runner wybiera tę konfigurację jako rodzica kolejnego eksperymentu. Nie oznacza to jej wdrożenia. W następnym żądaniu model otrzymuje zmierzony wynik, wybrane ustawienia i pozostałe dowody.
Kolejna decyzja musi wykorzystać wynik
Oto kompletna pierwsza kampania. Każdy wiersz to rzeczywista odpowiedź modelu, a nie wcześniej napisany krok skryptu demonstracyjnego:
| Iteracja | Co zaproponował agent | Co zrobił Python | Bieżący najlepszy wynik |
|---|---|---|---|
| 1 | Włącz filtry podmiotu i daty | Zweryfikował i przetestował; wybrał ulepszenie | 19/20 |
| 2 | Usuń duplikaty identycznych potwierdzeń | Przetestował; wybrał, ponieważ liczba zapisów spadła bez pogorszenia odpowiedzi | 19/20 |
| 3 | Obniż min_confidence z 0.7 do 0.6 | Przetestował; wybrał, ponieważ ostatni nieudany scenariusz przeszedł | 20/20 |
| 4 | Zakończ | Zarejestrował decyzję o zakończeniu; nie wprowadził kolejnej zmiany | 20/20 |
Druga odpowiedź odwoływała się do scenariusza powtarzanych potwierdzeń. Ta historia zapisuje language = German trzy razy. Deduplicacja zachowuje jeden rekord zamiast trzech, zachowując odpowiedź. W całym zestawie średnia liczba przechowywanych rekordów spadła z 1,70 do 1,60, a sukces nadal wynosił 19/20.
Trzecia propozycja dotyczyła innej awarii. Użyteczna preferencja językowa miała dostarczony confidence równy 0.6, poniżej bieżącego progu 0.7. Obniżenie progu do 0.6 dopuściło ten fakt, nadal odrzucając niepewną propozycję kuriera z wynikiem 0.4. Sukces osiągnął 20/20; średnia liczba przechowywanych rekordów wyniosła 1,65, ponieważ pamięć zachowała dodatkowy użyteczny fakt.
Przy czwartym wywołaniu agent zdecydował się zakończyć: na podstawie dostarczonych dowodów nie miał kolejnej popartej nimi zmiany do zaproponowania. To decyzja modelu, a nie dowód globalnej optymalności konfiguracji.
Kolejne żądanie zawiera bieżące wyniki i wcześniejsze decyzje. Po zobaczeniu, że naprawa wyszukiwania pomogła, agent przeszedł do przechowywania i dopuszczania zapisów. Runner nie dostarczył tych kolejnych patchy ani wcześniej napisanej sekwencji kroków.
Reguła wyboru jest stała: wymagaj przejścia wszystkich twardych kontroli, preferuj lepszy kompletny sukces scenariuszy, a przy równym sukcesie preferuj mniej przechowywanych rekordów. Testy obejmują również ścieżkę odrzucenia, uruchamiając propozycję regresywną przygotowaną skryptowo; w tych trzech kampaniach nie była ona zmierzoną regresją jakości.
Oddzielny przebieg deweloperski zawiera rzeczywiste odrzucenie walidacyjne: agent powołał się na agent-01, identyfikator kandydata, tak jakby był scenariuszem. Odpowiedź pasowała do JSON Schema, ale jej odwołanie nie identyfikowało dostarczonego zdarzenia, więc Python odrzucił ją przed ewaluacją. Kontroler zwraca odrzuconą odpowiedź i konkretny błąd walidacji jako informację zwrotną; testy offline sprawdzają to zachowanie. W trzech opisanych niżej kampaniach nie wystąpiły błędy walidacji.
Powtarzaj kampanię wyszukiwania, nie deterministyczny test
Ta sama konfiguracja pamięci i te same dane wejściowe produkują te same odpowiedzi. Powtarzanie tej ewaluacji nie dostarcza nowych dowodów dotyczących jakości odpowiedzi. Runner sprawdza nową konfigurację raz i ponownie wykorzystuje zweryfikowane wyniki rodziców do porównań.
Zewnętrzny agent może wybierać różne propozycje, dlatego uruchomiliśmy trzy niezależne kampanie. Każda rozpoczęła się od tego samego wyniku bazowego 13/20, otrzymała świeżą historię i miała najwyżej cztery decyzje modelu. Żadna kampania nie otrzymała odkryć z poprzedniej.
| Kampania | Decyzje modelu | Ocenione propozycje | Propozycje odrzucone przed ewaluacją | Wybrany sukces | Dlaczego się zakończyła |
|---|---|---|---|---|---|
| 1 | 4 | 3 | 0 | 20/20 | Agent zakończył |
| 2 | 4 | 3 | 0 | 20/20 | Agent zakończył |
| 3 | 4 | 3 | 0 | 20/20 | Agent zakończył |
Wszystkie trzy kampanie wybrały tę samą sekwencję: włączyć oba filtry wyszukiwania, usunąć duplikaty potwierdzeń, obniżyć próg confidence do 0.6, a następnie zakończyć.
Wykonano 12 wywołań modelu: dziewięć propozycji ocenionych przez Python, a następnie trzy decyzje o zakończeniu. Każda kampania wykonała konfigurację bazową oraz trzy nowe konfiguracje na 20 historiach: 80 uruchomień narzędzia pamięci na kampanię. 20 historii pozostało przez cały czas takie samo.
Wszystkie trzy kampanie wybrały te same ustawienia końcowe. To mała obserwacja dotycząca jednego modelu, prompta, targetu i publicznego zestawu testów. Nie szacuje ona, jak niezawodnie optymalizator będzie ulepszał nieznane systemy. Silniejsze porównanie należy do późniejszej części cyklu: powtarzanych kampanii przy wyrównanych budżetach, konkurencyjnych metod propozycji i testach, których proposer nie może zobaczyć.
Odczytuj jakość i koszt na właściwym poziomie
Eksperyment ma dwa różne rodzaje kosztów. Uruchamianie narzędzia pamięci wykorzystuje lokalny czas CPU i nie wykonuje wywołań modelu. Uruchamianie zewnętrznego proposera wykorzystuje tokeny wejściowe i wyjściowe. Zerowe pole kosztu dostawcy w raporcie ewaluacji pamięci opisuje tylko wewnętrzne narzędzie; nie jest kosztem kampanii.
W ramach zarejestrowanego badania z 11 września 2026 roku użyliśmy GPT-5.6 Luna (gpt-5.6-luna), z wysiłkiem rozumowania low, zapisanym schematem i instrukcjami SGR oraz maksymalnie 4 096 tokenami wyjściowymi na wywołanie. Program wyłączył automatyczne retry SDK i ustawił 60-sekundowy timeout żądania. Zachowano dokładne żądania, zwrócone identyfikatory modeli, zużycie i czasy trwania wywołań.
Szacowany koszt oparty na tokenach dla 12 wywołań modelu wynosi USD 0.039177, przy skonfigurowanym budżecie USD 0.50. Obliczenie korzysta z opublikowanych stawek modelu, uwzględnia dopłatę za zapis cache zgłoszoną w danych o zużyciu i pomija rabaty za odczyt cache. To konserwatywny szacunek na podstawie zarejestrowanego zużycia, a nie faktura. Sprzęt i czas deweloperski nie wchodzą do tej kwoty.
Przed każdym wywołaniem runner rezerwuje górne oszacowanie na podstawie ograniczonego rozmiaru wejścia i maksymalnej liczby tokenów wyjściowych. Jeśli pozostały budżet nie wystarczy na pokrycie tej rezerwy, zatrzymuje się. Nieudane lub przerwane wywołania pozostają w rejestrze; gdy zużycie jest niedostępne, zachowana zostaje zarezerwowana kwota zamiast wartości zero.
Jeśli chodzi o jakość odpowiedzi, 20/20 oznacza, że każda odpowiedź i każda mająca zastosowanie twarda kontrola przeszły pomyślnie dla tych 20 przygotowanych historii. Nie oznacza to gotowej do produkcji pamięci. Wszystkie historie są publicznymi przypadkami deweloperskimi; wybrane trace’y i informacje zwrotne z zestawu są dostępne dla proposera. Obejmują aktualizacje, pytania historyczne, niepewność, duplikaty, czynniki rozpraszające, separację właścicieli, usuwanie i zabronione zapisy. Etykiety search, evaluation i adversarial organizują pierwotny zestaw; nie czynią żadnego z tych przypadków ukrytym zestawem testowym.
Ten mały zestaw czerpie pomysły z LongMemEval, MemoryAgentBench, VehicleMemBench i GateMem. Dane wejściowe i scoring są nasze; wyniki nie odtwarzają tych benchmarków.
Możesz również porównać w repozytorium cztery ręcznie przygotowane konfiguracje. Pokazują one, dlaczego akceptowanie większej liczby faktów może pogorszyć odpowiedzi i jak poprawić przechowywanie bez podnoszenia jakości odpowiedzi. Pokazują również określaną przez człowieka stronę tej samej infrastruktury eksperymentalnej: autor dostarcza kandydatów, a Python je ocenia. Są użytecznymi porównaniami edukacyjnymi, a nie dowodem, że agentic search przewyższa kompetentnego człowieka lub inną metodę wyszukiwania.
Uruchom świeżą kampanię agenta
Aby pozwolić agentowi wybierać nowe propozycje, sklonuj projekt towarzyszący i pobierz zarejestrowane dowody:
git clone --branch v0.2.2 --depth 1 https://github.com/slavadubrov/meta-engineering-ai-lab.git
cd meta-engineering-ai-lab
uv sync --frozen
uv run --frozen python scripts/fetch_evidence.py
uv run --frozen python -m lab verify artifacts/agent-study-03 --source
Pobieranie sprawdza SHA-256 i odtwarza pełne nagrania w artifacts/. Nie wykonuje wywołań modelu. Jeśli dowody zostały już pobrane, pomiń ten krok i uruchom polecenie weryfikacyjne.
Zapisz OPENAI_API_KEY w lokalnym pliku .env.local. Repozytorium ignoruje ten plik. Następnie uruchom:
uv run --frozen --env-file .env.local python -m lab campaign \
--live --campaigns 3 --iterations 4 --budget-usd 0.50 \
--output artifacts/my-agent-study
--live jawnie włącza wywołania dostawcy. Obecność klucza w środowisku nie uruchamia aktywnego agenta w offline’owych poleceniach pamięci ani w przeglądarce. --campaigns 3 tworzy trzy niezależne historie agentów; --iterations 4 ogranicza liczbę decyzji w każdej z nich. Używaj nowego katalogu wyjściowego dla każdego badania: istniejące dowody nigdy nie są nadpisywane.
Otwórz artifacts/my-agent-study/report.md, aby zobaczyć wyniki kampanii i odwołania do każdego żądania, odpowiedzi i ewaluacji Pythona. Porównaj proponowane zmiany z opisaną wyżej kampanią: agent może wybrać inaczej, mimo że testy pamięci są deterministyczne.
README mapuje kod i polecenia. Zamrożony raport kampanii oraz suma kontrolna archiwum i indeks przykładów pozwalają bezpośrednio przeanalizować dowody przedstawione w tym artykule.
Oddziel historię eksperymentów od pamięci użytkownika
Narzędzie pamięci przechowuje miasto i język Ady. Historia eksperymentów przechowuje to, co zobaczył agent, proponowany patch, każde odrzucenie, wynikowe pomiary i informację, która konfiguracja stała się kolejnym rodzicem. Te magazyny służą różnym celom.
Każda iteracja zachowuje dokładne żądanie z instrukcjami i schematem, odpowiedź dostawcy, zużycie i czasy, wynik walidacji oraz każdą ukończoną ewaluację. Nieudane propozycje pozostają widoczne. Hashe plików wiążą zapisane dowody z implementacją i danymi wejściowymi użytymi w eksperymencie.
Są to dane syntetyczne, więc publiczny zapis może zachować pełne stany. Rzeczywiste trace’y wymagają oddzielnej polityki retencji: usunięcie faktu z narzędzia pamięci nie usuwa wcześniejszych kopii z logów eksperymentów ani backupów. Test usuwania w demo sprawdza rekordy narzędzia i późniejsze odczyty, a nie usunięcie z każdego możliwego magazynu.
Co kolejny artykuł powinien zakwestionować
Mamy teraz agenta wewnątrz pętli ulepszania. Proponuje zmianę, otrzymuje zmierzony wynik, wybiera kolejną zmianę i może zdecydować o zakończeniu. Nieprawidłowe propozycje podążają oddzielną ścieżką odrzucenia i pozostają w rejestrze. Uprawnienia agenta ograniczają się do konfiguracji; testowanie i przegląd wdrożenia pozostają oddzielnymi obowiązkami.
Kolejnym ryzykiem jest sam ewaluator. Jeśli sukces nagradza przechowywanie każdego faktu, agent może nauczyć się zachowywać zgadywane informacje. Jeśli zestaw pytań dotyczy wyłącznie bieżącego miasta, może przeoczyć zmianę niszczącą użyteczną historię. Bardziej zaawansowany proposer może sprawniej wykorzystywać słabe pomiary.
Część 2, Najpierw spraw, by dało się to oceniać, dopiero potem zapewniaj autonomię, pyta, jak testować te pomiary, zanim damy proposerowi większą swobodę. Wynik 20/20 z pierwszej kampanii jest punktem wyjścia do tego badania.