Debugowanie z AI działa najlepiej, gdy dajesz modelowi to samo, co dostałby kolega przy twoim biurku: cały błąd, kod, który go wywołał, czego się spodziewasz, co dzieje się zamiast tego i co już wykluczasz. Model nie może uruchomić twojego programu ani zobaczyć twoich danych, więc wszystko, co wie o błędzie, pochodzi z tego, co wkleisz. Najbardziej przydatny pojedynczy nawyk to prośba o przyczynę, zanim poprosisz o poprawkę.
Wklej wszystko, nie tylko błąd
Obie poniższe zakładki opisują ten sam błąd. Skrypt czyta plik CSV wyeksportowany z Excela i kończy się KeyError: 'email', choć plik wyraźnie ma kolumnę email.
KeyError oznacza, że słownik nie ma klucza 'email'. Możesz uniknąć błędu, używając .get(), które zwraca None, zamiast zgłaszać wyjątek:
email = row.get("email")
Albo najpierw sprawdź:
if "email" in row:
email = row["email"]
Pierwsza odpowiedź poprawnie wyjaśnia, czym jest KeyError, ale jej rada w tym przypadku szkodzi. Z row.get("email") awaria znika, a każdy e-mail zmienia się w None. Model odpowiedział na najczęstszą wersję błędu, bo tylko ją opisywał prompt.
Pełny opis zadziałał dzięki dwóm liniom. "Zawodzi tylko pierwsza kolumna" i "zapisany z Excela jako CSV UTF-8" to wskazówki prowadzące do znacznika kolejności bajtów i żadnej z nich nie ma w komunikacie błędu. Rzadko wiadomo, który ze szczegółów jest wskazówką, i właśnie dlatego wkleja się wszystkie.
Pięć rzeczy, które trzeba dołączyć
- Pełny błąd. Cały traceback albo wynik z konsoli, a nie jego parafrazę. Numery linii i łańcuch wywołań pokazują, gdzie zaczęła się awaria, a to często kilka ramek od miejsca, w którym wyszła na wierzch.
- Kod, który go wywołał. Funkcję, która zawodzi, i kod, który ją wywołuje. Jeśli błąd wspomina linię, upewnij się, że ta linia jest w tym, co wklejasz.
- Oczekiwane a faktyczne. Po jednym zdaniu. Przy błędach bez żadnego komunikatu (zły wynik, pusta strona, wolne zapytanie) to jest cały opis błędu.
- Twoje środowisko. Wersję języka, system operacyjny, framework i wersje bibliotek, gdy mogą mieć znaczenie. Błędy kodowania znaków, ścieżek i dat często zależą od platformy.
- Co już próbujesz. To powstrzymuje model przed ponownym proponowaniem tego samego, a wynik każdej próby jest dowodem. "Usunięcie części z e-mailem sprawia, że działa" zawęziło błąd z CSV do jednej kolumny.
Poproś o przyczynę przed poprawką
Prośba o poprawkę zachęca model do zmieniania kodu, aż błąd zniknie. Prośba o przyczynę każe mu rozumować, dlaczego błąd występuje, a poprawka z tego wynika. Poproś o krótką uszeregowaną listę przyczyn ze sposobem sprawdzenia każdej, a potem sam wykonaj te sprawdzenia. Ten szablon robi właśnie to:
TypeError: Cannot read properties of undefined (reading 'map')function UserList() {
const [users, setUsers] = useState();
useEffect(() => {
fetch("/api/users")
.then((res) => res.json())
.then((data) => setUsers(data));
}, []);
return (
<ul>
{users.map((u) => (
<li key={u.id}>{u.name}</li>
))}
</ul>
);
}- Komponent renderuje się, zanim pojawią się jakiekolwiek dane.
useState()zaczyna odundefined, a React renderuje komponent raz, zanim uruchomi efekt, więcusers.mapjest wywoływane naundefined. Już to samo daje dokładnie twój błąd, przy każdym ładowaniu. Sprawdzenie: dodajconsole.log(users)tuż przedreturn. Jeśli wypiszeundefined, a zaraz potem pojawi się błąd, to jest to. - API zwraca coś innego niż tablicę. Gdyby zwracało obiekt w rodzaju
{ users: [...] }, błąd byłby inny (users.map is not a function), więc to nie jest wklejony przez ciebie błąd. Może to jednak być kolejny problem, gdy przyczyna 1 zostanie naprawiona. Sprawdzenie:console.log(data)w drugim.then. - Zapytanie się nie udaje. Na razie bez znaczenia: ponieważ pierwszy render rzuca wyjątek, React nigdy nie uruchamia efektu, więc zapytanie nawet nie jest wysyłane. Sprawdzenie: zakładka Network nie pokazuje żadnego zapytania
/api/users, co przy okazji potwierdza przyczynę 1.
Odpowiedź robi coś, co pomija odpowiedź zaczynająca od poprawki: wyklucza przyczyny, bo błąd, który by dały, różni się od wklejonego, albo dlatego, że kod nigdy nie dochodzi do miejsca, w którym mogłyby wystąpić. Z tego samego powodu ważny jest dokładny tekst błędu. Prośba, żeby model wypisał przyczyny przed odpowiedzią, to lekka forma chain-of-thought prompting: najpierw jest rozumowanie, a wniosek się na nim opiera.
Zrób minimalną reprodukcję
Minimalna reprodukcja to najmniejszy program, który nadal pokazuje błąd: dane wpisane na sztywno zamiast wywołania bazy danych, jedna funkcja zamiast całego modułu. Jej budowanie często pozwala znaleźć błąd, zanim o cokolwiek zapytasz, bo każdy usunięty element albo zostawia błąd (nie miał z nim związku), albo sprawia, że znika (miał). Gdy tak się nie stanie, reprodukcja jest idealnym promptem: na tyle krótkim, że model przeczyta każdą linię, i wolnym od niezwiązanego kodu, który mógłby go wysłać w pogoń za złym problemem.
Jeśli błąd zależy od danych, dołącz kilka wierszy, które go wywołują. Model potrafi rozumować o [{"id": 1, "name": null}]; nie potrafi rozumować o "niektórych wierszach na produkcji".
Gdy poprawki przestają działać
Jeśli trzecia poprawka od modelu zawodzi w ten sam sposób, czwarta prośba o poprawkę raczej nie da nic lepszego. Bardziej pomagają dwie rzeczy:
- Daj mu nowe dowody. Dodaj linię z print albo logiem, która pokazuje faktyczne wartości w miejscu awarii, uruchom ją i wklej wynik. Dowody, które przeczą teorii modelu, to najszybsza droga do lepszej.
- Zacznij nową rozmowę. Długie wątki debugowania zapełniają się porzuconymi teoriami i starymi wersjami kodu, a model może dalej na nich budować. Nowy czat z aktualnym kodem, błędem, dowodami i linią "już wykluczone: X i Y" często zachodzi dalej w jednej odpowiedzi.
Uważaj na pewne siebie odpowiedzi o działaniu bibliotek. Model może opisać opcję albo funkcję, która nie istnieje; jak to sprawdzić, opisują halucynacje AI. Gdy kod nie jest zepsuty, ale nie rozumiesz, dlaczego robi to, co robi, lepszym narzędziem jest prompt do wyjaśniania kodu.
Najczęściej zadawane pytania
Jak poprosić ChatGPT albo Claude'a o naprawę kodu?
Wklej pełny komunikat błędu i kod, który go wywołał, a potem dodaj trzy krótkie linie: czego się spodziewasz, co dzieje się zamiast tego i co już próbujesz. Zanim poprosisz o poprawkę, poproś o najbardziej prawdopodobną przyczynę i sposób, żeby ją potwierdzić. Samo "napraw to" daje poprawkę najczęstszej wersji błędu, która może nie być twoją.
Czy wklejać do AI cały projekt?
Nie. Wklej funkcję, w której występuje błąd, kod, który ją wywołuje, i próbkę danych, które dostaje. Jeszcze lepiej: zredukuj problem do najmniejszego programu, który nadal go pokazuje. Niezwiązane pliki spowalniają odpowiedź i dają modelowi więcej miejsc do szukania problemu, którego tam nie ma.
Dlaczego po poprawce od AI błąd znika, a program nadal nie działa?
Poprawka zajęła się objawem. Na przykład zamiana row["email"] na row.get("email") zatrzymuje KeyError, ale jeśli klucza brakuje przez błąd wcześniej w przepływie danych, każdy e-mail jest teraz po cichu None. Prośba najpierw o przyczynę i o sposób jej potwierdzenia chroni przed poprawkami, które tylko ukrywają problem.
Co zrobić, gdy AI ciągle proponuje poprawki, które nie działają?
Przestań prosić o poprawki i zamiast tego daj mu dowody. Opisz, co zmieniła każda próba, dodaj linię z print albo logiem, która pokazuje faktyczne wartości, i wklej jej wynik. Jeśli rozmowa jest długa, zacznij nową z czystym podsumowaniem: kod, błąd, dowody i już wykluczone poprawki.