Как сократить расходы на токены и повысить точность LLM. Java.. Java. Kotlin.. Java. Kotlin. llm.. Java. Kotlin. llm. spring.. Java. Kotlin. llm. spring. spring boot.. Java. Kotlin. llm. spring. spring boot. spring data.. Java. Kotlin. llm. spring. spring boot. spring data. spring framework.. Java. Kotlin. llm. spring. spring boot. spring data. spring framework. spring security.. Java. Kotlin. llm. spring. spring boot. spring data. spring framework. spring security. tool.. Java. Kotlin. llm. spring. spring boot. spring data. spring framework. spring security. tool. Блог компании Spring АйО.. Java. Kotlin. llm. spring. spring boot. spring data. spring framework. spring security. tool. Блог компании Spring АйО. Программирование.

Когда количество доступных LLM инструментов (tool-ов) разрастается, традиционные подходы к tool calling становятся непрактичными — утилизация токенов улетает ещё до начала общения. К тому же, модели становится сложнее выбрать нужный набор tool-ов для решения проблемы.

В новом переводе от команды Spring АйО читаем о паттерне Tool Search Tool, предложенном Anthropic и реализованном в Spring AI с помощью ToolSearchToolCallAdvisor. Он позволяет LLM динамически находить нужные инструменты по мере необходимости, экономя до 64% токенов и повышая точность.


По мере того как AI-агенты подключаются к всё большему числу сервисов — Slack, GitHub, Jira, MCP-серверы — библиотеки инструментов стремительно разрастаются. В типичной конфигурации с несколькими серверами может насчитываться более 50 инструментов, потребляющих свыше 55 000 токенов до начала самого диалога. Ещё хуже то, что точность выбора инструмента снижается, когда модель сталкивается с 30+ инструментами с похожими названиями.

Комментарий от Михаила Поливаха

Здесь наверное для вообще общего понимания статьи нужно сделать пару пояснений.

Довольно часто AI Agent-ы взаимодействуют с какими-либо внешними системами, и всё чаще это происходит через MCP протокол. У какого-то ресурса есть MCP сервер, который может быть написать с помощью Spring AI или ещё чего угодно, и MCP client запрашивает этот MCP server, где последний представляет собой некоторый прокси к этому самому ресурсу. MCP server знает

– О том, что может выполнять ресурс
– О том, какие данные он может возвращать

и т.д.

Проблема в том, что с популяризацией MCP протокола и AI Agent-ов поулчилось так, что абстрактный AI Agent рабоатет с огромным количеством MVP серверов, например с MCP серверами для:

– Мессенджера 
– Почты
– Файловой системы
– Менеджеру пакетов (например npm) и т.д.

И каждый MVP сервер предлагает оргомное количество функционала. Чаще всего, MCP хост не задумывается, и просто все тулы, что предлагает каждый MVP Server запихивает в контекст LLM. 

Как Вы можете догадаться, это вполне себе может привести (и приводит!) к огромному потреблению токенов и, соответственно, сильно удоражает пользование AI Агентами. Это проблема. Её решают.

Эту проблему решает паттерн Tool Search Tool, предложенный компанией Anthropic: вместо загрузки всех определений инструментов заранее, модель обнаруживает нужные инструменты по запросу. Изначально ей предоставляется только инструмент поиска, с помощью которого она запрашивает доступные возможности по мере необходимости, и получает в контекст только соответствующие определения. Это обеспечивает значительную экономию токенов при сохранении доступа к сотням инструментов.

Ключевая идея: хотя этот подход был впервые реализован в Claude от Anthropic, мы можем применить ту же концепцию для любой LLM-модели с помощью Recursive Advisors в Spring AI. Spring AI предоставляет переносимую абстракцию, делающую возможным динамическое обнаружение инструментов для OpenAI, Anthropic, Gemini, Ollama, Azure OpenAI и любых других провайдеров LLM, поддерживаемых Spring AI.

Наши предварительные тесты показывают, что реализация паттерна Tool Search Tool в Spring AI обеспечивает сокращение числа токенов на 34–64% при использовании моделей OpenAI, Anthropic и Gemini, сохраняя при этом полный доступ к сотням инструментов.

Проект Spring AI Tool Search Tool доступен по адресу: spring-ai-tool-search-tool.

Как работает вызов инструментов

Сначала разберёмся, как работает вызов инструментов (он же tool calling) в Spring AI при использовании ToolCallAdvisor — специального рекурсивного советника, который:

Как сократить расходы на токены и повысить точность LLM - 1
  • Перехватывает запрос ChatClient до того, как он попадёт в LLM

  • Включает определения инструментов (т.е. этих самых tool-ов) в промпт, отправляемый модели — для всех зарегистрированных инструментов!

  • Обнаруживает запросы на вызов инструментов в ответе модели

  • Выполняет запрошенные инструменты с помощью ToolCallingManager

  • Повторно обращается к модели с результатами вызова инструментов до тех пор, пока не будет получен окончательный ответ

Вызов инструментов происходит в рекурсивном цикле — советник (advisor) продолжает обращаться к LLM до тех пор, пока не прекратятся запросы на использование инструментов.

Проблема

Стандартный механизм вызова инструментов (например, ToolCallAdvisor) отправляет все определения инструментов в LLM заранее. Это приводит к трём серьёзным проблемам при работе с большими наборами инструментов:

  • Раздувание контекста — огромное потребление токенов ещё до начала диалога

  • Путаница в инструментах — модели сложно выбрать правильный инструмент при наличии 30+ схожих

  • Повышенные затраты — вы платите за передачу определений инструментов, даже если они не используются в запросе

Решение: Tool Search Tool

Расширив ToolCallAdvisor из Spring AI, мы создали ToolSearchToolCallAdvisor, который реализует динамическое обнаружение инструментов. Он перехватывает цикл вызова инструментов и выборочно подставляет определения только тех инструментов, которые модель определяет как нужные:

Как сократить расходы на токены и повысить точность LLM - 2

Процесс работает следующим образом:

  • Индексация: в начале диалога все зарегистрированные инструменты индексируются в ToolSearcher (но не отправляются в LLM)

  • Первичный запрос: в LLM отправляется только определение Tool Search Tool (TST) — экономия токенов в контексте

  • Запрос на обнаружение: когда LLM нужны определённые возможности, она вызывает TST с поисковым запросом

  • Поиск и расширение: ToolSearcher находит подходящие инструменты (например, «Tool XYZ»), и их определения добавляются в следующий запрос

  • Вызов инструмента: теперь LLM видит как TST, так и определения найденных инструментов и может вызвать нужный

  • Выполнение инструмента: найденный инструмент выполняется, а результат передаётся обратно в LLM

  • Ответ: LLM генерирует окончательный ответ, используя результаты выполнения инструментов

В коде это выглядит следующим образом:

var toolSearchToolCallAdvisor = ToolSearchToolCallAdvisor.builder()
    .toolSearcher(toolSearcher)
    .maxResults(5)
    .build();

ChatClient chatClient = chatClientBuilder
    .defaultTools(new MyTools())  // 100s of tools registered but NOT sent to LLM initially
    .defaultAdvisors(toolSearchToolCallAdvisor) // Activate Tool Search Tool
    .build();

Плагиновые стратегии поиска

Интерфейс ToolSearcher абстрагирует реализацию поиска, поддерживая несколько стратегий (см. tool-searchers для готовых реализаций):

Стратегия

Реализация

Оптимально для

Semantic

VectorToolSearcher

Запросы на естественном языке, нечеткое соответствие

Keyword

LuceneToolSearcher

Точное совпадение терминов, известные названия инструментов

Regex

RegexToolSearcher

Шаблоны названий инструментов (например, get_*_data)

Начало работы

Репозиторий проекта на GitHub: spring-ai-tool-search-tool.

Подробные инструкции по настройке и примеры кода доступны в руководстве Quick Start (v1.x), а также в сопутствующем примере приложения (v1.x).

Maven Central (1.0.1):

<dependency>
    <groupId>org.springaicommunity</groupId>
    <artifactId>tool-search-tool</artifactId>
    <version>1.0.1</version>
</dependency>

<!-- Choose a search strategy -->
<dependency>
    <groupId>org.springaicommunity</groupId>
    <artifactId>tool-searcher-lucene</artifactId>
    <version>1.0.1</version>
</dependency>

Версия v1.0.x совместима с Spring AI 1.1.x и Spring Boot 3, а версия v2.0.x — с Spring AI 2.x и Spring Boot 4.

Комментарий от Михаила Поливаха

Здесь частично речь про будущую совместимость – Spring AI 2.x ещё не вышел и пока непонятно когда выйдет.

Пример использования

@SpringBootApplication
public class Application {

    @Bean
    CommandLineRunner demo(ChatClient.Builder builder, ToolSearcher toolSearcher) {
        return args -> {
            var advisor = ToolSearchToolCallAdvisor.builder()
                .toolSearcher(toolSearcher)
                .build();

            ChatClient chatClient = builder
                .defaultTools(new MyTools())
                .defaultAdvisors(advisor)
                .build();

            var answer = chatClient.prompt("""
                Help me plan what to wear today in Amsterdam.
                Please suggest clothing shops that are open right now.
                """).call().content();
            
            System.out.println(answer);
        };
    }

    static class MyTools {

		@Tool(description = "Get the weather for a given location at a given time")
		public String weather(String location, 
            @ToolParam(description = "YYYY-MM-DDTHH:mm") String atTime) {...}

		@Tool(description = "Get clothing shop names for a given location at a given time")
		public List<String> clothing(String location,
				@ToolParam(description = "YYYY-MM-DDTHH:mm") String openAtTime) {...}

		@Tool(description = "Current date and time for a given location")
		public String currentTime(String location) {...}
        
        // ... potentially hundreds more tools
    }
}

Для приведённого выше примера поток выполнения будет следующим:

  • Запрос пользователя:
    «Помоги мне решить, что надеть сегодня в Амстердаме. Порекомендуй магазины одежды, которые сейчас открыты.»

  • Инициализация:
    Индексируются все инструменты: weather, clothing, currentTime (+ потенциально ещё сотни)

  • Первый вызов LLM — модель видит только toolSearchTool
    → LLM вызывает: toolSearchTool(query=”current time date”) → [“currentTime”]

  • Второй вызов LLM — модель видит toolSearchTool + currentTime
    → LLM вызывает: currentTime(“Amsterdam”) → “2025-12-08T11:30”
    → затем: toolSearchTool(query=”weather location”) → [“weather”]

  • Третий вызов LLM — модель видит toolSearchTool + currentTime + weather
    → LLM вызывает: weather(“Amsterdam”) → “Ясно, 15°C”
    → затем: toolSearchTool(query=”clothing shops”) → [“clothing”]

  • Четвёртый вызов LLM — модель видит toolSearchTool + currentTime + weather + clothing
    → LLM вызывает: clothing(“Amsterdam”, “2025-12-08T11:30”) → [“H&M”, “Zara”, “Uniqlo”]

  • Финальный ответ:
    «С учётом солнечной погоды 15°C в Амстердаме, рекомендую надеть лёгкие слои. Вот магазины одежды, которые сейчас открыты: H&M, Zara, Uniqlo…»

Измерения производительности

 ⚠️ Предупреждение: это предварительные, ручные измерения, полученные после нескольких запусков. Они не усреднены по множеству итераций и должны рассматриваться как иллюстративные, а не как статистически точные.

Для оценки экономии токенов мы провели предварительные тесты с демонстрационным приложением и следующей конфигурацией:

  • Задача:
    «Помоги мне решить, что надеть сегодня в Амстердаме. Порекомендуй магазины одежды, которые сейчас открыты.»

  • Набор инструментов:
    Всего 28 инструментов:
    • 3 релевантных — weather, clothing, currentTime
    • 25 нерелевантных «заглушек» — специально добавлены, чтобы показать, как эффективно поиск отбирает только нужные инструменты среди множества нерелевантных

  • Стратегии поиска:
    • Lucene (на основе ключевых слов)
    • VectorStore (семантический поиск)

  • Тестируемые модели:
    Gemini (gemini-3-pro-preview)
    OpenAI (gpt-5-mini-2025-08-07)
    Anthropic (claude-sonnet-4-5-20250929)

Измерения проводились с использованием специального TokenCounterAdvisor, отслеживающего и агрегирующего использование токенов.

Результаты с использованием Lucene-поиска

Модель

Подход

Всего токенов

Токены запроса

Токены ответа

Запросов

Экономия

Gemini

С TST

2 165

1 412

231

4

60%

Без TST

5 375

4 800

176

3

OpenAI

С TST

4 706

2 770

1 936

5

34%

Без TST

7 175

5 765

1 410

3

Anthropic

С TST

6 273

5 638

635

5

64%

Без TST

17 342

16 752

590

4

Результаты с использованием VectorStore-поиска

Модель

Подход

Всего токенов

Токены запроса

Токены ответа

Запросов

Экономия

Gemini

С TST

2 214

1 502

234

4

57%

Без TST

5 122

4 767

73

3

OpenAI

С TST

3 697

2 109

1 588

4

47%

Без TST

6 959

5 771

1 188

3

Anthropic

С TST

6 319

5 642

677

5

63%

Без TST

17 291

16 744

547

4

Ключевые наблюдения

  • Значительная экономия токенов во всех моделях:
    Паттерн Tool Search Tool обеспечил снижение общего потребления токенов на 34–64% в зависимости от модели и стратегии поиска.

  • Основной фактор — токены запроса:
    Экономия достигается в первую очередь за счёт сокращения токенов промпта — с TST в контекст подставляются только обнаруженные инструменты, а не все 28 сразу.

  • Компромисс: больше запросов, меньше токенов:
    Подход с TST требует 4–5 запросов против 3–4 без него, но суммарная стоимость токенов значительно ниже.

Комментарий от Евгения Сулейманова

Очень важное утверждение о том, что главный “налог” tool-calling – это не сами вызовы, а раздувание промпта всеми схемами инструментов, и TST логично режет его за счет lazy-discovery, параллельно улучшая выбор среди однотипных tools. Но это не бесплатная магия: вы меняете “один жирный запрос” на 4–5 тонких, поэтому важно мерить не только токены, а end-to-end стоимость (latency + число round-trip-ов) и добавить кэш результатов поиска/подобранных инструментов между итерациями. Качество будет упираться в качество метаданных инструментов: стабильные имена/ID, хороший description с синонимами, явные входы/выходы, плюс фильтрация “опасных”/дорогих инструментов на уровне searcher.

Для прода я бы добавил guardrails: fallback на “полный список” при провале поиска, лимиты на расширение контекста, и A/B-валидацию точности выбора инструмента (не только успешность ответа). В целом это правильный шаг к масштабируемым агентам в MCP-мире, и ценность Spring AI здесь именно в переносимой рекурсивной архитектуре advisor-ов, которую можно докручивать под разные модели и качества tool-библиотек.

  • Обе стратегии поиска эффективны:
    Lucene и VectorStore показали сравнимую производительность, при этом VectorStore дал немного лучшую эффективность для OpenAI в данном тесте.

  • Все модели корректно завершили задачу:
    Все три модели (Gemini, OpenAI, Anthropic) поняли, что нужно сначала вызвать currentTime, прежде чем обращаться к другим инструментам — это демонстрирует корректное понимание зависимостей между инструментами.

  • Разные стратегии обнаружения:
    Модели продемонстрировали различные подходы: некоторые запрашивали все нужные инструменты сразу, другие — по одному. Тем не менее, все они использовали параллельный вызов инструментов, где это было возможно, чтобы оптимизировать выполнение.

  • Старые модели могут испытывать трудности:
    Более ранние версии моделей могут не справляться с паттерном поиска инструментов: пропускать нужные инструменты или принимать неэффективные решения. В таких случаях рекомендуется:

    • Добавить systemMessageSuffix для дополнительной инструктивности

    • Попробовать разные конфигурации tool-searcher

    • Использовать паттерн LLM as Judge для обеспечения надёжного поведения на разных моделях

Когда использовать

Подход Tool Search Tool

Традиционный подход

Более 20 инструментов в системе

Небольшая библиотека инструментов (<20)

Определения инструментов занимают более 5 000 токенов

Все инструменты регулярно используются в каждом сеансе

Разработка MCP-систем с несколькими серверами

Очень компактные определения инструментов

Наблюдаются проблемы с точностью выбора инструментов

Заключение

Паттерн Tool Search Tool — это шаг к созданию масштабируемых AI-агентов. Объединяя инновационный подход Anthropic с переносимой абстракцией Spring AI, мы можем строить системы, которые эффективно управляют тысячами инструментов и при этом сохраняют высокую точность вне зависимости от провайдера LLM.

Сила рекурсивной архитектуры советников Spring AI заключается в том, что она позволяет реализовывать сложные сценарии обнаружения инструментов, которые работают универсально — будь то модели GPT от OpenAI, Claude от Anthropic, локальные модели Ollama или любой другой LLM, поддерживаемый Spring AI. Вы получаете все преимущества динамического обнаружения инструментов — без привязки к конкретной реализации или провайдеру.


Как сократить расходы на токены и повысить точность LLM - 3

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.

Автор: spring_aio

Источник

Rambler's Top100