Sampling: когда сервер сам обращается к модели

Урок 2 из 18 курса «MCP: продвинутые темы»: официальный курс Anthropic Academy (Антропик) на русском языке. Этот урок бесплатный.

Сэмплинг (Sampling) в Протоколе Контекста Модели (MCP): Делегирование Вызовов LLM

Протокол Контекста Модели (MCP, Model Context Protocol) от Anthropic представляет собой мощный фреймворк для создания сложных приложений, которые интегрируют большие языковые модели (LLM), такие как Claude. Он позволяет серверной логике эффективно взаимодействовать с возможностями искусственного интеллекта. Однако прямое интегрирование LLM в серверное приложение может быть сопряжено с рядом сложностей, особенно когда речь идет о распределении ресурсов, управлении затратами и обеспечении безопасности. Именно здесь на помощь приходит концепция сэмплинга.

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

Что такое Сэмплинг (Sampling)?

В своей основе сэмплинг в контексте MCP — это механизм, который позволяет серверу делегировать запросы к языковой модели Claude своему подключенному клиенту. Вместо того чтобы сервер напрямую обращался к Claude, он просит клиента сделать этот вызов от его имени. Этот подход значительно переносит ответственность, управление и, что немаловажно, затраты на генерацию текста с сервера на клиента.

По сути, сэмплинг создает своего рода "прокси-запрос", где сервер формулирует задачу для LLM, но исполнение этой задачи инициируется и оплачивается клиентом. Это открывает новые возможности для создания распределенных и экономически эффективных приложений, использующих мощь Claude.

Проблема, которую решает Сэмплинг

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

В такой ситуации у вас есть два основных подхода к интеграции Claude:

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

  2. Использование сэмплинга: Сервер генерирует промпт с запросом на суммаризацию и отправляет его клиенту с просьбой: "Не могли бы вы вызвать Claude для меня?" Клиент, у которого уже есть настроенное соединение с Claude (поскольку он является конечным пользователем, инициирующим взаимодействие), выполняет вызов, используя свои собственные учетные данные и оплачивая токены. Затем клиент возвращает сгенерированный текст серверу.

Второй подход, основанный на сэмплинге, значительно упрощает серверную часть. Он позволяет серверу оставаться "чистым" от специфики LLM-интеграции, фокусируясь исключительно на своей бизнес-логике, в то время как клиент берет на себя все аспекты взаимодействия с Claude.

Как работает Сэмплинг?

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

  1. Сервер выполняет свою основную работу: На этом этапе сервер обрабатывает данные, собирает информацию (например, статьи из Википедии) или выполняет любую другую логику, которая предшествует необходимости использования LLM.

  2. Сервер создает промпт: Основываясь на своей логике, сервер формулирует запрос для языковой модели. Это может быть промпт для суммаризации, генерации текста, ответа на вопрос и т.д.

  3. Сервер отправляет запрос на сэмплинг клиенту: Вместо прямого вызова Claude, сервер формирует специальный запрос в протоколе MCP, который сигнализирует клиенту о необходимости выполнить вызов LLM. Этот запрос включает в себя промпт и другие параметры, необходимые для Claude.

  4. Клиент вызывает Claude: Получив запрос на сэмплинг от сервера, клиент, используя предоставленный промпт и свои собственные учетные данные (ключ API), обращается к Claude через Anthropic SDK или напрямую через API.

  5. Клиент возвращает сгенерированный текст серверу: После получения ответа от Claude, клиент передает сгенерированный текст обратно серверу через MCP.

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

Преимущества Сэмплинга

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

  • Снижение сложности сервера: Серверу не нужно напрямую интегрироваться с языковыми моделями. Он не беспокоится о специфических библиотеках для работы с LLM, управлении версиями API, обработке различных типов ответов от модели или оптимизации вызовов. Это значительно упрощает разработку, тестирование и поддержку серверного кода, позволяя разработчикам сосредоточиться на основной бизнес-логике.

  • Перенос бремени затрат: Одним из наиболее значимых преимуществ является то, что клиент оплачивает использование токенов, а не сервер. В сценариях, где каждый пользователь генерирует уникальный контент с помощью ИИ, оплата токенов клиентом гарантирует справедливое распределение расходов. Это позволяет разработчикам публичных сервисов предлагать мощные функции ИИ без риска непредвиденных и высоких операционных издержек.

  • Отсутствие необходимости в ключах API на сервере: Это критически важно для безопасности. Хранение ключей API на сервере всегда представляет риск компрометации. Делегируя вызов клиенту, вы устраняете необходимость в хранении этих чувствительных данных на публично доступном сервере, значительно снижая вероятность их утечки или несанкционированного использования.

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

Когда использовать Сэмплинг?

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

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

  • Публичных инструментов генерации контента: Где пользователи создают уникальные тексты, резюме или ответы.
  • Образовательных платформ: Где студенты могут использовать ИИ для помощи в обучении или исследованиях.
  • Демонстрационных приложений: Где вы хотите показать возможности вашего сервера, не неся при этом все расходы на LLM.

Концептуальная реализация Сэмплинга

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

На стороне сервера, в коде вашего инструмента (например, функции, помеченной декоратором @mcp.tool()), вы будете использовать специальный метод, такой как ctx.session.create_message. Вместо прямого вызова LLM, этот метод формирует запрос на сэмплинг. В этом запросе вы указываете параметры, аналогичные обычному вызову Claude: промпт, роль пользователя, максимальное количество токенов и системный промпт. Важно отметить, что здесь используется специальный объект SamplingMessage, который сигнализирует клиенту о необходимости выполнить вызов LLM.

На стороне клиента, вы должны реализовать асинхронную функцию, которая будет выступать в роли sampling_callback. Эта функция принимает параметры запроса от сервера (например, CreateMessageRequestParams), извлекает из них промпт и другие настройки, а затем выполняет фактический вызов Claude, используя, например, Anthropic SDK и свой собственный ключ API. После получения ответа от Claude, sampling_callback формирует результат (CreateMessageResult) и возвращает его серверу. Этот sampling_callback затем передается в конструктор ClientSession при инициализации клиента, тем самым 'обучая' клиент обрабатывать запросы на сэмплинг.

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

Урок входит в темы

Полезные гиды