Наблюдаемость: логи и метрики
Нельзя улучшить то, что не видно. Логи и метрики делают поведение LLM наблюдаемым.
Наблюдаемость — способность по логам и метрикам понимать, что и как делает ваша LLM-функция в проде: что запросили, что ответили, сколько это стоило и не сломалось ли.
Что логировать по каждому запросу
| Поле | Зачем |
| модель и версия промпта | понять, какой конфиг отвечал |
| входные сообщения (или их хеш/сводка) | воспроизвести и отладить |
| ответ модели | проверить качество, разобрать жалобы |
usage (токены) | учёт стоимости |
| латентность | следить за скоростью |
stop_reason и ошибки | ловить обрывы и сбои |
| request id | обращаться в поддержку провайдера |
Метрики, за которыми следят
- Латентность (p50/p95): не деградирует ли скорость.
- Токены и стоимость: суммарно и на запрос; тренды по дням.
- Доля ошибок: 429, 5xx, таймауты, обрывы по
max_tokens. - Качество: доля ответов, прошедших валидацию формата; обратная связь пользователей.
Осторожно с приватностью
В логи попадают тексты пользователей — это персональные данные. Не логируйте лишнее, маскируйте чувствительное (почты, телефоны), соблюдайте сроки хранения и требования регуляторов (GDPR и аналоги). Никогда не логируйте ключи API.
Зачем это на практике
Без логов вы узнаёте о проблеме от пользователя, а не от системы, и не можете её воспроизвести. С логами вы видите: вот этот запрос дал плохой ответ — какой был промпт, какая версия, сколько токенов, не оборвался ли он по лимиту. Метрики по токенам ловят дрейф расходов раньше, чем придёт большой счёт. Метрики латентности показывают, когда провайдер «тормозит» и пора включать фолбэк. А request_id из ответа — это то, что просит поддержка провайдера, когда вы сообщаете о сбое.
Практика: единая точка логирования
Раз вызовы LLM собраны в один слой (урок про архитектуру), там же удобно логировать: каждый вызов оборачивается записью запроса/ответа/метрик. Это даёт сквозную картину без дублирования.
def call_llm_logged(messages, prompt_version):
t0 = time.monotonic()
resp = client.messages.create(model=MODEL, max_tokens=512, messages=messages)
log.info({
"prompt_version": prompt_version,
"model": MODEL,
"input_tokens": resp.usage.input_tokens,
"output_tokens": resp.usage.output_tokens,
"latency_ms": int((time.monotonic() - t0) * 1000),
"stop_reason": resp.stop_reason,
"request_id": resp._request_id,
})
return resp
Итог
- Логируйте модель, промпт-версию, ввод/вывод, токены, латентность, причину остановки и ошибки.
- Следите за метриками: латентность, стоимость, доля ошибок, качество.
- Уважайте приватность: маскируйте ПДн, не логируйте ключи.