Как отладить LlamaIndex с примерами кода: практическое руководство по поиску и устранению ошибок

Практическое руководство по отладке конвейера RAG-приложения, построенного на фреймворке LlamaIndex. Содержит конкретные примеры кода на Python для диагностики проблем на каждом этапе: загрузка данных, чанкирование, работа ретривера, формирование промптов, логирование и проверка ограничений контекста LLM.
LlamaIndex — мощный фреймворк для создания RAG-приложений (Retrieval-Augmented Generation), который стал стандартом де-факто для работы с собственными данными в LLM-проектах. Однако при его использовании разработчики сталкиваются с типичными проблемами: нерелевантный ретривел (поиск), плохое качество ответов модели, ошибки загрузки данных или проблемы с производительностью. Отладка такого стека требует системного подхода. Данное руководство проведет вас через основные этапы диагностики и устранения неполадок в LlamaIndex с конкретными примерами кода на Python.

Первый и самый частый источник проблем — этап индексации данных. Если ваш индекс построен некорректно, все последующие этапы обречены на провал. Начните с проверки загрузчиков документов. Убедитесь, что документы загружаются полностью и их текст извлекается правильно.

Пример диагностики загрузки:
from llama_index.core import SimpleDirectoryReader
documents = SimpleDirectoryReader("./data").load_data()
print(f"Загружено документов: {len(documents)}")
for i, doc in enumerate(documents[:2]):  # Посмотрим на первые два
 print(f"Док {i}, ID: {doc.id_}, длина текста: {len(doc.text)}")
 print(f"Начало текста: {doc.text[:200]}...")
 print("---")

Если текст обрезан или содержит мусор (например, бинарные данные PDF), проблема в загрузчике. Возможно, потребуется использовать специализированный загрузчик (например, `PDFReader` из `llama-index-readers-file`) или предобработку текста.

Второй критический момент — чанкирование (разбиение текста на фрагменты). Неправильный размер чанка или разделитель могут разрушить смысл.

Пример настройки и проверки чанкирования:
from llama_index.core.node_parser import SentenceSplitter
node_parser = SentenceSplitter(chunk_size=512, chunk_overlap=50)
nodes = node_parser.get_nodes_from_documents(documents)
print(f"Создано нод (чанков): {len(nodes)}")
for i, node in enumerate(nodes[:3]):
 print(f"Чанк {i}: {node.text[:150]}...")
 print(f"Метаданные: {node.metadata}")
 print("---")

Поэкспериментируйте с `chunk_size` (256, 512, 1024) и `chunk_overlap` (20, 50). Слишком большие чанки дают шум, слишком маленькие теряют контекст.

Третий этап — отладка ретривера (поиска). Если система находит не те документы, проверьте, как работает поиск по индексу в изоляции.

Пример тестирования векторного поиска:
from llama_index.core import VectorStoreIndex
index = VectorStoreIndex(nodes)  # Используем созданные ноды
retriever = index.as_retriever(similarity_top_k=3)
query = "Ваш тестовый запрос"
retrieved_nodes = retriever.retrieve(query)
print(f"Для запроса '{query}' найдено {len(retrieved_nodes)} нод:")
for i, node_with_score in enumerate(retrieved_nodes):
 print(f"#{i+1}, Скор: {node_with_score.score:.4f}")
 print(f"Текст: {node_with_score.node.text[:200]}...")
 print("---")

Низкие скоры (< 0.7 для многих моделей эмбеддингов) указывают на слабую релевантность. Возможные причины: некачественные эмбеддинги (попробуйте другую модель, например, `text-embedding-ada-002` через `OpenAIEmbedding`), плохое чанкирование или необходимость в гибридном поиске (векторный + ключевые слова).

Четвертый шаг — проверка промптинга и постобработки. Иногда ретривер находит правильные чанки, но LLM дает плохой ответ из-за некорректного промпта.

Пример извлечения и проверки промпта:
from llama_index.core import PromptTemplate
from llama_index.core.llms import ChatMessage
# Создаем кастомный промпт для отладки
qa_prompt_tmpl = (
 "Контекстная информация:\n{context_str}\n\n"
 "Вопрос: {query_str}\n\n"
 "Ответь четко на основе только приведенного контекста. Если ответа нет в контексте, скажи 'Не знаю'.\n"
)
qa_prompt = PromptTemplate(qa_prompt_tmpl)
# Вручную формируем вход для LLM
context_str = "\n\n".join([n.node.text for n in retrieved_nodes])
messages = [
 ChatMessage(role="system", content="Ты — помощник, отвечающий на вопросы."),
 ChatMessage(role="user", content=qa_prompt.format(context_str=context_str, query_str=query))
]
print("=== ПРОМПТ, ОТПРАВЛЯЕМЫЙ В LLM ===")
for msg in messages:
 print(f"{msg.role.upper()}: {msg.content[:500]}...")
print("===")

Запустив этот промпт напрямую через интерфейс OpenAI Playground или другую LLM, вы сможете оценить, проблема в промпте или в чем-то еще.

Пятый аспект — логирование и трассировка. Включите детальное логирование LlamaIndex, чтобы увидеть внутреннюю работу.

import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
# Теперь при выполнении вашего кода (например, index.as_query_engine().query("..."))
# в консоль будут выводиться подробные логи: этапы индексации, запросы к эмбеддинг-модели, к LLM и т.д.

Шестая распространенная проблема — ошибки токенизации и ограничения контекста. Если ваш запрос с контекстом превышает `context_window` модели, ответ будет обрезан.

Пример проверки длины:
from llama_index.core.llms import OpenAI
llm = OpenAI(model="gpt-4")
total_tokens = llm.get_token_count(context_str + "\n\n" + query)
print(f"Общее количество токенов в запросе: {total_tokens}")
print(f"Лимит модели {llm.model}: {llm.context_window}")
if total_tokens > llm.context_window:
 print("ПРЕДУПРЕЖДЕНИЕ: Запрос превышает лимит контекста!")

В этом случае нужно уменьшать `similarity_top_k` у ретривера или использовать методы сжатия контекста, например, `SentenceWindowRetriever` или реранкинг.

Систематически проходя каждый этап конвейера — загрузка, чанкирование, индексация, поиск, промптинг и генерация — и используя приведенные примеры кода для его изоляции и проверки, вы сможете эффективно диагностировать и устранять большинство проблем в вашем RAG-приложении на LlamaIndex.
372 5

Комментарии (13)

avatar
h34eg8hd9m2 31.03.2026
Проблема часто в препроцессинге данных. Как правильно настраивать сплиттеры?
avatar
qvv2gl9 01.04.2026
Примеры с использованием LangChain для сравнения были бы очень кстати.
avatar
b33oplcovfca 01.04.2026
Спасибо! Пункт про валидацию загруженных данных — ключевой. Многие это упускают.
avatar
s62lge6f0 01.04.2026
Спасибо за структурированный подход. Часто начинаешь искать ошибку не с того конца.
avatar
ttfuare 01.04.2026
А есть рекомендации по отладке именно с локальными моделями (Ollama, LM Studio)?
avatar
f6a4q0bxe5pr 01.04.2026
Всегда проверяйте эмбеддинг-модель! Часто корень проблем именно в ней, а не в логике.
avatar
td0v6k 01.04.2026
Есть ли best practices для отладки комбинации разных ретриверов (гибридный поиск)?
avatar
j8j0k1hywq 02.04.2026
LlamaIndex иногда молча падает. Хорошо бы разобрать логирование и обработку исключений.
avatar
ty65uss8w 02.04.2026
Отличное руководство! Как раз столкнулся с проблемой нерелевантного ретривела. Жду продолжения.
avatar
448do1j3je 02.04.2026
Хороший общий план. Но для новичков не хватает базовых шагов: 'сначала проверьте это'.
Вы просмотрели все комментарии