# RAG та LLM у 2026: Retrieval-Augmented Generation для співбесід з data science > Retrieval-Augmented Generation (RAG) пояснений для співбесід з data science у 2026 році. Векторні бази, стратегії chunking, моделі векторизації, agentic RAG, Graph RAG та архітектура конвеєра, готового до продакшну. - Published: 2026-06-06 - Updated: 2026-06-06 - Author: SharpSkill - Tags: RAG, retrieval augmented generation, LLM, data science, vector database, interview preparation, AI engineering - Reading time: 10 min --- Retrieval-Augmented Generation (RAG) став стандартною архітектурою для прив'язки відповідей LLM до фактичних та актуальних даних. На співбесідах з data science та інженерії штучного інтелекту у 2026 році питання про RAG тепер з'являються поряд із класичними темами ML, перевіряючи як системне мислення, так і практичні навички реалізації. > **Що таке RAG в одному реченні?** > > Retrieval-Augmented Generation поєднує систему пошуку (векторний пошук по базі знань) із генератором LLM, тож модель відповідає на основі реальних документів, а не покладається на запам'ятовані тренувальні дані. ## Як працює конвеєр RAG від початку до кінця Система RAG працює у дві фази: **офлайн-фаза інжесту**, що будує базу знань, та **онлайн-фаза запитів**, що отримує релевантний контекст і генерує відповідь. Під час інжесту сирі документи проходять очищення, розбиття на фрагменти (chunking) та векторизацію (embedding), перш ніж потрапити до векторної бази. Під час інференсу запит користувача йде тим самим шляхом векторизації, а пошук найближчих сусідів отримує найрелевантніші фрагменти. Ці фрагменти стають частиною промпта LLM, прив'язуючи згенеровану відповідь до вихідного матеріалу. ```python # rag_pipeline.py from langchain_openai import OpenAIEmbeddings, ChatOpenAI from langchain_community.vectorstores import Chroma from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnablePassthrough # Offline: ingest documents into the vector store def build_index(documents: list[str]) -> Chroma: splitter = RecursiveCharacterTextSplitter( chunk_size=512, # tokens per chunk chunk_overlap=64, # overlap preserves context at boundaries separators=["\n\n", "\n", ". ", " "] ) chunks = splitter.create_documents(documents) embeddings = OpenAIEmbeddings(model="text-embedding-3-large") return Chroma.from_documents(chunks, embeddings) # Online: retrieve + generate def query(vectorstore: Chroma, question: str) -> str: retriever = vectorstore.as_retriever( search_type="mmr", # Maximal Marginal Relevance for diversity search_kwargs={"k": 5, "fetch_k": 20} ) prompt = ChatPromptTemplate.from_template( "Answer based on this context only:\n{context}\n\nQuestion: {question}" ) chain = ( {"context": retriever, "question": RunnablePassthrough()} | prompt | ChatOpenAI(model="gpt-4o", temperature=0) ) return chain.invoke(question).content ``` Цей конвеєр охоплює основний цикл RAG: розбий, векторизуй, збережи, отримай, згенеруй. Параметр `search_type="mmr"` гарантує, що отримані фрагменти є водночас релевантними та різноманітними, зменшуючи надлишковість у вікні контексту. ## Стратегії chunking, які справді мають значення Chunking визначає якість пошуку більше за будь-який інший компонент. Поганий chunking означає, що пошуковик повертає фрагменти, яким або бракує контексту, або вони розбавляють сигнал нерелевантним вмістом. У продакшн-системах 2026 року домінують три підходи до chunking: **Chunking фіксованого розміру** розбиває текст за встановленою кількістю токенів (зазвичай 256-512 токенів) із перекриттям (overlap). Простий у реалізації, але розриває речення та думки посередині. **Семантичний chunking** виявляє межі тем, вимірюючи схожість векторів між сусідніми реченнями. Коли схожість падає нижче порогу, починається новий фрагмент. Кожен фрагмент несе цілісну думку, а не довільний зріз тексту. **Пізній chunking (late chunking)** спершу застосовує модель-трансформер до всього документа, створюючи контекстні вектори токенів, і лише потім розбиває на фрагменти. Це зберігає далекосяжні залежності, які традиційний chunking руйнує. ```python # semantic_chunking.py import numpy as np from sentence_transformers import SentenceTransformer def semantic_chunk(text: str, threshold: float = 0.3) -> list[str]: """Split text where semantic similarity drops below threshold.""" model = SentenceTransformer("all-MiniLM-L6-v2") sentences = text.split(". ") embeddings = model.encode(sentences) chunks, current_chunk = [], [sentences[0]] for i in range(1, len(sentences)): # Cosine similarity between consecutive sentences sim = np.dot(embeddings[i-1], embeddings[i]) / ( np.linalg.norm(embeddings[i-1]) * np.linalg.norm(embeddings[i]) ) if sim < threshold: # topic shift detected chunks.append(". ".join(current_chunk)) current_chunk = [sentences[i]] else: current_chunk.append(sentences[i]) chunks.append(". ".join(current_chunk)) # final chunk return chunks ``` Ключове усвідомлення для співбесіди: розмір фрагмента — це компроміс між точністю та повнотою (precision-recall). Малі фрагменти (100 токенів) підвищують точність пошуку, але фрагментують контекст. Великі фрагменти (1000 токенів) зберігають контекст, але розбавляють специфічність векторів. Більшість продакшн-систем зупиняється на 256-512 токенах із 10-20% перекриттям. ## Векторні бази та моделі векторизації у продакшні Векторна база зберігає вектори та підтримує швидкий приблизний пошук найближчих сусідів (ANN). Вибір правильної комбінації моделі векторизації та векторної бази безпосередньо впливає на затримку та точність пошуку. [Моделі векторизації](https://huggingface.co/spaces/mteb/leaderboard) у 2026 році зосередилися навколо кількох високопродуктивних варіантів. `text-embedding-3-large` від OpenAI (3072 виміри) та опенсорсні альтернативи, як-от `bge-m3` від BAAI чи `embed-v4` від Cohere, пропонують потужний багатомовний пошук. [Лідерборд MTEB](https://huggingface.co/spaces/mteb/leaderboard) залишається стандартним бенчмарком для порівняння якості векторизації. Векторні бази, як-от [Pinecone](https://www.pinecone.io/), Weaviate, Milvus, Qdrant і pgvector, роблять різні компроміси: | База | Індексація | Керована | Сильна сторона | |----------|----------|---------|----------| | Pinecone | Власна | Так | Простота, безсерверне масштабування | | Weaviate | HNSW | Так/Самостійно | Гібридний пошук (вектори + BM25) | | Milvus | IVF, HNSW | Так/Самостійно | Набори даних мільярдного масштабу | | Qdrant | HNSW | Так/Самостійно | Фільтрація + зберігання payload | | pgvector | IVF, HNSW | Самостійно | Інтеграція з PostgreSQL | Для обговорень на співбесіді ключовим є розуміння алгоритму HNSW (Hierarchical Navigable Small World): він будує багатошаровий граф, де кожен вузол з'єднується з найближчими сусідами, забезпечуючи пошук O(log n) ціною вищого споживання пам'яті. ## Гібридний пошук: поєднання щільного та розрідженого пошуку Чистий векторний пошук зазнає невдачі при точних збігах ключових слів та рідкісних термінах. Чистий лексичний пошук (BM25) пропускає семантичну схожість. Гібридний пошук поєднує обидва підходи, і у 2026 році це стандарт за замовчуванням для продакшн-систем RAG. Стандартний патерн використовує [Reciprocal Rank Fusion (RRF)](https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf) для злиття ранжованих результатів обох пошуковиків: ```python # hybrid_retrieval.py from rank_bm25 import BM25Okapi import numpy as np def reciprocal_rank_fusion( dense_results: list[str], sparse_results: list[str], k: int = 60 ) -> list[str]: """Merge dense (vector) and sparse (BM25) results using RRF.""" scores: dict[str, float] = {} for rank, doc_id in enumerate(dense_results): scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1) for rank, doc_id in enumerate(sparse_results): scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1) # Sort by combined RRF score, highest first return sorted(scores.keys(), key=lambda d: scores[d], reverse=True) ``` Гібридний пошук вирішує проблему «розбіжності словника», коли користувач запитує про «скасування підписки», а релевантний документ використовує формулювання «політика припинення облікового запису». BM25 ловить точний збіг термінів, тоді як векторний пошук вловлює семантичний зв'язок. ## Реранкінг: фільтр другого етапу Пошук повертає кандидатів. Реранкінг сортує їх за справжньою релевантністю. Реранкери типу cross-encoder, як-от [Cohere Rerank](https://cohere.com/rerank) чи `bge-reranker-v2.5-gemma2-lightweight`, оцінюють кожну пару запит-документ спільно, даючи значно точніші оцінки релевантності, ніж схожість bi-encoder. Двоетапний конвеєр пошуку — широкий перший етап (топ 50-100 кандидатів через вектори + BM25), а потім точний реранкінг (топ 5-10 для промпта) — є стандартом у продакшні. Це утримує затримку керованою: перший етап використовує швидкий пошук ANN, а дорогий cross-encoder обробляє лише невеликий набір кандидатів. > **Реранкінг — підказка для співбесіди** > > Cross-encoder точніші за bi-encoder, бо обробляють запит і документ разом крізь усі шари трансформера. Bi-encoder векторизують їх незалежно, втрачаючи тонкі сигнали взаємодії. Компромісом є швидкість: cross-encoder неможливо проіндексувати заздалегідь. ## Agentic RAG: за межами одноразового пошуку Наївний RAG отримує один раз і генерує. [Agentic RAG](https://arxiv.org/abs/2501.09136) розглядає LLM як агента-міркувальника, який вирішує, коли шукати, що шукати і чи достатнім є отриманий контекст. У 2026 році agentic RAG є домінантним патерном для складних запитів, що потребують багатоетапного міркування. Агент може: - **Самооцінка**: Оцінити, чи отримані документи відповідають на питання - **Повторний запит**: Переформулювати пошуковий запит, якщо початкові результати недостатні - **Маршрутизація (routing)**: Обрати між різними джерелами знань (векторна БД, SQL-база, API) - **Перевірка**: Перехресно звірити факти у кількох отриманих уривках ```python # agentic_rag.py from langgraph.graph import StateGraph, END from typing import TypedDict class RAGState(TypedDict): question: str documents: list[str] generation: str retries: int def retrieve(state: RAGState) -> RAGState: """Retrieve documents from vector store.""" docs = vectorstore.similarity_search(state["question"], k=5) return {"documents": [d.page_content for d in docs]} def grade_documents(state: RAGState) -> str: """Decide if documents are relevant enough to answer.""" prompt = f"Are these documents relevant to: {state['question']}?\n" prompt += "\n".join(state["documents"]) relevance = llm.invoke(prompt) # returns 'relevant' or 'not_relevant' return "generate" if "relevant" in relevance.content else "rewrite" def rewrite_query(state: RAGState) -> RAGState: """Reformulate the query for better retrieval.""" new_query = llm.invoke( f"Rewrite this query for better search results: {state['question']}" ) return {"question": new_query.content, "retries": state["retries"] + 1} # Build the agent graph workflow = StateGraph(RAGState) workflow.add_node("retrieve", retrieve) workflow.add_node("grade", grade_documents) # conditional routing workflow.add_node("rewrite", rewrite_query) workflow.add_node("generate", generate_answer) workflow.set_entry_point("retrieve") workflow.add_edge("retrieve", "grade") workflow.add_conditional_edges("grade", grade_documents, {"generate": "generate", "rewrite": "rewrite"}) workflow.add_edge("rewrite", "retrieve") # retry loop workflow.add_edge("generate", END) ``` Цей патерн — отримай, оціни, за потреби переформулюй і повтори — відомий як Corrective RAG (CRAG). Фреймворк LangGraph моделює робочий процес як спрямований циклічний граф з умовним розгалуженням, що спрощує додавання кроків перевірки, контрольних точок за участю людини (human-in-the-loop) чи маршрутизації між кількома джерелами. ## Graph RAG: пошук структурованих знань [Graph RAG](https://microsoft.github.io/graphrag/) витягує сутності та зв'язки з документів у граф знань, а потім запитує і граф, і векторне сховище. Ця архітектура зменшує галюцинації при фактологічних запитах, прив'язуючи відповіді до явних зв'язків між сутностями замість неструктурованої схожості тексту. Конвеєр інжесту витягує трійки (суб'єкт, предикат, об'єкт) з кожного фрагмента документа. Під час запиту система визначає релевантні сутності у питанні, обходить граф знань у пошуку пов'язаних фактів і поєднує контекст із графа з уривками, отриманими векторно. Graph RAG чудово справляється з питаннями, що потребують багатокрокового (multi-hop) міркування, як-от «Яка команда веде проєкт, що використовує фреймворк, згаданий у документі X?» — запитами, що вимагають поєднання фактів із кількох документів. Чистий векторний пошук тут має труднощі, бо жоден окремий фрагмент не містить повної відповіді. > **Компроміс Graph RAG** > > Graph RAG значно підвищує фактологічну точність (до 40% менше галюцинацій при запитах, насичених сутностями), але потребує зрілого конвеєра витягання сутностей. Зашумлене витягання дає зашумлений граф, що може погіршити результати нижче рівня наївного RAG. ## Оцінювання систем RAG: метрики, що мають значення Оцінювання RAG поділяється на метрики пошуку та метрики генерації. Обидва набори потрібно вимірювати незалежно, щоб діагностувати збої. **Метрики пошуку:** - **Recall@k**: Чи з'явилися релевантні документи у топ k результатів? - **MRR (Mean Reciprocal Rank)**: Наскільки високо ранжовано перший релевантний результат? - **NDCG**: Чи відповідає ранжування ідеальному порядку релевантності? **Метрики генерації:** - **Вірність (faithfulness)**: Чи використовує відповідь лише інформацію з отриманого контексту? (Вимірює галюцинації) - **Релевантність відповіді**: Чи відповідь стосується початкового питання? - **Точність контексту**: Чи дійсно отримані фрагменти використані у відповіді? Фреймворки на кшталт [Ragas](https://docs.ragas.io/) та [DeepEval](https://docs.confident-ai.com/) автоматизують ці оцінки, використовуючи патерни LLM-як-суддя (LLM-as-judge). [Найпопулярніші питання співбесід з data science](/blog/data-science/top-25-data-science-interview-questions-2026) дедалі частіше включають проєктування оцінювання RAG — варто очікувати питання про те, як виміряти, чи правильно працює система RAG. ## Режими збоїв у продакшні та налагодження Системи RAG зазнають невдач передбачувано. Знання цих патернів є необхідним як для співбесід, так і для реального розгортання. **Забруднення вікна контексту** трапляється, коли забагато отриманих фрагментів розбавляють релевантний сигнал. LLM отримує 10 фрагментів, але лише 2 містять корисну інформацію. Виправлення: використовуйте реранкер для фільтрації та зменшіть top-k у пошуковику. **Артефакти chunking** виникають, коли розбиття фіксованого розміру розриває речення, таблиці чи блоки коду посередині елемента. Отриманий фрагмент є синтаксично неповним і семантично марним. Це вирішує семантичний chunking або розбиття з урахуванням документа (з повагою до заголовків, абзаців, блоків коду). **Дрейф векторів (embedding drift)** виникає, коли модель векторизації оновлюється, але векторне сховище досі містить вектори зі старої моделі. Запити, закодовані новою моделлю, шукають у векторному просторі, побудованому старою, погіршуючи якість пошуку. Рішення: повторно векторизуйте весь корпус після будь-якої зміни моделі. **Застарілі індекси** видають неактуальну інформацію, бо конвеєр інжесту відстав від оновлень документів. У [системах машинного навчання](/blog/data-science/machine-learning-algorithms-explained) це аналогічно розбіжності тренування-обслуговування (training-serving skew) — система пошуку бачить інший розподіл даних, ніж той, що існує у продакшні. ## Висновок - RAG поєднує пошук (векторний пошук по базі знань) із генерацією LLM, щоб давати прив'язані до фактів відповіді без перенавчання моделі - Стратегія chunking має найбільший вплив на якість пошуку — семантичний та пізній chunking перевершують розбиття фіксованого розміру у більшості сценаріїв - Гібридний пошук (щільні вектори + розріджений BM25) з Reciprocal Rank Fusion є продакшн-стандартом, що вирішує проблему розбіжності словника, з якою не справляється чистий векторний пошук - Реранкери cross-encoder додають шар точності після широкого пошуку, обробляючи лише невеликий набір кандидатів, щоб тримати затримку прийнятною - Agentic RAG (отримай, оціни, переформулюй, повтори) та Graph RAG (витягання зв'язків між сутностями) — два головні архітектурні досягнення 2026 року, що опрацьовують складні багатокрокові запити, на яких наївний RAG зазнає невдачі - Оцінювання має відокремлювати метрики пошуку (Recall@k, MRR) від метрик генерації (вірність, релевантність відповіді), щоб діагностувати, де ламається конвеєр - Найпоширеніші продакшн-збої — забруднення контексту, артефакти chunking, дрейф векторів, застарілі індекси — мають прості виправлення, щойно їх виявлено --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/uk/blog/data-science/rag-retrieval-augmented-generation-llm-data-science-interview-2026