🎯 開發動機與痛點解決
核心問題:傳統的 AI 助手在處理複雜研究任務時,往往只能提供表面資訊,缺乏深度分析和多源驗證能力。
主要解決的痛點
- 資訊孤島問題:LLM 模型被困在預訓練資料中,無法獲取即時、多元的外部資訊
- 研究效率低落:人工研究需要大量時間搜尋、整理、分析不同來源的資料
- 品質控制困難:缺乏統一的評估標準來衡量研究報告的完整性和準確性
- 客製化需求:不同使用情境需要不同的搜尋 API 和模型配置
Open Deep Research 透過 多模型協作 和 智慧搜尋整合,讓 AI 能夠像人類研究員一樣,進行深度、全面的資料蒐集與分析。
🛠️ 技術框架與設計模式
LangGraph
用於構建複雜的 LLM 應用程式流程,支援狀態管理和工作流程編排
LangChain
提供統一的 LLM 介面,支援多種模型供應商(OpenAI、Anthropic、Google 等)
Model Context Protocol
開放標準協定,讓 LLM 能夠安全地存取外部資料源和工具
AsyncIO
非同步程式設計,支援並行搜尋和處理,大幅提升效能
核心設計模式
async def supervisor(state: SupervisorState, config: RunnableConfig):
configurable = Configuration.from_runnable_config(config)
research_model_config = {
"model": configurable.research_model,
"max_tokens": configurable.research_model_max_tokens,
"api_key": get_api_key_for_model(
configurable.research_model,
config
)
}
lead_researcher_tools = [ConductResearch, ResearchComplete]
research_model = configurable_model.bind_tools(
lead_researcher_tools
)
return Command(
goto="supervisor_tools",
update={
"supervisor_messages": [response],
"research_iterations": state.get(
"research_iterations",
0
) + 1
}
)
class AgentState(MessagesState):
supervisor_messages: Annotated[
list[MessageLikeRepresentation],
override_reducer
]
research_brief: Optional[str]
raw_notes: Annotated[
list[str],
override_reducer
] = []
notes: Annotated[
list[str],
override_reducer
] = []
final_report: str
def override_reducer(current_value, new_value):
if isinstance(new_value, dict) and \
new_value.get("type") == "override":
return new_value.get("value", new_value)
else:
return operator.add(current_value, new_value)
async def select_and_execute_search(
search_api: str,
query_list: list[str],
params_to_pass: dict
) -> str:
if search_api == "tavily":
return await tavily_search.ainvoke({
'queries': query_list,
**params_to_pass
})
elif search_api == "duckduckgo":
return await duckduckgo_search.ainvoke({
'search_queries': query_list
})
elif search_api == "exa":
search_results = await exa_search(
query_list,
**params_to_pass
)
else:
raise ValueError(
f"不支援的搜尋 API: {search_api}"
)
@tool(description="執行深度網路搜尋的工具")
async def tavily_search(
queries: List[str],
max_results: Annotated[int, InjectedToolArg] = 5,
topic: Annotated[
Literal["general", "news", "finance"],
InjectedToolArg
] = "general",
config: RunnableConfig = None
) -> str:
search_results = await tavily_search_async(
queries,
max_results=max_results,
topic=topic,
include_raw_content=True,
config=config
)
formatted_output = "搜尋結果: \n\n"
unique_results = {}
for response in search_results:
for result in response['results']:
url = result['url']
if url not in unique_results:
unique_results[url] = {
**result,
"query": response['query']
}
return formatted_output
🎮 使用情境與應用場景
📊 市場研究與商業分析
自動蒐集競品資訊、市場趨勢、產業報告,生成深度的商業洞察報告。適合投資分析師、市場研究員、創業者使用。
🔬 學術研究與文獻回顧
整合 ArXiv、PubMed 等學術資料庫,協助研究人員快速梳理相關文獻,發現研究缺口和前沿動態。
💻 技術調研與選型
比較不同技術框架、工具或解決方案,提供技術決策支援。特別適合技術主管和架構師。
📈 投資盡職調查
深度分析目標公司的財務狀況、競爭優勢、風險因子,生成投資決策報告。
🌐 政策法規研究
追蹤法規變化、政策影響分析,協助合規團隊和法務人員掌握最新動態。
實際範例:「分析台灣 2025 年 AI 產業發展趨勢,包含政策支持、關鍵企業動態、技術突破和國際比較」
🏗️ 軟體架構設計
架構特色:
- 階層式設計:督導者負責協調,研究員專注執行
- 並行處理:多個研究員同時工作,大幅提升效率
- 模組化工具:支援多種搜尋 API 和外部工具整合
- 狀態管理:完整的執行狀態追蹤和錯誤復原機制
- 可擴展性:輕鬆新增新的搜尋來源和處理工具
❓ 常見問題 Q&A
Q: 研究監督者如何決定要使用多少研究員來研究主題?
A: 研究監督者透過以下機制來智慧決定研究員數量:
🧠 決策機制詳解
1. 配置限制
系統設定最大並行研究單元數量(預設為 5 個),這是不可超越的硬性限制
2. LLM 智慧分析
監督者使用大型語言模型分析研究主題的複雜度和可拆分性
3. 並行適用性評估
判斷不同子主題是否可以獨立研究,避免相互依賴的問題
4. 成本效益權衡
平衡時間節省與成本增加,避免過度細分研究任務
max_concurrent_research_units = configurable.max_concurrent_research_units
lead_researcher_tools = [ConductResearch, ResearchComplete]
research_model = configurable_model.bind_tools(lead_researcher_tools)
conduct_research_calls = all_conduct_research_calls[:max_concurrent_research_units]
overflow_calls = all_conduct_research_calls[max_concurrent_research_units:]
for overflow_call in overflow_calls:
error_message = "錯誤:已超過最大並行研究單元數量限制"
🎯 決策考量因素
適合並行研究的情況:
- 比較類型問題(A vs B vs C)
- 多個獨立實體的分析
- 不同角度或維度的研究
- 可獨立完成的子主題
不適合並行的情況:
- 需要前置知識的連續性問題
- 高度相關且互相依賴的主題
- 簡單的單一概念解釋
- 成本效益不划算的細分
實際運作流程:
監督者接收問題 → 分析複雜度 → 評估並行可能性 → 決定研究員數量 → 分配具體任務 → 監控協調整個研究過程
Q: 研究者如何決定搜尋到的內容品質?
A: Open Deep Research 使用多層次的品質控制機制來確保搜尋內容的可信度和相關性:
🔍 內容品質控制架構
多元搜尋源策略
整合 Tavily(準確性)、ArXiv(學術)、PubMed(醫學)、Exa(AI摘要)等高品質搜尋源
AI 智慧摘要
使用專門的摘要模型提取關鍵資訊,移除無關內容,保持事實準確性
去重與來源驗證
透過 URL 去重避免重複資訊,確保來源的多樣性和可信度
迭代品質改善
持續評估內容完整性,自動補充不足的資訊,直到達到品質標準
search_result = {
'title': str,
'url': str,
'content': str,
'score': float,
'raw_content': str
}
async def summarize_webpage(model, webpage_content):
summary = await model.with_structured_output(Summary).ainvoke([
HumanMessage(content=summarize_webpage_prompt.format(
webpage_content=webpage_content,
date=get_today_str()
))
])
return f"""
{summary.summary}
{summary.key_excerpts}
"""
def deduplicate_and_format_sources(search_response):
unique_sources = {}
for source in sources_list:
if source['url'] not in unique_sources:
unique_sources[source['url']] = source
return formatted_unique_sources
if state.get("tool_call_iterations", 0) >= max_react_tool_calls:
return Command(goto="compress_research")
else:
return Command(goto="researcher")
🎯 五層品質控制流程
第一層:來源選擇
根據研究主題選擇最適合的搜尋 API(學術用 ArXiv、醫學用 PubMed、一般用 Tavily 等)
第二層:內容摘要
使用專門的摘要模型(預設 gpt-4.1-nano)提取關鍵資訊,過濾雜訊
第三層:去重整合
移除重複的 URL 和內容,確保資訊來源的多樣性
第四層:壓縮整理
使用壓縮模型(預設 gpt-4.1-mini)整合多個來源,產生連貫的研究發現
第五層:品質評估
持續評估內容完整性,必要時進行補充搜尋,直到達到研究標準
summarize_webpage_prompt = """
請遵循以下準則創建高品質摘要:
1. 識別並保留網頁的主要主題或目的
2. 保留核心事實、統計數據和關鍵數據點
3. 保持來自可信來源的重要引述
4. 維持時間敏感事件的時間順序
5. 保留任何列表或分步驟的指導
6. 包含相關日期、姓名和地點
7. 總結冗長解釋但保持核心訊息完整
處理不同內容類型:
- 新聞文章:專注於 5W1H(誰、什麼、何時、何地、為什麼、如何)
- 科學內容:保留方法論、結果和結論
- 觀點文章:維持主要論點和支持觀點
- 產品頁面:保留關鍵功能、規格和獨特賣點
目標:創建能夠獨立使用的全面摘要
"""
🚀 快速開始
git clone https://github.com/langchain-ai/open_deep_research.git
cd open_deep_research
uv venv
source .venv/bin/activate
uv pip install -r pyproject.toml
cp .env.example .env
uvx --refresh --from "langgraph-cli[inmem]" \
--with-editable . \
--python 3.11 langgraph dev --allow-blocking
from open_deep_research.deep_researcher import deep_researcher_builder
from langgraph.checkpoint.memory import MemorySaver
import uuid
async def research_example():
graph = deep_researcher_builder.compile(
checkpointer=MemorySaver()
)
config = {
"configurable": {
"thread_id": str(uuid.uuid4()),
"search_api": "tavily",
"research_model": "openai:gpt-4.1",
"max_concurrent_research_units": 5
}
}
result = await graph.ainvoke({
"messages": [{
"role": "user",
"content": "分析 2025 年生成式 AI 的發展趨勢"
}]
}, config)
return result["final_report"]