Введение в Prompt Engineering и API нейросетей: фундамент взаимодействия с LLM

Курс закладывает основу для работы с большими языковыми моделями через понимание механики промптинга и программного доступа к ИИ. Слушатели освоят базовые техники управления контекстом и напишут первый скрипт для автоматизации запросов.

1. Анатомия промпта и детерминизм: как управлять вероятностным выводом модели

Анатомия промпта и детерминизм: как управлять вероятностным выводом модели

Один из самых неочевидных фактов при первой работе с большими языковыми моделями (LLM) заключается в том, что при отправке абсолютно идентичного запроса дважды, вы, скорее всего, получите два разных ответа. В классическом программировании вызов функции get_user(id=5) всегда возвращает один и тот же результат. В мире нейросетей запрос «Напиши функцию сортировки» каждый раз запускает вероятностный процесс. Понимание того, как обуздать эту случайность и превратить вероятностный генератор текста в предсказуемый программный модуль — фундамент Prompt Engineering.

Иллюзия понимания и механика следующего токена

Языковые модели не обладают сознанием, не «думают» над ответом целиком и не планируют структуру абзацев заранее. В своей основе архитектура Transformer, на которой построены современные LLM, выполняет одну узкую математическую задачу: авторегрессионное предсказание следующего токена.

Токен — это базовая единица текста для нейросети. В зависимости от токенизатора, это может быть целое слово, слог или отдельный символ. Получив на вход последовательность токенов, модель вычисляет вероятности для всех возможных следующих токенов из своего словаря (который может содержать 50–100 тысяч вариантов).

Если мы подаем на вход фразу «Столица Франции — это», внутри модели происходит расчет логитов (сырых числовых оценок) для каждого слова в словаре. Затем эти оценки преобразуются в вероятности.

!Дерево вероятностей при генерации текста

Модель видит, что токен «Париж» имеет вероятность 94%, токен «прекрасный» — 4%, а токен «город» — 1.9%. В этот момент вступает в работу алгоритм сэмплирования (выборки). Если бы модель всегда выбирала токен с максимальной вероятностью (жадное декодирование, greedy decoding), она бы стала абсолютно детерминированной, но ее тексты стали бы сухими, зацикленными и неестественными. Чтобы текст был похож на человеческую речь, алгоритм «бросает кости» с учетом этих вероятностей. В 94 случаях из 100 выпадет «Париж», но есть шанс, что генерация пойдет по пути «Столица Франции — это прекрасный...». Выбор одного токена навсегда меняет контекст для предсказания следующего.

Температура: математика «креативности»

Главный параметр, управляющий тем, как именно модель «бросает кости», называется температурой (). Это не абстрактная метафора, а конкретный делитель в функции Softmax, которая преобразует сырые логиты нейросети в итоговые вероятности от 0 до 1.

Формула Softmax с учетом температуры выглядит так:

Где:

  • — итоговая вероятность выбора конкретного токена .
  • — логит (сырая оценка), которую нейросеть присвоила токену .
  • — параметр температуры (обычно в диапазоне от 0.0 до 2.0).
  • — сумма экспонент всех возможных токенов в словаре (нормализация, чтобы сумма всех вероятностей равнялась 1).
  • !Влияние температуры на распределение вероятностей

    Изменение параметра радикально меняет форму распределения вероятностей:

  • (Снижение температуры). При делении логита на число меньше единицы, разрывы между значениями в экспоненте резко увеличиваются. Токен-лидер забирает себе почти 100% вероятности, а шансы остальных стремятся к нулю. При модель переходит в режим жадного декодирования. Вывод становится детерминированным (предсказуемым). Это критически важно для задач классификации, написания кода, извлечения JSON и работы с фактами.
  • (Нейтральная температура). Формула работает в базовом режиме. Сохраняется баланс между логикой и вариативностью.
  • (Повышение температуры). Деление на число больше единицы сглаживает разницу между логитами. Токен, который изначально имел 90%, может упасть до 40%, а маловероятные токены (1-2%) получают существенный вес. Текст становится непредсказуемым. При значениях модель начинает генерировать бессвязный набор букв, так как вероятности всех слов в словаре становятся почти равными. Этот режим используют для генерации идей, стихов или маркетинговых слоганов.
  • Альтернативные ограничители: Top-K и Top-P

    Температура меняет значения вероятностей, но не исключает маловероятные токены полностью. Даже при остается микроскопический шанс, что модель выдаст совершенно неуместное слово. Для жесткого отсечения «хвоста» маловероятных вариантов в API нейросетей используются параметры Top-K и Top-P (Nucleus Sampling).

    Метод Top-K

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

    Если установить , модель на каждом шаге будет выбирать только из 5 самых логичных слов. Это предотвращает внезапные галлюцинации, но может сделать текст слишком шаблонным.

    Метод Top-P (Nucleus Sampling)

    Вместо фиксированного количества токенов, Top-P отбирает динамическое количество токенов, сумма вероятностей которых достигает порога .

    Рассмотрим пример. Модель предсказывает следующее слово после фразы «Кот спит на...»:

  • «диване» — 0.50
  • «ковре» — 0.30
  • «полу» — 0.15
  • «потолке» — 0.04
  • «шпагате» — 0.01
  • Если мы установим параметр Top-P равным , алгоритм начнет суммировать вероятности сверху вниз: . Порог пройден. В выборке останутся только три слова: «диване», «ковре» и «полу». Абсурдные варианты «потолке» и «шпагате» будут отсечены.

    | Сценарий использования | Рекомендуемые настройки | | :--- | :--- | | Строгий парсинг, JSON, SQL-запросы | , Top-P не имеет значения | | Аналитика, саммаризация документов | , Top-P = 0.5 - 0.7 | | Написание статей, email, чат-боты | , Top-P = 0.9 | | Брейншторминг, креативные тексты | , Top-P = 1.0 |

    Инженерная практика рекомендует изменять только один из параметров (либо Температуру, либо Top-P), оставляя второй в значении по умолчанию (1.0), так как их одновременное изменение делает поведение модели труднопредсказуемым.

    Анатомия промпта как инструмент сужения вероятностей

    Если параметры API (Температура, Top-P) управляют тем, как модель выбирает токен из готового распределения вероятностей, то сам текст промпта формирует это распределение (исходные логиты ).

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

    1. Role (Роль)

    Назначение роли — это не игра в театр. В архитектуре трансформеров слова представлены в виде многомерных векторов (эмбеддингов). Задавая роль, вы смещаете вектор внимания модели в определенный кластер ее весов.

    Сравните:

  • Без роли: «Объясни, как работает транзистор». Модель может выбрать тон из учебника физики, детской энциклопедии или форума радиолюбителей.
  • С ролью: «Ты — Senior Hardware Engineer. Объясни работу транзистора». Слова «Senior» и «Engineer» резко повышают логиты для профессиональных терминов (затвор, сток, исток, легирование) и обнуляют вероятности для детских аналогий.
  • 2. Context (Контекст)

    Модель не знает, кто вы, зачем вам нужен ответ и где он будет использоваться. Контекст сужает вариативность форматов. Фраза «Этот текст будет использоваться как короткий пост в профессиональном Telegram-канале для программистов» отсекает вероятности генерации длинных вступлений и побуждает модель использовать специфическое форматирование.

    3. Task (Задача)

    Ядро промпта. Задача должна содержать активный глагол и конкретный объект воздействия. «Сделай ревью кода» — плохая задача, так как слово «ревью» многозначно. «Найди уязвимости SQL-инъекций в предоставленном Python-коде и напиши исправленный вариант» — точная задача, максимизирующая вероятности токенов, связанных с безопасностью.

    4. Constraints и Format (Ограничения и формат вывода)

    Самый мощный инструмент детерминизма на уровне текста. Ограничения говорят модели, чего делать нельзя.
  • «Не используй сторонние библиотеки, только встроенные модули Python».
  • «Верни результат строго в формате JSON с ключами "error" и "solution", без приветствий и поясняющего текста».
  • Последнее ограничение критически важно для программной интеграции LLM. Если модель вернет идеальный JSON, но перед ним напишет «Конечно, вот ваш код:», парсер на вашей стороне выдаст ошибку, и система упадет.

    Управление вероятностным выводом модели — это двусторонний процесс. С одной стороны, мы используем строгую структуру промпта (Роль, Контекст, Задача, Формат), чтобы заставить нейросеть присвоить максимальные логиты нужным нам токенам. С другой стороны, мы применяем математические ограничители (Температуру и Top-P), чтобы запретить алгоритму сэмплирования отклоняться от этого идеального пути. Только комбинация лингвистической точности и правильных параметров API позволяет превратить LLM из непредсказуемого собеседника в надежный вычислительный модуль.

    2. Программный доступ к LLM: работа с API, токенизация и управление параметрами генерации

    Программный доступ к LLM: работа с API, токенизация и управление параметрами генерации

    Когда пользователь взаимодействует с нейросетью через веб-интерфейс, платформа скрывает от него десятки вычислительных процессов. Чат-окно создает иллюзию непрерывного диалога с живым собеседником, маскируя тот факт, что каждый запрос — это изолированная транзакция, требующая строгой сериализации данных, точного подсчета ресурсов и явной передачи всего исторического контекста. Переход от веб-интерфейса к программному доступу через API (Application Programming Interface) требует смены парадигмы: текст перестает быть просто набором букв и становится структурированным JSON-объектом, а каждое сгенерированное слово приобретает конкретную финансовую стоимость.

    Архитектура REST API в контексте языковых моделей

    Взаимодействие с коммерческими и открытыми LLM (Large Language Models) стандартизировано вокруг архитектуры REST. Разработчик отправляет HTTP-запрос на определенный URL (endpoint), передавая данные в формате JSON, и получает обратно JSON-ответ.

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

    Типичный POST-запрос к конечной точке генерации текста (например, /v1/chat/completions) состоит из трех обязательных блоков:

  • Заголовки (Headers): содержат метаданные запроса и ключи авторизации. Ключевой заголовок Authorization: Bearer <API_KEY> подтверждает право пользователя на использование вычислительных мощностей сервера.
  • Модель (Model): явное указание версии нейросети (например, gpt-4o, claude-3-opus, llama-3-70b). Разные модели имеют разную архитектуру, размер контекстного окна и стоимость.
  • Массив сообщений (Messages): структурированный контекст диалога.
  • API не обладает встроенной памятью. Если вы хотите, чтобы модель «помнила» ваш предыдущий вопрос, вы обязаны отправить всю историю переписки в массиве сообщений при каждом новом запросе.

    Токенизация BPE: экономика и алгоритмика текста

    Для API текст не существует в виде символов или слов. Перед отправкой на сервер строка проходит через алгоритм токенизации. Современные модели используют алгоритм Byte Pair Encoding (BPE).

    BPE работает не с лингвистическими правилами, а со статистикой встречаемости последовательностей байтов. Алгоритм начинает с отдельных байтов и итеративно объединяет самые частые соседние пары в единый токен. Например, в английском языке последовательность букв " t", "h", "e" встречается настолько часто, что сливается в один токен " the" (включая пробел перед словом).

    Этот статистический подход порождает серьезную техническую и экономическую асимметрию между языками. Английский текст, на котором обучалось большинство моделей, токенизируется крайне эффективно: одно слово обычно равно одному токену. Тексты на языках с кириллическим, арабским или иероглифическим письмом разбиваются на токены гораздо менее оптимально.

    Сравним фразу на двух языках с использованием популярного токенизатора cl100k_base:

  • Фраза "Hello, beautiful world!" разбивается на 5 токенов.
  • Фраза "Привет, прекрасный мир!" может быть разбита на 12–15 токенов, так как русские слова часто дробятся на отдельные слоги или даже символы из-за их меньшей частотности в обучающей выборке токенизатора.
  • Эта разница напрямую влияет на стоимость работы системы. Биллинг в API LLM рассчитывается строго по количеству обработанных токенов. При этом входящие токены (промпт) и исходящие (ответ модели) тарифицируются по-разному, так как генерация ответа требует больше вычислительных ресурсов, чем параллельное чтение промпта.

    Формула расчета стоимости одного API-вызова выглядит так:

    Где и — количество токенов во входящем запросе и сгенерированном ответе соответственно, а и — тарифные ставки за один токен (обычно указываются за 1000 или 1 000 000 токенов).

    Управление генерацией: параметры JSON-нагрузки

    Помимо массива сообщений, JSON-нагрузка позволяет передать параметры, жестко контролирующие поведение модели. Если Температура и Top-P управляют вероятностным распределением (что определяет креативность), то следующие параметры управляют границами и структурой вывода.

    Ограничение длины и логика остановки

    Параметр max_tokens (или max_completion_tokens) устанавливает жесткий лимит на количество токенов, которые модель может сгенерировать в ответе. Это предохранитель от бесконечной генерации и перерасхода бюджета. Однако достижение лимита max_tokens обрывает текст на полуслове.

    Для смысловой остановки используется параметр stop (stop sequences). Это массив строк (до 4 элементов), при генерации любой из которых модель немедленно прекращает работу, не включая саму стоп-последовательность в финальный ответ. Например, если вы просите модель сгенерировать ровно 5 идей и передаете в параметр stop строку "6.", генерация гарантированно остановится после пятого пункта, даже если модель планировала продолжать список. Это критически важно при парсинге данных, когда требуется извлечь строго определенный блок текста.

    Штрафы за повторения

    Для управления лексическим разнообразием API предоставляет два математических инструмента: presence_penalty и frequency_penalty. Они принимают значения от -2.0 до 2.0 и модифицируют сырые логиты (вероятности) токенов перед финальным выбором.

    | Параметр | Принцип действия | Метафора | Сценарий применения | | :--- | :--- | :--- | :--- | | Presence Penalty (Штраф за присутствие) | Применяет фиксированный штраф к токену, если он уже встречался в сгенерированном тексте хотя бы один раз. | «Мы об этом уже говорили, давай сменим тему». | Генерация мозговых штурмов, сюжетов, поиск новых идей. Заставляет модель переходить к новым концепциям. | | Frequency Penalty (Штраф за частоту) | Применяет динамический штраф, который растет пропорционально тому, сколько раз токен уже был сгенерирован. | «Ты слишком часто повторяешь это слово, подбери синоним». | Написание статей, копирайтинг, устранение слов-паразитов и тавтологии в длинных текстах. |

    Структура ответа и извлечение данных

    Ответ сервера (Response) — это многоуровневый JSON-объект. Разработчику редко нужен весь объект целиком; ценность представляет только сгенерированный текст и статистика использования.

    Типичный ответ содержит массив choices. Поскольку API позволяет генерировать несколько вариантов ответа на один запрос (параметр n), результаты возвращаются списком. В 99% случаев используется один вариант, поэтому целевой текст всегда находится по пути choices[0].message.content.

    Не менее важным является блок usage, который возвращается в конце ответа. Он содержит ключи prompt_tokens, completion_tokens и total_tokens. Именно эти цифры приложение должно логировать для мониторинга расходов и предотвращения исчерпания лимитов (Rate Limits), которые провайдеры устанавливают на количество токенов в минуту (TPM — Tokens Per Minute).

    Реализация базового клиента на Python

    Для отправки запроса не обязательно использовать специализированные SDK (Software Development Kit). Понимание работы на уровне базовых HTTP-запросов дает полный контроль над процессом. Ниже представлен скрипт с использованием стандартной библиотеки requests, демонстрирующий сборку JSON-нагрузки и парсинг ответа.

    В этом скрипте явно видна граница между инструкциями для модели (внутри массива messages) и инструкциями для движка генерации (параметры на уровне словаря payload).

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

    3. Техники структурированного промптинга: Few-Shot, Chain-of-Thought и системные инструкции

    Техники структурированного промптинга: Few-Shot, Chain-of-Thought и системные инструкции

    Нейросеть, обученная на терабайтах человеческих знаний и способная написать сонет в стиле Шекспира за две секунды, может уверенно провалить школьную задачу по арифметике. Это происходит не из-за отсутствия «знаний», а из-за архитектурной особенности: авторегрессионная модель не обдумывает ответ заранее. Она предсказывает следующий токен на основе текущего контекста. Если контекст не задает строгих рамок логики или формата, модель выбирает наиболее вероятный, поверхностный путь. Чтобы перевести LLM из режима генерации правдоподобного текста в режим решения конкретных бизнес-задач, применяется структурированный промптинг — набор техник, жестко форматирующих контекстное окно.

    Системные инструкции: фундамент поведения

    В программном взаимодействии с LLM через API (где сообщения разделяются по ролям) системный промпт — это корневая директива. Если пользовательский промпт содержит текущую задачу, то системный определяет глобальные правила игры, ограничения и персону модели.

    Системная инструкция решает три фундаментальные задачи:

  • Задание ролевой модели. Активация специфичных весов нейросети, связанных с определенной предметной областью.
  • Определение формата вывода. Жесткая фиксация структуры ответа (например, только валидный JSON, отсутствие приветствий).
  • Установка границ (Guardrails). Блокировка нежелательного поведения.
  • Слабый системный промпт выглядит как пожелание: «Ты полезный ассистент службы поддержки интернет-магазина». При таком подходе модель может начать давать советы конкурентов, извиняться на три абзаца или использовать сложный технический жаргон.

    Инженерный системный промпт работает как алгоритм с четкими условиями: > Ты — AI-ассистент первой линии поддержки магазина электроники. > Твоя задача: классифицировать проблему клиента и предложить одно решение. > > Ограничения: > 1. Отвечай не более чем 3 предложениями. > 2. Никогда не упоминай названия других магазинов. Если клиент спрашивает о конкурентах, отвечай: "Я могу проконсультировать вас только по нашему ассортименту". > 3. Если проблема связана с возвратом средств, не пытайся ее решить. Выведи строго одну фразу: "Перевожу диалог на оператора". > 4. Не используй вводные слова ("Конечно", "С радостью"). Начинай ответ сразу по сути.

    Задавая такие рамки, мы сужаем распределение вероятностей (тот самый механизм, которым управляет параметр Temperature). Модель физически теряет возможность сгенерировать токен «Конечно», потому что в ее контексте жестко прописан запрет на это слово.

    In-Context Learning: от Zero-Shot к Few-Shot

    Модели не дообучаются (не меняют свои внутренние веса) в момент вашего к ним обращения. Однако они обладают способностью к In-Context Learning (обучению в контексте) — умению распознавать паттерны внутри переданного им текста и продолжать их.

    Zero-Shot Prompting (Промптинг без примеров) — это постановка задачи «в лоб». Мы полагаемся на то, что модель видела подобную задачу на этапе тренировки. Запрос: «Определи тональность отзыва: "Батарея держит всего два часа, полный мусор". Тональность:» Проблема Zero-Shot в его непредсказуемости. Модель может ответить «Негативная», а может написать «Этот отзыв выражает крайнее недовольство пользователя...», сломав парсер в вашем приложении.

    Few-Shot Prompting (Промптинг с несколькими примерами) решает проблему непредсказуемости. Мы передаем модели примеров пар «входные данные эталонный результат» до того, как задать целевой вопрос.

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

    Пример структурированного Few-Shot запроса для извлечения сущностей: > Извлеки из текста название компании и сумму сделки в формате JSON. > > Текст: Вчера ООО "Ромашка" подписала контракт на поставку оборудования стоимостью 1.5 млн рублей. > Результат: {"company": "ООО Ромашка", "amount": "1500000"} > > Текст: Корпорация "Глобал" приобрела стартап за \rightarrow\rightarrow\rightarrow$ сделай вывод.

    Нюансы применения и цена рассуждений

    Использование структурированного промптинга, особенно Chain-of-Thought, имеет свою цену в архитектуре ИИ-решений.

    Во-первых, это увеличивает задержку ответа (latency). Генерация промежуточных рассуждений требует времени. Если пользователю нужен мгновенный ответ в чате, длинная цепочка CoT сделает систему визуально медленной. Во-вторых, это напрямую влияет на стоимость. В API тарификация идет за каждый сгенерированный токен. Если финальный ответ состоит из 10 токенов, а цепочка рассуждений к нему — из 200, стоимость вызова возрастает в 20 раз.

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

    Архитектура надежного промпта для интеграции в код всегда строится по принципу матрешки. На внешнем уровне находится системная инструкция, задающая жесткие границы и формат. Внутри располагаются Few-Shot примеры, калибрующие ожидания. И в самом центре — пользовательский запрос, который при необходимости сопровождается требованием расписать шаги (CoT). Такой синтез техник превращает вероятностный генератор текста в детерминированный инструмент для обработки данных.

    4. Практикум: создание первого Python-клиента для автоматизированного взаимодействия с нейросетью

    Практикум: создание первого Python-клиента для автоматизированного взаимодействия с нейросетью

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

    Изоляция секретов: управление API-ключами

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

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

    Она позволяет вынести все секреты в скрытый файл .env, который располагается в корне проекта:

    Этот файл обязательно добавляется в .gitignore. В самом Python-скрипте значения загружаются в память при старте приложения:

    Такой подход обеспечивает мобильность кода: на локальном компьютере разработчика скрипт читает тестовые ключи из .env, а при развертывании в Docker или Kubernetes — получает боевые ключи напрямую из защищенного хранилища среды исполнения, при этом сам код не меняется ни на символ.

    Проектирование клиента: объектно-ориентированный подход

    Отправка единичного HTTP-запроса через библиотеку requests требует передачи полного набора параметров: URL, заголовков с авторизацией, тела запроса. Если в проекте десятки вызовов к нейросети из разных модулей, дублирование этого кода приведет к хаосу. Оптимальное архитектурное решение — инкапсулировать логику работы с API внутри отдельного класса.

    !Архитектура класса LLMClient

    Класс LLMClient берет на себя рутину: он хранит базовые настройки, автоматически подставляет заголовки авторизации и обрабатывает сетевые таймауты.

    Обратите внимание на параметр timeout=30. При программном взаимодействии с LLM задержки (latency) могут быть значительными. Генерация длинного ответа иногда занимает 10–20 секунд. Если сетевое соединение оборвется без явного сигнала, стандартный метод requests.post будет ждать ответа бесконечно, блокируя выполнение всей программы. Явное указание таймаута гарантирует, что через 30 секунд скрипт прервет ожидание и выбросит исключение, которое можно обработать.

    Динамическое формирование контекста для Few-Shot

    В предыдущих материалах разбиралась структура In-Context Learning: передача модели примеров (Few-Shot) и системных инструкций. При работе через API этот контекст передается в виде массива словарей messages.

    Программный подход позволяет формировать этот массив динамически, собирая его как конструктор перед отправкой. Рассмотрим задачу маршрутизации обращений в техподдержку. Нам нужно классифицировать входящий текст по трем категориям: Hardware, Software, Network.

    !Процесс сборки массива сообщений

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

    Разделение ролей на system, user и assistant позволяет модели четко отличать правила игры от примеров и от текущей задачи. Установка температуры в максимизирует вероятность того, что модель выберет токен из разрешенного списка, не пытаясь проявить креативность и добавить лишние слова вроде «Я думаю, это категория...».

    Построение отказоустойчивости: Rate Limits и парсинг

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

    Обработка HTTP 429 и Exponential Backoff

    Провайдеры API защищают свои серверы от перегрузок с помощью механизма Rate Limiting. Если ваш скрипт отправляет запросы слишком быстро, сервер вернет статус-код 429 Too Many Requests. Стандартная реакция неопытного разработчика — остановить выполнение скрипта. Профессиональный подход — использовать алгоритм Exponential Backoff (экспоненциальная задержка).

    Суть алгоритма: при получении ошибки 429 скрипт делает паузу, а затем повторяет запрос. Если снова возникает ошибка — пауза удваивается. Это снижает нагрузку на сервер провайдера и позволяет скрипту самостоятельно «пробить» лимит без участия человека.

    Модифицируем метод отправки запроса в нашем классе:

    Очистка JSON от Markdown-разметки

    Часто от модели требуется вернуть структурированные данные в формате JSON для дальнейшей обработки в коде. Даже если в системном промпте строго указано «выведи только валидный JSON без комментариев», модели, обученные на огромных массивах данных из GitHub и StackOverflow, имеют сильную тенденцию оборачивать код в Markdown-блоки:

    json { "status": "success", "entities": ["Apple", "Microsoft"] }

    Если передать такую строку напрямую в стандартный парсер json.loads(), он немедленно выбросит ошибку json.decoder.JSONDecodeError, так как обратные кавычки и слово «json» не являются частью стандарта JSON.

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

    json и и (?:json)?\n?(.*?)\n?

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

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