Wskazówki praktyczne: Strategie dzielenia na fragmenty RAG: Kompletny przewodnik inżynierski
Praktyczne wskazówki: Strategie dzielenia na fragmenty RAG: Kompletny przewodnik inżynierski – umowy, sprawdzenia oraz gotowe miejsca na kod dla zespołów wdrażających ten wzorzec.
Poniższe notatki przedstawiają praktyczny plan działania oparty na książce „RAG Chunking Strategies: The Complete Engineering Guide”. Nacisk kładziony jest na umowy, sprawdzenia oraz miejsca zastępcze dla kodu, a nie na motywacyjne aspekty. Podczas przechodzenia przez etap przeglądu, 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.
Główny kompromis: kontekst versus precyzja
Faza kontekstu kluczowych kompromisów handlowych funkcjonuje najlepiej, gdy traktowana jest jako mierzalna powierzchnia. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. Zarejestruj 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. Oddziel zasadę dzielenia na fragmenty od zasady wyszukiwania. Zmiana jednej z nich nie powinna zmuszać do przepisywania drugiej, gdy zmieniają się metryki jakości.
[ TOO SMALL CHUNKS ] [ TOO LARGE CHUNKS ]
Loss of Context / Meaning "Lost in the Middle" Effect
(e.g., "IF request is made...") (Dense with irrelevant fluff)
│ │
└───────────────► 🎯 ◄─────────────────┘
THE GOLDILOCKS ZONE
(High Precision + Context)
Strategia 1: Dzielenie o stałej wielkości i rekurencyjne dzielenie (Bazy referencyjne)
Etap rekurencyjny o stałej wielkości w Strategii 1 działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. 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 przeglądania całej struktury. Oddziel zasadę dzielenia na fragmenty od zasady ich pobierania. Zmiana jednej z nich nie powinna zmuszać do przepisywania drugiej, gdy zmieniają się metryki jakości.
Dzielenie na fragmenty o stałej wielkości (Podejście naiwne)
Metoda dzielenia na kawałki o stałej wielkości – etap „Naive” funkcjonuje najlepiej, gdy traktowany jest jako mierzalna powierzchnia do analizy. Zapisz jeden idealny przekaz, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres pracy. Zdokumentuj zarówno prawidłowy przebieg procesu, jak i ścieżkę naprawczą. Próby ponownych działań, kontrola przez ludzi oraz obsługa wiadomości nieodebranych stanowią część produktu, a nie elementy dodawane później. Oddziel zasady dzielenia na kawałki od zasad wyszukiwania danych. Zmiana jednych nie powinna zmuszać do przepisywania drugich, gdy zmieniają się metryki jakości. Metoda dzielenia na kawałki o stałej wielkości – etap „Naive” funkcjonuje najlepiej, gdy traktowany jest jako mierzalna powierzchnia do analizy. Zapisz jeden idealny przekaz, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres pracy. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań.
Rekurencyjne dzielenie na kawałki znaków (Podstawa w produkcji)
W fazie rekurencyjnego dzielenia na fragmenty znaków należy zdefiniować 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. Należy rejestrować czasy 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. Należy podawać fragmenty tekstu, które faktycznie stanowiły podstawę odpowiedzi. Bez tych odniesień operatorzy nie mogą odróżnić halucynacji od luki w indeksowaniu.
# Example: LangChain Recursive Character Splitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=50,
separators=["\n\n", "\n", ". ", " ", ""]
)
Strategia 2: Dzielenie na fragmenty z uwzględnieniem struktury i semantyki
Dla etapu Strategiczny 2 – Semantyka z uwzględnieniem struktury, należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany 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 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ć bez konieczności czytania całej struktury. Należy podawać konkretne fragmenty tekstu, na których opiera się odpowiedź. Bez tych odniesień operatorzy nie będą w stanie odróżnić halucynacji od luki w indeksowaniu.
Dzielenie na fragmenty z uwzględnieniem struktury (typowe dla dokumentów)
W fazie strukturalnie świadomego dzielenia dokumentu na fragmenty należy zdefiniować dane wejściowe, osobę odpowiedzialną za tę czynność oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić tę czynność 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ń, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. Należy podać fragmenty tekstu, które faktycznie stanowią podstawę odpowiedzi. Bez tych odniesień operatorzy nie będą w stanie odróżnić halucynacji od luki w indeksowaniu. W fazie strukturalnie świadomego dzielenia dokumentu na fragmenty należy zdefiniować dane wejściowe, osobę odpowiedzialną za tę czynność oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić tę czynność na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe rozwiązania.
zakończenie.Semantyczne dzielenie na fragmenty (granice oparte na znaczeniu)
Podczas przechodzenia przez etap semantycznego dzielenia na fragmenty opartych na znaczeniu granic, 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. Zapisz czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z wersji demonstracyjnej do środowisk współdzielonych. Zmierz stopień odzyskiwania informacji na ustalonej serii pytań przed dostosowywaniem promptów. Częste zmiany promptów rzadko poprawiają słabą skuteczność wyszukiwania.
Sentence A ──► Embed ──┐
Sentence B ──► Embed ──┴── Similarity: 0.89 (Keep together)
Sentence C ──► Embed ──── Similarity: 0.32 (Drop below threshold -> CUT HERE)
Strategia 3: Zaawansowane architektury zachowujące kontekst
Gdy przechodzisz przez etap Strategii 3 – Zaawansowane zachowanie kontekstu – 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. 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. Zmierz stopę odzyskiwania informacji na ustalonej serii pytań przed dostosowywaniem promptów. Częste zmiany promptów rzadko naprawiają słabe możliwości wyszukiwania.
1. Dzielenie na małe i duże fragmenty (rodzic-dziecko)
Gdy przechodzisz przez pierwszy etap dzielenia na małe i duże fragmenty typu rodzic-dziecko, 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 zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponowne, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dopinane później. Zmierz stopień przywoływania informacji na podstawie ustalonego zestawu pytań przed dostosowywaniem promptów. Częste zmiany promptów rzadko naprawiają słabe mechanizmy wyszukiwania. Gdy przechodzisz przez pierwszy etap dzielenia na małe i duże fragmenty typu rodzic-dziecko, 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 odrzucaj ciche, częściowe ukończenie zadań.
2. Późne dzielenie na fragmenty
Faza 2 Late Chunking działa najlepiej, gdy traktuje się ją jako mierzalną powłokę. Zapisz jeden idealny przepis transkrypcji, jeden przypadek awarii oraz notatkę o cofnięciu zmian, zanim rozszerzysz zakres pracy. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z wersji demonstracyjnej do środowisk współdzielonych. Rozdziel politykę dzielenia na fragmenty od polityki wyszukiwania. Zmiana jednej z nich nie powinna zmuszać do przepisywania drugiej, gdy zmieniają się metryki jakości.
Matryca decyzji produkcyjnych
Etap macierzy decyzji produkcyjnych działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię. Zapisz jeden idealny przepis realizacji, jeden przypadek niepowodzenia oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. 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. Oddziel zasadę dzielenia na fragmenty od zasady pobierania danych. Zmiana jednej z nich nie powinna zmuszać do przepisywania drugiej w przypadku zmian wskaźników jakości.
Podsumowanie zasad inżynieryjnych prowadzących do sukcesu
Zasady inżynieryjne dotyczące etapów pracy działają najlepiej, gdy traktuje się je jako mierzalną powierzchnię. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian przed rozszerzeniem zakresu. Zdokumentuj zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później. Oddziel zasadę dzielenia na fragmenty od zasady wyodrębniania informacji. Zmiana jednej nie powinna zmuszać do przepisywania drugiej w momencie zmian wskaźników jakości. Zasady inżynieryjne dotyczące etapów pracy działają najlepiej, gdy traktuje się je jako mierzalną powierzchnię. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian przed rozszerzeniem zakresu. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań.
Czas zabrać się do pracy..
Aby proces mógł przejść na kolejny etap, 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. 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. Należy podawać fragmenty tekstu, które faktycznie stanowiły podstawę odpowiedzi. Bez tych odniesień operatorzy nie są w stanie odróżnić halucynacji od luki w indeksowaniu.
Wymagania wstępne
W fazie Wstępnych wymagań należy zdefiniować 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. 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. Należy podawać konkretne fragmenty tekstu, na których opiera się odpowiedź. Bez tych odniesień operatorzy nie będą w stanie odróżnić halucynacji od braku danych w indeksie.
pip install langchain langchain-community langchain-experimental llama-index llama-index-embeddings-openai openai chromadb
export OPENAI_API_KEY="your-openai-api-key"
1. Recurencyjne dzielenie tekstu na fragmenty (LangChain)
W fazie 1 Recursive Character Chunking należy zdefiniować dane wejściowe, osobę odpowiedzialną za tę czynność oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić tę czynność od 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. Należy podać fragmenty tekstu, które faktycznie stanowią podstawę odpowiedzi. Bez tych odniesień operatorzy nie będą w stanie odróżnić halucynacji od luki w indeksowaniu. W fazie 1 Recursive Character Chunking należy zdefiniować dane wejściowe, osobę odpowiedzialną za tę czynność oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić tę czynność od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Należy nadać nazwy poszczególnym elementom, zdefiniować kryteria sukcesu oraz odrzucić ciche, częściowe ukończenie zadania.
from langchain_text_splitters import RecursiveCharacterTextSplitter
# Sample document
sample_text = """
# RAG System Design
Retrieval-Augmented Generation (RAG) decouples knowledge storage from reasoning capability.
Instead of forcing the AI to answer strictly from memory, RAG searches an external database first.
## The Ingestion Pipeline
1. Document Extraction: PDFs and web pages are converted into clean text.
2. Chunking: Documents are chopped into smaller, manageable text blocks.
3. Vectorization: Each block is converted into a numeric representation.
"""
# Initialize Recursive Splitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=200, # Target chunk size in characters/tokens
chunk_overlap=30, # Overlap to prevent mid-sentence context loss
separators=["\n\n", "\n", ". ", " ", ""] # Try double line breaks first
)
chunks = text_splitter.create_documents([sample_text])
print(f"Total chunks created: {len(chunks)}\n")
for i, chunk in enumerate(chunks):
print(f"--- Chunk {i+1} ---")
print(chunk.page_content)
2. Podział na fragmenty rodzic-dziecko / małe na duże (LangChain + Chroma)
Gdy przechodzisz przez etap podziału na fragmenty rodzic-dziecko małe na duże, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co się dzieje w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zapisz czas wykonywania 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. Zmierz stopień odzyskiwania informacji na ustalonej serii pytań przed dostosowywaniem promptów. Częste zmiany promptów rzadko poprawiają słabą efektywność wyszukiwania.
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.retrievers import ParentDocumentRetriever
from langchain_community.vectorstores import Chroma
from langchain_community.storage import InMemoryStore
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document
# 1. Initialize Vector Store (for small child embeddings) and DocStore (for large parent text)
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(collection_name="parent_child_rag", embedding_function=embeddings)
docstore = InMemoryStore()
# 2. Define Parent (Big) and Child (Small) Splitters
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=600, chunk_overlap=50)
child_splitter = RecursiveCharacterTextSplitter(chunk_size=120, chunk_overlap=20)
# 3. Create the ParentDocumentRetriever
retriever = ParentDocumentRetriever(
vectorstore=vectorstore,
docstore=docstore,
child_splitter=child_splitter,
parent_splitter=parent_splitter,
)
# 4. Ingest Documents
docs = [
Document(
page_content="""
System Architecture: The Two Pipelines.
A production RAG framework runs on two main pipelines: Ingestion and Inference.
The Ingestion pipeline extracts text, creates chunks, embeds them, and stores them in a vector DB.
The Inference pipeline encodes user queries, performs vector similarity search, injects context into prompts, and generates LLM answers.
Hybrid search combines keyword and vector retrieval to handle exact SKU IDs alongside general concepts.
"""
)
]
retriever.add_documents(docs)
# 5. Query the Retriever
query = "What happens during inference in RAG?"
retrieved_parents = retriever.invoke(query)
print(f"Retrieved Parent Context (Full Block):\n")
print(retrieved_parents[0].page_content)
3. Podział semantyczny (LlamaIndex)
Gdy przechodzisz przez 3 etapy Semantic Chunking LlamaIndex, 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. 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. Zmierz stopę odzyskiwania informacji na ustalonej grupie pytań przed dostosowywaniem promptów. Częste zmiany promptów rzadko poprawiają słabą skuteczność wyszukiwania.
from llama_index.core.node_parser import SemanticSplitterNodeParser
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core.schema import Document
# 1. Initialize the Embedding Model used for detecting topic shifts
embed_model = OpenAIEmbedding(model="text-embedding-3-small")
# 2. Configure the Semantic Splitter
semantic_parser = SemanticSplitterNodeParser(
buffer_size=1, # Number of surrounding sentences to evaluate together
breakpoint_percentile_threshold=90, # Split threshold percentile (higher = fewer, larger chunks)
embed_model=embed_model
)
# 3. Sample document with distinct thematic shifts
raw_text = """
Quantum computing leverages qubits that can exist in superposition states, unlike classical bits.
Superposition allows algorithms to process vast potential outcomes simultaneously.
Entanglement further connects qubit states instantaneously across physical space.
On a totally different topic, baking sourdough bread requires maintaining a wild yeast starter.
You feed the starter equal parts flour and water every 24 hours to encourage fermentation.
Proper gluten development requires folding the dough during the bulk fermentation stage.
"""
doc = Document(text=raw_text)
# 4. Generate Nodes (Chunks)
nodes = semantic_parser.get_nodes_from_documents([doc])
print(f"Total Semantically Coherent Chunks: {len(nodes)}\n")
for i, node in enumerate(nodes):
print(f"--- Chunk {i+1} ---")
print(node.get_content().strip())
print("\n")
Streszczenie implementacji
Podczas prace nad etapem podsumowania implementacji 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 zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponowne, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dopinane później. Zmierz stopień odzyskiwania informacji na ustalonej grupie pytań przed dostosowywaniem promptów. Częste zmiany promptów rzadko naprawiają słabe możliwości wyszukiwania. Podczas prace nad etapem podsumowania implementacji 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. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadań.
Wniosek: Dzielenie na fragmenty to problem inżynieryjny, a nie problem sztucznej inteligencji
Metoda dzielenia na fragmenty jest najskuteczniejsza, gdy traktuje się ją jako mierzalną powierzchnię do analizy. Zapisz jeden idealny przepis realizacji, jeden przypadek niepowodzenia oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres pracy. Zarejestruj czas trwania operacji oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy przechodzi się z środowiska demonstracyjnego do współdzielonych środowisk. Oddziel zasady dzielenia na fragmenty od zasad wyszukiwania informacji – zmiana jednych nie powinna zmuszać do przepisywania drugich, gdy zmieniają się metryki jakości.
Lista kontrolna operacyjna
W fazie listy kontrolnej operacyjnej zdefiniuj dane wejściowe, osobę odpowiedzialną za daną czynność oraz kryteria zakończenia pracy przed dokonaniem zmian w kodzie. Operatorzy powinni móc ponownie wykonać daną czynność na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu systemu.