В статье разберем, как быстро создать собственного ИИ-агента с RAG, SQL-базой и поиском в Интернет на базе smolagents от Hugging Face. Предполагается, что у слушателей минимальные знания про ИИ-агентов, но есть некоторые знания в Python и базах данных.
Сразу извиняюсь за то, что представленный код далек от идеального, а статья поверхностна. Правильно будет воспринимать этот материал как вводный гайд по теме ИИ-агентов. Тем не менее статья может быть полезна в контексте автоматизации задач и процессов.
Сейчас из всех утюгов валятся новости про ИИ-ассистентов или ИИ-агентов, и о том, как они могут облегчить жизнь пользователям и срезать косты в некоторых бизнес-процессах. Эта тема заинтересовала и меня, поэтому я решил разобраться, как создать собственного ИИ-агента.
Итак, на сегодняшний день для создания ИИ-агентов существует несколько популярных фреймворков:
N8N - open-source low-code/no-code платформа для автоматизации процессов и построения ИИ-агентов. Позволяет визуально собирать сложные агенты с интеграцией LLM, инструментов, памяти и внешних сервисов. Особенно популярна когда нужна быстрая разработка production-ready агентов без глубокого программирования, а также для гибридных сценариев (автоматизация + AI).
LangChain - модульный open-source фреймворк для создания приложений на базе LLM, включая агентов. Позволяет описывать последовательности действий (chains - т.е. цепочек действий), интегрировать инструменты, память и внешние источники данных. Подходит для экспериментов и проектов средней сложности(для сложных агентов часто используют его расширение - LangGraph).
LlamaIndex (ранее известен как GPT Index) - модульный фреймворк с сильным акцентом на индексацию, retrieval и работу с большими объёмами данных. Подходит для построения агентов-исследователей и RAG-ориентированных систем, где ключевая ценность это точный поиск и синтез информации из документов, баз знаний или enterprise-данных.
Haystack (от deepset) - open-source фреймворк, ориентированный на создание высокопроизводительных поисковых и вопросно-ответных систем (в первую очередь RAG и semantic search). Поддерживает agentic подходы и compound AI системы, но основная сила - в надёжных retrieval-пайплайнах для production. Подходит для задач, где критична точность поиска по большим коллекциям документов.
Smolagents (от Hugging Face) - лёгковесная, минималистичная библиотека для создания агентов. Отличается простотой (агенты собираются в несколько строк кода), поддержкой code agents (агенты пишут и исполняют код) и фокусом на детерминированность и безопасность (sandbox-исполнение). Более предсказуемый и лёгкий подход по сравнению с многослойными абстракциями LangChain. Подходит для быстрых прототипов и задач, где важна прозрачность(контроль).
CrewAI - фреймворк для оркестрации multi-agent систем на основе ролевого подхода. Агенты получают роли, цели, backstory и инструменты, имитируя работу команды специалистов.
OpenAI Swarm - лёгковесный экспериментальный фреймворк от OpenAI для multi-agent оркестрации. Предоставляет простую модель handoff между агентами, нативную интеграцию с инструментами и моделями OpenAI. Подходит для быстрых экспериментов и проектов, тесно завязанных на экосистему OpenAI, но уступает в возможностях state management и надёжности production-систем.
Из этого списка я выбрал smolagents, т.к. на мой взгляд, этот фреймворк предоставляет лучшее сочетание простоты разработки и одновременно контроля над кодом.
Рекомендую пару вводных курсов по созданию ИИ-агентов:
В качестве идеи для создаваемого ИИ-агента я выбрал чат-ассистента для вымышленного магазина кроссовок. В качестве канала общения используется только текст через Telegram-бота.
Агент должен уметь искать релевантную информацию в векторном хранилище (RAG), при необходимости выполнять запросы к классической базе данных, а также осуществлять поиск в интернете.
RAG (Retrieval-Augmented Generation) это технология, которая объединяет большие языковые модели (LLM) с внешними источниками знаний для получения более точных и актуальных ответов. В отличие от обычных чат-ботов, RAG перед формированием ответа ищет информацию в документах или внешних источниках, что снижает риск галлюцинаций модели. Для реализации RAG обычно используются векторные хранилища(где хранятся т.н. эмбеддинги - векторное представление сущностей). В своем проекте я выбрал ChromaDB, хотя существует и другое популярное решение FAISS.
В рамках проекта RAG выступает в роли базы знаний. В ней хранятся инструкции по подбору и уходу за обувью, информация об офисах и складах компании, режиме работы и контактных данных. При изменении состава данных в RAG необходимо выполнять переиндексацию.
В качестве классической базы данных я использовал SQLite. Очевидно, что эта СУБД подходит только для небольших проектов, а в production-среде стоит выбирать более зрелые решения, например PostgreSQL или MongoDB. Однако для учебного проекта SQLite подходит оптимально.
Я предположил, что в базе данных будут храниться данные, которые часто меняются и поэтому не подходят для размещения в RAG. К таким данным относятся справочники номенклатуры и моделей, таблицы цен и остатки по складам.
Таким образом, при необходимости получить, например, информацию об остатках на конкретном складе, агент просто выполняет соответствующий запрос к базе данных. Также была предусмотрена таблица заказов или заявок, в которую агент будет записывать обращения клиентов на покупку кроссовок.
Поскольку не вся необходимая информация может находиться в RAG или базе данных, в агент был заложен механизм поиска в интернете. Поиск ограничен тематикой, связанной с кроссовками.
Работа с фреймворком smolagents ведется на языке Python. Насколько мне известно, большая часть решений в области ИИ разрабатывается именно на нем. Ссылки на вводные материалы по этому фреймворку были приведены выше, поэтому на базовых принципах работы я останавливаться не буду.
Для реализации функциональности, описанной в предыдущем пункте, ИИ-агент использует так называемые инструменты. В smolagents инструменты можно регистрировать напрямую при создании агента.
agent = ToolCallingAgent(
tools=[
# -- RAG
retrieve_knowledge,
#
# -- запросы к БД
search_models,
get_stock_and_price,
get_model_details,
create_order_request,
#
# -- ВЕБ-поиск
web_search_tool,
],
model=model,
)
Каждый инструмент представляет собой Python-функцию с аннотацией @tool, текстовым описанием и набором входных параметров. Эти описания используются моделью для понимания того, в каких случаях и с какими аргументами инструмент может быть вызван(см.соответствующий файлы в проекте в каталоге /tools).
Помимо инструментов, в конструктор агента передается модель. Это LLM, которая используется для рассуждений и принятия решений агентом. В типовом случае модель инициализируется стандартным способом, однако для некоторых LLM набор параметров и способ конфигурации могут отличаться.
llm_config = config["llm"]
model = OpenAIModel(
model_id=llm_config["model_id"],
api_base=llm_config["api_base"],
api_key=os.getenv("GEMINI_API_KEY"),
temperature=llm_config.get("temperature", 0.7),
# max_output_tokens=llm_config.get("max_tokens"), # не для всех моделей
# max_tokens=llm_config.get("max_tokens", 1024),
)
В моем проекте большинство параметров вынесено в конфигурационный файл config.yaml, а секреты хранятся в файле .env, который можно создать на основе .env.example.
Для рассуждений агента используется модель gemini-2.5-flash. На данный момент она показалась мне подходящей, так как ответы генерируются достаточно быстро и при этом остаются разумными по качеству. При необходимости модель, промпт и другие параметры можно легко изменить через конфигурационный файл.
На данном этапе агент уже полностью реализован(да, вот так просто). Осталось наполнить данными RAG и базу данных, а также подготовить системный промпт. И да, чуть не забыл, для работы через Telegram в проект необходимо добавить файл telegram_bot.py, который будет использовать созданного ИИ-агента для обработки сообщений пользователей.
В каталоге /knowledge_base/raw расположены текстовые файлы в формате Markdown (*.md), на основе которых формируются эмбеддинги для векторного хранилища ChromaDB. При необходимости вы можете без проблем заменить эти файлы своими данными.
Для построения эмбеддингов локально используется модель intfloat/multilingual-e5-large-instruct, которая задается в конфиг-файле. При желании код в файле rebuild_index.py можно доработать так, чтобы для построения эмбеддингов использовались файлы других типов. К слову, в сети полно готовых решений, позволяющих извлекать текст из файлов самых разных форматов.
После того как вы завершите формирование набора документов, таких как инструкции, FAQ, график работы или публичные контакты, необходимо запустить файл rebuild_index.py, например командой:
python3 rebuild_index.py
В файле init_sneakers_db.sql содержится код для создания необходимого набора таблиц и их первоначального наполнения вымышленными данными. Разумеется, вы можете создать свои собственные таблицы, но в этом случае не забудьте скорректировать запросы в соответствующих инструментах.
SQLite является достаточно простой СУБД, поэтому для создания и инициализации базы данных достаточно выполнить следующую команду:
sqlite3 data/sneakers.db < init_sneakers_db.sql
Системный промпт находится в конфиг-файле и представляет собой следующий текст:
system_prompt: |
Ты — дружелюбный и профессиональный консультант в магазине кроссовок SneakerHub.
Всегда отвечай на русском языке, вежливо и по делу.
КРИТИЧЕСКИЕ ПРАВИЛА (ОБЯЗАТЕЛЬНО СОБЛЮДАЙ, ИНАЧЕ ОШИБКА!):
1. СТРОГАЯ СПЕЦИАЛИЗАЦИЯ ИНСТРУМЕНТОВ — НЕ ПУТАЙ НИКОГДА!
- retrieve_knowledge: ТОЛЬКО общая информация, FAQ, рекомендации по выбору, описание моделей, для чего подходят кроссовки. НИКОГДА НЕ ИЩИ ЗДЕСЬ размеры, цвета, цены, наличие!
- search_models: Поиск моделей по бренду/модели/назначению + общее наличие и склады. Используй, когда пользователь хочет обзор моделей (например "какие беговые кроссовки есть").
- get_model_details: Подробности по одной конкретной модели (описание + остатки по складам). Используй, когда пользователь назвал модель и хочет узнать про неё.
- get_stock_and_price: Детальное наличие, цены и остатки по конкретным товарам (артикул, размер, цвет, склад). Используй, когда вопрос про конкретный размер, цвет, цену, склад или артикул.
2. ПРАВИЛА ВЫБОРА ИНСТРУМЕНТА (ДЕЛАЙ ТОЧНО ПО ЭТОМУ ПОРЯДКУ):
- Если пользователь спрашивает про конкретную модель (назвал бренд + модель) U94; вызывай get_model_details.
- Если спрашивает про наличие, размер, цвет, цену, склад, артикул U94; вызывай get_stock_and_price.
- Если хочет обзор моделей (какие есть беговые, для города и т.д.) U94; вызывай search_models.
- Если спрашивает общую информацию, FAQ, как выбрать, для чего подходят — вызывай retrieve_knowledge.
- Если ничего из вышеперечисленного — отвечай из общего знания или говори "уточните, пожалуйста".
3. ПРАВИЛА РАБОТЫ С JSON:
- Все три инструмента (search_models, get_model_details, get_stock_and_price) возвращают JSON.
- ОБЯЗАТЕЛЬНО парси JSON и используй данные из него для ответа.
- Показывай пользователю понятный текст, но держи в уме всю структуру JSON дл�� дальнейших вопросов.
- Если пользователь спрашивает про конкретный склад/размер/цвет — используй данные из "stock_by_warehouse" или "items", НЕ вызывай инструмент заново.
4. ФОРМАТ ВЫЗОВА ИНСТРУМЕНТОВ (СТРОГО СОБЛЮДАЙ!):
- Всегда используй формат:
<function=имя_инструмента>
<parameter name="параметр">значение</parameter>
...
</function>
- НЕ используй JSON внутри <function>! Только <parameter name="...">значение</parameter>
- Для final_answer всегда:
<function=final_answer>
<parameter name="content">твой ответ пользователю</parameter>
</function>
- НЕ пиши JSON, словари или кавычки внутри вызова.
5. ПРАВИЛА СКОРОСТИ И ЭФФЕКТИВНОСТИ:
- Отвечай максимально быстро. Старайся уложиться в 2–4 шага.
- НЕ вызывай один инструмент больше 1 раза подряд с похожими параметрами.
- Если после 1–2 вызовов можно ответить — сразу выдавай final_answer.
- НЕ зацикливайся и НЕ переспрашивай без необходимости.
- Используй историю диалога — если пользователь уже называл модель/размер, НЕ спрашивай заново.
6. ПОВЕДЕНИЕ:
- Будь полезным, предлагай альтернативы, помогай с выбором размера.
- Никогда не придумывай наличие, цены, остатки — только из инструментов.
- Если данных нет — сразу говори "не найдено" или предлагай уточнить.
Пример диалога:
Пользователь: нужны беговые кроссовки 43-44
Ты: Сначала вызываешь search_models(purpose="бег"), потом get_stock_and_price(size_min=43.0, size_max=44.0) для найденных моделей.
ДОПОЛНИТЕЛЬНЫЕ КРИТИЧЕСКИЕ ПРАВИЛА (ОБЯЗАТЕЛЬНО СОБЛЮДАЙ!):
9. ИСПОЛЬЗУЙ ДАННЫЕ ИЗ ПРЕДЫДУЩИХ ВЫЗОВОВ — ЗАПРЕТ НА ПОВТОРНЫЕ ЗАПРОСЫ:
- Если ты уже вызвал search_models или get_model_details и получил JSON с остатками по складам — НИКОГДА НЕ ВЫЗЫВАЙ get_stock_and_price заново!
- Используй данные из поля "stock_by_warehouse" или "items" для ответа на любые вопросы про наличие, склады, размеры.
- Если пользователь уточняет склад/размер/цвет — бери информацию из уже полученного JSON. НЕ ДЕЛАЙ НОВЫЙ ВЫЗОВ.
10. ПРАВИЛА ПОВТОРНЫХ ВЫЗОВОВ:
- Запрещено вызывать get_stock_and_price, если в предыдущем шаге уже есть данные по этой модели в JSON.
- Если нужно уточнить — спроси пользователя, но НЕ повторяй вызов инструмента.
11. ПРИМЕР ПОВЕДЕНИЯ НА ВОПРОС "беговые кроссовки 43-44":
1. Вызываешь search_models(purpose="бег")
2. Получаешь JSON с моделями и остатками.
3. Сразу выдаёшь final_answer на основе JSON — НЕ вызываешь get_stock_and_price!
12. ЗАПРЕТ НА ПОИСК НЕ ПО ТЕМЕ КРОССОВОК И ОБУВИ(ОЧЕНЬ ЖЁСТКО СОБЛЮДАЙ!):
- Инструмент web_search_tool (или DuckDuckGoSearchTool) можно вызывать ТОЛЬКО если вопрос напрямую касается кроссовок, обуви, брендов, моделей, релизов, отзывов, цен, трендов, выбора размера или ухода за кроссовками.
- ЗАПРЕЩЕНО вызывать поиск по любым другим темам: политика, новости, война, погода (если не связано с обувью), спорт (кроме бега/фитнеса в контексте кроссовок), знаменитости (кроме коллабораций с брендами), мемы и т.д.
- Если вопрос не про кроссовки — отвечай: "Извините, я специализируюсь только на кроссовках и обуви. Давайте поговорим про модели, размеры или уход?"
- Даже если пользователь спрашивает "что сейчас в тренде" — это можно искать ТОЛЬКО если речь про тренды в кроссовках/стритвире.
13. РЕГИСТРАЦИЯ ЗАЯВКИ ПОЛЬЗОВАТЕЛЯ
- Если пользователь изъявляет желание приобрести кроссовки и подтверждает свои намерения ("да, беру", "оформляй", "хочу купить", "хочу заказать", "заказываю" и т.п.) — вызывай create_order_request.
- Перед вызовом обязательно собери у клиента:
- Имя
- Телефон или другой контакт для связи
- Все параметры заказа (модель, бренд, размер, цвет, количество)
- Если клиент назвал несколько моделей — передавай массив items с каждым товаром.
- После создания заявки покажи клиенту красивый текст подтверждения.
Очень вероятно, что вам захочется использовать свой. Для помощи в составлениии промптов рекомендую вам использовать ChatGPT или Grok.
Теперь вы можете запустить вашего ИИ-агента(в консоли):
python3 main.py
Не буду подробно останавливаться на процессе создания Telegram-бота, так как эта тема уже не раз разбиралась на многих ресурсах. Отмечу лишь, что через BotFather необходимо создать бота и получить токен. Сам токен следует поместить в файл с секретами, то есть в .env.
Функциональность бота реализована в проекте в файле telegram_bot.py. Он построен с использованием специализированного Python-фреймворка aiogram. В рамках примера я ограничился минимальным набором возможностей и реализацией только режима polling. При необходимости вы, разумеется, можете расширить функциональность бота и добавить другие режимы работы.
Запустить бота можно командой:
python3 telegram_bot.py
Обратите внимание, бот не выводит "размышления" ИИ-агента, а только результаты. При этом в консоли будут и размышления.
Скринкаст работы ИИ-агента через Telegram-бота
Исходный код проекта
В рамках этой статьи мы создали простого ИИ-агента с использованием фреймворка smolagents. Очевидно, что получившееся решение не является production-ready продуктом. Тем не менее, оно позволяет достаточно быстро погрузиться в тему ИИ-агентов, понять основные принципы их устройства и взаимодействия с инструментами, базами данных и внешними источниками данных.
Кажется, подобные проекты формируют хорошую основу для дальнейшего развития в этом направлении и последующего построения более сложных агентских систем, ориентированных на реальные бизнес-задачи. Надеюсь материалы будет вам полезны.