Podręcznik uczestnika z objaśnieniami, przykładami i ćwiczeniami do samodzielnej nauki do Modułu 5
3. Pętla rozmowy nad RAG
Jedno wywołanie ask_rag() z M4 nie jest jeszcze interfejsem rozmowy. Użytkownik potrzebuje kolejnego pytania, zakończenia pracy i czytelnego wyniku. W R2 pytania pozostają niezależne; historii jeszcze nie interpretujemy.
1. Sprawdź wejście przed wywołaniem modelu
Walidator zwraca oczyszczony tekst albo zgłasza określony błąd. Najpierw sprawdza typ, ponieważ liczba nie ma metody strip(). Potem usuwa spacje na brzegach, wykrywa puste wejście i sprawdza długość. Limit dotyczy znaków, nie tokenów modelu.
Do pliku kod/moj_m5.py: validate_chat_message()
def validate_chat_message(message: object, max_chars=MAX_MESSAGE_CHARS) -> str:
if not isinstance(message, str):
raise TypeError('invalid_message')
clean = message.strip()
if not clean:
raise ValueError('empty_message')
if len(clean) > max_chars:
raise ValueError('message_too_long')
return clean
Test walidacji: bez LLM
assert m.validate_chat_message(" Stan DocAssist? ") == "Stan DocAssist?"
for value in [" ", "x" * 1001, 42]:
try:
m.validate_chat_message(value)
except (TypeError, ValueError) as error:
print(type(error).__name__, str(error))
Oczekiwane kody to empty_message, message_too_long i invalid_message. Interfejs przechwytuje znane błędy wejścia i pozwala spróbować ponownie. Nie każdy wyjątek oznacza awarię całej sesji.
2. Zachowaj znaczenie wyniku RAG
Gotowe answer_from_documents() wywołuje m4_tools.ask_rag(). Przenosi status, reason, odpowiedź, źródła, diagnostykę, parametry i ID indeksu. Nie traktuje liczby źródeł jako oceny prawdziwości. Funkcja wyświetlająca pokazuje tekst oraz informacje potrzebne do analizy.
Do pliku kod/moj_m5.py: print_chat_result()
def print_chat_result(result, debug=False):
print('DocAssist:', result.get('answer') or NO_DATA_MESSAGE)
print('Status:', result.get('status', result.get('event')))
if result.get('warnings'):
print('Ostrzeżenia:', ', '.join(result['warnings']))
if 'sources' in result:
print('ŹRÓDŁA PRZEKAZANE MODELOWI\n' + format_sources(result.get('sources') or []))
if debug:
print(json.dumps(result.get('diagnostics', {}), ensure_ascii=False, indent=2))
Etykieta „ŹRÓDŁA PRZEKAZANE MODELOWI” jest celowa. Lista sources opisuje kontekst dopuszczony do generowania. Nie dowodzi, że wszystkie twierdzenia są potwierdzone ani że model wykorzystał każdy fragment. W ćwiczeniu zachowujemy widoczny status i ostrzeżenia.
3. Zbuduj pętlę
Do pliku kod/moj_m5.py: run_chat()
def run_chat(*, debug=False, similarity_threshold=DEFAULT_SIMILARITY_THRESHOLD, input_fn=input):
"""R2: niezależne wywołania RAG, bez interpretacji historii."""
while True:
raw = input_fn('Ty: ')
try:
message = validate_chat_message(raw)
except (TypeError, ValueError) as e:
print('DocAssist:', e)
continue
if message.casefold() in EXIT_COMMANDS:
break
try:
print_chat_result(answer_from_documents(message, similarity_threshold=similarity_threshold), debug=debug)
except Exception:
logger.exception('Nieobsłużony błąd tury')
print('Nie udało się obsłużyć pytania.')
Kolejność to odczyt, walidacja, rozpoznanie zakończenia, RAG i prezentacja. continue przechodzi do następnej wiadomości po błędzie; break kończy pętlę. Parametr input_fn domyślnie wskazuje input, lecz w teście może czytać z listy. Dzięki temu sprawdzisz interfejs bez ręcznego wpisywania danych.
Test pętli: komunikat o pustym wejściu, potem wyjście
wiadomosci = iter([" ", "/exit"]) m.run_chat(input_fn=lambda prompt: next(wiadomosci))
Żadne pytanie nie dochodzi tu do RAG, więc nie potrzeba modelu. Do swobodnej rozmowy skonfiguruj moduł w trybie Ollama, a potem wywołaj m.run_chat(). Checkpoint obejmuje tylko zapisane żądania. Nie przełączaj trybu automatycznie po błędzie.
4. Ten sam TLS, dwie różne ścieżki
Pytanie brzmi: „Jak skonfigurować certyfikat TLS dla usługi docassist-api?”. W pilotażu top_k=3 i próg None dopuszczają kontekst, lecz bez procedury TLS. Model zwraca „Brak informacji w dostarczonym kontekście.”. Przy progu 1.0 wszystkie wyniki są odrzucone przed generacją.
| Warunki | Wynik RAG | Interpretacja |
|---|---|---|
| Próg None | answered, tekstowa odmowa, sources niepuste. | Powstał tekst, ale nie procedura TLS. |
| Próg 1.0 | insufficient_context / below_threshold, sources puste. | Brak kontekstu po filtrze; bez wywołania LLM odpowiedzi. |
Ćwiczenie 2. Rozdziel odmowę od filtrowania
- Uzupełnij trzy funkcje R2 i uruchom test etapu.
- W notebooku R2 wykonaj cztery próby RAG oraz trzy próby wejścia. Porównaj status, reason, similarity_threshold i sources dla TLS.
- Zapisz obserwację, konkretne pole jako dowód oraz wniosek.
- Wyjaśnij skutek umieszczenia kontroli /exit po wywołaniu RAG.
ENHANCER+ · Politechnika Warszawska · podręcznik do samodzielnej pracy · M5