Когда готовое решение ломает продукт
В 2025 году мы в Soft Skills Lab запустили пилот: AI-тренер для отработки переговоров. Цель - дать пользователю реалистичный диалог, где агент играет роль оппонента, запоминает контекст, реагирует на эмоции и следует сложному сценарию. Первый инстинкт - взять OpenAI Assistants API. Зачем изобретать велосипед, если есть готовый конструктор агентов с памятью, файлами и вызовами функций? Месяц спустя мы его выбросили. Вот что пошло не так.
Актуальность на 06.02.2026: OpenAI не стоит на месте. Assistants API получил несколько обновлений, включая поддержку более длинного контекста в модели GPT-4.5-Turbo (релиз конца 2025 года) и улучшенное управление файлами. Но фундаментальные архитектурные ограничения, о которых пойдет речь, никуда не делись. Если ваша логика сложнее цепочки "запрос-ответ", вы упретесь в потолок.
Три кита, которые не выдержали веса логики
OpenAI Assistants созданы для линейных диалогов и простых задач. Наш EdTech-агент требовал другого.
1. Память как черный ящик
Assistants хранят историю в Thread. Вы не контролируете, что именно и в каком виде запоминается. Нужно стереть конкретную реплику из середины диалога, потому что пользователь отвлекся? Нельзя. Хотите приоритезировать ключевые факты (имя, должность, цели) над шумом? Нет такого. Агент мог "забыть" условие, оговоренное пять реплик назад, или, наоборот, цепляться за случайную фразу.
# Пример: В Assistants API вы не можете модифицировать историю напрямую
# Вы только добавляете новые сообщения в thread
thread = client.beta.threads.create()
client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="Моя цель - получить повышение зарплаты на 20%"
)
# А как удалить или изменить это сообщение потом? Никак.
2. Условная логика? Забудьте
Сценарий тренировки - это дерево решений. "Если пользователь проявил агрессию, снизить тон. Если упомянул конкурента, спросить о преимуществах. Если трижды избегал вопроса, перейти к жесткой тактике". Assistants не умеют в if-else. Вы можете имитировать это через System Prompt, но это хак, который ломается на третьем шаге. Логика начинает "плыть", агент теряет нить сценария.
3. Логирование для юристов и методологов
В EdTech каждый ответ агента - это учебный материал. Нужно хранить не только финальный текст, но и полную цепочку reasoning: почему агент выбрал такую реплику, какие правила применил, какие варианты отбросил. Assistants дают только итоговое сообщение. Для аудита, улучшения сценариев и, что важно, для защиты в спорных ситуациях этого недостаточно. Подробнее о важности логирования в бизнес-контексте читайте в нашем разборе ИИ-агенты для бизнеса: практическое руководство.
Архитектура платформы, которая не боится сложности
Решение - своя платформа-оркестратор. Ее ядро не LLM, а движок диалога (dialogue engine), который решает, что делать дальше, а LLM - лишь один из исполнителей.
| Компонент | Задача | Технологии (актуально на 2026) |
|---|---|---|
| Движок состояний (State Machine) | Управление сценарием, переходы между шагами | Свой DSL на Python, библиотека transitions 0.9.1 |
| Менеджер памяти (Memory Manager) | Векторное и ключевое хранение фактов, управление историей | ChromaDB 0.5.0, Redis для быстрого доступа |
| Оркестратор LLM (LLM Gateway) | Роутинг запросов к разным моделям, fallback, логирование | Свой сервис на FastAPI, интеграция с AITunnel для доступа к множеству моделей |
| Логгер решений (Decision Logger) | Запись всего контекста, промптов, ответов, метаданных | Elasticsearch 8.15, кастомный формат логов |
1 Проектируем диалоговый движок
Сценарий описываем в YAML. Не в промпте, а в структурированном файле. Это дает версионность и возможность редактирования без переобучения модели.
# scenario_negotiation.yaml
states:
- id: greeting
prompt: "Представьтесь и спросите о цели встречи."
transitions:
- condition: "user_mentioned('зарплата')"
next_state: discuss_salary
- condition: "default"
next_state: clarify_goal
- id: discuss_salary
prompt: "Запросите обоснование для повышения на 20%. Если аргументы слабые, выразите сомнение."
# ...
Движок парсит этот файл, отслеживает текущее состояние и вычисляет условия перехода. Условия - это не промпты, а вызовы функций на Python, которые анализируют историю диалога.
2 Строим гибридную память
Память состоит из трех слоев:
- Оперативная (последние 10 реплик): всегда отправляется в контекст LLM.
- Фактологическая (ключевые данные): хранится в структурированном виде (JSON). Например: {"goal": "raise", "amount": 20, "currency": "%"}. В контекст попадает выжимка.
- Векторная (вся история): в ChromaDB для семантического поиска. Когда пользователь говорит "вернемся к тому, о чем говорили", мы ищем похожие темы.
Это дает контроль. Можно вручную удалить ошибочный факт или перевесить приоритеты.
3 Интегрируем LLM как сервис
Мы не завязываемся на одну модель. Для креативных ответов используем GPT-4.5-Turbo, для анализа тона - более дешевый Claude 3.7 Haiku, а для генерации учебных материалов подключаем локальную модель через Hugging Face. Оркестратор решает, какую модель вызвать, исходя из шага сценария и бюджета. Для упрощения работы с разными провайдерами используем шлюз вроде AITunnel, который дает единый API.
async def generate_response(state, memory, user_message):
# 1. Собираем контекст из памяти
context = memory.get_context_for_llm()
# 2. Берем промпт из текущего состояния сценария
prompt = state.get_prompt()
# 3. Выбираем модель (логика роутинга)
model = router.select_model(state.type, context.length)
# 4. Логируем ВХОДЯЩИЕ данные
logger.log_decision(context, prompt, model)
# 5. Вызов API
response = await llm_gateway.call(model, prompt, context)
# 6. Логируем ИСХОДЯЩИЕ данные
logger.log_response(response)
return response
4 Логируем все. Буквально все
Каждый вызов LLM пишется в Elasticsearch с полным снапшотом: timestamp, user_id, состояние сценария, сырой промпт, ответ, токены использования, продолжительность вызова, выбранная модель. Это не только для отладки. Через месяц мы анализируем логи: на каких шагах пользователи чаще всего сходят со сценария? Какие реплики агента получают низкие оценки? Это золотая жила для итераций продукта. Без такого детального логирования вы летите вслепую.
Цена вопроса: что выиграли, что потеряли
Переход на кастомную платформу - это не про экономию. Это про контроль.
| Критерий | OpenAI Assistants | Кастомная платформа |
|---|---|---|
| Скорость прототипирования | Максимальная. За день работающий бот. | Месяцы разработки. |
| Гибкость логики | Очень низкая. Только линейный диалог. | Любая сложность. Деревья, графы, циклы. |
| Контроль над памятью | Нулевой. Черный ящик. | Полный. Редактируем, фильтруем, приоритезируем. |
| Стоимость владения | Плата за токены + вызовы Assistants API. Просто. | Сервера, разработка, но дешевые локальные модели для части задач. |
| Вендор-лок | 100% зависимость от OpenAI. | Можно сменить модель в любой момент. |
Главный выигрыш - предсказуемость. AI-агент в EdTech не может сегодня быть добрым, а завтра - саркастичным из-за апдейта модели. Наша платформа изолирует бизнес-логику от капризов базовой LLM. Как и в истории Preply vs Duolingo, ключ - в симбиозе, где AI выполняет четко очерченную роль, а не тянет на себе весь продукт.
Партнерский материал: Хотите глубоко разобраться в создании контента для таких агентов? Курс "AI-креатор: создаём контент с помощью нейросетей" от Skillbox научит работать с промптами и генерировать учебные материалы, которые закладывают в память агента.
FAQ: частые вопросы от тех, кто стоит перед выбором
А если использовать новый OpenAI Agent SDK?
К февралю 2026 года OpenAI Agent SDK стал кроссплатформенным. Это шаг вперед, но SDK все равно строится поверх тех же Assistants API или прямых вызовов ChatCompletion. Он абстрагирует рутину, но не решает фундаментальных проблем с памятью и логикой. Подойдет для агентов средней сложности, но не для нашего кейса.
Не проще ли взять готовый фреймворк вроде LangChain?
LangChain, особенно с LangSmith Agent Builder, мощный инструмент. Но он добавляет еще один слой абстракции и сложности. Когда ваша бизнес-логика специфична (как в EdTech), вы тратите больше сил на борьбу с фреймворком, чем на реализацию фич. Иногда фреймворки слишком сложны. Мы выбрали точечные библиотеки под конкретные задачи (векторная БД, state machine), а не монолит.
Какую модель LLM выбрать для ядра?
Не зацикливайтесь на одной. Используйте модель с самым большим контекстом и стабильным поведением для генерации ответов (например, GPT-4.5-Turbo). Для аналитических подзадач (классификация тона, извлечение сущностей) берите более быстрые и дешевые модели (Claude Haiku, Qwen3-7B). Архитектура "оркестратор + шлюз" позволяет гибко менять поставщиков.
Финал: неочевидный совет, который сэкономит год
Начните с OpenAI Assistants. Быстро сделайте прототип и покажите его реальным пользователям. Пока вы не получите обратную связь, вы не поймете, какие именно сложности требуются вашему агенту. Может быть, вашим пользователям хватит линейного диалога? Тогда не стройте космический корабль. Но если в первых же тестах упрутся в ограничения памяти и логики - у вас уже будут аргументы для бизнеса, чтобы закладывать время и бюджет на свою платформу. Не повторяйте нашу ошибку: мы полгода пытались запихнуть невпихуемое в Assistants, костылями имитируя логику. Только когда запустили пилот и увидели, как пользователи теряются, стало ясно - без своего движка не обойтись. Технологии меняются (смотрите планы OpenAI на триллион долларов), но принцип остается: если ваш агент должен думать, а не просто болтать, вам нужен собственный мозг для управления им.