Приложения искусственного интеллекта, созданные на Rust, постепенно переходят от первоначальных экспериментов к более практичным моделям, согласно живой презентации, организованной JetBrains совместно с Rust Foundation. Первая сессия была посвящена библиотеке Rig с открытым исходным кодом и тому, как использовать её для создания приложений на основе больших языковых моделей и агентов, способных вызывать инструменты и выполнять задачи внутри приложения.
Orhun Parmaksız, Developer Advocate, продемонстрировал небольшого программного агента, созданного с использованием Rig и Ratatui, а Stephen Korzeniewski, основной сопровождающий Rig в 0xPlaygrounds, объяснил внутреннюю архитектуру проекта и решения, лежащие в основе его программных интерфейсов.
Единый интерфейс для провайдеров моделей
Rig решает распространённую практическую проблему приложений для языковых моделей: у OpenAI, Anthropic, Gemini и других провайдеров разные программные интерфейсы, даже если некоторые сервисы заявляют о совместимости с интерфейсом OpenAI. Вместо непосредственной привязки частей приложения к интерфейсу одного провайдера Rig предоставляет единый интерфейс Rust, благодаря которому провайдера можно заменить без переписывания частей, связанных с моделью.
Библиотека организует приложение вокруг нескольких основных компонентов, включая клиент провайдера, модель дополнения, агента и доступные ему инструменты. Агент работает как более высокий уровень по сравнению с непосредственным запросом к модели: он добавляет инструкции, ограничения на количество токенов и возможности, необходимые для выполнения задач, выходящих за рамки потока входного и выходного текста.
Инструкции агента передаются в Rig в виде того, что называется preamble. Эти инструкции выполняют роль системного запроса и добавляются в начало каждого запроса. Сетевые соединения с провайдерами моделей управляются через асинхронные интерфейсы, при этом многие детали асинхронной работы остаются скрыты внутри библиотеки, чтобы код приложения сосредотачивался на настройке и требуемом поведении.
Инструменты превращают агента в часть приложения
Rig определяет инструмент через интерфейс Tool trait в Rust. Определение инструмента включает его имя, типы входных и выходных данных и ошибок, а также функцию, выполняемую при его вызове. В нём также описываются ожидаемые аргументы с использованием JSON Schema, благодаря чему модель получает структурированное описание данных, которые она может предоставить.
После регистрации инструмента у агента модель с поддержкой вызова инструментов может определить, когда его использовать, и включить результат в ответ. Функция может выполнять вычисление, обращаться к базе данных, получать информацию или подключаться к другому сервису. Инструмент также может принимать контекст, сохраняющий состояние, например количество вызовов или кэшированные результаты. Эта идея распространяется и на самих агентов: одного агента можно предоставить другому в качестве инструмента для делегирования задач между ними.
От демонстрационного примера к приложению, пригодному для тестирования
Проект Rat Code объединил эти компоненты в небольшом программном агенте, работающем в терминале с использованием Rig и Ratatui. Файл main.rs инициализирует клиента провайдера, модель и агента, тогда как возможности чтения и записи файлов, а также выполнения команд оболочки определяются отдельно, а затем регистрируются у агента через интерфейс инструментов Rig.
Приложение также использует интерфейс потоковой передачи Rig для обработки ответа по частям и обновления интерфейса терминала во время генерации ответа моделью. В презентации также рассматривались система хуков, механизм восстановления после вызовов инструментов и проектные решения, лежащие в основе абстракций библиотеки. Полный разбор кода начинается в записи на отметке 27:28.
RAG, локальные модели и тестирование
Rig не ограничивается размещёнными провайдерами моделей. Она поддерживает приложения с генерацией, дополненной извлечением, где документы и запросы пользователей преобразуются в векторные представления, после чего выполняется поиск семантически наиболее близких документов для добавления в контекст модели. Библиотека предоставляет интеграции с базами данных и абстракции для векторных хранилищ, а также возможность реализовать интерфейс векторного хранилища при использовании базы данных, не поддерживаемой напрямую.
Локальные модели также можно запускать через Ollama и llama.cpp либо использовать интеграцию rig-candle для непосредственного выполнения вывода внутри приложения Rust. Этот вариант позволяет включать веса модели в приложение и запускать поддерживаемые модели через WebAssembly без зависимости от размещённого интерфейса модели или отдельного локального сервера вывода.
Значение этих вариантов проявляется в том, где запускаются модели и хранятся данные, но одновременно они создают проблему тестирования интеграций. Rig в основном использует систему записи: тесты выполняются с реальными провайдерами, HTTP-трафик сохраняется в файлах YAML, а затем фиктивный сервер воспроизводит запросы и ответы в тестах непрерывной интеграции. Проект содержит около 1 700 записанных взаимодействий, которые воспроизводятся при каждом запросе на слияние в течение нескольких секунд.
Эти тесты проверяют сохранение работоспособности программной интеграции, но не измеряют качество результатов модели, которое может измениться после обновления модели провайдером. Поэтому в презентации упоминались запланированные тесты на живых моделях как отдельный подход для приложений, зависящих от качества ответа.
Редакционный взгляд: что важно разработчикам?
Практическая ценность Rig заключается не только в добавлении нового провайдера, но и в отделении уровня приложения от деталей интерфейсов моделей при сохранении инструментов, извлечения и локального вывода в единой структуре Rust. Это может снизить стоимость смены провайдера или способа запуска, но не устраняет поведенческие различия между моделями и само по себе не решает проблему оценки качества результатов. Механизм тестирования в проекте показывает, что обеспечение работоспособности соединения — это одно, а проверка того, что модель выдаёт требуемый результат, — другое, для чего нужны живые тесты и независимые критерии оценки.