Большие языковые модели и их ограничения

Большие языковые модели, которые предоставляют нам такие компании, как OpenAI в виде GPT, Anthropic в виде Claude Sonnet, Opus и так далее, Google в виде Gemini — это так называемые LLM-модели (Large Language Models). Вроде бы они умеют очень много, но если мы хотим построить систему, в которой модель должна отвечать нам только строго определённым образом и использовать какие-то определённые документы, которые мы ей предоставим, то без дополнительных библиотек и фреймворков нам может быть достаточно сложно реализовать такую задачу.

Почему больших языковых моделей может в реальности быть мало для решения таких задач? Во-первых, для взаимодействия с большой языковой моделью у нас не будет памяти, не будет запоминаться состояние диалога. Нет доступа к вашим данным — PDF, Word, база данных. Большая языковая модель по умолчанию не может к ним получить доступ, если вы пишете какое-то программное решение.

Для взаимодействия с вашими данными нужны какие-то инструменты, которые предоставят в нужном виде и формате большой языковой модели эти данные. Большая языковая модель не может работать с внешними запросами, API, файлами и так далее — всё это нужно ей предоставлять.

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

Нам нужно выбирать только релевантную информацию и давать её нашей модели. Вариант «вход → промпт → LLM-модель → выход» для сложных систем, где происходит взаимодействие с разными инструментами, нам не подойдёт. Нам нужен посредник между LLM-моделью и теми данными и задачами, которые у нас есть.

LangChain как фреймворк для работы с LLM

LangChain — это один из самых популярных инструментов, который стал стандартом де-факто для разработки таких систем. По сути, это некая операционная система для вашей LLM-модели. Ядро LangChain — это большая языковая модель, которую вы будете использовать: OpenAI, Gemini и так далее, либо какая-то ваша локальная модель.

Эта модель с помощью обёртки LangChain может взаимодействовать с документами, с памятью, с API, с базами данных и так далее. LangChain — это фреймворк, который соединяет LLM с внешним миром и позволяет создавать полноценные приложения, а не просто вызывать эту модель. Проще говоря, он помогает системе понимать контекст, работать с документами, использовать инструменты и запоминать состояние диалога.

Набор инструментов, который даёт нам LangChain:

  • модели
  • промпты
  • цепочки
  • загрузчики
  • векторные хранилища
  • разделители
  • память
  • агенты

Chain переводится как «цепочка», и всё взаимодействие от запроса пользователя до получения результата происходит по некой цепочке вызова различных инструментов. Промпт → модель → выходной парсер → следующий шаг. На каждом этапе каким-то образом готовятся и обрабатываются данные. Цепочки — это фундамент для подготовки данных и для выдачи конкретного требуемого результата от LLM-модели. Они последовательно соединяют компоненты для решения сложных задач и являются основой для создания систем с RAG, агентами и сложной логикой.

Пример работы RAG-системы

Когда мы хотим, чтобы модель каким-то образом ответила, мы берём Loaders (загрузчики) — они загружают данные из различных форматов: PDF, текст, HTML и так далее. Далее используется модуль Text Splitters (разделители) — умное разделение больших документов на семантически связанные чанки, кусочки, с которыми мы можем взаимодействовать для векторизации данных. Затем идёт векторное хранилище для того, чтобы мы могли взаимодействовать с этими данными и предоставить их большой языковой модели.

Примерно так происходит процесс: пользовательский запрос обращается к векторной базе данных. Векторная база данных находит релевантные кусочки, которые могут соответствовать этому запросу. Запрос попадает сразу в промпт, который пойдёт к LLM-модели, а релевантные кусочки, которые нашло векторное хранилище, тоже прикладываются к контексту. Этот большой объединённый промпт отправляется нашей LLM-модели, которая уже даёт ответ на основе полученных данных. Это классическая RAG-система.

За векторное хранилище и промпты отвечает LangChain как фреймворк. Он даёт все инструменты, чтобы делить данные на чанки и объединять запросы — все эти функции есть в LangChain.

Memory — это хранение контекста диалога, позволяет LLM помнить предыдущие сообщения. Агенты — это мозг, принимающий решения. Агент сам рассуждает и решает, какой инструмент использовать: API, базы данных, поиск ответа на вопрос. У агента есть набор инструментов, с которыми он может взаимодействовать и передавать результаты большой языковой модели.

Альтернативы и особенности LangChain

Когда мы пишем какую-то RAG-систему или сложную систему для взаимодействия с искусственным интеллектом, у нас есть два варианта:

  • использовать LangChain
  • написать свой код самостоятельно, не прибегая к стороннему фреймворку

Оба варианта имеют право на жизнь. Нужно понимать, что работа с большими языковыми моделями и построение RAG-системы — это не обязательно LangChain. Это может быть своя самописная система, где вы будете сами писать все функции для взаимодействия с моделью искусственного интеллекта.

LangChain — это не только Python. Хотя Python — самая зрелая и полная версия с максимумом интеграций, стандарт де-факто для большинства примеров и документации, с LangChain также можно работать на JavaScript. Есть и другие неофициальные библиотеки, которые тоже могут использовать этот фреймворк, но стандартом де-факто является Python.

Плюсы использования LangChain:

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

Минусы использования LangChain:

  • абстракции могут иногда мешать — проще написать прямой вызов API, чем разбираться в слоях LangChain
  • сложность отладки — вся логика инкапсулирована, найти ошибку в цепочке может быть нетривиально
  • избыточен для простых задач — для простого чатбота или вызова модели без внешних данных он не нужен

LangChain решает реальные проблемы больших языковых моделей: даёт моделям память, доступ к данным, возможность использовать инструменты. Мы получаем модульную архитектуру с гибкими строительными блоками — Chains, агенты, Loaders — для любых задач. Фреймворк ускоряет разработку и позволяет быстро перейти от MVP до production-ready системы.

Это инструмент, который желательно освоить, если вы хотите серьёзно работать с RAG-системами. Наверняка, изучая какие-то библиотеки и готовые решения, вы столкнётесь с этим фреймворком.