Как мы сократили расходы на LLM в 12 раз
Система обработки входящих документов: ~1 млн LLM-запросов в день, стартовые расходы – $18 000/мес. Через три месяца оптимизаций – $1 500/мес. Без деградации качества. Вот что именно сделали.
Исходная ситуация
Каждый документ проходил через GPT-4: извлечение сущностей, классификация, генерация summary. Один большой промпт, один дорогой вызов. Работало корректно – но цена была неприемлемой для продукта.
Шаг 1: Семантическое кэширование промптов
Не все миллион запросов уникальны. Анализ показал: ~35% запросов семантически близки к ранее обработанным. Кэш по косинусному расстоянию эмбеддинга запроса – если similarity > 0.95, возвращаем кэшированный ответ.
class SemanticCache:
def __init__(self, threshold=0.95):
self.threshold = threshold
self.cache = [] # [(embedding, response)]
def get(self, query_embedding):
for emb, response in self.cache:
sim = cosine_similarity(query_embedding, emb)
if sim >= self.threshold:
return response
return None
def set(self, embedding, response):
self.cache.append((embedding, response))
if len(self.cache) > 10_000:
self.cache.pop(0) # LRU Результат: -35% запросов к API. Latency кэш-хита – 5ms вместо 800ms.
Шаг 2: Маршрутизация по сложности
Не каждый запрос требует GPT-4. Простая классификация типа документа – задача для маленькой модели. Сложное извлечение со структурными зависимостями – GPT-4.
Добавили классификатор сложности: лёгкие запросы (~60%) → gpt-4o-mini, средние (~30%) → gpt-4o, тяжёлые (~10%) → claude-opus. Классификатор сам по себе дешёвый – один вызов mini с коротким промптом.
COMPLEXITY_PROMPT = """
Оцени сложность задачи: 'low', 'medium', 'high'.
Low: простая классификация, короткий текст.
Medium: извлечение сущностей, средний текст.
High: сложные зависимости, длинный контекст, рассуждения.
Ответь одним словом.
"""
async def route_request(task, context):
complexity = await classify_complexity(task, context)
model = MODEL_MAP[complexity]
return await call_llm(model, task, context) Результат: средняя стоимость запроса снизилась в 4.2 раза.
Шаг 3: Батчинг и параллелизм
Вместо обработки документов по одному – батчи по 20 штук с параллельными запросами. Для задач, которые не нужны в реальном времени, добавили очередь с приоритетами: срочные – сразу, фоновые – пакетами.
OpenAI Batch API (50% скидка для асинхронных задач) покрыл ~40% всей нагрузки. Задержка – до 24 часов, но для этих задач это нормально.
Шаг 4: Дистилляция для повторяющихся задач
Одна задача занимала ~25% всех запросов – классификация по фиксированной таксономии из 48 категорий. Идеальный кандидат для fine-tuning.
Сгенерировали 10 000 примеров через GPT-4, дообучили gpt-4o-mini. Accuracy – 94% против 96% у оригинала. Стоимость – в 80 раз дешевле. Для этой задачи 94% достаточно.
Итого
Каждый шаг независим и даёт измеримый результат. Начните с семантического кэша – самое быстрое внедрение и один из лучших ROI.