Автономный RAG-пайплайн

07.10.25

Интеграция - Нейросети

Статья посвящена разработке автономного RAG-пайплайна на готовой LLM. Никакого API, отправки своих данных куда-то в облака, на посторонние сервера и т.п. Автономный ИИ на 100%.

Предисловие

Всем привет!

Вводные слова выделены в отдельный блок, который можно пропустить и перейти непосредственно к сути.

 
 Предисловие

Содержание


Вводные сведения

Дано

  • Корпус специализированной текстовой информации на заданную тему.

Цель

  • Быстрый и удобный поиск информации по базе знаний.

Постановка задачи и требования

  1. Пользователь должен иметь возможность вводить в текстовое поле информацию в произвольной форме (в контексте тематики базы знаний).
  2. Система должна отвечать на вопрос "по-человечески" со ссылками на источники.
  3. Система должна работать автономно, не обращаясь к внешним источникам (через API или любым другим способом).
  4. Из пункта 3 следует, что система, развернутая локально, должна уметь работать без доступа к интернету.
  5. Система должна работать как на Windows, так и на Linux.
  6. Система, развернутая локально на обычном пользовательском ноутбуке, должна работать с приемлемой производительностью и с приемлемой точностью ответов (на данный момент точность достаточно оценивать "на глаз" без использования методик и дополнительных средств).
  7. Для написания вопросов и получения ответов может быть использована обычная html-страница и/или любое другое средство, реализующее отправку вопроса и получение ответа. Например, форма в 1С.

Средства реализации

Для решения поставленной задачи будем делать RAG-пайплайн на базе готовой LLM на языке программирования Python.

 

В теорию и терминологию вдаваться здесь смысла нет - информации и так предостаточно. Здесь пройдемся по основным шагам реализации и покажем то, что у нас в итоге получилось.

Возможно, кому-то данная информация окажется интересной и полезной.

 

Описание пайплайна

Общий порядок функционирования поискового инструмента следующий:

  1. Пользователь вводит свой вопрос.
  2. Пайплайн в базе знаний ищет топ-3 наиболее релевантных ответов, семантически их ранжируя.
  3. Формируется текстовый запрос к LLM, которая содержит:
    • исходный вопрос пользователя,
    • промпт - задание для LLM в виде "Сгенерируй ответ на вопрос, используя только информацию ниже." + дополнительные инструкции.
    • исходные тексты топ-3 релевантных ответов.
  4. LLM генерирует человеческий ответ на основе промпта и релевантных ответов.
  5. Полученный ответ вместе со ссылками на источники возвращается пользователю.

 

Итак, приступим к созданию нашего инструмента.

 

Подготовительные мероприятия

Самое главное на первоначальном этапе - это подготовить сырые исходники текстов в такой формат, чтобы наш пайплайн мог с ними работать.
Для этого тексты нужно превратить в эмбеддинги - в набор чисел (вектора), с которыми можно будет работать как с точками в многомерном пространстве.

Подготовка базы знаний

Во-первых, перевели всю имеющуюся информацию в txt-формат. Форматирование, картинки и прочее - все это удаляется. Часть перенесена простым Ctrl+C Ctrl+V из файлов, часть уже была в текстовом формате (тексты для видео).

Затем разбили на блоки по принципу 1 блок - 1 тема. Также, сделано это было вручную. Ссылки были заменены на [link], адреса электронной почты на [email] и т.п.

При этом, размер блоков подбирали, чтобы его размер был не более 700-900 токенов. Проверка размеров - с помощью программы на Python, которая считает токены для каждого блока. Если размер превышен - вручную делим его на части, чтобы блоки сохраняли смысл и контекст.

Формат текстовых файлов:

  • [вопрос/тема/контекст]
  • [ссылка на первоисточник]
  • [информация]

Пример:

 

На самом деле формат исходных raw-файлов вторичен - это может быть txt, json или любой другой формат. Всё равно дальше программа для формирования эмбеддингов будет эти файлы парсить и забирать из них все тексты.

Формат здесь вторичен, первично качество текстов. Всю второстепенную информацию (незначимые ссылки в текстах, незначимые для поиска символы и прочий шум) из текстов надо убирать.

Чем чище текст, тем лучше будет результат. 

Размер нашей базы знаний: > 230 000 токенов, разбитых на 572 блока.

 

Формирование эмбеддингов

Выбор модели

Для формирования эмбеддингов взяли готовую модель intfloat-e5-base.

Почему она:

  • открытая лицензия,
  • мультиязычная, знает русский язык,
  • достаточно легкая по размерам и требуемым ресурсам, работает оффлайн (о ресурсах см. Системные требования),
  • позволяет получать ответы на вопросы на приемлемом уровне.

Из того же семейства еще есть intfloat-e5-small и intfloat-e5-large. Выбран средний вариант в качестве компромисса для баланса между точностью и ресурсами.

Реализация

Небольшая программа на Python (158 строк кода) делает следующее:

  1. разбивает каждый блок текста на кусочки - чанки (chunk) заданного размера с перекрытием.
  2. для каждого чанка считает эмбеддинг - 768 чисел на каждый чанк.
  3. сохраняет эмбеддинги в json.
  4. сохраняет исходные тексты со ссылками в json.
     
  • Если тематический блок исходного текста небольшой, по нему строится 1 эмбеддинг.
  • Если размер блока превышает заданный в программе размер, блок разбивается на несколько чанков. Для каждого чанка считается свой эмбеддинг.

 

  • Кроме указания размера чанка, следует указать размер перекрытия. Перекрытие - это часть текста заданной длины из предыдущего чанка. Т.е. чанки одного блока идут внахлёст. Это даёт возможность сохранять контекст и связь между чанками одного исходного блока.
  • Размер чанков и перекрытий - настраиваемые параметры, которыми можно регулировать "фокус" для попадания в тему и в контекст.
    • Слишком большие чанки будут давать размытые эмбеддинги, в которые вопрос пользователя может не попасть или попасть неточно.
    • В слишком маленьких будет теряться смысл.
    • Размер перекрытий влияет на принадлежность чанка контексту.
 
 Пример кода

 

Вот здесь на примере видно перекрытие: начало нового чанка содержит часть старого в рамках одного исходного блока.

Здесь же хорошо видно, что конец 1-го чанка и начало 2-го - не обрезаны и содержат кусочки незаконченных предложений, которые кроме шума вряд ли что-то добавляют.

Поэтому, обрезать лучше по концу ближайшего предложения, а не размеру.

 

Когда эмбеддинги готовы их можно использоваться в пайплайне.

Повторное формирование эмбеддингво потребуется только, если исходные тексты будут изменены или потребуется изменить модель и/или параметры формирования.

 

Визуализация эмбеддингов

Каждый чанк - это вектор в 768-ом пространстве (количество координат зависит от выбранной модели).

 

Представить такую точку мысленно мы не можем, но может с помощью алгоритма UMAP снизить её размерность, например до 2 или до 3 и вывести на графике, который будет наглядной визуализацией нашей базы знаний.

Каждая точка на графике - это 1 чанк.

С помощью этого графика можно уже оценить корректность формирования эмбеддингов: точки близких тем в базе знаний на графике также расположены близко друг к другу.

 

Схожие по смыслу кусочки текстов сбиваются в кластеры.

 

Тексты из разных файлов-источников (выделены разными цветами) тоже могут оказаться близко за счет схожести тематики.

 

Если увеличить участок и посмотреть расшифровки точек, то видно, что темы точек совпадают и/или пересекаются.

Значит, можно предположить, что эмбеддинги построены правильно и можно их пробовать использовать дальше.

 

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

 

Трехмерная визуализация оказалась не такой информативной, как могло показать на первый взгляд. Хотя бы потому, что её приходится крутить мышкой, чтобы рассмотреть все точки.

 
 Дополнительные примеры

Выводы

Оставив за скобками факт, что "векторные отпечатки" разнообразных данных можно использовать для разных целей, в т.ч. классификации, группировок, поиска и т.п., в контексте темы статьи можно сделать выводы:

  • формирование эмбеддингов, на первый взгляд, выглядит правдоподобным.
  • можно переходить к следующему этапу.

 

Клиент-серверная часть

Векторное пространство, в которое будет погружаться наш пайплайн в поисках ответов на вопросы, готово.

Можно приступить к созданию самого инструмента.

Делаем его максимально универсальным. Таким, чтобы он мог работать и локально, и на веб-сервере.

Поэтому, архитектура решения - клиент-серверная.

Далее в статье сервер запущен локально и доступ к нему будет через http://127.0.0.1:8000. Если бы он был размещен где-нибудь на vds, сути бы это не изменило.

Подготовительные мероприятия

  • Устанавливаем Uvicorn+FastAPI.
  • Пишем программу server.py.

Чем будет заниматься server.py:

  • Загружает при запуске в память модели для работы пайплайна.
  • В фоновом режиме ждет подключения клиента.
  • Получает от клиента вопросы.
  • Передает вопросы в пайплайн для обработки.
  • Отправляет клиенту полученные результаты.

При первом подключении клиента, server.py отдает ему шаблон страницы, которая будет использоваться для взаимодействия клиента с языковой моделью.

Самая главная часть шаблона html-страницы - это отправка вопроса и получение ответа:

 

Суть server.py сводится к запуску асинхронного сервера, который принимает запросы от клиента, передаёт их в RAG-пайплайн для обработки и возвращает сгенерированные ответы:

 

Запускаем сервер:

uvicorn server_fastapi:app

 

Подключаемся как клиенты через браузер и сервер отдает нам шаблон страницы, на которой мы можем задавать вопросы:

 

Реализация RAG-пайплайна

Программный код здесь не приводится. Если заинтересует - желающие могут получить ссылку на github.

Первый этап работы RAG-пайплайна: поиск близких эмбеддингов

  1. полученный от клиента вопрос очищается от лишних символов, приводится к нижнему регистру.
  2. по очищенному вопросу формируется эмбеддинг. 
    question_emb = encode_text([normalize_text(question)])

     

  3. по эмбеддингу вопроса ищется топ-3 самых релевантных ответов из базы эмбеддингов, которую подготовили выше. Используется cosine similarity. Чем ближе полученное значение к 1, тем ближе текст вопроса к тексту источника.
    top_answers = search_top_k(question_emb, top_k=TOP_K_RETRIEVE)

Текущий результат уже можно отправлять клиенту.

Система будет просто отправлять клиенту ссылки на самые релевантные источники по заданному вопросу.

 

Но данных шагов недостаточно, потому что результат поиска может быть неадекватным.

Здесь, например, просто нарушен порядок - хотелось бы, чтобы источник о ценах был на 1-ом месте:

 

А здесь на 1-ое место попал вообще посторонний источник:

 

В первом проходе система формирует топ-3 релевантных ответов не только с учетом текста ответов, но и с учетом темы. При этом поиск по эмбеддингам не понимает смысла, а ищет только близость слов.

Поэтому на первые места в поиске могут выходить совершенно неподходящие по смыслу источники.

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

 

Дополнительно выведем сюда рассчитанные значения сходства вопроса и источника:

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

Второй этап работы пайплайна: reranker

  1. Для того, чтобы повысить общую адекватность поиска после нахождения топ-3 релевантных ответа, дополнительно ранжируем источники, но уже будем учитывать эмбеддинги источников без учета заголовков/тем. Т.е. будем анализировать только тексты.
  2. Результатом будет повторно отсортированный топ-3.

Теперь ретривер показывает немного лучший результат - на первые места встают источники, наиболее подходящие к вопросу:

Но проблема с попаданием нерелевантного источника все равно остаётся и score у неадекватного источника по-прежнему высок.

Третий этап работы пайплайна: cross-encoder

  1. Вместо обычного реранкера, который использовали на предыдущем этапе, будем использовать cross-encoder, который будет считать релевантность, учитывая весь контекст и структуру предложения.
    Для этого будет использовать модель "jinaai/jina-reranker-v2-base-multilingual" (см. Системные требования).
    Передадим в модель пару (вопрос, ответ) и получим оценку релевантности.

После этого, оценки источников выглядят уже по-другому и нерелевантный источник действительно оказывается нерелевантным:

Четвертый этап работы пайплайна: RAG

Будем считать, что в подавляющем числе случаев ретривер дает нам самые релевантные куски текстов по заданному вопросу. И может возвращать их нам в виде ссылок на первоисточники.

Теперь можно вдохнуть жизнь в наш пайплайн, наделив его небольшой каплей искусственного интеллекта.

Для этого, передадим найденные источники вместе с исходным вопросом, языковой модели "qwen2.5-1.5b-instruct-q5_k_m.gguf" (см. Системные требования).

Вместе с вопросом и источниками ответов передадим модели и задание - что именно от неё требуется.

Пусть промпт будет таким:

 

Инициализация и настройки модели базовые/простые без особых тонкостей: работает на cpu, 4 потока.

 

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

 

Результат

В результате мы получаем первый человеческий ответ от нашего RAG-пайплайна:

 

 

 

Чудес, конечно, не бывает. И наш маленький друг случается пишет невпопад.

Но учитывая, что даже в таком простом пайплайне уже есть много настроек, есть смысл покрутить их. И начать надо с самого начала - с эмбеддингов.

Если, например, какая-то мысль в источниках размазана по нескольким чанкам, то система этот смысл может просто не уловить между ними. При этом, она может дать релевантную выборку, но собрать адекватный ответ из которой будет проблематично.

 

Справедливости ради, надо сказать, что ссылки на источники система даёт вполне релевантные. А это вполне соответствует основной цели ("Быстрый и удобный поиск информации по базе знаний"), преследуемой при разработке данной системы.

 

Системные требования

Отдельно хочется остановиться на том, сколько ресурсов потребляет данный инструмент.

Учитывая, что тестовая клиент-серверная версия разворачивалась на обычном старом ноутбуке, можно сказать, что требования - минимальны. В этом плане соотношение цена/качество очень приемлемое.

Используется: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz 1.99 GHz, 4 ядра, 8.00Гб ОЗУ. Все расчеты: на 4 ядрах CPU.

Ниже будет приведена информация о потреблении ресурсов именно на нём, как на минимально возможном оборудовании. Будет легко экстраполировать эти показатели на любое оборудование.

 

Модели

В пайплайне используется 3 модели. Все 3 модели работают оффлайн. Доступ к сторонним серверам им не нужен.

При первом их использовании они загружаются из интернета, а все остальное время лежат где-нибудь в кэше или любом другом месте, которое можно указать при настройках сервера.

Список используемых моделей:

  1. Для эмбеддингов: models--intfloat--multilingual-e5-base. Размер на жестком диске: 1,05 Гб
  2. Для кросс-энкодинга: models--jinaai--jina-reranker-v2-base-multilingual. Размер: 0,55 Гб
  3. Для генерации: qwen2.5-1.5b-instruct-q5_k_m.gguf. Размер: 1,26 Гб

К этому еще нужно добавить Python-библиотеку Torch. Размер ~1,3-2.5Гб.

 

ОЗУ

При запуске server.py в ОЗУ сразу загружаются все модели.

uvicorn server_fastapi:app

Первое время при работе пайплайн занимает ~1.2Гб ОЗУ, а затем, после стабилизации, усаживается в несколько раз:

 

Запас ОЗУ, конечно, нужен, если всё это будет крутиться где-то на web-сервере, иначе oom-killer может прийти раньше, чем система будет готова к работе.

 

Формирование эмбеддингов

230 000 токенов исходного текста для модели с 768-мерным вектором формируются за 4-5 минут.

Делается это 1 раз, а затем готовые эмбеддинги просто используются.

 

Время обработки запросов

RAG-пайплайн функционирует в нескольких режимах.

  1. Режим поиска релевантных источников без кросс-энкодинга и генерации ответа. Время выполнения ~0сек.:


    Для удобства тестирования добавили специальные ключи, которые можно указывать в вопросе.
    Здесь указан ключ "-s", который выводит score по каждому источнику:

     
  2. Режим с кросс-энкодингом (ключ "-ce"). Время выполнения ~5-10 сек.:

     
  3. Режим генерации ответа (флаг "AI-ответ" + ключ "-2", ограничивающий количество источников для генерации ответа). Время выполнения ~20-30 сек.:

 

Программный код серверной части

Серверная часть реализована на Flask и FastAPI. В проекте есть выбор: server_fastapi.py или server_flask.py.

Функционал пайплайна будет идентичен.

 
 FastAPI


Проект, в целом, совсем небольшой. Общий объем программного кода: 980 строк

 

Программный код клиентской части

Клиентская часть может быть любой. В статье приводится пример html-страницы для взаимодействия с сервером.

 

Если говорить про 1С, то минимальный код для работы будет состоять из нескольких строк.

&НаСервере
Процедура ВопросПриИзмененииНаСервере()
	
	HTTPСоединение = Новый HTTPСоединение("127.0.0.1", 8000);

	СтруктураЗапроса = Новый Структура;
	СтруктураЗапроса.Вставить("question", Вопрос);
	СтруктураЗапроса.Вставить("use_RAG", ИспользоватьRAG);	
	СтруктураЗапроса.Вставить("format", Форматировать);	
	
	ЗаписьJSON = Новый ЗаписьJSON;
	ЗаписьJSON.УстановитьСтроку();
	ЗаписатьJSON(ЗаписьJSON, СтруктураЗапроса);
	ЗапросJSON = ЗаписьJSON.Закрыть();
	
	HTTPЗапрос = Новый HTTPЗапрос("/ask");
	HTTPЗапрос.Заголовки.Вставить("Content-type", "application/json");
	HTTPЗапрос.УстановитьТелоИзСтроки(ЗапросJSON);
	
	HTTPОтвет = HTTPСоединение.ВызватьHTTPМетод("POST", HTTPЗапрос);
	
	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(HTTPОтвет.ПолучитьТелоКакСтроку());
	
	Ответ = ПрочитатьJSON(ЧтениеJSON);
	ЧтениеJSON.Закрыть();
	
	Результат.УстановитьHTML(Ответ.answer, Новый Структура)

КонецПроцедуры

 

Для работы надо только текстовое поле и поле HTML-документа для вывода результата.

 

Если форматирование не требуется, можно получать просто json и дальше программно с ним что-то делать:

СтруктураЗапроса.Вставить("format", Ложь);

 

 

Или можно вообще не задействовать базу эмбеддингов, а напрямую просить RAG сгенерировать ответ по заданному промпту, используя свои данные:

 

Если вынести код запроса в отдельную функцию и делать подобные запросы фоново по выборке объектов, можно делать какую-нибудь классификацию/сигнализацию в рамках учетной системы, если возможности модели позволяют получать приемлемый уровень достоверности. Например, маркировать входящие письма в CRM.

 

 

Общая схема пайплайна

 

В целом, клиент-серверное взаимодействие можно представить в виде такой схемы:

 

А сам RAG-трубопровод можно представить следующим образом.

Пайплайн имеет 2 входа:

  • для векторного/семантического поиска по корпусу данных.
  • для простой rag-генерации с промптом и произвольными данными.

 

Наверно, на этом данную статью можно закончить. По ходу подготовки статьи возникло много идей, которые хочется реализовать🙂

Надеемся, данная информация окажется для вас полезной!

Вступайте в нашу телеграмм-группу Инфостарт

См. также

Администрирование веб-серверов Сервера Нейросети Программист Платные (руб)

Сервер поиска по метаданным и поиска по коду, Сервер экспорта и поиска по документации, Сервер синтаксической проверки кода

17.06.2025    17039    0    Infostart    20    

113

Инструментарий разработчика Нейросети Платные (руб)

Первые попытки разработки на 1С с использованием больших языковых моделей (LLM) могут разочаровать. LLMки сильно галлюцинируют, потому что не знают устройства конфигураций 1С, не знают нюансов синтаксиса. Но если дать им подсказки с помощью MCP, то результат получается кардинально лучше. Далее в публикации: MCP для поиска по метаданым 1С, справке синтакс-помошника и проверки синтаксиса.

9900 руб.

25.08.2025    19624    46    8    

54

Нейросети Пользователь 1С v8.3 1С:Управление нашей фирмой 1.6 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 Оптовая торговля, дистрибуция, логистика Россия Управленческий учет Платные (руб)

Расширение "Искусственный интеллект и нейросети в 1С: Работа с отзывами маркетплейсов" предназначено для применения искусственного интеллекта в повседневной деятельности селлеров на маркетплейсах. Среди функций - работа с отзывами, вопросами и чатами покупателей, диалог с нейросетями, генерация картинок, заполнение описаний номенклатуры и другое.

6000 руб.

03.04.2024    11564    6    0    

11

Мастера заполнения Нейросети 1С v8.3 1C:Бухгалтерия 1С:Управление торговлей 11 Платные (руб)

Расширение для заполнения описания товара (номенклатуры) с помощью модели ИИ ChatGPT с ключевыми словами. Расширение формирует продающее описание товара по его наименованию с помощью модели искусственного интеллекта. Будет полезно для владельцев интернет магазинов, каталогов товаров и продающих через маркетплейсы. Адаптировано для основных конфигураций: УТ, ЕРП, КА, УНФ. Прошло аудит на 1cfresh.com. Версия для автоматического заполнения

5000 руб.

13.03.2023    21423    50    50    

79

Нейросети Программист Бесплатно (free)

Большие языковые модели все чаще применяются для генерации кода на 1С, но до сих пор нет единого способа объективно сравнить их качество. Объясняем, как работают метрики BLEU, CodeBLEU и pass@k, и как их можно адаптировать для оценки LLM в экосистеме 1С. Показываем, какие задачи – от простых функций до рефакторинга – помогают полноценно оценить интеллект модели и ее знание платформы. Разбираем ключевую проблему проверки логики и синтаксиса в автоматическом режиме и показываем бенчмарк, который решает эту задачу, сравнивая ChatGPT, Claude, GigaChat и другие модели по единым стандартам.

31.10.2025    1339    Vaslot    5    

11

Нейросети Рефакторинг и качество кода Программист Бесплатно (free)

ИИ для код-ревью – не просто модный тренд, а реальный инструмент, который уже помогает разработчикам экономить время и повышать качество кода. В статье разбираемся, как запустить локальную LLM на базе Ollama, подключить ее к Git через Webhook и Python-скрипт, а также какие параметры модели отвечают за точность и галлюцинации. Делимся схемой работы, настройками и результатами тестирования, доказывая, что автоматизированное код-ревью действительно может работать – даже без космического бюджета.

30.10.2025    1725    user2100900    3    

5

Нейросети Бесплатно (free)

Если вам кажется, что искусственный интеллект – это просто модный хайп, то самое время пересмотреть свои взгляды. Показываем, как с помощью протокола MCP (Model Context Protocol) превратить языковую модель в полноценного помощника, способного работать с вашей базой 1С: запрашивать данные, анализировать метаданные и создавать новые объекты по команде. На живых примерах объясняем, как подключить MCP-сервер к IDE Cursor, безопасно использовать локальные модели и уже сегодня начать интегрировать 1С и приложения с ИИ. Вы получите готовый open-source проект, с которым сразу сможете начать свои эксперименты.

27.10.2025    5899    wonderboy    20    

40

Нейросети Программист Бесплатно (free)

Искусственный интеллект перестал быть только «чатиком для домашних дел» – отечественные on-prem LLM уже сегодня помогают автоматизировать бизнес-процессы. Поделимся практическими кейсами внедрения LLM, покажем примеры из 1С и других корпоративных систем и расскажем, где нейросети действительно заменяют человека, а где пока нет. Вы узнаете, как безопасно и эффективно использовать LLM в автоматизации, на что обратить внимание и какие перспективы это открывает для сообщества 1С.

27.10.2025    659    user1983065    0    

2
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. HomoCuriosus 28 07.10.25 15:35 Сейчас в теме
Добрый день.
Отличная статья! Все разложено по полочкам.
Как можно посмотреть программный код? Вы писали про github.
Для отправки сообщения требуется регистрация/авторизация