RAG krok za krokem

Najdi → vlož do promptu → odpověz se zdroji.

Co se naučíš: Složíš celý RAG včetně hybridního hledání a přeřazení a změříš si, jestli funguje.

10 min čtení + cvičeníNavazuje na:🗃️ Vektorová databáze

RAG (retrieval augmented generation) je nejužitečnější vzor celého oboru: místo abys doufal, že model něco ví, najdeš relevantní podklady a vložíš mu je do promptu. Model pak odpovídá z nich a může na ně odkázat. Je to lék na halucinace, na zastaralé znalosti i na to, že model nezná tvoje firemní data.


Celý postup

PŘÍPRAVA (jednou, při změně dat)
  dokumenty → rozsekat na chunky → embedding → uložit do vektorové DB

DOTAZ (při každé otázce)
  otázka → embedding → najdi K nejpodobnějších chunků
        → (rerank: seřaď je přesněji, vezmi top 3–5)
        → vlož do promptu jako podklady
        → model odpoví jen z nich + uvede zdroj

To je celé. Žádný trénink, žádné ladění modelu, jen chytré vyhledávání a poctivě sestavený prompt.


Jak vypadá prompt

[SYSTEM]
Odpovídáš zákazníkům e-shopu. Odpovídej VÝHRADNĚ z podkladů uvnitř <podklady>.
Když odpověď v podkladech není, napiš přesně: "To bohužel nevím."
U každého tvrzení uveď v hranatých závorkách číslo podkladu, ze kterého vychází.

[USER]
Otázka: Do kdy můžu vrátit zboží?

<podklady>
[1] (Obchodní podmínky → 5.2 Reklamace) Zboží lze vrátit do 14 dnů od převzetí…
[2] (Doprava → 3.1) Zásilku doručujeme do 2 pracovních dnů…
</podklady>

Tři věci, které tenhle prompt dělá správně: omezuje zdroj informací, povoluje nevím a vynucuje citace. Bez nich RAG degraduje na „model si to zase domyslí“.


Proč samotné vektorové hledání nestačí

Většina návodů skončí u „ulož embeddingy, hledej nejbližší, vlož do promptu“. V praxi právě tady RAG nejčastěji selhává, protože vektorové hledání má dvě slepá místa.

Nenajde přesné řetězce. Když se uživatel ptá na „chybu E4021“ nebo na článek „§ 82 odst. 3“, embedding tyhle tokeny rozmělní do významového průměru a najde dokumenty, které jsou „nějak o chybách“. Klasické fulltextové hledání (BM25) je najde přesně. Proto se dnes standardně kombinuje obojí, čemu se říká hybridní hledání: vezmi top 50 z vektorů, top 50 z BM25, slož je dohromady a teprve pak vyber.

Nerozlišuje mezi „podobné“ a „odpovídá na otázku“. Embedding otázky „jak vrátím zboží“ je blízko chunku, který o vracení zboží jen mluví, i chunku, který popisuje postup. Rozdíl mezi nimi pozná až model, který si obojí přečte.

Rerank je ten krok, který dělá největší rozdíl a nejčastěji chybí. Je to malý model, který dostane dvojici dotaz a chunk a vrátí skóre relevance. Je mnohem přesnější než porovnávání vektorů, protože vidí obojí najednou, ale je taky mnohem dražší, takže se pouští až na padesát kandidátů, ne na celou databázi. Typický efekt: z pěti chunků v promptu jsou najednou relevantní čtyři místo dvou.


Když se dotaz nedá hledat tak, jak přišel

Uživatel se ptá „a co ta druhá varianta?“. Tenhle dotaz nemá samostatně žádný význam, takže jeho embedding je k ničemu. Dvě obvyklé opravy:

  • Přepis dotazu. Malým a levným voláním modelu přepiš dotaz do samostatně srozumitelné podoby s využitím historie konverzace: „jaké jsou podmínky tarifu Standard“.
  • Víc dotazů naráz. Z jedné otázky vygeneruj tři různé formulace, hledej všemi a výsledky slouč. Pomůže to tam, kde uživatel používá jiná slova než dokumentace.

Obojí přidá jedno volání navíc, ale u konverzačního RAG je to obvykle rozdíl mezi „funguje“ a „nefunguje“.


Kde se to nejčastěji rozbije

RAG selhává skoro vždy v retrievalu, ne v generování. Když model odpoví špatně, první otázka zní: byla správná informace mezi nalezenými chunky?

PříznakPříčinaŘešení
Odpověď „nevím“, i když v datech jeRetrieval nenašel správný chunkLepší chunking, hybridní hledání, rerank
Odpověď je mimoNašly se tematicky blízké, ale špatné pasážeRerank, filtry, víc metadat
Odpověď je zastaraláV indexu zůstala stará verzeMazat/aktualizovat chunky při změně dokumentu
Model si přidal svojeChybí instrukce „jen z podkladů“Doplnit ji + citace + kontrola
Pomalé a drahéPosíláš 20 chunkůVezmi 3–5 nejlepších

💡 Změř retrieval odděleně od odpovědi. Vezmi 30 reálných otázek, u každé zapiš, který dokument obsahuje odpověď, a měř, jak často je mezi vrácenými. Dokud je tohle číslo nízké, ladit prompt nemá smysl.


Kolik chunků posílat

Méně, než by ses čekal. Tři až pět dobře vybraných překoná dvacet průměrných: dlouhý kontext zdražuje, zpomaluje a informace v něm se hůř využije (viz kontextové okno). Když si nejsi jistý, vezmi víc kandidátů z databáze, ale přeřaď je a do promptu pusť jen špičku.


Jak poznat, že RAG funguje

RAG má dvě části, které selhávají nezávisle, a proto se musí měřit odděleně. Kdo měří jen kvalitu odpovědi, nikdy nezjistí, kterou půlku má opravovat.

Co měříšOtázkaJak
RetrievalByla správná pasáž mezi nalezenými?recall@k na sadě otázek s označenou správnou pasáží
PořadíByla nahoře, nebo až pátá?MRR nebo podíl případů, kdy je správná pasáž první
UkotveníVychází odpověď z podkladů?zkontroluj, jestli tvrzení v odpovědi jsou v citovaných chuncích
OdpověďJe to správně a užitečné?ruční hodnocení nebo model jako porotce

Diagnostika je pak přímočará. Nízký recall znamená problém v chunkování nebo v hledání, nic jiného nepomůže. Vysoký recall a špatná odpověď znamená problém v promptu nebo v modelu. A dobrá odpověď bez ukotvení v podkladech je halucinace, která zrovna vyšla.

Na začátek stačí padesát otázek s ručně označenou správnou pasáží. Je to nudná půldenní práce a ušetří ti týdny hádání. Viz evaluace a halucinace.


Kdy RAG nestačí

  • Otázky přes celý korpus („kolik smluv končí letos?“), to je dotaz do databáze, ne hledání podobnosti. Nech model vygenerovat SQL nebo použij nástroj.
  • Vícekrokové otázky („porovnej podmínky u produktu A a B“), potřebuje víc hledání za sebou, tedy agenta.
  • Data, která se mění každou vteřinu: sáhni rovnou po API nástroji, ne po indexu.

Cvičení

  1. Uživatel se ptá „a kolik to stojí u té druhé varianty?“. Proč tenhle dotaz rozbije naivní RAG a jak to opravíš?
  2. Retrieval má recall@5 rovných 95 %, ale odpovědi jsou špatné ve třetině případů. Kde je chyba?
Náčrt řešení: rozbal, až si cvičení zkusíš sám
  1. Protože dotaz nedává samostatně smysl, takže jeho embedding i klíčová slova jsou k ničemu. „Druhá varianta“ může být cokoli. Oprava je přepis dotazu: levným voláním modelu ho s pomocí historie konverzace přeformuluj do samostatně srozumitelné podoby, třeba „kolik stojí tarif Standard“, a teprve tím hledej. Alternativně vygeneruj tři různé formulace a výsledky slouč.
  2. V generování, ne v hledání. Když je správná pasáž mezi nalezenými v 95 % případů, podklady jsou k dispozici a model je buď ignoruje, nebo si k nim domýšlí. Zkontroluj tři věci: jestli prompt jasně říká „odpovídej jen z podkladů“, jestli se správná pasáž nedostala až na pátou pozici (tam ji model přehlíží), a jestli tvrzení v odpovědi jsou doslova v citovaných chuncích. Viz halucinace.

Shrnutí

  • RAG = najdi podklady → vlož do promptu → nech odpovědět jen z nich, se zdroji.
  • Kvalita stojí a padá s vyhledáváním; měř ho odděleně od kvality odpovědi.
  • Tři až pět dobrých chunků poráží dvacet průměrných.
  • Na agregace a rychle se měnící data použij nástroje, ne vektorové hledání.
Chatbot odpovídá „nevím“, přestože odpověď v dokumentaci je. Kde hledat chybu?

V retrievalu. Správný chunk se nedostal mezi nalezené, může za to špatné sekání, chybějící kontext v chunku, jen sémantické hledání bez fulltextu nebo chybný filtr. Prompt v tomhle případě ladit nemá smysl.

Proč do promptu neposílat dvacet nalezených úryvků pro jistotu?

Protože každý token stojí peníze a čas a informace uprostřed dlouhého kontextu se hůř využije. Kvalitu zvedne spíš přeřazení kandidátů a poslání tří až pěti nejlepších.

Uživatel se ptá „kolik máme smluv, které letos končí?“. Proč je RAG špatný nástroj?

Protože to není hledání podobného textu, ale agregace nad daty. Vektorové hledání vrátí pár náhodných smluv. Správně je nechat model vygenerovat dotaz do databáze (nebo mu dát nástroj), který spočítá přesný výsledek.