Semble: поиск по коду для ИИ-агентов на 98% дешевле grep
Когда Claude Code или Cursor впервые открывают незнакомый репозиторий, они делают одно и то же: запускают grep по ключевому слову, находят десять файлов, читают каждый целиком и тратят на это половину контекстного окна. Половина прочитанного — тесты, legacy-совместимость и комментарии на китайском. Результат: агент дорого, медленно и неуверенно ориентируется в чужом коде. Semble, open-source библиотека от команды MinishLab, предлагает другой путь: искать по смыслу, возвращать только нужный фрагмент и делать это за миллисекунды на обычном процессоре.
Что такое Semble
Semble — это движок семантического поиска по коду, заточенный под потребности ИИ-агентов. Вместо того чтобы возвращать полные файлы по совпадению ключевых слов, он разбивает репозиторий на осмысленные блоки, индексирует их статическими эмбеддингами и отвечает на запросы агента точными фрагментами. По замерам авторов, Semble использует в среднем на 98% меньше токенов, чем классическая связка grep + read, при этом сохраняя 94% полноты ответа при бюджете всего в две тысячи токенов.
Индексирование среднего репозитория занимает около 250 мс, а поисковый запрос обрабатывается за 1,5 мс. Всё работает на CPU, без API-ключей, GPU и внешних сервисов. Библиотека написана на Python, распространяется под лицензией MIT и интегрируется с агентами через MCP-сервер, bash-скрипт или прямой Python API.
Почему grep не справляется с агентами
Классический grep ищет буквальные совпадения. Если агент спрашивает «как здесь работает аутентификация», grep найдёт все файлы, где встречается слово auth, включая тесты, документацию и конфиги. Агенту приходится читать каждый файл целиком, чтобы понять, где реальная логика, а где шум. Это не просто неэффективно — это архитектурный дефект масштабирования.
Семантический поиск решает проблему иначе. Он понимает, что запрос «аутентификация» ближе к функции verify_token, чем к комментарию в тесте. И возвращает не файл, а конкретный блок кода с номерами строк. Агент получает ровно столько контекста, сколько нужно для принятия решения, и не переполняет своё окно бесполезным текстом.
Авторы Semble провели бенчмарк на 1250 запросах по 63 репозиториям на 19 языках программирования. Результаты показывают, что grep+read требует полного контекстного окна в 100 тысяч токенов, чтобы достичь 85% полноты. Semble достигает 94% полноты при двух тысячах токенов. Разница в пятьдесят раз — и это напрямую влияет на стоимость и скорость работы агента.
Архитектура: как работает гибридный поиск
Semble использует двухстадийную архитектуру: быстрый отбор кандидатов и тонкая ранжировка. На первой стадии каждый файл разбивается на блоки с помощью библиотеки Chonkie, после чего каждый блок получает два независимых скора. Статический эмбеддинг от модели potion-code-16M оценивает семантическую близость запроса и фрагмента. Параллельно BM25 ищет лексические совпадения по идентификаторам и именам API. Два списка результатов объединяются через Reciprocal Rank Fusion.
Вторая стадия — ранжировка с учётом специфики кода. Если запрос выглядит как символ, например Foo::bar или getUserById, система увеличивает вес лексического ретривера. Если запрос сформулирован естественным языком, баланс смещается к семантике. Фрагменты, содержащие определение запрошенного символа, получают бонус перед фрагментами, где этот символ просто упоминается. Система также учитывает стемы идентификаторов: запрос parse config поднимет фрагменты с parseConfig, ConfigParser и config_parser.
Если из одного файла найдено несколько релевантных блоков, файл получает дополнительный вес, чтобы в топе оказался именно тот модуль, который в целом отвечает за запрошенную функциональность. Наконец, тесты, legacy-совместимость, примеры и TypeScript-заглушки понижаются в выдаче, чтобы на первом месте оказалась каноническая реализация.
Сравнение с конкурентами
На том же бенчмарке Semble показал NDCG@10 0,854. Это на уровне гибридной версии CodeRankEmbed с 137 миллионами параметров, которая индексируется за 57 секунд и отвечает за 16 мс. Semble индексируется в 218 раз быстрее и отвечает в 11 раз быстрее, уступая всего одному проценту в качестве. ColGREP, ещё один конкурент, индексируется за 5,8 секунды с NDCG@10 0,693. Простой BM25 работает ещё быстрее, но качество падает до 0,673, а grepai с трансформерной моделью уступает по скорости и качеству одновременно.
Ключевое преимущество Semble — отсутствие forward-pass трансформера во время запроса. Эмбеддинги статичны, BM25 работает по инвертированному индексу, а ранжировка — это линейная комбинация предпосчитанных сигналов. Поэтому система масштабируется линейно с размером репозитория и не требует GPU даже для кодовых баз в миллионы строк.
Как агенты используют Semble на практике
Semble предлагает три способа интеграции. MCP-сервер подключается к Claude Code, Cursor, Codex и OpenCode напрямую: агент вызывает инструмент search с естественно-языковым запросом и получает список фрагментов с путями файлов и номерами строк. Bash-интеграция подходит для подагентов Claude Code и Codex CLI, которые не могут напрямую вызывать MCP-инструменты. Python API позволяет встроить поиск в собственные инструменты и пайплайны.
Помимо прямого поиска, Semble умеет находить код, семантически близкий к уже известному фрагменту. Если агент нашёл функцию аутентификации и хочет понять, где она используется, он вызывает find_related с путём файла и номером строки. Система вернёт связанные реализации, что особенно полезно в больших монорепозиториях, где одна функция разбросана по десятку модулей.
Интересная деталь — встроенный счётчик экономии. Semble записывает, сколько символов файлов агенту не пришлось читать благодаря точечной выдаче, и переводит это в токены по формуле четыре символа на токен. За время тестирования команда MinishLab сэкономила 1,2 миллиона токенов при 89% экономии в среднем. Это не просто метрика для README — это прямое снижение счёта за API, если агент работает через облачные модели.
Ограничения и ожидания
Semble решает задачу поиска, но не заменяет полное понимание архитектуры. Если агенту нужно освоить новый фреймворк с нуля, одних фрагментов кода недостаточно — нужны документация, примеры и контекст использования. Кроме того, качество сильно зависит от того, насколько хорошо запрос сформулирован. Размытые запросы вроде «найди баг» дают размытые результаты, как и у любого поискового движка.
Также стоит помнить, что статические эмбеддинги не обновляются автоматически при изменении кода. После значительного рефакторинга индекс нужно перестраивать, хотя это занимает менее секунды для среднего репозитория. Для очень больших кодовых баз в миллионы строк задержка индексации может вырасти до нескольких секунд, что всё равно остаётся приемлемым для большинства рабочих процессов.
Часто задаваемые вопросы
Semble заменяет grep полностью?
Нет, а дополняет. Авторы рекомендуют использовать grep для точного поиска строковых литералов и быстрой проверки фактов, а Semble — для навигации по незнакомой кодовой базе и поиска по смыслу. Вместе они покрывают большинство информационных потребностей агента.
Нужен ли GPU для работы Semble?
Нет. Все вычисления выполняются на CPU. Статическая модель potion-code-16M не требует forward-pass во время запроса, а BM25 работает по инвертированному индексу. Это делает Semble доступным для локальной разработки и CI/CD без дополнительной инфраструктуры.
Какие языки программирования поддерживаются?
Бенчмарки проводились на 19 языках, включая Python, JavaScript, TypeScript, Rust, Go, Java, C++, Ruby и другие. Разбиение на блоки выполняется библиотекой Chonkie, которая учитывает синтаксис языка, поэтому качество сегментации остаётся высоким независимо от стека.
Итог
Semble демонстрирует, что узкое место агентов при работе с кодом — не качество модели, а качество поиска. Даже самый умный агент тратит токены и время впустую, если ему приходится читать полные файлы ради одной функции. Гибридный подход Semble, сочетающий статические эмбеддинги, BM25 и кодо-специфичную ранжировку, решает эту проблему без GPU и без облачных API. Для команд, которые строят агентные пайплайны, это означает дешевле, быстрее и предсказуемее — три качества, которые редко сочетаются в одном инструменте.