или авторизуйтесь, если у вас он уже есть
Обычно LLM под капотом чат бота начинается с большого системного промпта. Там тщательно описано как модели себя вести, чего не делать, в каком тоне отвечать. Но почему то, как только пользователь начинает давить, эмоционально или ситуацией LLM начинает вести себя не так вы ожидали, игнорировтаь ваши запреты, или просто начинать полностью исполнять инструкции пользователя.
В демо я показываю как одна и таже же модель встроена в разные виды архитектурного графа: простой ChatClientAgent с разными вариантами промптов (что бы показать что только промпт не работает), structured self-check и полноценный workflow, в котором анализ намеряний пользователя отделён от ответа, а дальнейшее действие выбирает код.
Пример собран на недавно вышедьшей Microsoft Agent Framework из типизированных Executor, условных рёбер WorkflowBuilder, structured output и настоящего AIFunction. И демонстрирует, как мы перекладываем отвественность за важные решения на код.
Тезисы
Хороший промпт улучшает ответ, но не разделяет ответственность. Если один LLM вызов анализирует запрос, следит за безопасностью и отвечает пользователю, то решения остаются внутри недетерминированной модели.
Structured output делает вывод модели доступным коду. ChatClientAgent возвращает типизированный результат: тип запроса, признак атаки и разобранные моделью данные.
Классификация полезна только тогда, когда влияет на следующий шаг. В self-check варианте модель может правильно распознать атаку и всё равно сформулировать неудачный ответ. В workflow результат анализа читает код и выбирает отдельную ветку.
Microsoft Agent Framework позволяет явно описать управление потоком. Узлы представлены типизированными Executor, а переходы — условными рёбрами WorkflowBuilder. Обычный разговор, медицинский запрос, атака и отчёт о тренировке проходят разными путями.
Инструменты должны вызываться из разрешённой ветки. Отчёт о тренировке превращается в типизированные аргументы, после чего workflow вызывает AIFunction calculate_man_days. Модель формулирует финальный ответ уже по результату вызова инструмента.
Граф полезен ещё и как средство наблюдаемости. По событиям завершения executors можно восстановить фактический путь запроса и увидеть, почему система ответила, отказала или вызвала инструмент.