Architektura RAG na AWS - S3 + OpenSearch + Bedrock
Czym jest RAG i dlaczego infrastruktura jest ważniejsza niż model
Retrieval-Augmented Generation to wzorzec architektoniczny, w którym LLM generuje odpowiedzi wykorzystując kontekst pobrany z zewnętrznej bazy wiedzy, zamiast polegać wyłącznie na danych treningowych. System pobiera odpowiednie fragmenty dokumentów w momencie zapytania i wstrzykuje je do promptu jako kontekst.
Z perspektywy infrastruktury, RAG ma trzy odrębne warstwy, z których każda musi skalować się niezależnie:
- Warstwa ingestion - dokumenty wpływają, są dzielone na fragmenty, wektoryzowane i indeksowane
- Warstwa wyszukiwania - zapytania użytkownika są wektoryzowane i dopasowywane do zapisanych wektorów
- Warstwa generacji - pobrany kontekst jest łączony z zapytaniem i wysyłany do LLM
Wybór modelu (Bedrock vs SageMaker vs self-hosting) jest omówiony w naszym porównaniu inferencji LLM. Ten artykuł skupia się na warstwach 1 i 2 - infrastrukturze, która decyduje o tym, czy RAG działa niezawodnie w skali.
“Wystarczy wywołać API” przestaje działać, gdy:
- Twój korpus dokumentów przekracza 10 000 stron, a ingestion trwa godziny
- Opóźnienie zapytań rośnie, bo indeks wektorowy nie jest odpowiednio skonfigurowany
- Koszty rosną, bo dokumenty są wektoryzowane wielokrotnie zamiast serwować z cache
- Jakość wyszukiwania spada, bo strategia podziału na fragmenty była potraktowana po macoszemu
Architektura referencyjna - S3 + OpenSearch Serverless + Bedrock
Przepływ danych
Dokumenty (PDF, HTML, Markdown)
|
v
S3 Bucket (surowe przechowywanie)
|
v
Lambda / Step Functions (chunking + preprocessing)
|
v
Bedrock Embeddings API (Titan Embeddings v2)
|
v
OpenSearch Serverless (indeks wektorowy, wyszukiwanie k-NN)
|
v
Zapytanie: wektoryzuj pytanie -> k-NN search -> pobierz top-k fragmentów
|
v
Bedrock Generation (Claude Sonnet 4.6 / Haiku) z pobranym kontekstem
|
v
Odpowiedź dla użytkownika
Składniki architektury
- S3 - przechowywanie dokumentów z wersjonowaniem i politykami lifecycle. Źródło prawdy dla całej surowej treści.
- Lambda / Step Functions - orkiestracja potoku przetwarzania. Obsługuje chunking, ekstrakcję metadanych i wywołania Bedrock Embeddings.
- Bedrock Titan Embeddings v2 - konwertuje fragmenty tekstu na wektory 1024-wymiarowe. Dostępny w regionie eu-central-1 (Frankfurt).
- OpenSearch Serverless (vector engine) - przechowuje wektory i wykonuje przybliżone wyszukiwanie k-najbliższych sąsiadów (k-NN) w momencie zapytania.
- Model generacji Bedrock - przyjmuje zapytanie + pobrane fragmenty i generuje odpowiedź. Claude Sonnet 4.6 dla jakości, Haiku 3.5 dla szybkości/niskiego kosztu.
Alternatywa - Bedrock Knowledge Bases (w pełni zarządzany RAG)
AWS oferuje Bedrock Knowledge Bases jako w pełni zarządzane rozwiązanie RAG. Obsługuje chunking, wektoryzację, indeksowanie i wyszukiwanie automatycznie.
Jak to działa
- Wskazujesz Knowledge Bases na bucket S3 zawierający Twoje dokumenty
- AWS automatycznie dzieli na fragmenty, wektoryzuje (używając Titan Embeddings) i indeksuje w zarządzanej bazie wektorowej
- W momencie zapytania wywołujesz jedno API, które pobiera kontekst i generuje odpowiedź
Kiedy używać Knowledge Bases
- Szybkie prototypowanie RAG (minuty do pierwszego zapytania)
- Korpus dokumentów poniżej 50 000 stron
- Domyślna strategia podziału (stały rozmiar z nakładką) jest wystarczająca
- Nie potrzebujesz własnej logiki wyszukiwania ani re-rankingu
Kiedy budować samodzielnie
- Potrzebujesz własnego chunkingu (semantyczny, hierarchiczny, specyficzny dla domeny)
- Wymagasz wyszukiwania hybrydowego (wektor + keyword BM25)
- Korpus przekracza 100 tys. stron i potrzebujesz kontroli nad przepustowością indeksowania
- Chcesz użyć innego vector store (Pinecone, pgvector, Qdrant)
- Potrzebujesz multi-tenancy z ścisłą izolacją danych
Porównanie kosztów
Cennik Knowledge Bases: storage za GB/miesiąc + zapytania za request. Dla małych korpusów może być tańszy niż samodzielnie zarządzany OpenSearch. W skali cennik per-query się kumuluje i samodzielne zarządzanie staje się bardziej ekonomiczne.
OpenSearch Serverless - cennik, skalowanie i pułapki kosztowe
OpenSearch Serverless to domyślny vector store dla niestandardowego RAG na AWS. Abstrahuje zarządzanie klastrem, ale wprowadza własną złożoność przez model OCU (OpenSearch Compute Unit).
Model OCU
OpenSearch Serverless rozlicza się w OCU - każdy OCU zapewnia jednostkę obliczeniową do indeksowania lub wyszukiwania:
- OCU indeksowania - obsługują ingestion dokumentów i indeksowanie wektorów
- OCU wyszukiwania - obsługują wykonywanie zapytań i wyszukiwanie k-NN
Minimum to 2 OCU dla wyszukiwania i 2 OCU dla indeksowania (4 OCU łącznie). Każdy OCU kosztuje ok. $0.24/godzinę w eu-central-1.
| Rozmiar obciążenia | OCU wyszukiwania | OCU indeksowania | Koszt miesięczny (ok.) |
|---|---|---|---|
| Minimum (dev/test) | 2 | 2 | ~2 800 PLN (~$700) |
| Mała produkcja (10 tys. dok., 1 tys. zapytań/dzień) | 2 | 2 | ~2 800 PLN (~$700) |
| Średnia (500 tys. dok., 50 tys. zapytań/dzień) | 4 | 2 | ~4 200 PLN (~$1 050) |
| Duża (5M dok., 500 tys. zapytań/dzień) | 8 | 4 | ~8 400 PLN (~$2 100) |
Typowe pułapki kosztowe
- Minimum 4 OCU zawsze działa - nawet przy zerowym ruchu płacisz ~2 800 PLN/miesiąc. Nie ma skalowania do zera.
- Typ kolekcji ma znaczenie - użyj typu “VECTORSEARCH”, nie “SEARCH” ani “TIMESERIES”. Zły typ marnuje OCU na funkcje, których nie potrzebujesz.
- OCU indeksowania przy burstach - duży ingestion wsadowy może tymczasowo wymagać więcej OCU indeksowania. Planuj ingestion poza godzinami szczytu.
Kiedy wybrać OpenSearch provisioned
Jeśli Twoje obciążenie jest duże i przewidywalne (>1M dokumentów, stabilny wolumen zapytań), domena OpenSearch provisioned z pluginem k-NN może być tańsza niż Serverless. Wymieniasz prostotę operacyjną na kontrolę kosztów.
Schemat wektoryzacji - wsadowy vs real-time
Ingestion wsadowy (Step Functions + Lambda)
Dla początkowego ładowania dokumentów i okresowych aktualizacji:
# Lambda: dzielenie dokumentu na fragmenty i generowanie wektorów przez Bedrock
import boto3
import json
bedrock = boto3.client("bedrock-runtime", region_name="eu-central-1")
s3 = boto3.client("s3")
def lambda_handler(event, context):
bucket = event["bucket"]
key = event["key"]
# Pobranie dokumentu z S3
response = s3.get_object(Bucket=bucket, Key=key)
text = response["Body"].read().decode("utf-8")
# Podział dokumentu na fragmenty (stały rozmiar z nakładką)
chunks = chunk_text(text, chunk_size=512, overlap=64)
# Generowanie wektorów dla każdego fragmentu
embeddings = []
for chunk in chunks:
embed_response = bedrock.invoke_model(
modelId="amazon.titan-embed-text-v2:0",
body=json.dumps({"inputText": chunk}),
)
vector = json.loads(embed_response["body"].read())["embedding"]
embeddings.append({"text": chunk, "vector": vector})
return {"chunks_processed": len(embeddings), "embeddings": embeddings}
def chunk_text(text, chunk_size=512, overlap=64):
"""Dzieli tekst na nakładające się fragmenty o rozmiarze ok. chunk_size tokenów."""
words = text.split()
chunks = []
start = 0
while start < len(words):
end = start + chunk_size
chunk = " ".join(words[start:end])
chunks.append(chunk)
start = end - overlap
return chunks
Ingestion real-time (API Gateway + Lambda)
Dla dokumentów przesyłanych przez użytkowników, które muszą być natychmiast wyszukiwalne:
- API Gateway przyjmuje upload
- Lambda dzieli i wektoryzuje w czasie rzeczywistym
- Wektory są indeksowane w OpenSearch natychmiast
- Opóźnienie: 2-10 sekund w zależności od rozmiaru dokumentu
Koszty wektoryzacji
Bedrock Titan Embeddings v2 kosztuje $0.00002 za 1K tokenów wejściowych (jedna z najtańszych dostępnych opcji).
Przykład: wektoryzacja 10 000 dokumentów, każdy średnio 2 000 tokenów:
- 10 000 x 2 000 / 1 000 x $0.00002 = $0.40 łącznie
Koszty wektoryzacji są pomijalnie małe. Prawdziwy koszt to OCU OpenSearch i tokeny generacji.
Wzorce skalowania
10 tys. dokumentów vs 10M dokumentów
Przy 10 tys. dokumentów wszystko mieści się w minimalnej konfiguracji OpenSearch (2 OCU wyszukiwania). Przy 10M dokumentów musisz myśleć o:
- Sharding indeksu - dystrybucja wektorów na wiele shardów dla równoległego wyszukiwania
- Priorytetowe ładowanie - przetwarzaj dokumenty w kolejności wg ważności; nie wszystko wymaga natychmiastowego indeksowania
- Filtrowanie metadanych - użyj pre-filtrów OpenSearch, aby zawęzić przestrzeń wyszukiwania k-NN przed porównywaniem wektorów
- Cache - cachuj często powtarzające się wektory zapytań i wyniki wyszukiwania w ElastiCache/DynamoDB
Optymalizacja opóźnienia zapytań
- Ustaw parametr
ef_searchna podstawie kompromisu precyzja/szybkość (wyższy = dokładniejsze, wolniejsze) - Używaj przybliżonego k-NN (algorytm HNSW) zamiast dokładnego wyszukiwania
- Ogranicz
kdo 5-10 fragmentów - więcej kontekstu nie zawsze poprawia jakość generacji - Wstępnie oblicz wektory dla częstych zapytań
Podział kosztów dla trzech scenariuszy
| Komponent | Mały (10 tys. dok., 1 tys. zapytań/dzień) | Średni (500 tys. dok., 50 tys. zapytań/dzień) | Duży (5M dok., 500 tys. zapytań/dzień) |
|---|---|---|---|
| S3 storage | ~4 PLN/miesiąc | ~40 PLN/miesiąc | ~320 PLN/miesiąc |
| OpenSearch Serverless | ~2 800 PLN/miesiąc | ~4 200 PLN/miesiąc | ~8 400 PLN/miesiąc |
| Bedrock embeddings (zapytania) | ~2 PLN/miesiąc | ~60 PLN/miesiąc | ~600 PLN/miesiąc |
| Bedrock generacja (Claude 3.5 Haiku) | ~120 PLN/miesiąc | ~6 000 PLN/miesiąc | ~60 000 PLN/miesiąc |
| Lambda compute | ~8 PLN/miesiąc | ~80 PLN/miesiąc | ~600 PLN/miesiąc |
| Razem | ~2 934 PLN/miesiąc | ~10 380 PLN/miesiąc | ~69 920 PLN/miesiąc |
Kluczowy wniosek: przy małej/średniej skali OpenSearch Serverless dominuje w rachunku. Przy dużej skali kosztem są tokeny generacji Bedrock. Optymalizuj odpowiednio - przy niskim wolumenie rozważ Knowledge Bases, żeby uniknąć minimum OCU; przy dużym wolumenie optymalizuj długość promptu i rozmiar cache.
Bezpieczeństwo i zarządzanie danymi
Izolacja sieciowa
- Deploy OpenSearch Serverless z dostępem VPC (bez publicznego punktu dostępowego)
- Użyj Bedrock VPC endpoint, aby wywołania API nigdy nie przechodziły przez publiczny internet
- Umieść funkcje Lambda w podsieciach VPC z odpowiednimi grupami bezpieczeństwa
IAM - zasada minimalnych uprawnień
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel"
],
"Resource": [
"arn:aws:bedrock:eu-central-1::foundation-model/amazon.titan-embed-text-v2:0",
"arn:aws:bedrock:eu-central-1::foundation-model/anthropic.claude-3-5-haiku-*"
]
},
{
"Effect": "Allow",
"Action": [
"aoss:APIAccessAll"
],
"Resource": "arn:aws:aoss:eu-central-1:*:collection/*"
}
]
}
Szyfrowanie i audyt
- OpenSearch Serverless szyfruje dane w spoczynku domyślnie (klucze AWS-managed lub CMK)
- Włącz logowanie CloudTrail dla wszystkich wywołań API Bedrock i OpenSearch
- Szyfrowanie server-side S3 dla wszystkich dokumentów
- Brak retencji danych w Bedrock - prompty i odpowiedzi nie są zapisywane ani używane do trenowania
Typowe błędy i jak ich unikać
Zbyt duże lub zbyt małe fragmenty
- Za duże (>1000 tokenów): pobrane fragmenty zawierają za dużo nieistotnego kontekstu, rozcieńczając sygnał
- Za małe (<100 tokenów): fragmenty tracą spójność i LLM nie może rozumować na ich podstawie
- Optimum: 256-512 tokenów z 10-15% nakładką dla większości typów dokumentów
- Wyjątek: kod, tabele i dane strukturalne lepiej dzielić semantycznie (na logiczne bloki)
Brak dostrajania parametrów k-NN
- Domyślny
ef_search=512jest często nadmiarowy dla produkcyjnych obciążeń - Zacznij od
ef_search=100i mierz recall względem zestawu testowego - Używaj
k=5jako domyślnej wartości; zwiększanie do 10+ rzadko poprawia jakość odpowiedzi, ale podwaja koszt generacji
Ignorowanie wyboru modelu wektoryzacji
- Titan Embeddings v2 (1024 wymiary) to solidny domyślny wybór dla treści w języku angielskim
- Dla treści wielojęzycznych (w tym polskich) rozważ Cohere Embed v3 (dostępny na Bedrock)
- Wymiar wektora bezpośrednio wpływa na koszty storage OpenSearch i szybkość wyszukiwania
Pominięcie ewaluacji wyszukiwania
- Zbuduj zestaw testowy 50-100 par pytanie/odpowiedź z Twoich rzeczywistych dokumentów
- Mierz precyzję wyszukiwania (czy właściwe fragmenty są zwracane?) zanim zaczniesz optymalizować generację
- Narzędzia: framework RAGAS, własne metryki precision @k
- Bez ewaluacji zgadujesz, czy słabe odpowiedzi wynikają z wyszukiwania czy generacji
Najczęściej zadawane pytania
Czy OpenSearch Serverless to jedyna opcja vector store na AWS?
Nie. Alternatywy to: Amazon Aurora z rozszerzeniem pgvector (tańsza dla małych obciążeń, bez minimum OCU), Amazon MemoryDB (dla ultra-niskiego opóźnienia), Amazon Neptune Analytics (dla RAG opartego o grafy) lub zewnętrzne usługi jak Pinecone. OpenSearch Serverless jest domyślnym wyborem ze względu na natywną integrację z Bedrock Knowledge Bases.
Ile kosztuje produkcyjny system RAG na AWS?
Dla zespołu przetwarzającego 50 000 zapytań/dzień na 500 tys. dokumentów używając Claude 3.5 Haiku: ok. 8 000-10 000 PLN/miesiąc. Dwa największe składniki kosztowe to OCU OpenSearch Serverless (~4 200 PLN) i tokeny generacji Bedrock (~6 000 PLN). Koszty wektoryzacji są pomijalnie małe.
Czy mogę używać RAG z modelami w eu-central-1 dla zgodności z RODO?
Tak. Titan Embeddings v2 i Claude Sonnet 4.6 są dostępne w regionie eu-central-1 (Frankfurt). Dla nowszych modeli jak Claude Sonnet 5 czy Opus 4.8, routing EU Geographic utrzymuje dane w granicach UE. OpenSearch Serverless w eu-central-1 zapewnia, że Twój indeks wektorowy pozostaje w Niemczech - najbliżej Polski z dostępnych regionów AWS.
Jakie jest opóźnienie zapytania RAG end-to-end?
Typowe opóźnienie end-to-end dla zapytania RAG (wektoryzacja pytania + wyszukiwanie k-NN + generacja odpowiedzi): 1.5-3 sekundy z Claude Sonnet 4.6, 800ms-1.5s z Claude 3.5 Haiku. Krok wyszukiwania (wektoryzacja + search) zajmuje 100-300ms; generacja dominuje łączne opóźnienie.
Czy powinienem użyć Bedrock Knowledge Bases czy budować samodzielnie?
Zacznij od Knowledge Bases jeśli: Twój korpus to poniżej 50 tys. stron, domyślny chunking wystarczy i chcesz dostarczyć rozwiązanie w dniach, nie tygodniach. Buduj samodzielnie jeśli: potrzebujesz własnego chunkingu, wyszukiwania hybrydowego, multi-tenancy lub kontroli kosztów OCU w skali. Wiele zespołów prototypuje na Knowledge Bases, a następnie migruje do samodzielnie zarządzanej infrastruktury, gdy wymagania się krystalizują.
Podsumowanie
- RAG na AWS to trójwarstwowa architektura: ingestion (S3 + Lambda + Embeddings), wyszukiwanie (OpenSearch Serverless) i generacja (Bedrock). Każda warstwa ma odrębne charakterystyki skalowania i czynniki kosztowe.
- OpenSearch Serverless to główny czynnik kosztowy przy niskim-średnim wolumenie (minimum ~2 800 PLN/miesiąc za 4 OCU). Przy dużym wolumenie dominują tokeny generacji Bedrock.
- Bedrock Knowledge Bases oferują najszybszą ścieżkę do produkcyjnego RAG, ale kosztem kontroli nad chunkingiem, dostrajaniem wyszukiwania i optymalizacją kosztów.
- Strategia podziału na fragmenty (chunking) ma większy wpływ na jakość odpowiedzi niż wybór modelu. Zainwestuj w ewaluację (RAGAS, precision@k) zanim zaczniesz optymalizować LLM.
- Dla rezydencji danych w UE deploy OpenSearch Serverless i Bedrock w eu-central-1 (Frankfurt). Wszystkie kluczowe komponenty RAG są dostępne in-region.
Potrzebujesz pomocy w zaprojektowaniu lub optymalizacji architektury RAG na AWS? Zespół inżynierów Devopsity buduje produkcyjne systemy wyszukiwania dla organizacji w Polsce i UE.
Budujesz system RAG na AWS?
Umów bezpłatną 30-minutową rozmowę o architekturze lub zostaw nam wiadomość. Omówimy Twoje wymagania i zaproponujemy optymalne podejście.