Dynamiczny dobór few-shot
Pobieranie przykładów dla poszczególnych zapytań
Dynamiczny dobór few-shot 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.
Od statycznych do dynamicznych przykładów
W podejściu few-shot statycznym te same przykłady są używane dla każdego zapytania. Dynamiczne few-shot pobiera dla każdego zapytania najbardziej trafne demonstracje z puli, dostosowując model do przykładów przypominających bieżące wejście.
Jest to uczenie kontekstowe wspomagane wyszukiwaniem: zwiększa trafność demonstracji, co jest jednym z najsilniejszych czynników wpływających na jakość ICL, szczególnie przy niejednorodnym ruchu.
class DynamicSelector:
def __init__(self, pool, embedder, index):
self.pool = pool # candidate demonstrations
self.embed = embedder
self.index = index # ANN index over pool embeddings
def select(self, query, k):
q = self.embed(query)
ids = self.index.search(q, k)
return [self.pool[i] for i in ids]Tworzenie embeddingów puli przykładów
Należy wcześniej wygenerować embeddingi dla każdej kandydującej demonstracji i przechowywać je w indeksie przybliżonych najbliższych sąsiadów (FAISS, HNSW lub wektorowa baza danych). W czasie obsługi zapytania należy wygenerować embedding wejścia tylko raz i pobrać najlepiej pasujące elementy.
Należy wybrać model embeddingów dopasowany do semantyki zadania; ogólny model może grupować dane według cech powierzchniowych zamiast według wymiaru przewidującego poprawną etykietę.
import numpy as np
def build_index(pool, embed):
vecs = np.stack([embed(d.input) for d in pool]).astype('float32')
vecs /= np.linalg.norm(vecs, axis=1, keepdims=True) # cosine via dot
index = HNSW(dim=vecs.shape[1])
index.add(vecs)
return indexPromptowanie kNN
Kanoniczna metoda (Liu et al., 2022) pobiera z etykietowanej puli k najbliższych sąsiadów zapytania i wykorzystuje ich jako demonstracje. Wybór oparty na wyszukiwaniu konsekwentnie przewyższa wybór losowy, ponieważ trafne demonstracje lepiej pomagają rozpoznać zadanie i dostarczają właściwej przestrzeni etykiet.
Pobrane etykiety pełnią również funkcję miękkiego apriorycznego klasyfikatora kNN, kierując model w stronę odpowiedzi sąsiadów.
def knn_prompt(query, selector, k, build):
demos = selector.select(query, k)
demos = order_by_similarity(embed(query), demos) # most similar last
return build(demos, query)Wyszukiwanie uwzględniające różnorodność
Wybór wyłącznie najlepszych k elementów może zwracać niemal duplikaty, marnując miejsce w kontekście. Należy zastosować MMR lub grupowanie pobranych kandydatów, aby zachować trafność, a jednocześnie zadbać o to, by wybrane demonstracje obejmowały różne aspekty zapytania.
Ma to największe znaczenie w przypadku wejść kompozycyjnych, w których każdy z różnych podaspektów wymaga reprezentatywnej demonstracji.
def diverse_retrieve(query, selector, k, pool_n=30, lam=0.7):
cand = selector.select(query, pool_n)
q = embed(query)
return mmr_against_query(cand, q, k, lam) # relevance + diversityOpóźnienia i budżet wyszukiwania
Dynamiczny wybór dodaje do każdego żądania wywołanie generowania embeddingu oraz wyszukiwanie w indeksie ANN. Należy uwzględnić to w budżecie: buforować embeddingi zapytań dla powtarzających się danych wejściowych, grupować wyszukiwanie i przechowywać indeks w pamięci.
W systemach o wysokiej wartości QPS etap wyszukiwania musi trwać poniżej milisekundy; w przeciwnym razie zysk wynikający z trafności zostanie zniwelowany przez dodatkowe opóźnienie końcowe.
from functools import lru_cache
@lru_cache(maxsize=50_000)
def cached_embed(text):
return embed(text)
# Plus: warm in-RAM HNSW, batched search, async prefetchNapięcie między buforowaniem a dynamicznymi przykładami
Dynamiczne przykłady uniemożliwiają buforowanie prefiksu promptu, ponieważ blok przykładów zmienia się dla każdego zapytania. Można temu zaradzić, zachowując stabilny buforowany preambuł (instrukcje oraz kilka uniwersalnych przykładów demonstracyjnych) i dołączając za nim wyłącznie pobrane przykłady zależne od zapytania.
Pozwala to odzyskać większość oszczędności wynikających z buforowania, zachowując jednocześnie trafność końcowej części dla każdego zapytania.
prompt = (
STATIC_PREAMBLE # cached: instructions + anchor demos
+ render(diverse_retrieve(query, selector, k)) # dynamic tail
+ format_query(query)
)Unikanie wycieku między zbiorem treningowym a testowym
Jeśli samo zapytanie znajduje się w puli (co często ma miejsce podczas ewaluacji), wyszukiwanie może zwrócić dokładną odpowiedź, zawyżając metryki. Podczas ewaluacji należy zawsze wykluczać zapytanie oraz niemal identycznych sąsiadów, których podobieństwo przekracza ustalony próg.
Na produkcji należy usuwać duplikaty z puli i zapobiegać zwracaniu użytkownikowi jego własnego wcześniejszego wejścia jako demonstracji.
def leak_safe_select(query, selector, k, sim_cap=0.97):
cand = selector.select(query, k + 5)
q = embed(query)
cand = [d for d in cand if cos(q, d.emb) < sim_cap]
return cand[:k]Zimny start i rozrost puli
Na początku pula jest mała, dlatego wyszukiwanie może zwracać słabo dopasowane elementy. Należy rozpocząć od wyselekcjonowanego statycznego zbioru, a następnie powiększać pulę na podstawie zweryfikowanych śladów z produkcji, zgodnie z harmonogramem ponownie generując embeddingi i tworząc indeks.
Należy śledzić wykorzystanie każdego przykładu i wynik, aby móc usuwać przykłady o małej wartości lub nieaktualne oraz utrzymywać zwięzły indeks.
def maybe_add_to_pool(trace, verified):
if verified and novelty(trace, index) > THRESH:
emb = embed(trace.input)
index.add(emb)
pool.append(Demo(trace.input, trace.output, trace.meta))Wybór nie tylko na podstawie podobieństwa
Trafność oparta na najbliższych sąsiadach jest dobrym ustawieniem domyślnym, ale nie zawsze jest optymalna. Zaawansowane selektory uwzględniają wartość informacyjną (czy demonstracja rozstrzyga niejednoznaczność zapytania?), różnorodność oraz pokrycie etykiet. Niektóre metody uczą strategii wyboru, która maksymalizuje dokładność wynikową, a nie surowe podobieństwo.
Wybór należy traktować jako dobieranie zbioru demonstracji, który najbardziej zmniejsza niepewność modelu dla danego zapytania.
def select_by_uncertainty_reduction(query, pool, k):
base = entropy(model_probs(build([], query)))
gains = []
for d in pool:
h = entropy(model_probs(build([d], query)))
gains.append((d, base - h)) # info gain per demo
return [d for d, _ in sorted(gains, key=lambda x: -x[1])[:k]]Ocena dynamicznego potoku
Należy porównać podejście dynamiczne ze statycznymi i losowymi ustawieniami bazowymi na odłożonych danych z kontrolą wycieku. Należy raportować dokładność, rozkład podobieństw wyszukanych elementów, opóźnienie kompleksowe oraz współczynnik trafień pamięci podręcznej.
System dynamiczny, który wygrywa pod względem dokładności, ale znacznie pogarsza ponowne wykorzystanie pamięci podręcznej, może mieć ujemny bilans kosztów; należy oceniać pełny cel, a nie tylko jakość.
def eval_pipeline(eval_set):
return {
'acc_dynamic': run(dynamic, eval_set),
'acc_static': run(static, eval_set),
'acc_random': run(random_sel, eval_set),
'p95_latency': latency_p95(),
'cache_hit': cache_hit_rate(),
}Architektura referencyjna
Od początku do końca: zweryfikowana pula demonstracji, model embeddingów, przechowywany w pamięci indeks ANN, selektor stosujący zabezpieczenia przed wyciekiem, różnorodność i porządkowanie według podobieństwa, stabilny buforowany preambuł oraz pętla sprzężenia zwrotnego, która powiększa i oczyszcza pulę.
Ta architektura przekształca promptowanie few-shot w system wyszukiwania wymagający związanego z nim rygoru operacyjnego.
def answer(query):
demos = leak_safe_select(query, selector, k=4)
demos = mmr_against_query(demos, embed(query), 4)
demos = order_by_similarity(embed(query), demos)
prompt = STATIC_PREAMBLE + render(demos) + format_query(query)
out = llm(prompt)
log_for_pool_growth(query, out)
return outSzybkie sprawdzenie
Proszę zdiagnozować myląco dobry wynik ewaluacji.
Podsumowanie
Najważniejsze wnioski:
- Dynamiczne few-shot pobiera demonstracje dla każdego zapytania, przewyższając podejście losowe i statyczne dzięki zwiększeniu trafności.
- Należy osadzić pulę w indeksie ANN; promptowanie kNN jest silnym ustawieniem domyślnym, a elementy należy porządkować według rosnącego podobieństwa.
- Należy dodać różnorodność (MMR) i rozważyć selektory uwzględniające wartość informacyjną lub redukcję niepewności.
- Należy chronić się przed wyciekiem podczas wyszukiwania, zarządzać opóźnieniami oraz zachować buforowany statyczny preambuł z dynamiczną końcową częścią.
- Należy powiększać i oczyszczać pulę na podstawie zweryfikowanych śladów oraz wspólnie oceniać dokładność, opóźnienie i współczynnik trafień pamięci podręcznej.
Często zadawane pytania
Czy lekcja „Dynamiczny dobór few-shot” jest bezpłatna?
Tak — pełny tekst „Dynamiczny dobór few-shot” 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 „Dynamiczny dobór few-shot”?
Pobieranie przykładów dla poszczególnych zapytań Ć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 „Dynamiczny dobór few-shot”?
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
- Zero-, one- i few-shot
- Projektowanie skutecznych przykładów
- Kolejność przykładów i ich aktualność
- Dynamiczny dobór few-shot