Introduction #
Deep Research is a research-oriented Agent AI based on the o3 model, launched by OpenAI on February 2nd.
According to OpenAI, users only need to provide a prompt, and the Agent will produce a research report like a researcher or analyst would.
If the user’s research details are not clear enough, the model will prompt the user to clarify the details; if the user’s question is sufficiently clear, the Agent will begin online analysis.
However, Google Gemini actually mentioned the concept of Deep Research back in December. JinaAI also started trying to implement it in January. Subsequently, perplexity also launched a Deep Research Agent. In addition, LangChain, Dify, HuggingFace, and others have also open-sourced their own implementation solutions.
Today, we’ll look at specific implementation methods from these open-source examples.
Deep Research #
Let’s first introduce its process in general terms, from an engineering perspective on how it’s driven by large language models.
First, it’s clear that at least two Agents are needed here:
- Research Agent: Used to decide whether to conduct research on the next topic, and if so, to provide a specific research direction.
- Report Agent: Used to summarize all the content organized by the researcher and produce the final research report.
Based on these two Agents, the general process applied to Deep Research is as follows:
- The user poses a question
- The Research Agent provides a specific topic
- Relevant information is obtained through search engines, vector database retrieval, and other means
- The Research Agent is consulted again to see if there’s another research topic; if so, return to step 2, otherwise continue
- All research data is given to the Report Agent, allowing the Report Agent to produce the final report
Overall, it’s similar to a Reason + Act model, with the addition of model reflection and requirement clarification based on this foundation.
However, in some strictly named implementations, the above process can only be defined as Deep Search. True Deep Research still needs to add a Planning Agent at the very beginning to generate a COT (Chain of Thought) for solving this problem. Each step given by the thought chain needs to go through the same steps as above, somewhat similar to the outline and each chapter of the report. In addition, it needs to have the ability to reflect, in order to keep the entire report close to the topic during the generation of each chapter. Finally, it collects the complete report for each step and gives the final, very long report.
Dify Implementation #
Overview #
Dify implements this using Dify’s Workflow functionality. For details, see the article DeepResearch: Building a Research Automation App with Dify.
The search part uses Tavily search. The model is called in two main places:
- Researcher implemented with gpt-4o: determines research direction and whether to end
- Reporter implemented with deepseek-r1: summarizes search results and produces the final report
gpt-4o Research #
The Researcher Agent is an LLM node in the Workflow iterator, using gpt-4o. Each request asks gpt-4o to provide nextSearchTopic
and shouldContinue
. The specific prompt is as follows:
You are a research agent investigating the following topic.
What have you found? What questions remain unanswered? What specific aspects should be investigated next?
## Output
- Do not output topics that are exactly the same as already searched topics.
- If further information search is needed, set nextSearchTopic.
- If sufficient information has been obtained, set shouldContinue to false.
- Please output in json format
```json
nextSearchTopic: str | None
shouldContinue: bool
deepseek-r1 Writing Report #
The report production stage uses an inference model, and the implementation here directly uses deepseek-r1 for this part of the work.
Let’s take a specific look at the prompt for the persona. The user
part of the prompt only passes the user’s query
and the findings
retrieved from the search interface. The key is the system
persona part.
LangChain Implementation #
Process Overview #
LangChain here is mainly source code, implementing a complete set of logic for planning, research, and report production.
Execution Steps #
LangChain broadly categorizes the models into two types:
planner_model
: Planning model, generally an inference model, used for ① planning the chapters and topics to be generated at the very beginning ② deciding whether to execute recursion or proceed to the next chapter during recursive callswriter_model
: Writing model, generally a non-inference model, used for ① generating a Query list before calling the query, facilitating the search ② writing the report for each chapter of the topic
Next, let’s look at the overall scheduling logic here, which has many detailed supplements to the process we mentioned earlier, very worth a look.
According to the code below, the overall execution process is roughly as follows:
- User inputs Query
generate_report_plan
: Generates a plan for report production, mainly producing the required topics and organizing the report’s directory structure. It first uses thewriter_model
to generate a Query list based on the topic, then uses the Query list to search the search engine, and finally lets theplanner_model
generate the entire report’s directory structure, chapters, topics, etc. based on the search results.human_feedback
: Reminds the user to review the generated plan. If approval fails, return to step 2 to replan; if approved, continue execution.build_section_with_web_research
: Builds the writing task for each chapter based on the chapter list steps in the plan. The specific execution of each chapter is defined insection_builder
.generate_queries
: Generates a query list based on the topic and current chapter, calling thewriter_model
heresearch_web
: Queries the search engine based on the Query list produced in the previous step. LangChain supports tavily, perplexity, exa, arxiv, pubmed, and linkup, etc.write_section
: Calls thewriter_model
to summarize this part of the content; then lets theplanner_model
perform reflection, i.e., determine whether the current chapter’s report output passes. If it fails, return to step a to rewrite; if it passes, produce the next chapter.
gather_completed_sections
: Collects the report outputs of all completed chapters and transforms them into the final contextinitiate_final_section_writing
: For chapters that don’t require research from step 2, this step uniformly calls thewrite_final_sections
method to generate the specific content for this chapterwrite_final_sections
: Based on all previously researched and generated chapters, calls thewriter_model
to generate content for chapters that don’t require research, theoretically including the conclusion part of the entire report.compile_final_report
: Concatenates the conclusion part from steps c and 6 into the final report output.
# Report section sub-graph --
# Add nodes
section_builder = StateGraph(SectionState, output=SectionOutputState)
section_builder.add_node("generate_queries", generate_queries)
section_builder.add_node("search_web", search_web)
section_builder.add_node("write_section", write_section)
# Add edges
section_builder.add_edge(START, "generate_queries")
section_builder.add_edge("generate_queries", "search_web")
section_builder.add_edge("search_web", "write_section")
# Outer graph --
# Add nodes
builder = StateGraph(ReportState, input=ReportStateInput, output=ReportStateOutput, config_schema=Configuration)
builder.add_node("generate_report_plan", generate_report_plan)
builder.add_node("human_feedback", human_feedback)
builder.add_node("build_section_with_web_research", section_builder.compile())
builder.add_node("gather_completed_sections", gather_completed_sections)
builder.add_node("write_final_sections", write_final_sections)
builder.add_node("compile_final_report", compile_final_report)
# Add edges
builder.add_edge(START, "generate_report_plan")
builder.add_edge("generate_report_plan", "human_feedback")
builder.add_edge("build_section_with_web_research", "gather_completed_sections")
builder.add_conditional_edges("gather_completed_sections", initiate_final_section_writing, ["write_final_sections"])
builder.add_edge("write_final_sections", "compile_final_report")
builder.add_edge("compile_final_report", END)
graph = builder.compile()
Writing Agent #
Query Generation #
As mentioned in the previous steps, this part is used to generate a list of queries to help search engines retrieve information. It is specifically used in step 2 and step a when processing each chapter. However, the prompts are slightly different.
Let’s first look at the prompts used in step 2 to generate queries for retrieving report plan-related data. The system
role prompt and user
prompt are as follows:
### system
You are performing research for a report.
<Report topic>
{topic}
</Report topic>
<Report organization>
{report_organization}
</Report organization>
<Task>
Your goal is to generate {number_of_queries} web search queries that will help gather information for planning the report sections.
The queries should:
1. Be related to the Report topic
2. Help satisfy the requirements specified in the report organization
Make the queries specific enough to find high-quality, relevant sources while covering the breadth needed for the report structure.
</Task>
### user
Generate search queries that will help with planning the sections of the report.
Next, when processing a specific chapter, it’s necessary to query relevant information for the current chapter. This also requires generating a list of queries for calling the search engine. The system
role prompt and user
prompt are as follows:
### system
You are an expert technical writer crafting targeted web search queries that will gather comprehensive information for writing a technical report section.
<Report topic>
{topic}
</Report topic>
<Section topic>
{section_topic}
</Section topic>
<Task>
Your goal is to generate {number_of_queries} search queries that will help gather comprehensive information above the section topic.
The queries should:
1. Be related to the topic
2. Examine different aspects of the topic
Make the queries specific enough to find high-quality, relevant sources.
</Task>
### user
Generate search queries on the provided topic.
Generation of Research-Required Sections #
This part involves generating reports for each section that requires research. The input mainly includes the overall report topic, section name, sub-topics for the current chapter, and so on. Additionally, it sets some restrictions on the word count, style, and other aspects of the generated report.
### system
You are an expert technical writer crafting one section of a technical report.
<Report topic>
{topic}
</Report topic>
<Section name>
{section_name}
</Section name>
<Section topic>
{section_topic}
</Section topic>
<Existing section content (if populated)>
{section_content}
</Existing section content>
<Source material>
{context}
</Source material>
<Guidelines for writing>
1. If the existing section content is not populated, write a new section from scratch.
2. If the existing section content is populated, write a new section that synthesizes the existing section content with the Source material.
</Guidelines for writing>
<Length and style>
- Strict 150-200 word limit
- No marketing language
- Technical focus
- Write in simple, clear language
- Start with your most important insight in **bold**
- Use short paragraphs (2-3 sentences max)
- Use ## for section title (Markdown format)
- Only use ONE structural element IF it helps clarify your point:
* Either a focused table comparing 2-3 key items (using Markdown table syntax)
* Or a short list (3-5 items) using proper Markdown list syntax:
- Use `*` or `-` for unordered lists
- Use `1.` for ordered lists
- Ensure proper indentation and spacing
- End with ### Sources that references the below source material formatted as:
* List each source with title, date, and URL
* Format: `- Title : URL`
</Length and style>
<Quality checks>
- Exactly 150-200 words (excluding title and sources)
- Careful use of only ONE structural element (table or list) and only if it helps clarify your point
- One specific example / case study
- Starts with bold insight
- No preamble prior to creating the section content
- Sources cited at end
</Quality checks>
### user
Generate a report section based on the provided sources.
Generation of Sections Not Requiring Research #
This part mainly involves generating content for sections that don’t require research after all the research-required sections have been completed. Theoretically, this also includes the conclusion part of the entire report.
### system
You are an expert technical writer crafting a section that synthesizes information from the rest of the report.
<Report topic>
{topic}
</Report topic>
<Section name>
{section_name}
</Section name>
<Section topic>
{section_topic}
</Section topic>
<Available report content>
{context}
</Available report content>
<Task>
1. Section-Specific Approach:
For Introduction:
- Use # for report title (Markdown format)
- 50-100 word limit
- Write in simple and clear language
- Focus on the core motivation for the report in 1-2 paragraphs
- Use a clear narrative arc to introduce the report
- Include NO structural elements (no lists or tables)
- No sources section needed
For Conclusion/Summary:
- Use ## for section title (Markdown format)
- 100-150 word limit
- For comparative reports:
* Must include a focused comparison table using Markdown table syntax
* Table should distill insights from the report
* Keep table entries clear and concise
- For non-comparative reports:
* Only use ONE structural element IF it helps distill the points made in the report:
* Either a focused table comparing items present in the report (using Markdown table syntax)
* Or a short list using proper Markdown list syntax:
- Use `*` or `-` for unordered lists
- Use `1.` for ordered lists
- Ensure proper indentation and spacing
- End with specific next steps or implications
- No sources section needed
3. Writing Approach:
- Use concrete details over general statements
- Make every word count
- Focus on your single most important point
</Task>
<Quality Checks>
- For introduction: 50-100 word limit, # for report title, no structural elements, no sources section
- For conclusion: 100-150 word limit, ## for section title, only ONE structural element at most, no sources section
- Markdown format
- Do not include word count or any preamble in your response
</Quality Checks>
### user
Generate a report section based on the provided sources.
Planning Agent #
Generating Report Plan #
The planning here refers to the planner_model
mentioned in step two above.
From the execution steps we’ve learned, the planner_model
will generate the overall chapters, sub-topics, and directory structure of the entire report based on the retrieved relevant content.
Let’s look at the prompts. The specific inputs in the system
role prompt include:
topic
: The topic passed by the userreport_organization
: Report organization, optionalcontext
: Context information queried from the search enginefeedback
: This is the specific feedback content when the user is dissatisfied with the generated plan in step 3. It’s not present during the initial generation
I want a plan for a report that is concise and focused.
<Report topic>
The topic of the report is:
{topic}
</Report topic>
<Report organization>
The report should follow this organization:
{report_organization}
</Report organization>
<Context>
Here is context to use to plan the sections of the report:
{context}
</Context>
<Task>
Generate a list of sections for the report. Your plan should be tight and focused with NO overlapping sections or unnecessary filler.
For example, a good report structure might look like:
1/ intro
2/ overview of topic A
3/ overview of topic B
4/ comparison between A and B
5/ conclusion
Each section should have the fields:
- Name - Name for this section of the report.
- Description - Brief overview of the main topics covered in this section.
- Research - Whether to perform web research for this section of the report.
- Content - The content of the section, which you will leave blank for now.
Integration guidelines:
- Include examples and implementation details within main topic sections, not as separate sections
- Ensure each section has a distinct purpose with no content overlap
- Combine related concepts rather than separating them
Before submitting, review your structure to ensure it has no redundant sections and follows a logical flow.
</Task>
<Feedback>
Here is feedback on the report structure from review (if any):
{feedback}
</Feedback>
The output is specified in the user
prompt, which includes the name, description, plan, whether research is needed, and related context for each chapter.
Generate the sections of the report. Your response must include a 'sections' field containing a list of sections.
Each section must have: name, description, plan, research, and content fields.
Reflection on Report Content #
This is the core of each section_builder. After the Agent has generated the current section chapter, it determines whether the chapter needs to be rewritten, which is the reflection step in the flowchart. The prompt here includes the content of the currently generated chapter.
The large language model returns whether the content passes or not. If it doesn’t pass, it needs to return a list of Queries for continuation or rewriting, providing a general direction for regenerating the section content. The specific prompt is as follows:
### system
Review a report section relative to the specified topic:
<Report topic>
{topic}
</Report topic>
<section topic>
{section_topic}
</section topic>
<section content>
{section}
</section content>
<task>
Evaluate whether the section content adequately addresses the section topic.
If the section content does not adequately address the section topic, generate {number_of_follow_up_queries} follow-up search queries to gather missing information.
</task>
<format>
grade: Literal["pass","fail"] = Field(
description="Evaluation result indicating whether the response meets requirements ('pass') or needs revision ('fail')."
)
follow_up_queries: List[SearchQuery] = Field(
description="List of follow-up search queries.",
)
</format>
### user
Grade the report and consider follow-up questions for missing information.
If the grade is 'pass', return empty strings for all follow-up queries.
If the grade is 'fail', provide specific search queries to gather missing information.
HuggingFace smolagents Implementation #
Overview #
HuggingFace provides a basic DeepResearch implementation in the smolagents
library example.
This implementation is primarily based on the classic ReAct prompting framework, which uses Reason + Act - setting specific tool sets for the Agent and allowing it to trigger multi-tool execution based on the problem. The example here encapsulates two Agents:
text_webbrowser_agent
: A ToolCallingAgent(MultiStepAgent) used to trigger browser tool function calls, encapsulating browser-related tools such as Google queries, browser visits to specific addresses, page down, page up, browser queries, archive queries, as well as tools for parsing text information in filesmanager_agent
: A CodeAgent(MultiStepAgent) instance that encapsulates the main execution framework of CodeAct. This part was previously implemented insmolagents
, and the main parameter passed here is thetext_webbrowser_agent
. It’s equivalent to this agent using another agent as a tool to drive its execution
🤗 smolagents: a barebones library for agents. Agents write python code to call tools and orchestrate other agents.
MultiStepAgent #
HuggingFace’s implementation is primarily based on MultiStepAgent. Both CodeAgent(MultiStepAgent) and ToolCallingAgent(MultiStepAgent) are subclasses of MultiStepAgent, and their overall processes are quite similar.
So let’s first look at the execution flow of MultiStepAgent:
The call path is: MultiStepAgent**.**run
→ MultiStepAgent**.**_run
→ MultiStepAgent**.**_execute_step
→ MultiStepAgent**.**planning_step
→ CodeAgent/ToolCallingAgent.step
→ MultiStepAgent**.**_run
→ … until a final_answer
is found or the number of recursions reaches max_steps
# https://github.com/huggingface/smolagents/blob/main/src/smolagents/agents.py
class MultiStepAgent:
def run(
self,
task: str,
stream: bool = False,
reset: bool = True,
images: Optional[List[str]] = None,
additional_args: Optional[Dict] = None,
max_steps: Optional[int] = None,
):
"""
Run the agent for the given task.
Args:
task (`str`): Task to perform.
stream (`bool`): Whether to run in a streaming way.
reset (`bool`): Whether to reset the conversation or keep it going from previous run.
images (`list[str]`, *optional*): Paths to image(s).
additional_args (`dict`, *optional*): Any other variables that you want to pass to the agent run, for instance images or dataframes. Give them clear names!
max_steps (`int`, *optional*): Maximum number of steps the agent can take to solve the task. if not provided, will use the agent's default value.
"""
...
if stream:
# The steps are returned as they are executed through a generator to iterate on.
return self._run(task=self.task, max_steps=max_steps, images=images)
# Outputs are returned only at the end. We only look at the last step.
return deque(self._run(task=self.task, max_steps=max_steps, images=images), maxlen=1)[0]
def _run(
self, task: str, max_steps: int, images: List[str] | None = None
) -> Generator[ActionStep | AgentType, None, None]:
final_answer = None
self.step_number = 1
while final_answer is None and self.step_number <= max_steps:
step_start_time = time.time()
memory_step = self._create_memory_step(step_start_time, images)
try:
final_answer = self._execute_step(task, memory_step)
except AgentError as e:
memory_step.error = e
finally:
self._finalize_step(memory_step, step_start_time)
yield memory_step
self.step_number += 1
if final_answer is None and self.step_number == max_steps + 1:
final_answer = self._handle_max_steps_reached(task, images, step_start_time)
yield memory_step
yield handle_agent_output_types(final_answer)
def _execute_step(self, task: str, memory_step: ActionStep) -> Union[None, Any]:
if self.planning_interval is not None and self.step_number % self.planning_interval == 1:
self.planning_step(task, is_first_step=(self.step_number == 1), step=self.step_number)
self.logger.log_rule(f"Step {self.step_number}", level=LogLevel.INFO)
final_answer = self.step(memory_step)
if final_answer is not None and self.final_answer_checks:
self._validate_final_answer(final_answer)
return final_answer
CodeAgent + ToolCallingAgent #
Previously, we gained a general understanding of MultiStepAgent. Now, let’s examine how the DeepResearch implementation creates a CodeAgent
instance.
Here, text_webbrowser_agent
and manager_agent
are defined; text_webbrowser_agent
is set with a max_steps of 20, while manager_agent
has a max_steps of 12.
Essentially, it encapsulates a CodeAgent based on gpt-o1, and within the CodeAgent, there’s another encapsulated ToolCallingAgent used to drive the execution of another agent.
The ToolCallingAgent primarily encapsulates many operations related to browsers, search, and file parsing.
Both of these Agents operate based on a Reason + Act inference execution method.
# https://github.com/huggingface/smolagents/blob/main/examples/open_deep_research/run_gaia.py
model_params = {
"model_id": model_id,
"custom_role_conversions": custom_role_conversions,
"max_completion_tokens": 8192,
}
if model_id == "o1":
model_params["reasoning_effort"] = "high"
model = LiteLLMModel(**model_params)
# web tools
WEB_TOOLS = [
SearchInformationTool(browser),
VisitTool(browser),
PageUpTool(browser),
PageDownTool(browser),
FinderTool(browser),
FindNextTool(browser),
ArchiveSearchTool(browser),
# inspect file as text tool
TextInspectorTool(model, text_limit),
]
# tool calling agent for web tools
text_webbrowser_agent = ToolCallingAgent(
model=model,
tools=WEB_TOOLS,
max_steps=20,
verbosity_level=2,
planning_interval=4,
name="search_agent",
description="""A team member that will search the internet to answer your question.
Ask him for all your questions that require browsing the web.
Provide him as much context as possible, in particular if you need to search on a specific timeframe!
And don't hesitate to provide him with a complex search task, like finding a difference between two webpages.
Your request must be a real sentence, not a google search! Like "Find me this information (...)" rather than a few keywords.
""",
provide_run_summary=True,
)
text_webbrowser_agent.prompt_templates["managed_agent"]["task"] += """You can navigate to .txt online files.
If a non-html page is in another format, especially .pdf or a Youtube video, use tool 'inspect_file_as_text' to inspect it.
Additionally, if after some searching you find out that you need more information to answer the question, you can use `final_answer` with your request for clarification as argument to request for more information."""
# ReAct code agent instance
manager_agent = CodeAgent(
model=model,
tools=[visualizer, ti_tool],
max_steps=12,
verbosity_level=2,
additional_authorized_imports=AUTHORIZED_IMPORTS,
planning_interval=4,
managed_agents=[text_webbrowser_agent],
)
Finally, let’s look at the prompts, which are relatively ordinary. Specifically, they are as follows:
You have one question to answer. It is paramount that you provide a correct answer.
Give it all you can: I know for a fact that you have access to all the relevant tools to solve it and find the correct answer (the answer does exist). Failure or 'I cannot answer' or 'None found' will not be tolerated, success will be rewarded.
Run verification steps if that's needed, you must make sure you find the correct answer!
Here is the task:
{question}
To solve the task above, you will have to use these attached files:
{files}
Zilliz Cloud Implementation #
Overview #
Zilliz implements a DeepSearch, where the search part has been changed from a search engine to knowledge base retrieval.
The flow chart is roughly as follows. The overall process is quite clear, so I don’t feel the need to reiterate it here. There are three points worth noting:
- The search here has been changed to approximate querying based on vector databases
- The content of Reflection is not generated by the model but retrieved from the vector database
- During the process of querying the vector database with the Query list, it will determine whether the knowledge base content matches the original Query and Query list. This is referred to as Rerank in the code, but it’s not actually reordering here
Open Source Deep Research Alternative to Reason and Search on Private Data. Written in Python.
Generating Query List #
This generation of queries is only for producing the initial query list. Subsequent unapproved query lists are generated above.
The input here is quite simple, consisting only of the original query, namely original_query
.
To answer this question more comprehensively, please break down the original question into up to four sub-questions. Return as list of str.
If this is a very simple question and no decomposition is necessary, then keep the only one original question in the python code list.
Original Question: {original_query}
<EXAMPLE>
Example input:
"Explain deep learning"
Example output:
[
"What is deep learning?",
"What is the difference between deep learning and machine learning?",
"What is the history of deep learning?"
]
</EXAMPLE>
Provide your response in a python code list of str format:
Rerank Judgment #
This mainly judges the relevance between the retrieval results and the Query. The input query
is the original Query + Query list, and retrieved_chunk
is the specific vector query result.
Based on the query questions and the retrieved chunk, to determine whether the chunk is helpful in answering any of the query question, you can only return "YES" or "NO", without any other information.
Query Questions: {query}
Retrieved Chunk: {retrieved_chunk}
Is the chunk helpful in answering the any of the questions?
Reflection Judgment #
Unlike previously seen implementations, this step mainly determines whether the content retrieved from the knowledge base is appropriate.
If it is appropriate, a final report is generated based on this content; if not, a new Query list is generated and the vector database is queried again.
The inputs here are the original Query question
, the Query list mini_questions
, and the mini_chunk_str
retrieved from the vector database.
For the output, if it passes, an empty list is returned; if it doesn’t pass, a new round of Query list is output for the next query.
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: {question}
Previous Sub Queries: {mini_questions}
Related Chunks:
{mini_chunk_str}
Respond exclusively in valid List of str format without any other text.
Generating Conclusions #
Generating the final conclusion. The inputs include the original Query question
, the Query list mini_questions
, and the vector database query results mini_chunk_str
You are a 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: {question}
Previous Sub Queries: {mini_questions}
Related Chunks:
{mini_chunk_str}
Summary #
Looking at the implementations above, they are actually quite similar, with the core mainly being a template of generating plans or Query lists + reflection.
- Dify’s implementation is primarily based on existing interface functionalities, realizing a small DeepSearch. It appears simple, user-friendly, and includes reflection, but lacks plan generation, and the final report is summarized by the last model.
- LangChain’s implementation is, in my opinion, the most comprehensive. It generates plans, produces content chapter by chapter, and reflects after each chapter is completed. This approach is indeed a complete DeepResearch implementation that can generate a very long report, though it’s time-consuming and expensive.
- HuggingFace’s smolagents example is based on MultiStepAgent implementation. It has planned steps and generates content according to these steps, but lacks reflection.
- Zilliz Cloud’s implementation can be considered a DeepSearch. The process is simplified compared to DeepResearch, includes reflection, and replaces retrieval with vector retrieval, but lacks chapter-by-chapter generation functionality.
Overall, I feel that LangChain’s implementation is more comprehensive, while Zilliz Cloud and HuggingFace’s implementations are also quite interesting.
Lastly, there are some implementations like JinaAI and deep-research that I haven’t looked into in detail. Those interested can explore them further.
References #
Open-source DeepResearch – Freeing our search agents
DeepResearch: Building a Research Automation App with Dify - Dify Blog
A Practical Guide to Implementing DeepSearch/DeepResearch
Try Deep Research and our new experimental model in Gemini, your AI assistant
smolagents/examples/open_deep_research at main · huggingface/smolagents
🤗 smolagents: a barebones library for agents. Agents write python code to call tools and orchestrate other agents.
Open Source Deep Research Alternative to Reason and Search on Private Data. Written in Python.
An AI-powered research assistant that performs iterative, deep research on any topic by combining search engines, web scraping, and large language models. The goal of this repo is to provide the simplest implementation of a deep research agent - e.g. an agent that can refine its research direction overtime and deep dive into a topic.
Keep searching, reading webpages, reasoning until it finds the answer (or exceeding the token budget)