Milvus
Zilliz
  • Home
  • Blog
  • Представляем DeepSearcher: Локальное глубокое исследование с открытым исходным кодом

Представляем DeepSearcher: Локальное глубокое исследование с открытым исходным кодом

  • Announcements
February 21, 2025
Stefan Webb

DeepSearcher DeepSearcher

В предыдущей заметке "Я построил глубокий исследователь с открытым исходным кодом - и вы тоже можете!" мы объяснили некоторые принципы, лежащие в основе исследовательских агентов, и создали простой прототип, который генерирует подробные отчеты по заданной теме или вопросу. Статья и соответствующий блокнот продемонстрировали фундаментальные концепции использования инструментов, декомпозиции запросов, рассуждений и размышлений. Пример из нашей предыдущей заметки, в отличие от Deep Research от OpenAI, работал локально, используя только модели и инструменты с открытым исходным кодом, такие как Milvus и LangChain. (Я рекомендую вам прочитать статью выше, прежде чем продолжить).

В последующие недели произошел взрыв интереса к пониманию и воспроизведению глубоких исследований OpenAI. Например, Perplexity Deep Research и Hugging Face's Open DeepResearch. Эти инструменты различаются по архитектуре и методологии, хотя имеют общую цель: итеративно исследовать тему или вопрос, просматривая веб-страницы или внутренние документы, и выдать подробный, обоснованный и хорошо структурированный отчет. Важно, что базовый агент автоматизирует рассуждения о том, какие действия следует предпринять на каждом промежуточном этапе.

В этом посте мы развиваем нашу предыдущую статью и представляем проект DeepSearcher от Zilliz с открытым исходным кодом. Наш агент демонстрирует дополнительные концепции: маршрутизацию запросов, поток условного выполнения и веб-ползание как инструмент. Он представлен в виде библиотеки Python и инструмента командной строки, а не блокнота Jupyter, и является более полнофункциональным, чем наш предыдущий пост. Например, он может вводить несколько исходных документов и задавать модель встраивания и используемую векторную базу данных через конфигурационный файл. Несмотря на то, что DeepSearcher все еще относительно прост, он является отличным примером агентного RAG и еще одним шагом на пути к созданию современных приложений ИИ.

Кроме того, мы изучаем потребность в более быстрых и эффективных сервисах вывода. Модели рассуждений используют "масштабирование выводов", то есть дополнительные вычисления, для улучшения своих результатов, и это в сочетании с тем фактом, что один отчет может потребовать сотни или тысячи вызовов LLM, приводит к тому, что пропускная способность выводов становится основным узким местом. Мы используем модель рассуждений DeepSeek-R1 на специально разработанном SambaNova оборудовании, которое в два раза быстрее по скорости вывода токенов в секунду, чем ближайший конкурент (см. рисунок ниже).

SambaNova Cloud также предоставляет услуги по созданию выводов для других моделей с открытым исходным кодом, включая Llama 3.x, Qwen2.5 и QwQ. Сервис обработки выводов работает на собственном чипе SambaNova под названием реконфигурируемый блок обработки данных (RDU), который специально разработан для эффективной обработки выводов в моделях генеративного ИИ, снижая стоимость и увеличивая скорость обработки выводов. Узнайте больше на их сайте.

Output Speed- DeepSeek R1 Скорость вывода - DeepSeek R1

Архитектура DeepSearcher

Архитектура DeepSearcher повторяет наш предыдущий пост, разбивая проблему на четыре этапа - определение/уточнение вопроса, исследование, анализ, синтез - хотя на этот раз с некоторым дублированием. Мы пройдемся по каждому этапу, выделяя улучшения DeepSearcher.

DeepSearcher Architecture Архитектура DeepSearcher

Определение и уточнение вопроса

Break down the original query into new sub queries: [
‘How has the cultural impact and societal relevance of The Simpsons evolved from its debut to the present?’,
‘What changes in character development, humor, and storytelling styles have occurred across different seasons of The Simpsons?’,
‘How has the animation style and production technology of The Simpsons changed over time?’,
‘How have audience demographics, reception, and ratings of The Simpsons shifted throughout its run?’]

При разработке DeepSearcher границы между исследованием и уточнением вопроса размыты. Первоначальный запрос пользователя декомпозируется на подзапросы, как и в предыдущем посте. См. выше исходные подзапросы, созданные на основе запроса "Как менялся сериал "Симпсоны" с течением времени?". Однако на следующем этапе исследования вопрос будет уточняться по мере необходимости.

Исследование и анализ

После разбивки запроса на подзапросы начинается исследовательская часть работы агента. В ней, грубо говоря, четыре этапа: маршрутизация, поиск, размышление и условное повторение.

Маршрутизация

Наша база данных содержит множество таблиц или коллекций из разных источников. Было бы эффективнее, если бы мы могли ограничить семантический поиск только теми источниками, которые имеют отношение к рассматриваемому запросу. Маршрутизатор запроса подсказывает LLM, из каких коллекций следует извлекать информацию.

Вот метод формирования запроса-маршрутизатора:

def get_vector_db_search_prompt(
    question: str,
    collection_names: List[str],
    collection_descriptions: List[str],
    context: List[str] = None,
):
    sections = []
    # common prompt
    common_prompt = f"""You are an advanced AI problem analyst. Use your reasoning ability and historical conversation information, based on all the existing data sets, to get absolutely accurate answers to the following questions, and generate a suitable question for each data set according to the data set description that may be related to the question.

Question: {question} “"” sections.append(common_prompt)

<span class="hljs-comment"># data set prompt</span>
data_set = []
<span class="hljs-keyword">for</span> i, collection_name <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(collection_names):
    data_set.append(<span class="hljs-string">f&quot;<span class="hljs-subst">{collection_name}</span>: <span class="hljs-subst">{collection_descriptions[i]}</span>&quot;</span>)
data_set_prompt = <span class="hljs-string">f&quot;&quot;&quot;The following is all the data set information. The format of data set information is data set name: data set description.

Data Sets And Descriptions: “"” sections.append(data_set_prompt + “\n”.join(data_set))

<span class="hljs-comment"># context prompt</span>
<span class="hljs-keyword">if</span> context:
    context_prompt = <span class="hljs-string">f&quot;&quot;&quot;The following is a condensed version of the historical conversation. This information needs to be combined in this analysis to generate questions that are closer to the answer. You must not generate the same or similar questions for the same data set, nor can you regenerate questions for data sets that have been determined to be unrelated.

Historical Conversation: “"” sections.append(context_prompt + “\n”.join(context))

<span class="hljs-comment"># response prompt</span>
response_prompt = <span class="hljs-string">f&quot;&quot;&quot;Based on the above, you can only select a few datasets from the following dataset list to generate appropriate related questions for the selected datasets in order to solve the above problems. The output format is json, where the key is the name of the dataset and the value is the corresponding generated question.

Data Sets: “"” sections.append(response_prompt + “\n”.join(collection_names))

footer = <span class="hljs-string">&quot;&quot;&quot;Respond exclusively in valid JSON format matching exact JSON schema.

Critical Requirements:

  • Include ONLY ONE action type
  • Never add unsupported keys
  • Exclude all non-JSON text, markdown, or explanations
  • Maintain strict JSON syntax""" sections.append(footer) return “\n\n”.join(sections)

Мы заставляем LLM возвращать структурированный вывод в виде JSON, чтобы легко преобразовать его в решение о том, что делать дальше.

После выбора различных коллекций баз данных с помощью предыдущего шага, шаг поиска выполняет поиск по сходству с помощью Milvus. Как и в предыдущем посте, исходные данные были определены заранее, разбиты на куски, встроены и сохранены в векторной базе данных. Для DeepSearcher источники данных, как локальные, так и онлайн, должны быть указаны вручную. Мы оставляем онлайн-поиск для будущих работ.

Отражение

В отличие от предыдущего поста, DeepSearcher демонстрирует настоящую форму агентской рефлексии, вводя предыдущие результаты в качестве контекста в подсказку, которая "размышляет" о том, содержат ли заданные вопросы и соответствующие извлеченные фрагменты какие-либо информационные пробелы. Это можно рассматривать как шаг анализа.

Вот метод создания подсказки:

def get_reflect_prompt(
   question: str,
   mini_questions: List[str],
   mini_chuncks: List[str],
):
    mini_chunk_str = ""
    for i, chunk in enumerate(mini_chuncks):
        mini_chunk_str += f"""<chunk_{i}>\n{chunk}\n</chunk_{i}>\n"""
    reflect_prompt = f"""Determine whether additional search queries are needed based on the original query, previous sub queries, and all retrieved document chunks. If further research is required, provide a Python list of up to 3 search queries. If no further research is required, return an empty list.

If the original query is to write a report, then you prefer to generate some further queries, instead return an empty list.

Original Query: <span class="hljs-subst">{question}</span>
Previous Sub Queries: <span class="hljs-subst">{mini_questions}</span>
Related Chunks: 
<span class="hljs-subst">{mini_chunk_str}</span>
&quot;&quot;&quot;</span>


footer = <span class="hljs-string">&quot;&quot;&quot;Respond exclusively in valid List of str format without any other text.&quot;&quot;&quot;</span>
<span class="hljs-keyword">return</span> reflect_prompt + footer

И снова мы заставляем LLM возвращать структурированный результат, на этот раз в виде интерпретируемых на Python данных.

Вот пример новых подзапросов, "обнаруженных" в результате размышлений после ответа на первоначальные подзапросы, приведенные выше:

New search queries for next iteration: [
  "How have changes in The Simpsons' voice cast and production team influenced the show's evolution over different seasons?",
  "What role has The Simpsons' satire and social commentary played in its adaptation to contemporary issues across decades?",
  'How has The Simpsons addressed and incorporated shifts in media consumption, such as streaming services, into its distribution and content strategies?']

Условное повторение

В отличие от нашего предыдущего поста, DeepSearcher иллюстрирует условный поток выполнения. После размышлений о том, являются ли вопросы и ответы на них полными, если есть дополнительные вопросы, которые необходимо задать, агент повторяет описанные выше шаги. Важно отметить, что поток выполнения (цикл while) является функцией вывода LLM, а не жестко закодирован. В данном случае есть только двоичный выбор: повторить исследование или сгенерировать отчет. В более сложных агентах их может быть несколько, например: перейти по гиперссылке, извлечь фрагменты, сохранить в памяти, обдумать и т. д. Таким образом, вопрос продолжает уточняться по усмотрению агента до тех пор, пока он не решит выйти из цикла и создать отчет. В нашем примере с Симпсонами DeepSearcher выполняет еще два раунда заполнения пробелов с помощью дополнительных подзапросов.

Синтез

Наконец, полностью разложенный вопрос и извлеченные фрагменты синтезируются в отчет с единственной подсказкой. Вот код для создания подсказки:

def get_final_answer_prompt(
   question: str, 
   mini_questions: List[str],
   mini_chuncks: List[str],
):
    mini_chunk_str = ""
    for i, chunk in enumerate(mini_chuncks):
        mini_chunk_str += f"""<chunk_{i}>\n{chunk}\n</chunk_{i}>\n"""
    summary_prompt = f"""You are an AI content analysis expert, good at summarizing content. Please summarize a specific and detailed answer or report based on the previous queries and the retrieved document chunks.
Original Query: <span class="hljs-subst">{question}</span>
Previous Sub Queries: <span class="hljs-subst">{mini_questions}</span>
Related Chunks: 
<span class="hljs-subst">{mini_chunk_str}</span>
&quot;&quot;&quot;</span>
<span class="hljs-keyword">return</span> summary_prompt

Преимущество этого подхода по сравнению с нашим прототипом, который анализировал каждый вопрос отдельно и просто объединял результаты, заключается в том, что отчет получается таким, что все разделы соответствуют друг другу, то есть не содержат повторяющейся или противоречивой информации. Более сложная система может сочетать в себе оба варианта, используя поток условного выполнения для структурирования отчета, подведения итогов, переписывания, отражения и разворота и т. д., что мы оставляем на будущее.

Результаты

Вот пример отчета, сгенерированного по запросу "Как менялись Симпсоны со временем?" с помощью DeepSeek-R1, передающего страницу Википедии о Симпсонах в качестве исходного материала:

Report: The Evolution of The Simpsons (1989Present)
1. Cultural Impact and Societal Relevance
The Simpsons debuted as a subversive critique of American middle-class life, gaining notoriety for its bold satire in the 1990s. Initially a countercultural phenomenon, it challenged norms with episodes tackling religion, politics, and consumerism. Over time, its cultural dominance waned as competitors like South Park and Family Guy pushed boundaries further. By the 2010s, the show transitioned from trendsetter to nostalgic institution, balancing legacy appeal with attempts to address modern issues like climate change and LGBTQ+ rights, albeit with less societal resonance.
…
Conclusion
The Simpsons evolved from a radical satire to a television institution, navigating shifts in technology, politics, and audience expectations. While its golden-age brilliance remains unmatched, its adaptability—through streaming, updated humor, and global outreach—secures its place as a cultural touchstone. The show’s longevity reflects both nostalgia and a pragmatic embrace of change, even as it grapples with the challenges of relevance in a fragmented media landscape.

Полный отчет можно найти здесь, а для сравнения - отчет, созданный DeepSearcher с GPT-4o mini.

Обсуждение

Мы представили DeepSearcher, агента для проведения исследований и написания отчетов. Наша система построена на идее, изложенной в предыдущей статье, с добавлением таких функций, как условный поток выполнения, маршрутизация запросов и улучшенный интерфейс. Мы перешли от локального вывода с небольшой 4-битной квантованной моделью рассуждений к онлайн-сервису вывода для массивной модели DeepSeek-R1, что качественно улучшило наш выходной отчет. DeepSearcher работает с большинством сервисов, таких как OpenAI, Gemini, DeepSeek и Grok 3 (скоро появится!).

Модели рассуждений, особенно используемые в исследовательских агентах, требуют большого количества выводов, и нам повезло, что мы смогли использовать самую быструю модель DeepSeek-R1 от SambaNova, работающую на их специализированном оборудовании. Для нашего демонстрационного запроса мы сделали шестьдесят пять обращений к сервису вывода DeepSeek-R1 от SambaNova, ввели около 25 тыс. лексем, вывели 22 тыс. лексем и потратили $0,30. Мы были впечатлены скоростью вывода, учитывая, что модель содержит 671 миллиард параметров и имеет размер 3/4 терабайта. Узнайте больше подробностей здесь!

Мы продолжим развивать эту работу в следующих постах, рассматривая дополнительные агентные концепции и пространство дизайна исследовательских агентов. А пока мы приглашаем всех попробовать DeepSearcher, отметить нас на GitHub и поделиться своими отзывами!

Ресурсы

    Try Managed Milvus for Free

    Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

    Get Started

    Like the article? Spread the word

    Продолжить чтение