Паттерны программирования при работе с LLM. agents.. agents. ai.. agents. ai. Function Calling.. agents. ai. Function Calling. llm.. agents. ai. Function Calling. llm. Natural Language Processing.. agents. ai. Function Calling. llm. Natural Language Processing. python.. agents. ai. Function Calling. llm. Natural Language Processing. python. rag.. agents. ai. Function Calling. llm. Natural Language Processing. python. rag. Анализ и проектирование систем.. agents. ai. Function Calling. llm. Natural Language Processing. python. rag. Анализ и проектирование систем. архитектура.. agents. ai. Function Calling. llm. Natural Language Processing. python. rag. Анализ и проектирование систем. архитектура. искусственный интеллект.. agents. ai. Function Calling. llm. Natural Language Processing. python. rag. Анализ и проектирование систем. архитектура. искусственный интеллект. Машинное обучение.. agents. ai. Function Calling. llm. Natural Language Processing. python. rag. Анализ и проектирование систем. архитектура. искусственный интеллект. Машинное обучение. паттерны.. agents. ai. Function Calling. llm. Natural Language Processing. python. rag. Анализ и проектирование систем. архитектура. искусственный интеллект. Машинное обучение. паттерны. паттерны проектирования.. agents. ai. Function Calling. llm. Natural Language Processing. python. rag. Анализ и проектирование систем. архитектура. искусственный интеллект. Машинное обучение. паттерны. паттерны проектирования. промпт-инжиниринг.

LLM – мощный инструмент, но его эффективность в продакшене зависит не от одного «хитрого промпта», а от всей архитектуры: что мы даём модели, как управляем её рассуждением и как проверяем/обрабатываем результат. В этой статье – компактная карта паттернов, разбитая по этапам конвейера: Input -> Reasoning -> Output.

Введение

Статей про LLM – вагон, и у всех свои “трюки”. Мне не хватало схемы, которая раскладывала бы эти “трюки” по полочкам.

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

С чем мы работаем? Наши инструменты.

В центре всего стоит LLM. Ее задача – предсказывать следующее слово на основе предыдущих. Мы даем ей текст, а она, токен за токеном, его продолжает.

Но есть важный нюанс: LLM на выходе дает не сам токен, а распределение вероятностей по всему своему словарю. А уже отдельный алгоритм сэмплирования (т.е. выбора следующего токена) решает, какой токен выбрать из этого распределения. В простейшем случае мы всегда берем самый вероятный (greedy-подход), но чаще всего мы управляем процессом с помощью параметров:

  • temperature: Наша “ручка креативности”. Низкая температура (близкая к 0) делает ответы более предсказуемыми и фактическими, высокая – более разнообразными и случайными.

  • top_p / top_k: Ограничивают выборку только самыми вероятными токенами, отсекая “хвост” распределения.

Но самый мощный рычаг управления генерацией это Structured Outputs. Вместо того чтобы просить LLM вернуть JSON и потом молиться, чтобы он был валидным, мы вмешиваемся в сам процесс сэмплирования.
На каждом шаге, перед выбором следующего токена, мы применяем “маску”, которая на лету запрещает все токены, нарушающие нашу заранее определенную структуру. Модель хотела бы сгенерировать что-то не то, но мы ей просто не позволяем.

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

Мы увидим дальше, как этот низкоуровневый механизм используется в сильных паттернах.

Еще один инструмент в нашем ящике это модели-эмбеддеры. В отличие от генераторов, они не пишут текст, а “понимают” его. Они превращают фрагмент текста в числовой вектор (эмбеддинг) так, чтобы похожие по смыслу тексты имели похожие векторы. Это позволяет нам сравнивать текст по смыслу.

Входные данные

Все начинается с контекста. Что мы “покажем” модели перед тем, как она начнет генерировать ответ? От этого зависит 90% успеха. На этом этапе мы формируем входные данные, которые получит LLM.

Промптинг

Это базовый уровень. Тут мы ставим задачу для LLM. В коде промпт обычно выглядит как большая строка, часто с плейсхолдерами для переменных. Перед отправкой в модель мы форматируем этот шаблон, подставляем в него запрос пользователя, найденные через RAG документы или примеры хороших ответов (few-shot prompting).
Именно здесь мы формулируем задачу для LLM, указываем стиль ответа, формат вывода.

Хороший материал на эту тему: https://www.promptingguide.ai/

RAG

Retrieval Augmented Generation – генерация дополненная поиском. Выполняем поиск информации, добавляем ее в контекст, генерируем ответ на основе найденной информации.
Тема очень популярная, различных подходов и хитростей тут много, можно набрать на еще одну статью.

Memory

Цель – дать LLM память, хотя бы в рамках одного диалога.
Возможные подходы:

  • Держать в контексте полную историю диалога – вычислительно дорого, длина ограничена.

  • Использовать скользящее окно диалога с несколькими последними сообщениями.

  • Сжатие диалога – иногда просим LLM сжать историю сообщений.

  • Дополнительные системы – например, даем LLM возможность сохранять факты о пользователе, как в фиче “Память” у веб версии ChatGPT. Пример “дополнительной системы” для памяти – https://arxiv.org/abs/2501.13956

Управление мышлением модели

На этом этапе мы управляем процессом ответа LLM. Это паттерны, которые заставляют модель не просто генерировать текст, а решать задачи.

Декомпозиция задачи

Частая проблема при решении сложных задач – модель пытается ответить сходу и ошибается. Мы можем разбить задачу на небольшие шаги. Самый простой вариант – Chain of Thought prompting (CoT, цепочка мыслей) . Мы просто добавляем инструкцию вида “думай по шагам”.
Другой вариант – мы вручную прописываем для модели жесткий план, которому она должна следовать при рассуждении.

Агенты и инструменты

Модель следует не заданному плану решения, а строит его сама, в реальном времени. Агент – это LLM, у которой есть доступ к набору инструментов (Tools), например:

  • Поиск в интернете

  • API вашей CRM

  • Интерпретатор кода

  • Вызов другой LLM системы Сам механизм, который позволяет модели “вызывать” различные инструменты называется Function Calling. Например: ReAct промптинг – просим модель сначала порассуждать, а затем вызвать подходящую функцию. (Вызов функции может выглядеть как сигнатура python функции в ответе модели, или как особый токен при генерации) Несколько агентов можно объединять в одну мультиагентную систему для совместного решения задач.

Routing

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

Schema Guided Reasoning

Это не столько отдельный паттерн, сколько дополнительный инструмент который прокачивает все остальные паттерны.
Суть Schema Guided Reasoning (SGR) – в использовании Structured Outputs не просто для форматирования финального ответа, а для управления самим процессом мышления модели. Мы описываем логику рассуждений в виде строгой схемы, например Pydantic-класса, и модель вынуждена заполнять схему шаг за шагом. Это гарантирует нам, что все этапы рассуждений будут пройдены, ничего не будет пропущено.
Используя Enum, вложенные классы и даже динамическое создание классов мы можем упаковывать сложные цепочки рассуждений в один запрос к LLM.
Подробнее: https://abdullin.com/schema-guided-reasoning/patterns

Выход: работаем с результатом генерации

Форматирование и валидация

Просим LLM указывать результат работы в определенном формате, например XML или JSON. (Для JSON можно использовать Structured Outputs чтобы гарантировать корректность)

В случае когда не получилось распарсить ответ, можно использовать исправляющий промпт вида "твой ответ дал ошибку: {ошибка}, исправь форматирование своего ответа..."

Guardrails

Ответ может быть идеальным по форме, но недопустимым по содержанию. Guardrails это фильтр безопасности, который может работать:

  1. На входе – опасные запросы от пользователя

  2. На выходе – недопустимые ответы нашей системы Может быть реализовано разными способами:

  • Обычные regex фильтры

  • Использование специализированных моделей-классификаторов (например Llama Guard)

  • Использование второй LLM для оценки ответа

Caching

Если мы получаем запрос на который уже отвечали ранее, то ответ можно просто достать из кеша. Это экономит время и вычисления. Кеширование может быть как на основе полного совпадения строки, так и на основе семантического сходства, для этого используются эмбеддинги запросов.
Пример – https://github.com/zilliztech/gptcache

Жизненный цикл

Тут не про обработку одного запроса, а про принципы разработки системы вцелом.

Observability (наблюдаемость)

Нельзя починить то, что невидно. Observability – возможность заглянуть под капот приложения. Не просто запрос и финальный ответ, а весь путь:

  • В какую подсистему Router отправил запрос?

  • Какие документы извлек RAG?

  • Какие “мысли” думал агент когда выбирал инструмент?

  • Сколько времени и токенов понадобилось на каждом шаге? Это основа для отладки и мониторинга, а также главный источник данных для Data Flywheel. Инструмент: https://phoenix.arize.com/

Evaluation (Оценка)

“Как понять что мои изменения не сломали то, что уже работало?” – Вместо ручной проверки “на глазок”, мы создаем наборы данных и прогоняем их через систему, замеряя метрики. Самый мощный подход здесь это LLM-as-a-Judge. Для оценки качества ответа нашей системы мы используем более мощную LLM, которая сравнивает результат с эталоном или оценивает по заданным критериям.

Fine-tuning (Дообучение)

Иногда промптов и RAG недостаточно, чтобы добиться нужного поведения системы. Fine-tuning это процесс дополнительного обучения LLM модели на вашем собственном датасете.

Data Flywheel (Маховик данных)

Система должна самосовершенствоваться. Цикл выглядит так:

  • Пользовали взаимодействуют с системой

  • Мы собираем запросы, ответы, обратную связь (лайки, дизлайки, копирование ответа, правки)

  • Эти данные становятся “топливом” – мы используем их для создания тестовых и обучающих датасетов

  • Обновленная, более умная система выкатывается в продакшен И так по кругу.

Заключение

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

Какими паттернами пользуетесь вы? Чего не хватает/лишнее в моей схеме? Жду ваших мнений в комментариях.

Автор: ya_ne_ivan

Источник

Rambler's Top100