Большие языковые модели и их ограничения
Большие языковые модели, которые предоставляют нам такие компании, как 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-системами. Наверняка, изучая какие-то библиотеки и готовые решения, вы столкнётесь с этим фреймворком.