ГлавнаяБлогRAG-системы: как избежать галлюцинаций и дать точный ответ
AI / Нейросети

RAG-системы: как избежать галлюцинаций и дать точный ответ

Узнайте, как исправить главную проблему RAG-систем — ложные ответы. Четыре шага: реранжинг, порог релевантности, цитирование и гибридный поиск. Попробуйте прямо сейчас!

Al
Редакция Algolitalgolit.ru
12 мин чтения20 июля 2026 г.

Почему RAG-системы выдумывают ответы и как это исправить

Вы когда-нибудь спрашивали RAG-систему о политике, которой нет в документах, и получали уверенный, но полностью вымышленный ответ? Это не баг, а архитектурная проблема: поиск Top-K гарантирует только «ближайшие» векторы, а не релевантные. В этой статье вы узнаете, как внедрить четыре ключевых улучшения, чтобы ваша RAG-система говорила «я не знаю» вместо того, чтобы галлюцинировать.

Шаг 1: Реранжинг — сначала широкий поиск, затем точная оценка

Векторный поиск быстр, но приблизителен. Он может выдать кусок про календарь праздников по запросу о сроке уведомления при увольнении, просто из-за случайной близости в пространстве эмбеддингов. Решение — двухэтапный подход.

Двухэтапный поиск

Сначала дешёвый и широкий поиск (Top-20 через HNSW-индекс), затем дорогой и точный реранжинг (Top-5). Реранжер — это cross-encoder, который смотрит на запрос и каждый кандидат вместе, а не по отдельности.

# Устанавливаем библиотеку для Cohere Rerank
# pip install cohere

import cohere

co = cohere.Client('YOUR_API_KEY')

def rerank_chunks(query, candidates, top_n=5):
    """
    candidates: список словарей с ключом 'chunk_text'
    Возвращает отреранжированные куски с оценками
    """
    response = co.rerank(
        model='rerank-english-v3.0',
        query=query,
        documents=[c['chunk_text'] for c in candidates],
        top_n=top_n
    )
    reranked = []
    for result in response.results:
        idx = result.index
        reranked.append({
            **candidates[idx],
            'rerank_score': result.relevance_score
        })
    return reranked

# Пример использования:
# top20 = vector_search(query_embedding, limit=20)
# top5 = rerank_chunks(user_question, top20)

Почему именно 20, а не 5? Если истинно лучший кусок оказался на 8-м месте в приблизительном поиске, вы даёте реранжеру шанс его найти.

Шаг 2: Порог релевантности — умение сказать «я не знаю»

Реранжинг не решает проблему отсутствия данных. Если в базе нет ничего по теме, система всё равно вернёт Top-5 «лучших из того, что есть». Нужен минимальный порог.

RELEVANCE_THRESHOLD = 0.5  # настраивается под ваши данные

def retrieve_with_abstention(query):
    top20 = vector_search(query, limit=20)
    reranked = rerank_chunks(query, top20, 5)
    best_score = reranked[0]['rerank_score'] if reranked else 0
    if best_score < RELEVANCE_THRESHOLD:
        return {'has_relevant_context': False, 'chunks': []}
    return {'has_relevant_context': True, 'chunks': reranked}

def answer_question(query):
    result = retrieve_with_abstention(query)
    if not result['has_relevant_context']:
        return "У меня нет информации об этом в доступных документах. Обратитесь в HR или уточните запрос."
    # далее сборка промпта с цитатами

Как выбрать порог? Прогоните набор известных вопросов (должны быть отвечены) и заведомо неотвечаемых. Посмотрите распределение оценок реранжера и выберите значение на стыке групп.

Шаг 3: Сборка промпта с цитатами

Даже с хорошими кусками важно, как вы их передаёте LLM. Просто вставить контекст — плохо: ответ невозможно проверить. Используйте нумерованные источники.

def build_grounded_prompt(query, chunks):
    context_block = '\n\n'.join(
        f'[{i+1}] (Источник: {c["metadata"]["source_file"]}, {c["metadata"]["department"]})\n{c["chunk_text"]}'
        for i, c in enumerate(chunks)
    )
    prompt = f'''Вы отвечаете на вопросы, используя ТОЛЬКО нумерованные источники ниже.
{context_block}
Инструкции:
- Отвечайте, используя ТОЛЬКО информацию из источников.
- После каждого утверждения указывайте номер источника в скобках, например [1].
- Если источники не дают полного ответа, скажите об этом — не додумывайте.
Вопрос: {query}
Ответ:'''
    return prompt

Пример ответа LLM: «Срок уведомления составляет 30 дней с даты подачи заявления [1][2]. Для увольнения также требуется одобрение руководителя [3].»

Теперь каждый источник можно сделать кликабельной ссылкой на оригинальный документ.

Шаг 4: Гибридный поиск — ловим то, что упускает векторный поиск

Векторный поиск плохо справляется с точными идентификаторами: кодами ошибок, номерами заказов. Например, запрос «ERR_4521» не имеет семантического смысла для эмбеддинга. Решение — добавить лексический поиск (BM25).

from rank_bm25 import BM25Okapi

tokenized_corpus = [chunk['chunk_text'].split() for chunk in all_chunks]
bm25 = BM25Okapi(tokenized_corpus)

def hybrid_search(query, vector_hits, alpha=0.5):
    """
    Комбинируем оценки векторного и лексического поиска.
    alpha — вес векторного поиска (0..1).
    """
    tokenized_query = query.split()
    bm25_scores = bm25.get_scores(tokenized_query)
    # Нормализуем обе оценки
    combined = []
    for i, chunk in enumerate(all_chunks):
        vec_score = vector_hits.get(i, 0)  # предполагаем, что vector_hits — dict {index: score}
        lex_score = bm25_scores[i]
        combined_score = alpha * vec_score + (1 - alpha) * lex_score
        combined.append((i, combined_score))
    combined.sort(key=lambda x: x[1], reverse=True)
    return [all_chunks[idx] for idx, _ in combined[:20]]

Гибридный поиск особенно полезен для кодов ошибок, названий продуктов и других точных строк.

Что делать прямо сейчас

  1. Добавьте реранжинг к вашему пайплайну: замените Top-K на Top-20 + реранжер до 5.
  2. Настройте порог релевантности: соберите тестовый набор и подберите значение.
  3. Перепишите промпт с нумерованными источниками и цитированием.
  4. Внедрите гибридный поиск для обработки точных идентификаторов.

Эти четыре шага превратят вашу RAG-систему из «уверенного лжеца» в надёжного помощника, который либо даёт проверяемый ответ, либо честно говорит, что не знает.

#RAG-системы#реранжинг#порог релевантности#гибридный поиск#цитирование
Al
Редакция Algolit

Пишем про алгоритмы, подготовку к собеседованиям и карьеру в IT — так, чтобы было понятно и полезно.

Хочешь закрепить знания на практике?

Решай задачи на Algolit — интерактивная платформа для обучения

Начать бесплатно →