Каждый раз, когда Octocode выполняет семантический поиск, каждый раз, когда Octomind направляет промпт нужной модели, каждый раз, когда один из наших продуктов общается с LLM — всё проходит через один и тот же кусок кода. В прошлом году мы вынесли его из Octocode. Теперь на нём работает всё.

Он называется Octolib. И мы только что открыли его исходники.

От внутреннего клея к общей инфраструктуре

Octolib начинался как самая неприятная часть Octocode, о которой никто не хотел думать.

Octocode нужны эмбеддинги, чтобы семантически понимать код. LLM, чтобы отвечать на вопросы о вашей кодовой базе. Реранкинг, чтобы выдавать результаты, которые действительно важны. Поначалу это означало три разных клиентских библиотеки, три разных подхода к обработке ошибок и три разных способа парсить использование токенов. (Я до сих пор помню, как добавлял эмбеддинги Cohere и пришлось изучать весь их SDK только ради того, чтобы получить вектор.)

Добавление нового провайдера означало правки кода в шести местах. Мы сделали то, что делает большинство команд: написали тонкую обёртку.

Потом у обёртки появились фичи. Потом появились провайдеры. Потом мы поняли, что Octomind — нашей платформе AI-агентов — нужно ровно то же самое. И Octobrain тоже.

Копировать обёртку три раза казалось глупым. Вынести её — очевидным.

Octolib — это и есть тот вынос. Самодостаточная Rust-библиотека для LLM-инференса, эмбеддингов и реранкинга со всеми основными провайдерами.

Одна строка, любой бэкенд

Идея простая. Одна строка provider:model. Одно API. Любой бэкенд.

let provider = ProviderFactory::get_provider_for_model("openai:gpt-5.5")?;
let response = provider.chat_completion(params).await?;

Замените openai:gpt-5.5 на anthropic:claude-opus-4-5-20251101, deepseek:deepseek-chat, nvidia:meta/llama-3.3-70b-instruct или openrouter:anthropic/claude-opus-4.5. Код не меняется. Тип ответа не меняется. Подсчёт использования токенов и стоимости продолжает работать.

Вот трейт, который делает это возможным:

#[async_trait]
pub trait AiProvider {
    fn name(&self) -> &str;
    fn supports_model(&self, model: &str) -> bool;
    async fn chat_completion(&self, params: ChatCompletionParams) -> Result<ProviderResponse>;
    fn get_model_pricing(&self, model: &str) -> Option<Pricing>;
}

Каждый провайдер реализует один и тот же интерфейс. У OpenAI собственная нативная реализация. NVIDIA NIM, Cerebras, Together, Ollama и локальные эндпоинты идут через общий OpenAI-совместимый слой. Фабрика разбирает строку модели и направляет вызов к нужному бэкенду.

Скучно по задумке. В этом и суть.

LLM-провайдеры

Провайдер Тип Чат Структурированный вывод Кэширование
OpenAI Нативный
Anthropic Нативный
Google (Gemini) Нативный
DeepSeek Нативный
Moonshot Нативный
MiniMax Нативный
Z.ai Нативный
OpenRouter OpenAI-совместимый
NVIDIA NIM OpenAI-совместимый
Cerebras OpenAI-совместимый
Together OpenAI-совместимый
Cloudflare Workers AI OpenAI-совместимый
OctoHub OpenAI-совместимый
Ollama OpenAI-совместимый
Локальные эндпоинты OpenAI-совместимый

Эмбеддинги и реранкинг

Провайдер Эмбеддинги Реранкинг Локально
Jina
Voyage
Cohere
OpenAI
Google
FastEmbed

Новые провайдеры появляются в виде pull request'ов. Если нужен провайдер, которого нет, шаблон лежит в src/llm/providers/openai.rs.

То, о чём никто не говорит, пока оно не сломается

Мульти-провайдерные библиотеки больше не редкость. Разница в деталях, которые имеют значение, только когда вы гоняете их по-серьёзному.

Отслеживание стоимости. Каждый ответ включает использование токенов и рассчитанную стоимость. Для нативных API-провайдеров мы поддерживаем таблицы цен по моделям. Для прокси и агрегаторов, которые хостят open-weight модели, мы используем эталонные цены, подобранные по имени модели. Если upstream API не возвращает поле со стоимостью, мы вычисляем её сами по количеству токенов.

Звучит несущественно. Но это не так. Попробуйте погонять тысячи запросов через пять провайдеров и угадать, куда ушли ваши деньги.

Структурированный вывод. Не все провайдеры поддерживают ограничения по JSON-схеме. Octolib знает, какие поддерживают — OpenAI, Anthropic, DeepSeek, Moonshot, MiniMax — и обрабатывает различия в формате запроса. Вы устанавливаете response_format и получаете распарсенный JSON. Никакого ручного prompt engineering. Никаких костылей вроде "пожалуйста, ответь валидным JSON".

Эмбеддинги и реранкинг. Та же абстракция провайдера применяется к generate_embeddings() и rerank(). Jina, Voyage, Cohere, OpenAI, FastEmbed — одно API, разные бэкенды. Современные RAG-пайплайны затрагивают три разных типа сервисов. Управлять отдельными клиентами для каждого — рутина, которой вы не должны заниматься.

Никаких panic, никаких println. Это библиотека, а не приложение. Каждая публичная функция возвращает Result. Ошибки несут контекст. Отладочный вывод идёт через tracing, а не в stdout. Это не самые впечатляющие фичи. Но именно они отличают библиотеку, которой доверяешь в продакшне, от той, что будит тебя в 3 часа ночи.

Три продукта, одна библиотека

Octolib — это AI-слой всего нашего стека:

  • Octocode — семантический поиск кода, Q&A по кодовой базе, суммаризация диффов
  • Octomind — рассуждение агентов, вызовы инструментов, многошаговые рабочие процессы
  • Octobrain — поиск знаний, обработка документов, пайплайны эмбеддингов

Когда мы добавляем новую модель — скажем, reasoning-модель от DeepSeek или новейший релиз Claude — мы обновляем Octolib один раз. Каждый продукт получает её. Когда OpenAI меняет формат ответа API или Anthropic вводит ценообразование для кэша, фикс живёт в одном месте.

Вот почему мы её вынесли. Не потому что код-обёртка интересен. А потому что поддерживать четыре версии одной и той же обёртки дорого, а ошибки в интеграциях с провайдерами означают сломанные продукты.

Вопрос про Rust

Нас иногда об этом спрашивают. Короткий ответ: мы строим инфраструктуру на Rust, а Octolib — это инфраструктура.

Длинный ответ: вызовы LLM — это I/O-bound сетевые запросы. Но окружающий пайплайн — генерация эмбеддингов, реранкинг, подсчёт токенов, батчинг запросов, валидация структурированного вывода — выигрывает от сочетания async-производительности Rust и корректности на этапе компиляции. Когда вы гоняете инференс на масштабе, где важны миллисекунды, вам не нужны паузы сборщика мусора или ошибки типов в рантайме на горячем пути.

И экосистема Rust для AI-инфраструктуры быстро взрослеет. Candle для локального инференса. tokio для async. serde для бесконечного парсинга JSON. Всё стыкуется чисто.

FAQ

Что такое Octolib?

Octolib — это open-source Rust-библиотека для LLM-инференса, эмбеддингов и реранкинга. Одна API-строка (provider:model) направляет вызовы в OpenAI, Anthropic, Google, DeepSeek, OpenRouter, Ollama и 10+ других провайдеров. На ней работают Octocode, Octomind и Octobrain.

Чем Octolib отличается от LiteLLM или LangChain?

Octolib — нативная для Rust, инфраструктурного уровня и узкая по охвату. Она занимается маршрутизацией провайдеров, структурированным выводом, отслеживанием стоимости и реранкингом — и больше ничем. Никаких агентов, никаких chains, никаких prompt-шаблонов. Если вы строите AI-функции на Rust и хотите тонкий, предсказуемый слой между вашим кодом и 15+ провайдерами — это ваша ниша.

Какие провайдеры поддерживаются?

15 LLM-провайдеров (OpenAI, Anthropic, Google Gemini, DeepSeek, Moonshot, MiniMax, Z.ai, OpenRouter, NVIDIA NIM, Cerebras, Together, Cloudflare Workers AI, OctoHub, Ollama, кастомные локальные эндпоинты) и 6 провайдеров эмбеддингов/реранкинга (Jina, Voyage, Cohere, OpenAI, Google, FastEmbed).

Работает ли с локальными моделями?

Да. Ollama и любой OpenAI-совместимый локальный эндпоинт работают из коробки. FastEmbed запускает эмбеддинги локально без API. Меняется только строка provider:model.

Как работает отслеживание стоимости?

Каждый ответ включает использование токенов и рассчитанную стоимость. Нативные провайдеры используют таблицы цен по моделям. Агрегаторы используют эталонные цены по имени модели. Если upstream API не возвращает поле стоимости, Octolib вычисляет её по количеству токенов.

Готова ли библиотека к продакшну?

На ней каждый день работают три продукта (Octocode, Octomind, Octobrain). В коде библиотеки нет panic. Каждая публичная функция возвращает Result. Отладочный вывод идёт через tracing. Лицензия — Apache-2.0.

Open source, открытая экосистема

Octolib — это часть большей картины. Octocode — open source. Архитектура Octomind задокументирована публично. Мы строим публично, потому что проблемы, которые мы решаем — как разговаривать с десятью разными AI-провайдерами и не сойти с ума — не уникальны только для нас.

Библиотека на GitHub. Она компилируется через cargo check. Она запускает примеры без какой-либо настройки, кроме API-ключа. Если вы строите AI-функции на Rust и устали писать один и тот же boilerplate для провайдеров в третий раз, она может сэкономить вам пару недель.

Мы добавляем провайдеров по мере развития событий. Следующий, вероятно, уже в pull request'е.