Strategie logowania i dokumentowania
Zapisywanie wersji promptów, danych wejściowych i wyników w celu umożliwienia powtarzalnego debugowania.
Strategie logowania i dokumentowania to bezpłatna lekcja AI Prompt Engineering na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Prompt Engineering, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Prompt Engineering zawiera 4 lekcji w sumie.
Dlaczego rejestrowanie promptów ma znaczenie
Bez rejestrowania błędy promptów pozostają niewidoczne, dopóki nie zgłosi ich użytkownik. Rejestrowanie pozwala:
- Wykrywać regresje natychmiast po ich wystąpieniu
- Dokładnie odtwarzać każdy wcześniejszy błąd
- Mierzyć poprawę w czasie wraz z rozwojem promptów
- Kontrolować zachowanie modelu pod kątem zgodności z wymaganiami lub bezpieczeństwa
Rejestrowanie nie jest opcjonalne w produkcyjnych systemach promptów — stanowi podstawę niezawodnych aplikacji LLM.
Minimalny wpis dziennika
Każda interakcja z promptem powinna rejestrować co najmniej następujące pola:
timestamp: UTC w formacie ISO 8601prompt_id: użyty szablon promptumodel: dokładna nazwa i wersja modelutemperature: parametr próbkowaniainput: wiadomość użytkownika (lub hash, jeśli zawiera PII)output: odpowiedź modelulatency_ms: czas odpowiedzitokens_used: tokeny wejściowe + wyjściowe
import time, json
from datetime import datetime, timezone
def logged_call(prompt_id, system_prompt, user_message, model='gpt-4o', temperature=0.7):
start = time.time()
resp = client.chat.completions.create(
model=model,
messages=[
{'role': 'system', 'content': system_prompt},
{'role': 'user', 'content': user_message}
],
temperature=temperature
)
latency = int((time.time() - start) * 1000)
output = resp.choices[0].message.content
log_entry = {
'timestamp': datetime.now(timezone.utc).isoformat(),
'prompt_id': prompt_id,
'model': model,
'temperature': temperature,
'input': user_message,
'output': output,
'latency_ms': latency,
'input_tokens': resp.usage.prompt_tokens,
'output_tokens': resp.usage.completion_tokens
}
append_log(log_entry)
return outputFormat strukturalnego rejestrowania
W plikach dzienników należy używać JSON rozdzielanego znakami nowej linii (JSONL). Każdy wiersz jest kompletnym, prawidłowym obiektem JSON. Ten format jest:
- Łatwy do dopisywania bez blokowania
- Czytelny dla jq, pandas i wszystkich agregatorów logów
- Przystosowany do przetwarzania strumieniowego — każdy wiersz można przetworzyć w momencie jego nadejścia
import json
LOG_FILE = 'prompt_logs.jsonl'
def append_log(entry):
with open(LOG_FILE, 'a') as f:
f.write(json.dumps(entry) + '\n')
def read_logs():
with open(LOG_FILE) as f:
return [json.loads(line) for line in f if line.strip()]
# Query: all entries for prompt_id 'summarize_v3'
logs = read_logs()
summarize_logs = [e for e in logs if e['prompt_id'] == 'summarize_v3']
print(f'Total calls to summarize_v3: {len(summarize_logs)}')Wersjonowanie promptów
Prompty zmieniają się w czasie. Bez wersjonowania nie można odtworzyć wcześniejszego zachowania ani porównywać wyników modelu dla różnych wersji promptu. W każdym wpisie dziennika należy używać identyfikatora wersji.
Proste wersjonowanie: ciąg wersji semantycznej (np. v1.2.3) albo hash commita git. Wersje promptów należy przechowywać w osobnym pliku, aby każdą wersję można było pobrać i odtworzyć jej działanie.
PROMPTS = {
'summarize': {
'v1': 'Summarize the following text.',
'v2': 'Summarize the following text in 3 sentences.',
'v3': 'Summarize the following text in exactly 3 sentences. '
'Start each sentence on a new line. No bullet points.'
}
}
CURRENT_VERSIONS = {'summarize': 'v3'}
def get_prompt(prompt_id):
version = CURRENT_VERSIONS[prompt_id]
return version, PROMPTS[prompt_id][version]
version, prompt = get_prompt('summarize')
log_entry['prompt_version'] = versionObsługa PII w dziennikach
Dane wejściowe użytkownika mogą zawierać dane osobowe umożliwiające identyfikację (PII). Rejestrowanie surowych danych wejściowych może naruszać przepisy RODO lub CCPA. Dostępne opcje:
- Hash: przechowywać SHA-256 danych wejściowych — można go powtarzalnie wykorzystywać do deduplikacji, ale nie do odtwarzania
- Redakcja: użyć wyrażenia regularnego lub modelu NER do zastąpienia PII przed zarejestrowaniem
- Oddzielny magazyn: rejestrować PII w zaszyfrowanym magazynie z kontrolą dostępu, a w głównym dzienniku zapisywać tylko identyfikator referencyjny
import hashlib, re
def redact_pii(text):
# Redact email addresses
text = re.sub(r'[\w.-]+@[\w.-]+\.\w+', '[EMAIL]', text)
# Redact phone numbers (US format)
text = re.sub(r'\b\d{3}[-.]\d{3}[-.]\d{4}\b', '[PHONE]', text)
return text
def hash_input(text):
return hashlib.sha256(text.encode()).hexdigest()[:16]
log_entry['input'] = redact_pii(user_message)
log_entry['input_hash'] = hash_input(user_message)Śledzenie opóźnień i kosztów
Dzienniki umożliwiają tworzenie pulpitów do monitorowania kosztów i opóźnień. Należy śledzić metryki dla poszczególnych wersji promptu, aby wykrywać regresje wydajności lub kosztów po zmianie promptu:
def compute_cost(entry, price_per_1m_input=5.0, price_per_1m_output=15.0):
input_cost = entry['input_tokens'] / 1_000_000 * price_per_1m_input
output_cost = entry['output_tokens'] / 1_000_000 * price_per_1m_output
return input_cost + output_cost
def prompt_stats(prompt_id, version):
logs = [e for e in read_logs()
if e['prompt_id'] == prompt_id and e.get('prompt_version') == version]
if not logs:
return
avg_latency = sum(e['latency_ms'] for e in logs) / len(logs)
total_cost = sum(compute_cost(e) for e in logs)
print(f'{prompt_id} {version}: {len(logs)} calls, avg {avg_latency:.0f}ms, total ${total_cost:.4f}')Rejestrowanie oceny wyników
Oprócz surowych dzienników należy przechowywać oceny wyników obok każdego wpisu dziennika. Umożliwia to analizę trendów: czy jakość wyników poprawia się w kolejnych wersjach promptu?
def evaluated_call(prompt_id, system_prompt, user_message, evaluator_fn):
output = logged_call(prompt_id, system_prompt, user_message)
score = evaluator_fn(user_message, output)
# Update the last log entry with the evaluation score
logs = read_logs()
last = logs[-1]
last['eval_score'] = score
last['eval_pass'] = score >= 0.8
# Rewrite the last line
with open(LOG_FILE, 'a') as f:
# In practice, use a DB or separate eval log
pass
return output, scoreDokumentacja promptu
Każdy szablon promptu powinien mieć powiązany wpis dokumentacji obejmujący:
- Cel: jakie zadanie wykonuje ten prompt
- Zmienne: jakie symbole zastępcze występują i jakich wartości oczekują
- Znane ograniczenia: dane wejściowe, dla których wiadomo, że prompt zawodzi
- Historia wersji: co zmieniło się w każdej wersji i dlaczego
- Przypadki testowe: odnośnik do zestawu testów dla tego promptu
PROMPT_DOCS = {
'summarize': {
'purpose': 'Summarize a single text passage into 3 sentences.',
'variables': {'text': 'The passage to summarize (max 2000 tokens)'},
'known_limitations': [
'Fails to preserve numbers accurately for texts with many statistics',
'May not summarize correctly for non-English text'
],
'versions': {
'v1': 'Initial version — vague length instruction',
'v2': 'Added 3-sentence limit',
'v3': 'Added line-break and no-bullet formatting fix'
},
'test_suite': 'tests/test_summarize.py'
}
}Korzystanie ze scentralizowanych usług rejestrowania
W systemach produkcyjnych należy zapisywać dzienniki w scentralizowanej usłudze zamiast w plikach lokalnych:
- LangSmith: natywna dla LangChain platforma śledzenia i oceny
- Weights and Biases Prompts: śledzenie eksperymentów dotyczących promptów
- Datadog / Grafana: standardowe pulpity operacyjne z niestandardowymi metrykami
- Supabase / PostgreSQL: przeszukiwanie dzienników za pomocą SQL na potrzeby doraźnej analizy
Schemat pozostaje taki sam; zmienia się tylko miejsce docelowe.
# Example: writing to Supabase
from supabase import create_client
supabase = create_client('https://xxx.supabase.co', 'your-anon-key')
def log_to_supabase(entry):
supabase.table('prompt_logs').insert(entry).execute()
# Now query with SQL:
# SELECT prompt_id, prompt_version, AVG(latency_ms), COUNT(*)
# FROM prompt_logs
# WHERE timestamp > NOW() - INTERVAL '7 days'
# GROUP BY prompt_id, prompt_version
# ORDER BY COUNT(*) DESC;Alerty przy nagłych wzrostach liczby błędów
Należy skonfigurować alerty uruchamiane, gdy odsetek nieudanych wywołań przekroczy określony próg. Przykład: jeśli w ciągu 5 minut ponad 10% wywołań promptu zwróci nieprawidłowy kod JSON, należy wysłać alert.
from collections import deque
from datetime import datetime, timezone, timedelta
recent_results = deque(maxlen=100) # sliding window
def track_and_alert(prompt_id, success, alert_fn, threshold=0.10):
recent_results.append({'success': success, 'time': datetime.now(timezone.utc)})
window = [
r for r in recent_results
if r['time'] > datetime.now(timezone.utc) - timedelta(minutes=5)
]
if not window:
return
fail_rate = sum(1 for r in window if not r['success']) / len(window)
if fail_rate > threshold:
alert_fn(f'ALERT: {prompt_id} failure rate {fail_rate:.0%} in last 5 min')Przechowywanie i archiwizacja
Należy zdefiniować zasady przechowywania logów:
- Surowe logi wywołań: 30 dni (krocząco) — duża objętość danych, potrzebne do debugowania niedawnych problemów
- Metryki zagregowane: 1 rok — potrzebne do analizy trendów i prognozowania kosztów
- Logi błędów: bezterminowo — potrzebne do analizowania wzorców przyczyn źródłowych
Po 30 dniach należy kompresować i archiwizować surowe logi. Nie wolno usuwać logów błędów — są one pamięcią instytucjonalną inżynierii promptów.
Sprawdzenie wiedzy
Jaka jest główna zaleta stosowania formatu JSON rozdzielanego znakami nowego wiersza (JSONL) w logach promptów w porównaniu z pojedynczą dużą tablicą JSON?
Podsumowanie: logowanie i dokumentacja
Najważniejsze praktyki dotyczące logowania i dokumentowania promptów:
- Logowanie każdego wywołania: timestamp, prompt_id, version, model, temperature, input, output, latency, tokens
- Stosowanie formatu JSONL: ułatwia dopisywanie danych i wykonywanie zapytań za pomocą standardowych narzędzi
- Wersjonowanie promptów: każda zmiana otrzymuje nową wersję; logi odwołują się do tej wersji
- Obsługa danych PII: przed zapisaniem należy usuwać lub haszować poufne dane wejściowe
- Śledzenie kosztu i opóźnienia: umożliwia wykrywanie regresji po aktualizacjach promptów
- Alerty przy nagłych wzrostach liczby błędów: monitorowanie odsetka błędów w ruchomym oknie
To kończy Kurs 17 dotyczący debugowania błędów promptów. Następny temat: prompt injection i obrona przed nim.
Często zadawane pytania
Czy lekcja „Strategie logowania i dokumentowania” jest bezpłatna?
Tak — pełny tekst „Strategie logowania i dokumentowania” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Prompt Engineering, przejdź na CoddyKit PRO. Kurs AI Prompt Engineering zawiera 4 lekcji w sumie.
Co nauczysz się w „Strategie logowania i dokumentowania”?
Zapisywanie wersji promptów, danych wejściowych i wyników w celu umożliwienia powtarzalnego debugowania. Ćwiczysz AI Prompt Engineering z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć AI Prompt Engineering?
Nie wymagamy żadnego doświadczenia. AI Prompt Engineering w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Strategie logowania i dokumentowania”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji AI Prompt Engineering?
Tak. Każda lekcja AI Prompt Engineering zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Diagnozowanie nieoczekiwanych wyników
- Analiza przyczyn źródłowych promptów
- Systematyczne podejście do debugowania
- Strategie logowania i dokumentowania