Гайд · TNWS AI

Как добавлять правила конкретного клиента через динамические instructions Pydantic AI

4 мин—

Динамические instructions в Pydantic AI: передача разрешённого языка ответа из deps, два тестовых клиента и защита от недоверенного текста.

Что решаем и кому подходит

Поисковый вопрос: «как сделать динамические инструкции Pydantic AI на каждом запуске». Подставить разрешённый язык ответа для текущего клиента без создания общего глобального промпта для всех пользователей. Официальный пример использует @agent.instructions и RunContext, а динамические инструкции пересчитываются при каждом запуске — в отличие от некоторых исторических system prompts. Правило должно поступать из доверенной серверной конфигурации; пользовательский текст не становится автоматически административной настройкой. Инструкция опирается на актуальную официальную документацию Pydantic AI, проверенную 20 сентября 2026 года. Примеры предназначены для Python 3.10+ с пакетом pydantic-ai. Используйте модель и учётные данные, доступные именно вашему аккаунту; пример идентификатора из документации не является обещанием доступа. Демонстрационные коды, статусы и суммы вымышлены.

Порядок действий

  1. Определите объект зависимостей с допустимым языком, контролируемым приложением.
  2. Задайте стабильную базовую инструкцию на уровне агента; добавьте функцию под @agent.instructions, читающую ctx.deps.
  3. При каждом запуске передавайте собственный экземпляр зависимостей и тестируйте два значения последовательно.
  4. Сверяйте результат по языку и предметному смыслу; запретите неизвестные значения языка до передачи в агент.

До сетевого запуска установите pydantic-ai и настройте ключ провайдера предусмотренным им способом. Примеры не содержат действующих секретов. Для воспроизводимого теста зафиксируйте версии Python, пакета и выбранной модели; после обновления снова выполните как удачный, так и отрицательный сценарий. Вызов run_sync использован для наглядного скрипта вне уже работающего асинхронного цикла. Там, где проект асинхронный, применяйте документированный await agent.run(...) и управляйте ресурсами на стороне приложения.

Готовый шаблон для запуска

from dataclasses import dataclass
from pydantic_ai import Agent, RunContext

@dataclass
class Policy:
    language: str

agent = Agent("openai:gpt-5.2", deps_type=Policy,
              instructions="Ответь кратко и не выдумывай отсутствующие факты.")

@agent.instructions
def language_rule(ctx: RunContext[Policy]) -> str:
    if ctx.deps.language not in {"русский", "английский"}:
        raise ValueError("Язык не разрешён")
    return f"Отвечай на языке: {ctx.deps.language}."

ru = agent.run_sync("Назови один цвет неба.", deps=Policy("русский"))
en = agent.run_sync("Назови один цвет неба.", deps=Policy("английский"))
print(ru.output, en.output)

Конкретный вход и ожидаемый результат

Для одного и того же безопасного вопроса «Назови один цвет неба» первый запуск передаёт Policy("русский"), второй — Policy("английский"). Ожидаются ответы на соответствующих языках, хотя конкретные слова не обязаны совпадать буквально. При значении Policy("неизвестный") функция явно отклоняет конфигурацию. Этот пример не измеряет вероятность правильного ответа и не говорит, что языковая инструкция технически запрещает ответ модели на другом языке; критерий проверяется по фактическому выводу.

Почему этот способ работает

Пользователь может написать «ответь на другом языке» прямо в вопросе. Если продукт должен строго соблюдать настройку клиента, проверяйте язык после генерации и при необходимости запускайте контролируемую коррекцию или возвращайте ошибку. Не помещайте в динамическую инструкцию весь объект с секретами: текст инструкции будет доступен провайдеру модели и может попасть в диагностику. Храните в зависимостях только идентификатор настройки, а необходимый безопасный текст собирайте внутри функции. Документация отмечает пересчёт динамических instructions на каждом запуске, что делает их уместнее для меняющейся политики, чем старые сообщения, неявно перенесённые из истории.

Пограничный случай и предметная проверка

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

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

Критерии приёмки

  1. При двух запусках используются разные значения ctx.deps.language без изменения глобального состояния.
  2. Недопустимый язык отклоняется явно.
  3. Приложение отдельно проверяет фактический язык результата, не считает одну инструкцию жёсткой гарантией.

Проверка успешного выполнения Python-программы не равна проверке верности ответа нейросети. Сопоставьте результат с входом и с доверенным источником данных, затем повторите тест на отрицательном примере. Формулировка текста может отличаться от образца; условия приёмки описывают наблюдаемое поведение, которое действительно нужно пользователю. Если один критерий не соблюдён, не скрывайте сбой повтором без ограничения: сохраните минимальный безопасный воспроизводимый пример и исправьте соответствующий слой — данные, схему, инструмент, инструкцию или обработку ошибки.

Частые ошибки и чего не делать

  • Не передавайте непроверенную строку из пользовательского сообщения как текст привилегированной инструкции.
  • Не включайте пароли, номера карт и ключи API в функции, собирающие инструкции.
  • Не подменяйте изоляцию клиентов общей изменяемой глобальной переменной.

Вопросы и ответы

Когда вычисляется функция instructions?

Документация указывает: при каждом запуске агента.

Сохранит ли она значение из прошлого запуска?

Нет, функция читает зависимости текущего вызова.

Гарантирует ли она язык ответа?

Нет; правило надо проверять на результате.

Официальные источники

Частые вопросы

Когда вычисляется функция instructions?

Документация указывает: при каждом запуске агента.

Сохранит ли она значение из прошлого запуска?

Нет, функция читает зависимости текущего вызова.

Гарантирует ли она язык ответа?

Нет; правило надо проверять на результате.

Читайте также

Комментарии

Пока тихо. Скажите первое слово