Гайд · TNWS AI

Как разделить поиск и сборку ответа RAG на спаны MLflow Tracing

4 мин—

Размечаем вручную поиск фрагмента и формирование ответа; проверяем вложенные спаны без вызова платной модели.

Задача и применимость

Поисковый запрос: «как отследить отдельные шаги RAG пайплайна через mlflow trace». Найти шаг, на котором RAG-приложение потеряло опорный документ, вместо того чтобы гадать по итоговому ответу. Инструкция применима к Python-клиенту и Tracking Server актуальной ветки MLflow GenAI, проверенной по официальной документации 20 сентября 2026 года. Для конкретной установки сначала посмотрите mlflow.__version__: при отличии интерфейса от приведённого руководства закрепите совместимую версию и проверьте её документацию. Учебные данные вымышлены; ни один описанный пример не является запросом к реальному магазину.

Что происходит в системе

Декоратор @mlflow.trace автоматически захватывает имя функции, аргументы, результат, время выполнения и ошибки; при вложенных вызовах появляется отношение родитель–дочерний спан. Поэтому при ошибочном ответе можно проверить, вернул ли retrieval пустую строку или потеря произошла при сборке ответа. В промышленном RAG замените словарь своим поиском, но оставьте одинаковый контрольный набор вопросов и известные ID фрагментов. Иначе сравнение старой и новой версии не будет осмысленным.

Пошаговое выполнение

  1. Запустите локальный MLflow Tracking Server и привяжите приложение к отдельному эксперименту.
  2. Разметьте функцию поиска и функцию формирования ответа декоратором @mlflow.trace.
  3. Вызовите обёртку с контрольным вопросом и выведите итог в консоль.
  4. Откройте эксперимент и вкладку Traces, раскройте дерево спанов.
  5. Проверьте содержимое каждого шага и повторите опыт с запросом без подходящего документа.

Для локального опыта нужен Python 3.10+, установленный пакет mlflow и запущенный отдельно командой mlflow server локальный сервер. Адрес http://localhost:5000 из примеров справедлив при стандартном локальном запуске; в контейнере и удалённом окружении задайте настоящий доступный URI. Вызовы реальной модели выполняйте только с подходящими ключами и подтверждённой доступностью модели. Фрагмент ниже — готовый шаблон контроля конкретной операции:

import mlflow
mlflow.set_tracking_uri("http://localhost:5000")
mlflow.set_experiment("RAG Проверка спанов")
DOCS = {"возврат": "Возврат оформляют после подтверждения заявки."}

@mlflow.trace(name="retrieve")
def retrieve(question: str) -> str:
    return DOCS.get("возврат", "") if "возврат" in question.lower() else ""

@mlflow.trace(name="compose_answer")
def compose_answer(fragment: str) -> str:
    return fragment or "В базе нет подтверждённого ответа."

@mlflow.trace(name="rag_request")
def rag_request(question: str) -> str:
    return compose_answer(retrieve(question))

print(rag_request("Как оформить возврат?"))

Пример входа и ожидаемого результата

Вход — «Как оформить возврат?». Ожидаемая строка — «Возврат оформляют после подтверждения заявки.». Внутри одной трассы должны быть дочерние retrieve и compose_answer; для «Как проверить доставку?» ответ должен сообщить отсутствие подтверждённого ответа. Это демонстрационная база из одной записи, а не проверка способности нейросети рассуждать.

Как интерпретировать измерение

Представьте, что в базе есть и политика обмена, и политика возврата. Если ответ описал обмен, а спан retrieve действительно вернул фрагмент об обмене, виноваты поиск либо данные индекса. Если retrieve отдал правильный фрагмент, а compose_answer его исказил, проверять надо шаблон генерации или модель. Для больших документов разумнее журналировать идентификаторы и короткие безопасные фрагменты, чтобы трассы не превратились в склад персональных данных. Декоратор по умолчанию сохраняет входы и выходы, так что в примере используются вымышленные данные.

Границы решения и особые случаи

Не вызывайте каждый шаг отдельно вне родительской функции, ожидая одного связанного дерева. Не называйте весь процесс LLM-вызовом: поиск не становится генерацией только потому, что обслуживает нейросеть. У конкретного провайдера может быть автоматическая инструментализация; ручные спаны полезны для собственного кода между вызовами. При переходе на настоящий LLM сравнивайте trace с фактическим пользовательским результатом, но не принимайте существование спана за доказательство точности ответа.

Критерии проверки результата

  1. Одна трасса содержит оба вложенных шага с читаемыми входами и выходами.
  2. Запрос без документа даёт проверяемый отказ, а не придуманное правило.
  3. После смены поиска можно локализовать ошибку по результату retrieve.

Если критерий не выполняется, сохраните номер версии пакета, безопасный входной пример и фактический результат. Затем меняйте по одной переменной: адрес сервера, параметры вызова, конфигурацию эксперимента либо редакцию шаблона. Такой подход помогает установить причину отличия без предположений о том, что модель «обязана» отвечать строго одной строкой. После успешного теста на заглушке повторите проверку на малом наборе разрешённых рабочих данных; обучающий пример сам по себе не является нагрузочным, приватностным или качественным аудитом.

Типичные ошибки и что не делать

  • Не загружайте реальные частные документы в учебный эксперимент.
  • Не путайте время поиска с общим временем запроса.
  • Не считайте успешный статус спана мерой фактической достоверности.

Учитывайте, что трассировка и оценка могут сохранять содержимое входа и выхода. До подключения клиентов организуйте контроль доступа и обработку персональных данных. Не помещайте секреты API в промпты, параметры функций, журналы или опубликованные скриншоты. Если пример использует детерминированную функцию, его успешная проверка подтверждает корректность механики MLflow и теста, но не качество какой-либо нейросети.

FAQ

Нужен ли ключ модели?

Нет, этот учебный сценарий не обращается к модели.

Что означает родительский спан?

Он объединяет дочерние операции одного вызова.

Где смотреть результат?

В Traces выбранного эксперимента.

Официальные источники

Частые вопросы

Нужен ли ключ модели?

Нет, этот учебный сценарий не обращается к модели.

Что означает родительский спан?

Он объединяет дочерние операции одного вызова.

Где смотреть результат?

В Traces выбранного эксперимента.

Читайте также

Комментарии

Пока тихо. Скажите первое слово