RAG chatbotembeddings, wyszukiwanie wektorowe i wdrożenie w 2026

rag5 min czytania20 lipca 2026

Autor: DevStudio.it

TL;DR

RAG (Retrieval-Augmented Generation) to chatbot, który przed odpowiedzią wyszukuje relevantne fragmenty w bazie wiedzy, a dopiero potem generuje tekst LLM. Kluczowe elementy: chunking, embeddingi, magazyn wektorowy (np. pgvector w Branchly) i prompt z cytowanymi źródłami. Poniżej pipeline od PDF/FAQ do API w Next.js — techniczny kąt uzupełniający artykuł o treści bazy wiedzy, nie o samym pisaniu FAQ.

Dla kogo

  • Zespołów produktowych wdrażających chatbot na stronie firmowej lub w SaaS
  • Developerów szukających alternatywy dla „wrzuć cały regulamin do promptu”
  • Firm z setkami stron dokumentacji, gdzie fine-tuning modelu nie ma sensu ekonomicznego
  • CTO oceniających koszt inference vs jakość odpowiedzi

Fraza (SEO)

rag chatbot wdrożenie, embeddings vector search, pgvector nextjs, chatbot ai baza wiedzy technicznie 2026

RAG vs prompt stuffing — dlaczego embeddingi

Podejście Limit Koszt Aktualizacja wiedzy
Cały FAQ w system prompt Okno kontekstu (~128k tokenów i mniej efektywnie) Wysoki przy każdym pytaniu Ręczna edycja promptu
Fine-tuning Drogi, wolna iteracja Jednorazowy + retrain Retrain
RAG + embeddings Skaluje do tysięcy chunków Embedding raz + tanie query Re-index chunków

Embedding to wektor (np. 1536 wymiarów) reprezentujący semantykę akapitu. Pytanie użytkownika też staje się wektorem — szukasz najbliższych sąsiadów cosinusowych, nie dopasowania słów kluczowych.

Pipeline wdrożenia — 6 kroków

[Dokumenty] → chunking → embedding API → [vector store][User question] → embedding → top-k retrieval → prompt + LLM → odpowiedź + źródła
  1. Ingest — markdown z repo, PDF oferty, eksport FAQ z Branchly
  2. Chunking — 400–800 tokenów, overlap 50–100, nagłówek w metadanych
  3. Embedtext-embedding-3-small (tańszy) lub -large (dokładniejszy)
  4. Store — tabela document_chunks z kolumną embedding vector(1536)
  5. Query — embed pytania → ORDER BY embedding <=> query_vec LIMIT 5
  6. Generate — GPT-4o-mini z instrukcją: „Odpowiedz tylko na podstawie kontekstu”

Chunking — praktyyczne reguły

Źle pocięty tekst = złe odpowiedzi, nawet z dobrym modelem.

  • Dziel po nagłówkach Markdown (##), nie na środku zdania
  • Do metadanych: source_url, locale, updated_at, section_title
  • Tabele i listy cen — osobny chunk z kontekstem „Cennik 2026”
  • Duplikaty między PL/EN — osobne embeddingi per język, filtr locale w query

Przykład rekordu w Branchly (branchly.cloud) z pgvector:

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE document_chunks (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  content TEXT NOT NULL,
  embedding vector(1536),
  source_url TEXT,
  locale TEXT DEFAULT 'pl',
  updated_at TIMESTAMPTZ DEFAULT now()
);

CREATE INDEX ON document_chunks
  USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

Dla <10k chunków wystarczy ivfflat; powyżej rozważ HNSW lub dedykowany silnik (Qdrant, Pinecone) — nadal możliwe jako rozszerzenie tego samego API.

Kod ingest w Next.js

// scripts/ingest-knowledge.ts
import OpenAI from 'openai';
import { db } from '@/lib/db';

const openai = new OpenAI();

async function embedAndStore(chunks: { text: string; meta: ChunkMeta }[]) {
  for (const batch of chunk(chunks, 50)) {
    const res = await openai.embeddings.create({
      model: 'text-embedding-3-small',
      input: batch.map((c) => c.text),
    });

    for (let i = 0; i < batch.length; i++) {
      await db.$executeRaw`
        INSERT INTO document_chunks (content, embedding, source_url, locale)
        VALUES (
          ${batch[i].text},
          ${JSON.stringify(res.data[i].embedding)}::vector,
          ${batch[i].meta.sourceUrl},
          ${batch[i].meta.locale}
        )
      `;
    }
  }
}

Uruchamiasz po deployu treści lub z cron na DevStudioIT Cloud — nie przy każdym pytaniu użytkownika.

Endpoint chat z RAG

// app/api/chat/route.ts
import OpenAI from 'openai';
import { streamText } from 'ai';

export async function POST(req: Request) {
  const { message, locale } = await req.json();

  const queryEmbedding = await embed(message);
  const chunks = await db.$queryRaw<Chunk[]>`
    SELECT content, source_url
    FROM document_chunks
    WHERE locale = ${locale}
    ORDER BY embedding <=> ${queryEmbedding}::vector
    LIMIT 5
  `;

  const context = chunks.map((c, i) => `[${i + 1}] ${c.content}`).join('\n\n');

  return streamText({
    model: openai('gpt-4o-mini'),
    system: `Odpowiadaj po polsku. Używaj wyłącznie kontekstu poniżej. Jeśli brak danych — powiedz, że nie wiesz.
    
Kontekst:
${context}`,
    messages: [{ role: 'user', content: message }],
  });
}

Front-end: widget na stronie firmowej z linkami do source_url pod odpowiedzią — buduje zaufanie i redukuje halucynacje.

Jakość retrieval — co poprawia trafność

  • Hybrid search: BM25 (pełnotekst w Postgres) + vector, merge wyników — lepsze na SKU i kody produktów
  • Re-ranking: po top-20 wektorowym, cross-encoder lub LLM wybiera top-5 (drożej, precyzyjniej)
  • Query rewrite: LLM przepisuje pytanie użytkownika na „search query” przed embed
  • Threshold: jeśli max similarity < 0,75 — odpowiedź „Nie mam tej informacji” zamiast zgadywania

Loguj question, chunk_ids, similarity scores w Branchly — co tydzień review 20 rozmów z niskim score.

Koszty i latency (orientacyjnie 2026)

  • Embedding 1M tokenów text-embedding-3-small: rząd wielkości kilku USD
  • GPT-4o-mini z 2k tokenów kontekstu: grosze na rozmowę
  • pgvector query <50 ms przy indeksie — bottleneck to LLM (TTFT ~300–800 ms)
  • Cache embeddingów dla identycznych pytań (hash normalized question) — 30% oszczędności na support FAQ

Hosting na DevStudioIT Cloud (devstudioit.cloud): Route Handler ze streamingiem, limity rate per IP, klucze OpenAI w env.

Bezpieczeństwo i RODO

  • Nie indeksuj danych osobowych klientów, wewnętrznych cenników B2B
  • Rate limiting i CAPTCHA na publicznym /api/chat
  • Retencja logów rozmów — polityka 90 dni, anonimizacja
  • Informacja w polityce prywatności o przetwarzaniu przez OpenAI (DPA, region EU jeśli wymagane)

Metryki sukcesu po wdrożeniu

Po 4 tygodniach produkcji mierz:

  • Answer accuracy — ręczna ocena 50 losowych rozmów (cel: >85% trafnych)
  • Fallback rate — ile razy bot odmawia z powodu niskiego similarity (cel: 10–20%, nie 0% — zero oznacza overfitting)
  • Średnia liczba chunków w kontekście vs latency
  • Kliknięcia w source_url pod odpowiedzią — proxy zaufania użytkownika

Dashboard w Branchly: tabela chat_logs z kolumnami question, chunk_ids, user_rating (thumbs up/down w UI). Iteruj chunking co kwartał, nie codziennie — stabilność odpowiedzi ważniejsza niż chase na 100% accuracy.

FAQ

Czy RAG zastępuje artykuł o bazie wiedzy?

Nie — tam opisujemy co wrzucić (FAQ, regulaminy). Tu jak technicznie wyszukać i wygenerować odpowiedź.

pgvector vs Pinecone?

pgvector w Branchly = mniej moving parts dla małego/średniego projektu. Pinecone/Qdrant gdy >500k chunków lub multi-tenant z izolacją.

Jak często re-index?

Przy zmianie treści na stronie — webhook z CMS → partial re-ingest zmienionych URL-i, nie cała baza.

Czy można bez OpenAI?

Tak — lokalne modele embedding (Ollama, sentence-transformers) + Llama; trade-off: jakość PL i ops GPU.

Co z wielojęzycznością?

Filtr locale w SQL + osobne chunki; nie mieszaj PL i DE w jednym embed bez normalizacji języka pytania.

CTA

Potrzebujesz chatbota, który cytuje Waszą dokumentację zamiast wymyślać?

Powiązane wpisy

AI chatbot na stronie firmowej — kiedy się opłaca, a kiedy nie (2026)
9 min czytania
Chatbot AI w firmie: 7 scenariuszy, które realnie oszczędzają czas
6 min czytania
Chatbot AI dla firmy: jak wdrożyć i ile kosztuje w 2026
6 min czytania

O autorze

Budujemy szybkie strony WWW, aplikacje web/mobile, chatboty AI i hosting — z naciskiem na SEO i konwersję.

Przydatne linki

Od teorii do produkcji — Branchly, hosting i realizacje.

Podoba Ci się nasze podejście? Zbudujmy coś razem.

Rozpocznij konfigurację projektu