Тестирование LLM-функций
LLM недетерминирован, но это не повод не тестировать код вокруг него.
Тестировать нужно свой код (сборку промптов, парсинг, обработку ошибок, логику инструментов), а качество ответов модели проверять отдельными оценочными тестами.
Проблема: реальный API в тестах — плохо
Дёргать настоящий API в юнит-тестах медленно, стоит денег и нестабильно (ответы каждый раз разные, бывают 429). Поэтому в тестах API подменяют фейком (mock), который возвращает заранее заданный ответ.
Тест с фейк-клиентом (запускаемо)
Бизнес-функция принимает клиент как зависимость; в тесте подставляем фейк и проверяем логику без сети. Чистый Python:
def classify_sentiment(client, text):
# Логика: дергает client.complete и парсит ответ
raw = client.complete(f"Тон сообщения одним словом: {text}")
return raw.strip().lower()
class FakeClient:
def __init__(self, canned):
self.canned = canned
self.calls = []
def complete(self, prompt):
self.calls.append(prompt)
return self.canned
# Тест: не дёргаем реальный API, подставляем фейк
fake = FakeClient(canned=" Позитивный ")
result = classify_sentiment(fake, "Отличный сервис!")
assert result == "позитивный", result
assert len(fake.calls) == 1
print("Результат:", result)
print("Вызовов API:", len(fake.calls))
print("Тест пройден")
Вывод:
Результат: позитивный Вызовов API: 1 Тест пройден
Здесь проверена ваша логика (обрезка пробелов, приведение к нижнему регистру) — без обращения к модели. Передача клиента как аргумента (dependency injection) делает подмену тривиальной.
Что именно покрывать юнит-тестами
- Сборка промпта/сообщений из входных данных.
- Парсинг ответа: корректный JSON, частичный, мусор.
- Обработка ошибок: 429, таймаут, обрыв по
max_tokens. - Диспетчер инструментов: известный/неизвестный инструмент, плохие аргументы.
Оценочные тесты (evals) — про качество модели
Отдельно проверяют качество ответов на наборе примеров с ожидаемым результатом: точность классификации, доля валидного JSON, прохождение проверок. Поскольку вывод недетерминирован, оценивают не «равно строке», а по критериям (содержит нужное, проходит схему, оценка судьёй). Evals гоняют при смене промпта или модели, чтобы поймать регресс.
Итог
- Юнит-тесты — на ваш код вокруг LLM, с фейком вместо реального API.
- Передавайте клиент как зависимость — так его легко подменить в тесте.
- Качество модели проверяют отдельными оценочными тестами по критериям, а не по точному совпадению.