Управление токенами и кэширование ответов - MCP: Создание ИИ-агентов на практике (Python & TypeScript) - Qpel.AI

Управление токенами и кэширование ответов

В прошлом разделе мы разобрали, как уменьшить контекст — это первый шаг к оптимизации. Теперь углубимся в управление токенами и кэширование ответов. Эти два инструмента помогут вам заметно сократить расходы и ускорить работу MCP-агентов.

Управление токенами: почему это важно?

Каждое обращение к LLM (будь то Claude, GigaChat или YandexGPT) стоит денег. Цена зависит от количества токенов. Токены — это не просто слова, а единицы текста, на которые модель разбивает ваш запрос и свой ответ. Больше токенов — выше стоимость.

Эффективно управлять токенами — значит:

  1. Минимизировать входной контекст. Отправляйте LLM только ту информацию, которая нужна для ответа. Ничего лишнего.
  2. Ограничивать длину ответов. LLM иногда генерирует слишком длинные ответы. Укажите максимальное количество токенов для ответа в параметрах запроса. Это не только экономит токены, но и делает ответы точнее.
  3. Мониторить использование токенов. Большинство LLM-провайдеров дают API для отслеживания токенов. Встройте этот мониторинг в своих агентов, чтобы видеть, куда уходят ресурсы, и быстро реагировать на перерасход.

Совет: Считайте токены перед отправкой запроса. Многие библиотеки для работы с LLM умеют это. Например, для OpenAI-совместимых моделей используйте tiktoken.

Кэширование ответов: ускоряем и экономим

Представьте: ваш агент несколько раз подряд задаёт LLM один и тот же вопрос или очень похожий. Каждый раз он платит за токены и ждёт ответа. Кэширование решает эту проблему. Оно сохраняет ответы LLM на частые запросы и выдаёт их из кэша, если запрос уже был.

Как работает кэширование?

  1. Запрос: Агент формирует запрос к LLM.
  2. Проверка кэша: Перед отправкой запроса, агент смотрит, нет ли уже ответа на идентичный или очень похожий запрос в кэше.
  3. Кэш-хит: Если ответ найден (кэш-хит), он мгновенно возвращается из кэша. Это быстро и бесплатно.
  4. Кэш-мисс: Если ответа нет (кэш-мисс), запрос уходит к LLM. Полученный ответ сохраняется в кэше для будущих запросов.

Виды кэширования для MCP-агентов

  • Простое кэширование "ключ-значение": Самый базовый вариант. Ключ — это хэш запроса (или его части), значение — ответ LLM. Идеально для запросов, которые всегда дают один и тот же ответ (например, факты).
  • Семантическое кэширование: Более продвинутый подход. Использует эмбеддинги (векторные представления) запросов. Это позволяет находить в кэше ответы на семантически похожие, но не идентичные запросы. Очень полезно, когда формулировки могут немного отличаться, но суть вопроса одна.
  • Кэширование с TTL (Time To Live): Ответы хранятся в кэше определённое время, а затем удаляются. Это не даёт информации устареть.

Реализация кэширования

Для кэширования можно использовать:

  • Встроенные механизмы: Некоторые фреймворки или библиотеки для LLM уже имеют базовые функции кэширования.
  • Библиотеки для кэширования: Например, functools.lru_cache в Python для кэширования функций или специализированные библиотеки вроде cachetools.
  • Внешние хранилища: Для сложных или распределённых систем подойдут Redis, Memcached или обычная база данных.

Пример (Python, псевдокод):

import hashlib
import json
from datetime import datetime, timedelta

# Простой in-memory кэш
cache = {}

def get_llm_response_cached(prompt: str, max_tokens: int = 100, cache_ttl_seconds: int = 3600):
    # Генерируем ключ кэша из запроса и параметров
    cache_key = hashlib.md5(f"{prompt}-{max_tokens}".encode('utf-8')).hexdigest()

    if cache_key in cache:
        cached_data = cache[cache_key]
        if datetime.now() < cached_data['expiry_time']:
            print("Возвращаем из кэша!")
            return cached_data['response']
        else:
            print("Кэш устарел, удаляем.")
            del cache[cache_key]

    print("Отправляем запрос к LLM...")
    # Здесь был бы реальный вызов LLM API
    llm_response = f"Ответ LLM на '{prompt}' с макс. {max_tokens} токенами."

    # Сохраняем ответ в кэш
    cache[cache_key] = {
        'response': llm_response,
        'expiry_time': datetime.now() + timedelta(seconds=cache_ttl_seconds)
    }
    return llm_response

# Тестируем
print(get_llm_response_cached("Какая столица России?"))
print(get_llm_response_cached("Какая столица России?")) # Будет из кэша
print(get_llm_response_cached("Какая столица России?", max_tokens=50)) # Новый запрос, другой ключ

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

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

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