Представьте, что вы сдаете экзамен с открытой книгой: технически у вас есть все ответы, но почему-то это только усложняет поиск нужного.
- С чего вообще начать поиск?
- Как понять, что ваши источники верны?
- Как оптимизировать свое время, чтобы не потратить всю энергию на избыточные поиски?
Эффективный поиск нужной информации — задача не из легких.
Дайте агенту вопрос, и он окажется в похожей ситуации: у него ограниченное окно контекста, поэтому, как и мы, люди, он должен извлекать информацию для выполнения определенных задач (вместо того чтобы держать все в памяти). При поиске агенты сталкиваются со следующими проблемами:
- Неэффективный поиск: каждый запрос стоит токенов и времени. Агент, который ищет неуклюже (например, открывает каждый файл, чтобы просто посмотреть, что внутри, или постоянно перефразирует один и тот же запрос), может заполнить свой контекст результатами поиска еще до того, как найдет что-то полезное.
- Слишком много контекста сразу: один поисковый запрос, который выгружает полный экспорт данных или десяток документов, заполняет окно контекста за один раз, не оставляя места для самой работы.
- Неактуальный или устаревший контекст: устаревшая или не относящаяся к делу информация может выглядеть для модели так же убедительно, как и правильный ответ. Как только она попадает в окно контекста, агент может начать опираться на нее (и ошибка будет повторяться на каждом последующем шаге).
К счастью, в распоряжении агента есть несколько методов, позволяющих извлекать правильную информацию. Задача фреймворка агента — стратегически применять эти методы, чтобы предоставить модели нужный контекст в нужное время для конкретной задачи.
В этом блоге рассматриваются проблемы поиска для агентов (поиск и извлечение только той информации, которая необходима для текущей задачи), доступные нам методы борьбы с ними, а также то, как учитывать их при проектировании фреймворка агента (на примере фреймворка Deep Agents от LangChain).
Чтобы узнать больше о том, как управлять контекстом после того, как он попал в окно контекста, ознакомьтесь с этим блогом о проектировании контекста (Context Engineering).
Наш пример: агент для конкурентного анализа
Давайте посмотрим, как это можно применить в реальном сценарии: агент для конкурентного анализа. Каждый понедельник агент исследует сотни конкурентов и пишет отчет по шаблону команды. Ему необходимо:
- Найти заметки о компании А за прошлую неделю
- Найти конкретный показатель выручки в огромном экспорте рыночных данных
- Искать в архиве новостей что-то новое
Каждая из этих задач представляет собой разный тип поиска и, следовательно, сталкивается с разными проблемами. Мы создали нашего агента с использованием фреймворка Deep Agents, поэтому есть несколько методов, которые мы можем применить «из коробки», чтобы минимизировать эти проблемы.
1. Неэффективный поиск
Наш агент должен найти три вещи для каждого конкурента. Если на каждую из них уходит десяток попыток (открытие файлов просто чтобы посмотреть, что внутри, или перефразирование поиска, потому что в источнике используются другие слова), его окно контекста заполнится неудачными результатами еще до того, как он напишет хоть слово отчета.
Следовательно, лучший поиск — это тот, который агенту не нужно повторять, а это означает использование правильного инструмента для каждой задачи.
Начните со встроенных инструментов файловой системы
Один из самых распространенных способов поиска информации для агента — использование файловой системы. Однако если наш агент открывает каждый файл, чтобы посмотреть, что внутри, он ищет очень неэффективно: каждый прочитанный файл попадает в окно контекста, поэтому оно может заполниться просто от просмотра.
Лучший подход — сначала проверять имена и ключевые слова (так же, как вы просматриваете указатель книги, а не читаете каждую страницу во время экзамена с открытой книгой). Два распространенных инструмента файловой системы делают именно это:
- glob находит файлы по шаблону имени. Например, **/company-a*.md находит заметки о компании А за прошлую неделю.
- grep ищет внутри файлов, не загружая их в окно контекста. Он сопоставляет буквальный текст и может возвращать соответствующие файлы, соответствующие строки или их количество.
Каждый агент Deep Agent поставляется с этими встроенными инструментами, наряду с ls, read_file, write_file и edit_file. Одни и те же инструменты работают независимо от того, где находятся файлы (состояние агента, локальный диск, постоянное хранилище или песочница), потому что все они проходят через бэкенд агента.
Добавьте инструмент поиска, когда ключевых слов недостаточно
Grep отлично подходит, когда вы знаете, какие слова искать, но он сопоставляет только тот текст, который вы ему даете. Это проблема для третьей задачи в нашем примере: поиск в архиве новостей чего-то нового. Если наш агент будет искать через grep «финансирование компании А», он пропустит статью под заголовком «Компания А закрывает раунд серии B на 50 млн долларов», хотя это именно то, что он ищет.
Чтобы искать по смыслу, а не по точным словам (семантический поиск), добавьте инструмент поиска, поддерживаемый векторным хранилищем. Инструмент поиска — это любой инструмент, который агент может вызвать для получения информации: он принимает запрос, ищет его в источнике данных и возвращает то, что нашел (наиболее близкие совпадения).
То, как инструмент поиска сопоставляет данные, зависит от источника данных, стоящего за ним. При поддержке векторного хранилища он сопоставляет по смыслу, но инструмент поиска может работать и поверх других источников данных:
- База данных SQL для структурированных запросов (например, показатели продаж или записи о клиентах)
- API поиска (для получения свежей информации из интернета)
- MCP-сервер (для инструментов, которые кто-то уже создал, например, поиск по документации)
Более глубокий взгляд на то, как работает семантический поиск, см. в руководстве LangChain.
Позвольте агенту решать, когда искать
Многие системы поиска ищут один раз в начале, а затем отвечают. Это работает для FAQ-бота (двухэтапный RAG), но не для нашего агента. Допустим, в середине исследования компании C он находит статью о запуске продукта, о котором не знал, и теперь ему нужна цена этого продукта (о чем он не мог знать заранее, чтобы искать). При однократном поиске отчет выйдет без этой информации.
Исследовательским агентам нужен агентный поиск (вместо двухэтапного RAG): агент сам решает, когда искать, что искать и нужно ли ему больше данных. В Deep Agents это работает по умолчанию: агент работает в цикле и может вызывать любой инструмент столько раз, сколько ему нужно.
Упакуйте свои знания о поиске как навык
Чтобы помочь агенту хорошо искать, вы можете упаковать свои знания о поиске как навык: набор инструкций для конкретной задачи (например, какой индекс использовать, как формулировать запросы и как оформлять цитаты).
Агент видит только название каждого навыка и краткое описание, пока задача не потребует его; затем он загружает полные инструкции, поэтому узкоспециализированные знания доступны тогда, когда они нужны, не занимая контекст в остальное время (метод, называемый прогрессивным раскрытием). Вот видео с объяснением.
2. Слишком много контекста сразу
Однако, несмотря на оптимизацию процесса поиска, даже правильный поиск может вернуть слишком много данных. Нашему агенту нужно только одно число из экспорта рыночных данных (квартальная выручка компании B), но загрузка всех 40 000 строк для его поиска заполнит окно контекста. У нашего инструмента поиска та же проблема: если он возвращает каждую новостную статью прямо в модель, четыре результата на поиск по пяти компаниям быстро накапливаются.
Чтение больших файлов по одной странице за раз
Инструменты файловой системы созданы для того, чтобы возвращать как можно меньше данных. Функция read_file считывает файл по одной странице за раз (по умолчанию 100 строк), а агент может задать смещение (строку, с которой нужно начать) и лимит (количество считываемых строк), чтобы перейти к нужной части. Таким образом, чтобы найти выручку Компании B, агент выполняет поиск с помощью grep, а затем считывает всего несколько строк вокруг найденного совпадения.
Позвольте управляющей оболочке выгружать результаты чрезмерного размера
Иногда инструмент все равно возвращает больше данных, чем ожидалось. Когда результат работы инструмента оказывается слишком большим (более примерно 20 000 токенов), оболочка сохраняет его в файл в директории /large_tool_results/ и предоставляет агенту путь вместе с небольшим превью (первыми и последними несколькими строками). После этого агент может прочитать только те части, которые ему необходимы, используя смещение и лимит функции read_file.
Сделайте так, чтобы ваш поисковый инструмент возвращал пути к файлам
Вы можете применить ту же идею к собственному инструменту поиска, не дожидаясь срабатывания лимита размера: настройте его так, чтобы он записывал каждый результат в файл и возвращал только пути. Это первая часть паттерна под названием «получение, выгрузка, делегирование» (в руководстве по RAG от LangChain это описано подробно).
Вот упрощенный инструмент поиска. Он выполняет поиск, сохраняет каждый результат в качестве файла в бэкенде агента и возвращает только список путей к файлам:
Теперь главный агент видит четыре коротких пути вместо четырех полных статей.
3. Неактуальный или устаревший контекст
Небольшие результаты не помогут, если они оказались неверными. Любой из этих четырех файлов может относиться к другой компании с похожим названием или оказаться материалом двухлетней давности. Посторонняя или устаревшая информация выглядит для модели столь же убедительно, как и правильный ответ, поэтому цель состоит в том, чтобы полностью оградить от нее контекст главного агента.
Позвольте субагентам фильтровать результаты
Тем не менее, главному агенту все равно приходится читать эти файлы, чтобы выяснить, какие из них имеют значение (и каждая открытая им посторонняя статья попадает в его контекст). Здесь на сцену и выходит часть «делегирование» из паттерна «получение, выгрузка, делегирование»: субагент читает каждый полученный файл и возвращает только ключевые факты.
- Определите субагента: описание указывает главному агенту, когда его использовать (один файл за вызов), а системный промпт указывает субагенту, что делать с этим файлом.
- Предоставьте главному агенту поисковый инструмент и субагента. Передайте тот же бэкенд, который вы использовали в search_news, чтобы субагент мог читать файлы, сохраненные инструментом.
Теперь процесс выглядит следующим образом:
- Поиск: главный агент вызывает search_news и получает в ответ четыре пути.
- Делегирование: он отправляет каждый путь субагенту-аналитику фрагментов, и они могут работать параллельно.
- Синтез: каждый аналитик возвращает краткую сводку со своим источником. Главный агент объединяет их и выполняет поиск повторно, если чего-то не хватает.
Необработанные результаты отправляются в файлы, зашумленное чтение происходит в субагентах с их собственными контекстными окнами, а главный агент видит исключительно выводы. Все постороннее остается в контексте субагента, а контекстное окно главного агента остается чистым!
Используйте свежие источники
Фильтрация действительно отсекает лишние результаты, но она не может исправить результаты, которые устарели. Наш агент для конкурентного анализа запускается каждый понедельник, поэтому индекс за прошлый месяц не поймает новости этой недели.
Решение: поисковый API или сервер MCP могут предоставлять агенту актуальную информацию (а не то, что было проиндексировано несколько месяцев назад). Если ваши данные содержат даты, фильтрация по дате в инструменте поиска также поможет отсечь старые результаты.
Будьте осторожны с извлеченным текстом
С другой стороны, актуальные релевантные результаты могут создавать проблемы! Поскольку извлеченный текст — это данные, а не инструкции, все, что вы извлекаете, может содержать внедрение промпта (prompt injection) (и ни одна стратегия промптов или разделителей не предотвращает это полностью). Обязательно проверяйте выходные данные: убедитесь, что ответы ссылаются на те источники, которые вы ожидаете, и что утверждения соответствуют им.
Стратегии извлечения информации, о которых стоит помнить
Вот на что следует обратить внимание (независимо от того, на базе какой оболочки вы строите систему):
- Используйте наиболее эффективный рабочий инструмент. Если вы знаете ключевые слова, grep работает лучше поиска по эмбеддингам. Сохраняйте семантический поиск для тех случаев, когда он действительно необходим.
- Используйте постраничное чтение вместо загрузки. Читайте большие файлы по частям, а не целиком.
- Возвращайте указатели вместо полезной нагрузки. Записывайте извлеченный контент в файлы и передавайте агенту пути к ним.
- Делегируйте чтение. Позвольте субагентам читать и делать краткие выжимки, чтобы главный агент видел только заключения.
- Проверяйте обоснованность (grounding). Сверяйте ответы с извлеченными данными и относитесь к извлеченному тексту как к ненадежному.
Попробуйте
Хотите узнать больше от живого преподавателя? Я буду рассказывать об этом 9 ноября: Зарегистрируйтесь ЗЕСТЬ!
Извлечение — это лишь половина дела: то, как информация находит путь к агенту. Как нам управлять контекстным окном агента по мере того, как он со временем накапливает информацию?
Чтобы узнать больше, ознакомьтесь с:
- Блог об инженерии контекста с использованием Deep Agents
- Курс по Deep Agents на LangChain Academy (бесплатно, онлайн и в индивидуальном темпе).






.webp)





