Skip to content

Commit

Permalink
✨ (deep_research): introduce deep research feature for comprehensive …
Browse files Browse the repository at this point in the history
…report generation

Add a new deep research feature to perform in-depth, structured research on complex topics. This feature includes planning report structures, researching each section, writing detailed content, and compiling a comprehensive final report. It supports both synchronous and asynchronous web searches using the Tavily API. The feature is integrated into the toolset, replacing the previous research tool, and includes detailed prompts and configuration for generating and grading report sections.
  • Loading branch information
kyaukyuai committed Feb 26, 2025
1 parent 2631c45 commit 951587d
Show file tree
Hide file tree
Showing 17 changed files with 2,059 additions and 41 deletions.
6 changes: 5 additions & 1 deletion langgraph.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
{
"dependencies": ["."],
"graphs": {
"agent": "./slack_ai_agent/agents/simple_long_term_memory_agent.py:graph"
"agent": "./slack_ai_agent/agents/simple_long_term_memory_agent.py:graph",
"deep_research_agent": "./slack_ai_agent/agents/deep_research_agent.py:graph",
"sync_deep_research_agent": "./slack_ai_agent/agents/sync_deep_research_agent.py:graph",
"research_agent": "./slack_ai_agent/agents/research_agent.py:graph",
"summarize_agent": "./slack_ai_agent/agents/summarize_agent.py:graph"
},
"env": ".env",
"auth": {
Expand Down
72 changes: 72 additions & 0 deletions slack_ai_agent/agents/configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import os
from dataclasses import dataclass
from dataclasses import fields
from enum import Enum
from typing import Any
from typing import Optional

from langchain_core.runnables import RunnableConfig


DEFAULT_REPORT_STRUCTURE = """Use this structure to create a report on the user-provided topic:
1. Introduction (no research needed)
- Brief overview of the topic area
2. Main Body Sections:
- Each section should focus on a sub-topic of the user-provided topic
3. Conclusion
- Aim for 1 structural element (either a list of table) that distills the main body sections
- Provide a concise summary of the report"""


class SearchAPI(Enum):
PERPLEXITY = "perplexity"
TAVILY = "tavily"


class PlannerProvider(Enum):
OPENAI = "openai"
GROQ = "groq"


class WriterProvider(Enum):
ANTHROPIC = "anthropic"
OPENAI = "openai"
GROQ = "groq"


@dataclass(kw_only=True)
class Configuration:
"""The configurable fields for the chatbot."""

report_structure: str = (
DEFAULT_REPORT_STRUCTURE # Defaults to the default report structure
)
number_of_queries: int = 2 # Number of search queries to generate per iteration
max_search_depth: int = 2 # Maximum number of reflection + search iterations
planner_provider: PlannerProvider = (
PlannerProvider.OPENAI
) # Defaults to OpenAI as provider
planner_model: str = "o3-mini" # Defaults to OpenAI o3-mini as planner model
writer_provider: WriterProvider = (
WriterProvider.ANTHROPIC
) # Defaults to Anthropic as provider
writer_model: str = "claude-3-5-sonnet-latest" # Defaults to Anthropic as provider
search_api: SearchAPI = SearchAPI.TAVILY # Default to TAVILY

@classmethod
def from_runnable_config(
cls, config: Optional[RunnableConfig] = None
) -> "Configuration":
"""Create a Configuration instance from a RunnableConfig."""
configurable = (
config["configurable"] if config and "configurable" in config else {}
)
values: dict[str, Any] = {
f.name: os.environ.get(f.name.upper(), configurable.get(f.name))
for f in fields(cls)
if f.init
}
return cls(**{k: v for k, v in values.items() if v})
Loading

0 comments on commit 951587d

Please sign in to comment.