Гайд · TNWS AI
Как сделать простой RAG-поиск в smolagents через retriever tool
Минимальный RAG в smolagents: детерминированный retriever tool, русский запрос, ожидаемый фрагмент, проверка источника и ограничения примера.
Задача и применимость
Актуальный поисковый запрос: «как собрать agentic RAG в smolagents с retriever tool». Дать агенту доступ к двум локальным фрагментам и потребовать ответ только по найденному контексту. Официальный пример agentic RAG оформляет retriever как Tool с входом query и строковым выходом, затем передаёт его агенту. Ни сам retriever, ни LLM не гарантируют полноту: качество нужно измерять отдельно на размеченных вопросах. Материал сверён 26 сентября 2026 года с официальной документацией Hugging Face smolagents. Документация прямо помечает API экспериментальным, поэтому перед производственным использованием закрепите версию пакета и повторите тесты. Примеры рассчитаны на Python 3.10+; доступ к конкретной модели и провайдеру проверяется в вашем аккаунте, а не предполагается этой инструкцией.
Пошаговая настройка
- Подготовьте маленький корпус вымышленных документов с идентификаторами.
- Реализуйте детерминированный поиск по словам как проверяемую учебную замену vector store.
- Вызовите retriever напрямую и убедитесь, что вопрос о возврате выбирает документ D2.
- Подключите tool к агенту и потребуйте указывать ID источника; затем проверьте ответ по исходному фрагменту.
До сетевого запуска установите smolagents, настройте HF_TOKEN или другой документированный способ аутентификации и вынесите идентификатор модели в HF_MODEL_ID. Не вставляйте действующий токен в код, prompt, скриншот или статью. Сначала выполните детерминированную часть примера без модели, затем интеграционный run. Так ошибка схемы или бизнес-логики не смешивается с изменчивым поведением LLM.
Готовый шаблон
from smolagents import Tool
class TinyRetriever(Tool):
name = "retrieve_docs"
description = "Ищет релевантные фрагменты в учебной базе знаний."
inputs = {"query": {"type": "string", "description": "Русский вопрос"}}
output_type = "string"
def forward(self, query: str) -> str:
docs = {
"D1": "Доставка тестового заказа занимает два дня.",
"D2": "Возврат тестового заказа принимается в течение 14 дней.",
}
query_text = query.lower()
ranked = sorted(
docs.items(),
key=lambda x: sum(word.strip(".,?") in query_text for word in x[1].lower().split()),
reverse=True,
)
return "\n".join(f"[{k}] {v}" for k, v in ranked[:1])
retriever = TinyRetriever()
result = retriever("Какой срок возврата тестового заказа?")
print(result)
assert result.startswith("[D2]")
Конкретный вход и ожидаемые данные
Вход — «Какой срок возврата тестового заказа?». Ожидаемый retrieval — [D2] Возврат тестового заказа принимается в течение 14 дней. Финальный ответ должен сообщать 14 дней и ссылаться на D2, не добавляя условия о сохранности упаковки, которых в корпусе нет. Для вопроса о доставке должен выбираться D1. Числа вымышлены и относятся только к тестовому корпусу.
Почему схема работает
Учебное ранжирование по пересечению слов прозрачно и фактически проверяется без модели. В настоящем RAG его заменяют BM25, embeddings или гибридным поиском, но критерии остаются: релевантный документ попал в top-k и ответ следует ему. Агентный цикл полезен, когда модель может уточнить запрос или сделать несколько поисков; для одного стабильного вопроса обычный retrieval pipeline может быть проще и дешевле.
Фактическая проверка и пограничный случай
Создайте набор минимум из двадцати вопросов с ожидаемыми ID и измерьте Recall@k независимо от генерации. Затем проверьте groundedness ответа отдельно. Если D2 не извлечён, промпт генератора это не исправит. Если D2 извлечён, но ответ добавляет лишнее условие, проблема уже в генерации или проверке. Такой разбор не позволяет маскировать плохой поиск хорошим стилем текста.
Протокол воспроизводимости
Для каждого прогона запишите четыре независимых артефакта: точный обезличенный вход, ожидаемое действие, фактическое действие и предметно правильный результат. Не ограничивайтесь снимком финального ответа: он не показывает, был ли вызван нужный инструмент. Повторите опыт не менее трёх раз на одной модели с одинаковыми настройками, затем отдельно после смены версии. В отчёте различайте ошибку маршрутизации, неверный аргумент, сбой Python-кода и неподтверждённую генерацию. Если результат нестабилен, не выбирайте удачный прогон вручную: укажите долю успеха на фиксированном наборе. Настройки температуры и провайдера фиксируйте только если они действительно переданы вашему model-клиенту. Такой протокол позволяет повторить вывод и не превращает единичный удачный ответ в обещание качества.
Синтаксис Python проверяется до публикации через ast.parse. Выполнение с реальной моделью здесь не заявляется: без учётных данных нельзя честно подтвердить доступность конкретного inference provider и поведение модели. Проверяемая часть примера выполняется локально там, где она не требует LLM. Для сетевой части заранее запишите модель, версию smolagents, вход, ожидаемый tool call и предметный эталон, затем сохраните обезличенную трассу.
Критерии приёмки
- Прямой вопрос о возврате получает D2, а вопрос о доставке — D1.
- Финальный факт и ID источника совпадают с переданным фрагментом.
- При отсутствии релевантного документа агент сообщает недостаток данных, а не угадывает.
Успешное завершение Python-процесса не равно правильному ответу агента. Сверяйте три слоя отдельно: корректность аргументов tool, фактическое наблюдение из доверенного кода и соответствие финальной фразы этому наблюдению. Если хотя бы один слой не прошёл, результат не должен автоматически попадать в CRM, базу знаний или действие с побочным эффектом.
Типичные ошибки и чего не делать
- Не оценивайте RAG только по убедительности финального текста.
- Не смешивайте документы разных клиентов без фильтра до ранжирования.
- Не называйте пересечение слов семантическим vector search.
Не увеличивайте число шагов и повторов как универсальное лечение. Сначала найдите первый неверный вызов. Не обещайте одинаковое поведение другой модели или будущей версии библиотеки. Все коды и статусы в примерах вымышлены; заменяя их реальными, соблюдайте авторизацию, минимизацию данных и правила хранения журналов.
FAQ
Обязательны ли embeddings?
Нет; retriever tool может использовать любой проверенный поиск.
Зачем ID документа?
Чтобы сопоставить ответ с конкретным полученным фрагментом.
Когда agentic RAG избыточен?
Когда достаточно одного предсказуемого поиска и шаблонного ответа.
Официальные источники
Частые вопросы
Обязательны ли embeddings?
Нет; retriever tool может использовать любой проверенный поиск.
Зачем ID документа?
Чтобы сопоставить ответ с конкретным полученным фрагментом.
Когда agentic RAG избыточен?
Когда достаточно одного предсказуемого поиска и шаблонного ответа.
Читайте также
Как ограничить число шагов агента smolagents через max_steps
Настройка max_steps в smolagents на читающем инструменте: что именно ограничивается, тест успешного запроса, исчерпание бюджета и критерии.
Как проверить финальный ответ smolagents через final_answer_checks
Финальная проверка ответа smolagents на обязательную ссылку на код: сигнатура callback, точный пример, пределы булевой проверки и ошибки.
Как разобрать ошибку агента smolagents через replay и память
Диагностика smolagents через replay, memory.steps и get_full_steps: что смотреть, как обезличить данные и почему трасса не доказывает качество.
Комментарии
Пока тихо. Скажите первое слово