Локальный RAG на Python: от файла до ответа с источниками за семь шагов
Построение систем на базе генеративного искусственного интеллекта требует понимания не только возможностей крупных нейросетей, но и механизмов их взаимодействия с внешними данными. В статье разбирается проект local-docs-ai, демонстрирующий создание локального приложения на Python, способного отвечать на вопросы по загруженным документам, предоставляя точные цитаты и ссылки на исходный текст. Курс состоит из семи практических занятий, охватывающих весь цикл обработки: от чтения файлов до генерации ответа с учетом найденного контекста.
# Семь занятий по локальному RAG на Python: как построить помощника с источниками
Технология RAG (Retrieval-Augmented Generation, или генерация с дополнениями) становится стандартом для создания узкопрофильных ИИ-ассистентов. В отличие от обучения модели с нуля, этот подход позволяет гибко обновлять базу знаний без изменения весов нейросети. Проект local-docs-ai, разработанный автором курса, предлагает прозрачный путь создания такого приложения: от загрузки Markdown-файлов до вывода цитированного ответа.
В данной статье мы пройдемся по ключевым этапам реализации, объясняя технические процессы простым языком и выделяя проверенные факты о работе системы.
Архитектура и подготовка окружения
Основой системы является связка простых библиотек Python, терминального интерфейса и двух специализированных моделей, работающих локально через API Ollama.
Схема работы приложения: 1. Индексация: При первом запуске приложение сканирует папку с документами (форматы .md и .txt), разбивает их на фрагменты и преобразует текст в числовые векторы с помощью модели embeddinggemma. Результаты сохраняются в файле data/index.json. 2. Поиск: При запросе векторизуется сам вопрос. Затем система ищет в индексе фрагменты, семантически близкие к вопросу, используя метрику косинусной близости. 3. Генерация: Найденные отрывки и исходный вопрос подаются в языковую модель qwen3:1.7b. Она формирует ответ, опираясь исключительно на предоставленный контекст.
Система имеет ограничения: она поддерживает до 50 файлов общим объемом до 1 МБ и пропускает формат PDF. Это сделано намеренно, чтобы вся индексируемая структура помещалась в оперативную память и могла быть легко проверена в обычном коде.
Прозрачность процессов: от текста к векторам
Главная особенность курса и инструмента — возможность визуализировать каждый шаг «кухни». Обычно пользователь видит только финальный ответ. Здесь же можно отслеживать:
* Диагностика: Команда docqa.py doctor проверяет наличие необходимых моделей Ollama (embeddinggemma и qwen3:1.7b) и доступность API-сервера на порту 11434. * Поиск по кусочкам: Команда search выводит только найденные фрагменты без генерации ответа. Это позволяет сразу оценить, корректно ли сработал поиск, или проблема кроется в формулировке запроса. * Разбиение документов: Файлы разбиваются не по длине текста, а с учетом заголовков Markdown. Однако автор предупреждает, что простой разбор регулярными выражениями может ошибочно считать закодированный в коде текст за заголовки, и длинные строки могут быть нарезаны по жесткому лимиту в 1000 символов. * Векторное представление: Для каждого фрагмента вычисляется векторное представление. Если индексация прерывается, используется механизм временных файлов для сохранения прогресса.
Особый акцент делается на проверку целостности данных. Система сравнивает SHA-256 хеш исходных файлов с записью в индексе. Если документ изменен, но индекс не пересобран, система выдаст ошибку, защищая от использования устаревшей информации. Это важно, так как изменение даже одного слова требует пересчета векторов.
Алгоритм поиска и генерации
Сердцем поиска является функция сравнения векторов. Приложение использует формулу косинусного угла для определения релевантности.
Простое объяснение: Представьте, что текст и вектор — это стрелки в пространстве. Косинусный угол показывает, насколько эти стрелки направлены в одну сторону. Чем ближе угол к нулю, тем более похожи смыслы текста и запроса. Значение 0.8 не означает «надежность на 80%», а лишь указывает на высокую степень сходства направлений.
Система выбирает три наиболее релевантных фрагмента, чтобы сформировать контекст для генеративной модели. Если ни один фрагмент не подходит, поиск возвращает пустой список, и модель должна сгенерировать отказ от ответа.
При формировании запроса к языковой модели используется специальный системный промпт, который четко инструктирует модель: * Отвечать только на основании предоставленных цитат. * Использовать обозначения вида [1], [2] для ссылки на фрагменты. * Сообщать о невозможности найти ответ, если фактов недостаточно.
Такой подход предотвращает «галлюцинации» модели, заставляя её работать как редактор, а не как фантазер.
Заключение
Курс по локальному RAG демонстрирует, как сложные технологии могут быть доступны разработчику, знакомому с основами Python. Использование терминальных команд (index, search, ask) и веб-интерфейса на Streamlit обеспечивает гибкость в проверке гипотез. Главное преимущество подхода — полное отсутствие зависимостей от интернета для работы ядра системы и прозрачность всех этапов обработки данных, что критически важно для задач, требующих высокой точности и проверки источников.
Проект открыт для изучения, и репозиторий содержит все примеры кода для повторения занятий.