Notatki praktyczne: Budowa LLM, Część 1 — Szkolenie: Przewidywanie następnego tokena
Krok po kroku instrukcja obsługi Notatek praktycznych: Budowanie LLM, Część 1 — Szkolenie: Przewidywanie następnego tokena: umowy, sprawdzenia oraz miejsca na kod do wstawić dla zespołów wdrażających ten wzorzec.
Niech to służy jako wersja przeznaczona dla operatorów, zawierająca zasady przedstawione w „Building LLM, Part 1 — Training: Predicting the Next Token”: wyraźne etapy, uporządkowane sekcje kodu oraz notatki dotyczące napraw, które przetrwają przeniesienie obowiązków. Etap Przeglądu działa najlepiej, gdy traktowany jest jako mierzalna powierzchnia do analizy. Zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. Zapisuj czasy wykonywania zadań oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy przechodzi się od wersji demonstracyjnej do środowisk współdzielonych.
Dlaczego najpierw Vision Transformer?
Dla etapu Why a Vision Transformer należy zdefiniować dane wejściowe, osobę odpowiedzialną za ten krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania stanu ukrytego. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepiej używać ustrukturyzowanych wyników z walidacją schematu niż tekstu swobodnego.
Jedna idea: przewidzenie następnego tokena
W fazie przewidywania jednej idei należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponownych działań, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, należy preferować ustrukturyzowane wyniki z walidacją schematu zamiast tekstu w formie swobodnej.
logits, _ = model(ids) # ids = the tokens so far, shape (1, T)
probs = F.softmax(logits[0, -1], dim=-1) # one probability per vocabulary token
Text → tokens: dlaczego musieliśmy stworzyć własny tokenizer
Dla tokenów tekstu należy zdefiniować etap przygotowawczy, dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, łatwe do przetestowania jednostki nad rozbudowanymi skryptami. Gdy dany krok zawiedzie, powinno to wskazywać na konkretną przyczynę, a nie na skomplikowaną strukturę procesu. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepsze są ustrukturyzowane wyniki z walidacją schematu niż swobodny tekst. Dla tokenów tekstu należy zdefiniować etap przygotowawczy, dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy rejestrować czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk.
import glob
from tokenizers import Tokenizer, models, trainers, pre_tokenizers
from llm_transformer.prep_tales import strip_gutenberg, RAW_DIR
# read every raw .txt book and strip its Project Gutenberg header/footer,
# leaving just the story text - one big string per book
tales_texts = [strip_gutenberg(open(p, encoding="utf-8", errors="ignore").read())
for p in sorted(glob.glob(f"{RAW_DIR}/*.txt"))] # 12 books, ~809k words
tok = Tokenizer(models.BPE())
tok.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False) # start from bytes
trainer = trainers.BpeTrainer(vocab_size=8192, special_tokens=["<|endoftext|>"],
initial_alphabet=pre_tokenizers.ByteLevel.alphabet())
tok.train_from_iterator(tales_texts, trainer) # learn the 7,935 merges
tok.save("tales_bpe.json")
tok = Tokenizer.from_file("tales_bpe.json") # reload the trained tokenizer
ids = tok.encode("Once upon a time").ids # -> [412, 987, 15, 733] (integers)
idx = torch.tensor(ids).unsqueeze(0) # (1, 4) — a batch of one sequence
vocab_size = tok.get_vocab_size() # 8192 - sets the NUMBER OF ROWS below
Token → wektor: wyszukiwanie, a nie obliczenia
Gdy przechodzisz przez etap wyszukiwania wektora tokenów, najpierw zapisz specyfikację: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Zachowuj w pamięci podręcznej stabilne instrukcje systemowe oraz schematy narzędzi. Ponowne wysyłanie identycznego prefiksu jest częstą przyczyną marnotrawstwa zasobów.
self.token_embed = nn.Embedding(vocab_size, n_embed) # the 8,192 x 256 table
# .weight IS a learnable (8192, 256) parameter tensor — 2.1M weights, trained by backprop;
# each id's row is nudged only on steps where that token appears in the batch
...
tok_emb = self.token_embed(idx) # idx (B, T) -> vectors (B, T, 256), one row per id
Wyjątek: maska przyczynowa
Gdy pracujesz nad etapem przyczynowym wyjątku, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj jednocześnie ścieżkę prawidłowego działania oraz ścieżkę naprawczą. Próby ponowne, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. Zachowuj w pamięci podręcznej stabilne instrukcje systemu oraz schematy narzędzi. Ponowne wysyłanie identycznego preambułu jest częstą przyczyną nadmiernego obciążenia.
# tril = torch.tril(torch.ones(T, T)) — a lower-triangular matrix of 1s, made once
attn = q @ k.transpose(-2, -1) / math.sqrt(head_size) # scores, (B, T, T)
attn = attn.masked_fill(self.tril[:T, :T] == 0, float('-inf')) # blank out the future
attn = F.softmax(attn, dim=-1) # -inf -> weight 0
out = attn @ v
Jedna praca, wszystkie konteksty naraz
Gdy przechodzisz przez każdą fazę kontekstu w ramach jednego procesu, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Zachowuj w pamięci tymczasowej stabilne instrukcje systemowe oraz schematy narzędzi. Ponowne wysyłanie identycznego prefiksu to częsty powód marnotrawstwa zasobów. Gdy przechodzisz przez każdą fazę kontekstu w ramach jednego procesu, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk.
W trakcie jednego przebiegu: co faktycznie oblicza attn @ V
Analiza tego, co działa najlepiej podczas jednego przebiegu, pozwala traktować to jako mierzalną wartość. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres badania. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny poufnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Ustal limit tokenów na jeden ruch i sesję. Narzędzia typu agentic intensywnie rozszerzają kontekst; sztywne ograniczenia zapobiegają temu, by demonstracje przerodziły się w niespodziewane rachunki.
Jedna próba, wiele lekcji: przewidywania T, straty T
Faza „jedna próba, wiele lekcji” działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię do analizy. Zapisz jeden udany przypadek, jeden przypadek niepowodzenia oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres pracy. Zdokumentuj zarówno ścieżkę pomyślnego przebiegu, jak i ścieżkę przywracania stanu. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości nieodebranych stanowią część produktu, a nie elementy dodawane później. Przydziel budżet tokenów na każdy ruch i sesję. Narzędzia typu agentic intensywnie rozszerzają kontekst; sztywne limity zapobiegają temu, by demonstracje przerodziły się w niespodziewane rachunki.
logits = self.lm_head(x) # (B, T, vocab)
B, T, C = logits.shape
loss = F.cross_entropy(logits.reshape(B*T, C), # every position ...
targets.reshape(B*T)) # ... vs the token that actually followed
Każda porażka to klasa w słowniku (podobnie jak w ViT, ale z 8 192 klasami)
The Each loss is a stage works best when treated as a measurable surface. Należy zarejestrować jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzy się zakres projektu. Lepiej używać małych, łatwych do przetestowania jednostek niż rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Określ budżet tokenów na każdą rundę i sesję. Narzędzia typu agentic intensywnie wykorzystują kontekst; sztywne limity zapobiegają pojawieniu się nieoczekiwanych rachunków. The Each loss is a stage works best when treated as a measurable surface. Należy zarejestrować jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzy się zakres projektu. Zapisuj czas trwania operacji oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy przechodzi się od demonstracji do środowisk współdzielonych.
Jak budowany jest batch — i jak powstaje jego jedyna strata
Aby określić, w jaki sposób przechodzi się przez etapy przetwarzania partii danych, należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić, nie musząc czytać całej struktury aplikacji. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepiej używać ustrukturyzowanych wyników z walidacją schematu niż tekstu w formie swobodnej.
Szkolenie: obserwowanie spadku straty
Aby móc śledzić etap straty podczas szkolenia, należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg procesu, jak i ścieżkę naprawczą. Próby ponownych działań, mechanizmy ludzkiej kontroli oraz obsługa błędów stanowią część produktu, a nie elementy dodawane później. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepiej używać ustrukturyzowanych wyników z walidacją schematu niż tekstu w formie swobodnej.
for step in range(train_steps):
xb, yb = get_batch(train_data) # random (context, next-token) windows
_, loss = model(xb, yb) # forward: T predictions -> one mean loss
opt.zero_grad(); loss.backward() # backprop the loss into all 9M parameters
opt.step() # nudge them downhill
To, co stworzyliśmy — i co następuje
Dla sekcji „To, co zbudowaliśmy” i „Etap” należy określić dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy dany krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepsze są ustrukturyzowane wyniki z walidacją schematu niż tekst w formie swobodnej. Dla sekcji „To, co zbudowaliśmy” i „Etap” należy określić dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Obok wyników funkcjonalnych należy rejestrować czas trwania oraz koszt tokenów lub zapytań. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do wspólnych środowisk.
List kontrolny operacyjny
Podczas przechodzenia przez etap listy kontrolnej operacyjnej najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie.
Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć możliwość cichego, częściowego ukończenia zadania.
Zachowuj w pamięci tymczasowej stabilne instrukcje systemu oraz schematy narzędzi. Ponowne wysyłanie identycznego początku komunikatu jest częstą przyczyną marnotrawstwa zasobów.
Zachowaj prostotę procesu renderowania i odkładaj kosztowne operacje na później, dopiero po dokonaniu pomiarów i zastosowaniu mechanizmów memoizacji. Przedwczesna memoizacja może ukrywać błędy związane ze starymi danymi.
Gdy budżet na to pozwala, dodaj test dymny, który sprawdza kluczową ścieżkę w procesie CI przy użyciu narzędzi testowych, a nie rzeczywistych, płatnych API.
Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę przywracania. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości nieodebranych stanowią część produktu, a nie elementy dodawane później.
Zanim wdrożysz całą architekturę, zamroź wersje produktu, utwórz „złoty zapis” dla krytycznej ścieżki działania i potwierdź kroki odwracające zmiany. Środowiska współdzielone wymagają ograniczeń szybkości, weryfikacji uprawnień użytkowników oraz wyraźnego odpowiedzialnego za rotację haseł. Wolisz nudną niezawodność od pomysłowych, jednorazowych demonstracji.
Uwaga dotycząca wersji 44c72473e486: unikaj przechowywania kluczy dostawcy w repozytorium, ustaw ograniczenie liczby tokenów na sesję oraz przechowuj zapisy obok plików testowych, aby późniejsze zmiany modeli pozostały porównywalne.
Dla etapu 0 notatki dotyczącej wzmocnienia bezpieczeństwa należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadania.
Szczegóły wzmocnienia bezpieczeństwa 0/729: zmierz czas wykonywania, klasę błędów oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę, opierając się na ustalonej serii pytań, a nie na indywidualnych obserwacjach.
Gdy przechodzisz przez pierwszy etap notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz warunki kontraktu: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury.
Szczegół wzmocnienia bezpieczeństwa 1/729: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie osobistych obserwacji.
Etap drugi notatki dotyczącej wzmocnienia bezpieczeństwa działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię do analizy. Zapisz jeden idealny przepływ działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres prac. Wolij małe, testowalne jednostki nad rozbudowane skrypty. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji.
Szczegół wzmocnienia 2/729: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.
W trzecim etapie notatki dotyczącej wzmocnienia określ dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Zapisuj czas wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk.
Szczegół wzmocnienia 3/729: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.
Gdy przechodzisz przez etap nr 4 notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno prawidłowy przebieg działania, jak i ścieżkę odzyskiwania. Próby ponownych działań, kontrola przez ludzi oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później.
Szczegół nr 4/729 dotyczący wzmocnienia bezpieczeństwa: zmierz czas wykonywania operacji, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie informacji anegdotycznych.
Etap nr 5 notatki dotyczącej wzmocnienia bezpieczeństwa działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię do analizy. Zapisz jeden idealny przepływ działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres prac. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć przypadki cichego, częściowego ukończenia zadania.
Szczegół wzmocnienia 5/729: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.
W etapie 6 notatki dotyczącej wzmocnienia określ dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić, nie musząc czytać całej struktury.
Szczegół wzmocnienia 6/729: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.
Gdy przechodzisz przez etap nr 7 notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz warunki kontraktu: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji.
Szczegół nr 7/729 dotyczący wzmocnienia bezpieczeństwa: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie informacji anegdotycznych.
Etap nr 8 notatki o wzmocnieniu bezpieczeństwa działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię do analizy. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres prac. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy przechodzi się od środowiska demonstracyjnego do wspólnych środowisk.
Szczegóły wzmocnienia 8/729: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.
W fazie 9 notatki dotyczącej wzmocnienia określ dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Zdokumentuj zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponowne, kontrolne punkty ludzkie oraz obsługa wiadomości błędnych stanowią część produktu, a nie element późniejszej dopracowywania.
Szczegóły wzmocnienia 9/729: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.
Gdy przechodzisz przez etap 10 notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć możliwość cichego, częściowego ukończenia zadania.
Szczegół 10/729 dotyczący wzmocnienia bezpieczeństwa: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie informacji anegdotycznych.
Etap 11 notatki dotyczącej wzmocnienia bezpieczeństwa funkcjonuje najlepiej, gdy jest traktowany jako mierzalna powierzchnia do analizy. Zapisz jeden idealny przykład działania, jeden przypadek niepowodzenia oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres prac. Utrzymuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności przeglądania całej struktury.
Szczegóły wzmocnienia bezpieczeństwa 11/729: zmierz czas przetwarzania ściany, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.