Podręcznik uczestnika z objaśnieniami, przykładami i ćwiczeniami do samodzielnej nauki do Modułu 6
6. R5. Od objawu do potwierdzonej przyczyny
6.1. Jedna zmiana, porównanie i regresja
ENHANCER+ · Moduł 6 · Ewaluacja RAG · Podrozdział
Eksperyment powinien mieć hipotezę, bazę, wariant, ten sam zestaw przypadków i regułę decyzji. Hipotezę zapisz przed uruchomieniem. Jeśli jednocześnie zmienisz top_k, prompt i model, wynik pokaże zachowanie całego nowego systemu, ale nie wskaże wpływu pojedynczej zmiany.
Zbuduj kontrolę konfiguracji
R5 · Do pliku kod/moj_m6.py · zastąp całą definicję
def compare_configs(baseline, candidate):
changes = {k: [baseline.get(k), candidate.get(k)]
for k in set(baseline) | set(candidate)
if k != 'config_id' and baseline.get(k) != candidate.get(k)}
if len(changes) != 1:
raise ValueError('Eksperyment wymaga dokładnie jednej zmiany.')
return changes
config_id jest etykietą wariantu, więc samo nadanie nowej nazwy nie liczy się jako zmiana badanego czynnika. Pozostałe różnice pozostają istotne. Informacje organizacyjne, np. autor i data eksperymentu, zapisuj w karcie eksperymentu, a nie w porównywanych parametrach wykonywania.
Przykład top_k 3 wobec 5
Hipoteza brzmi: przy tej samej reprezentacji pytania i indeksie szerszy zestaw udostępni wymaganą grupę dla T004. W wariancie nie zmieniasz progu, promptu, modelu ani kontraktów. Zachowujesz oba przebiegi z osobnymi identyfikatorami.
Notebook warsztatu · przykład wywołania
baseline = ref.read_json(E / 'baseline_config.json')
candidate = dict(baseline, config_id='topk5', top_k=5)
changes = w.compare_configs(baseline, candidate)
ref.save_json(E / 'candidate_config.json', candidate)
ids = ref.read_json(ROOT / 'dane/przypadki/checkpoint_subset.json')
before = w.run_retrieval(cases, baseline, E, test_ids=ids)
after = w.run_retrieval(cases, candidate, E, test_ids=ids)
comparison = w.compare_retrieval(before, after)
ref.save_json(E / 'retrieval_comparison.json', comparison)
print([x for x in comparison if x['change'] != 'unchanged'])
Zmiana top_k w tym wyszukiwaniu poszerza zwracaną część uporządkowanej listy. Nie jest nowym sposobem liczenia podobieństwa. Jeżeli na granicy występują remisy albo implementacja wyszukiwania jest niedeterministyczna, zapisz także sposób ich rozstrzygania. W pakietowym indeksie pełne wyniki pozwalają skontrolować kolejność bez domysłów.
Sparuj wyniki przez kontrakt
Nie porównuj pierwszego wiersza jednego pliku z pierwszym wierszem drugiego. Użyj test_id, turn_id i contract_hash. Funkcja poniżej odrzuca różny zakres lub duplikaty. Dla każdej pary potwierdza jedną zmianę konfiguracji i liczy zmianę pokrycia końcowego kontekstu.
R5 · Do pliku kod/moj_m6.py · zastąp całą definicję
def compare_retrieval(before, after):
key = lambda r: (r['test_id'], r['turn_id'], r['contract_hash'])
left = {key(r): r for r in before}
right = {key(r): r for r in after}
if set(left) != set(right) or len(left) != len(before) or len(right) != len(after):
raise ValueError('Różne kontrakty lub duplikaty porównywanych tur.')
comparison = []
for k in left:
a, b = left[k], right[k]
compare_configs(a['config'], b['config'])
comparable = a['status'] == b['status'] == 'completed'
ma = a['metrics']['context']['group_coverage'] if comparable else None
mb = b['metrics']['context']['group_coverage'] if comparable else None
delta = mb - ma if ma is not None and mb is not None else None
comparison.append({
'test_id': k[0], 'turn_id': k[1],
'before_result_id': a['result_id'], 'after_result_id': b['result_id'],
'comparable': comparable, 'before_coverage': ma, 'after_coverage': mb,
'coverage_delta': delta,
'change': 'ND' if delta is None else
('improved' if delta > 0 else 'regressed' if delta < 0 else 'unchanged'),
})
return comparison
change=improved w tym pliku oznacza tylko poprawę pokrycia grup. Nie oznacza automatycznie lepszej odpowiedzi, niższego szumu ani krótszego czasu. Wiersz ND może wynikać z braku oczekiwanych grup lub z niewykonanej poprawnie próby. Pole comparable pozwala rozróżnić te sytuacje.
W dostarczonym porównaniu T004 przechodzi z pokrycia 0 do 1. Inne przypadki z oczekiwanymi źródłami w podzbiorze zachowują pełne pokrycie. T006 i T106 mają pokrycie N/D. Nie oznacza to, że cały wariant jest bezwarunkowo lepszy: oceń wszystkie dodatkowo przekazane fragmenty i powtórz odpowiedzi, jeśli chcesz wypowiedzieć się o jakości asystenta.
Próba z nowym promptem
Pakiet udostępnia rag_conditions_v1. Wariant dopowiada zachowanie warunków i kolejności oraz rozdzielenie zwykłej procedury od postępowania po niepowodzeniu. Nie wkleja do promptu wzorcowej odpowiedzi z kontraktu. Przekazywanie poprawnej odpowiedzi modelowi podczas testu zafałszowałoby ocenę.
Notebook warsztatu · przykład wywołania
RUN_PROMPT_EXPERIMENT = False # wymaga świadomego wyboru Ollama
if RUN_PROMPT_EXPERIMENT:
assert MODE == 'ollama', 'Nowy prompt wymaga nowych odpowiedzi.'
candidate_prompt = dict(config, config_id='conditions',
prompt_version='rag_conditions_v1')
w.compare_configs(config, candidate_prompt)
selected = ['M6-T101', 'M6-T003', 'M6-T006']
answers_before = w.run_assistant(cases, config, E, test_ids=selected)
answers_after = w.run_assistant(cases, candidate_prompt, E, test_ids=selected)
# Oceń oba zbiory ręcznie; sprawdź narzędzie i kontekst każdej pary.
Ten kod wymaga jawnego trybu Ollama. Używa tych samych kontraktów i pozostałych parametrów. Ponieważ pełna tura obejmuje selektor, sprawdź, czy oba wykonania użyły tej samej ścieżki oraz kontekstu. Jeżeli selektor wybrał inne narzędzie, para nie izoluje już samego promptu odpowiedzi. Zapisz to jako osobną obserwację. W badaniu izolowanej generacji można zamrozić ranking i użyć answer_from_results, ale należy jawnie nazwać taki zakres.
Regresja i decyzja
Regresja oznacza pogorszenie wcześniej spełnianego wymagania. Prowadź listy przypadków poprawionych, pogorszonych, bez zmian i nieocenionych. Sprawdź błędy krytyczne, a dopiero potem korzyści w średnich. Zestaw regresyjny powinien obejmować ważne ścieżki, także brak danych, odmowę, doprecyzowanie i rozmowę.
Zapisz w experiment_log.jsonl hipotezę, zmianę, identyfikatory przebiegów, plik porównania, skutki uboczne i decyzję. Wybraną konfigurację skopiuj do final_config.json. Gdy dowody nie wystarczają, zachowaj bazę i opisz decyzję jako tymczasową albo nierozstrzygniętą. Nie wybieraj wariantu tylko dlatego, że jedna odpowiedź brzmi lepiej.
Lokalne chatboty, agenci i systemy RAG z własną bazą wiedzy · Moduł 6 · Wydanie 29.09.2026