跳至主内容

走进GPT Researcher的故事

· 5 min read
Elisha Kramer
Core Contributor @ GPT Researcher

GPTR reflecting ourselves

巴诺书店之梦

记得年少时,我走进巴诺书店,新书的油墨清香弥漫在空气中,指尖轻抚过那些启迪思想、触动心灵的书籍书脊。我总会轻声对自己说:总有一天,我的名字也会出现在这里。

对我而言,书籍不仅仅是故事——它们是人类经历的映照,是人们更清晰地认识自我的途径。莎士比亚曾说:"艺术的目的是为自然举起一面镜子。"这个观点深深影响了我。艺术、写作和讲故事不仅关乎娱乐,更是以全新方式理解自我的过程。

但世界变了。书店逐渐消失,人们的注意力转移,小说——曾经是深度思考和反思的巅峰——让位于新的参与形式。那种漫长沉浸式的阅读体验被更动态、更具互动性的方式所取代。

编程之旅:辛巴时刻

大约9年前,就像《狮子王》中的辛巴一样,我开启了一段充满疑虑与不确定的新旅程。离开熟悉的写作世界,我踏入了陌生的编程领域。起初这就像一门外语——无尽的语法行、毫无意义的调试错误,以及那些让我感觉自己像个开发者世界中的冒牌货的沮丧时刻。

这段旅程充满艰辛——我苦苦寻找自己的位置,遭遇合约取消,无数次被打得落花流水。每一次拒绝、每一个错失的机会都让我质疑自己是否选错了道路。也许我不该投身建设——也许我本就属于故事的世界。

Even when I finally landed a job at Fiverr, working with JavaScript, MySQL, HTML, and CSS, I still felt like I had abandoned my identity as a writer.

探索GPT Researcher

一年前的某个夜晚,当我深陷人工智能研究的兔子洞时,偶然发现了GPT Researcher。这个概念瞬间击中了我——AI不仅仅是一个工具;它是拓展人类知识、精炼我们问题、重塑研究方式的手段。

我联系了Assaf,原本没抱太大期望。但他不仅礼貌回应,还热情接纳了我。当看到我的第一次代码提交被合并时——那一刻仿佛是我旧日梦想的回响。只是这一次,我不再仅仅是书写故事。我正在构建一个能帮助他人发现他们自己故事的工具。

研究者魔镜中的邪恶女巫

大约在那段时间,我发现自己反复向GPT Researcher提出同一个问题:

"谁是Elisha Kramer?"

起初,它就像白雪公主里的魔镜,给出一些泛泛的回答,比如"Elisha Kramer是一位具有网页开发经验的软件工程师"。它从我的LinkedIn、GitHub和Udemy个人资料中提取信息,描绘出我的职业画像。但后来,事情开始变得诡异起来。

我对GPT Researcher进行了更多提交。更多贡献。在编码过程中,我提出了一个不同的问题。

"ElishaKay在Github上是做什么的?"

随着时间的推移,答案发生了变化,因为GPT Researcher不断从网络搜索结果中获取新的信息来源。

"ElishaKay 是一位活跃的开源贡献者,拥有多个代码库,过去一年提交了超过500次代码。"

天啊!它正在学习。又一次提交。又一个新功能。又一行文档。是时候更具体一些了。

"GPT Researcher中的ElishaKay是谁?"

"ElishaKay是GPT Researcher的核心贡献者,通过重要的代码和文档贡献改进了研究工作流程并增强了AI检索能力。"

现在我们聊得不错。但我还没完。就像邪恶女巫一样,我不断卷土重来。更多提交。更多改进。更多功能。

直到最后,我问道:

"告诉我关于GPT Researcher的信息以及改进它的技巧"

GPT Researcher回头看着我说:

"GPTR是一个蓬勃发展的开源社区。最好的前进道路是继续投资于这个社区——通过代码贡献、文档改进以及帮助新贡献者入门。该项目的优势在于其协作性质。"

就在那一刻我意识到——我不仅仅是在使用GPT Researcher。我正在成为它故事的一部分。

AI作为我们自身的镜子

这种不断演变的反馈帮助我构建了自己的自我叙事。GPT Researcher不仅仅是在反映已知内容——它还在从我的工作和更广泛的互联网中提取上下文。

它映射出我自身的旅程,每一步都在精进,模糊了固定身份的幻象,拥抱不断进化的自我。

每一次查询、每一次提交、每一次改进都塑造了这个工具——反过来,它也塑造了我。

共建社区

GPT Researcher不仅仅是一个工具。它是开源精神的体现,一个充满活力、不断进化的生态系统,在这里知识不是静止的,而是持续被精炼的。它不仅仅是在回答问题;它是在进行对话,根据最新的贡献、研究和发现,不断塑造和重塑叙述。 这不再只是关于我。这是关于我们。 138位贡献者组成的网络。一个被20,000颗星标关注的开源项目。一场推动AI驱动研究边界的集体运动。

每一位研究者、每一位开发者、每一位通过完善问题、贡献功能或使用工具来满足好奇心的探索者,都是更宏大图景的一部分。人工智能不仅仅是输出答案的黑匣子——它是帮助我们完善思维、挑战假设、拓展认知的工具。 这个过程如同生活本身,是一个不断迭代的历程。 我们提供的背景信息越多,获得的洞察就越深刻。我们投入越多,它反映的不仅是我们曾经的模样,更是我们正在成为的样子。

一个仍在书写的故事

虽然我曾梦想在巴诺书店的书脊上看到自己的名字,但现在我看到了更伟大的事物。 我的文字不再局限于单一书籍——它们存在于每一行代码中,每一次贡献里,每位研究者打磨问题的过程中。 我们不仅是使用者。我们是建设者。 而这不仅仅是我的故事。 这是我们的故事。 它仍在被书写。

介绍深度研究:开源替代方案

· 8 min read

AI深度研究的黎明

随着"深度研究"能力的出现,人工智能研究领域正在经历一场革命性变革。但究竟什么是深度研究?为什么您应该关注它?

深度研究代表了AI驱动信息检索的下一阶段进化——它远超简单搜索,能够对复杂主题提供全面、多层次的分析。与传统搜索引擎仅返回链接列表不同,也不同于仅提供表层摘要的第一代AI助手,深度研究工具通过复杂算法以前所未有的深度和广度探索主题,模拟人类研究者处理复杂课题的方式。

真正深度研究能力的关键特征包括:动态优化查询和结果的迭代分析(InfoQ, 2025)、整合多种数据格式的多模态处理(Observer, 2025)、获取最新洞见的实时数据检索(WinBuzzer, 2025),以及为学术技术应用提供规范引用的结构化输出(Helicone, 2025)。

近几个月来,我们看到主要厂商纷纷推出自己的深度研究解决方案,每家都在市场中拥有独特的方法和定位:

  • Perplexity AI 专注于速度,能在三分钟内通过实时数据检索提供研究成果(Analytics Vidhya, 2025)。其经济高效的模型(提供免费起步套餐)让更广泛的用户群体能够进行高级研究,不过也有分析人士指出,为了追求速度可能会牺牲一定的准确性(Medium, 2025)。

  • OpenAI的深度研究(基于O3模型构建)优先考虑深度和精确性,凭借先进的推理能力在技术和学术应用中表现出色(Helicone, 2025)。其结构化输出包含详细引用,确保可靠性和可验证性。然而每月200美元的费用(Opentools, 2025)意味着相当大的投入,且生成完整报告可能需要5-30分钟(ClickItTech, 2025)。

  • 谷歌的Gemini 2.0强调文本、图像、音频和视频的多模态集成,在企业应用中表现尤为突出(Adyog, 2024)。每月20美元的定价相比OpenAI的解决方案更为经济实惠,不过部分用户指出其在定制灵活性方面存在局限(Helicone, 2025)。

深度研究真正令人兴奋之处在于其潜力:通过民主化高级知识合成(Medium, 2025),自动化耗时研究任务显著提升生产力(The Mobile Indian, 2025),以及通过先进推理能力为跨学科研究开辟新途径(Observer, 2025)。

然而,当前市场的一个关键限制是可访问性——最强大的深度研究工具仍被昂贵的付费墙或封闭系统所阻挡,这使得许多本可从中获益最多的研究人员、学生和小型组织无法触及这些工具。

介绍GPT Researcher深度研究工具 ✨

我们很高兴宣布对这一趋势的回应:GPT Researcher深度研究——一个先进的开源递归研究系统,能够以深度和广度探索主题,同时保持成本效益和透明度。

GPT Researcher 深度研究不仅与行业巨头的性能相匹配,还在多个关键指标上超越它们:

  • 高性价比: 每次深度研究操作成本约为0.40美元(使用o3-mini模型并开启"high"推理强度)
  • 高效省时: 大约5分钟即可完成研究
  • 完全可定制: 调整参数以满足您特定的研究需求
  • 透明性: 完全可见的研究过程和方法论
  • 开源: 可免费使用、修改并集成到您的工作流程中

工作原理:递归研究树

GPT Researcher深度研究之所以如此强大,在于其采用树状探索模式,通过智能递归方法将广度与深度完美结合:

Research Flow Diagram

  1. 广度探索: 在每一层级,它会生成多个搜索查询来探索您主题的不同方面
  2. 深度探索: 对于每个分支,它会递归地深入挖掘,追踪有希望的线索并揭示隐藏的联系
  3. 并发处理: 利用异步/等待模式同时运行多个研究路径
  4. 上下文管理: 自动汇总并综合所有分支的研究发现
  5. 实时追踪: 提供研究进度在广度和深度两个维度的更新

想象部署一支AI研究员团队,每位成员遵循自己的研究路径,同时相互协作以全面理解您的主题。这正是GPT Researcher深度研究方法的力量所在。

快速上手,只需几分钟

将深度研究整合到您的项目中非常简单:

from gpt_researcher import GPTResearcher
import asyncio

async def main():
# Initialize researcher with deep research type
researcher = GPTResearcher(
query="What are the latest developments in quantum computing?",
report_type="deep", # This triggers deep research mode
)

# Run research
research_data = await researcher.conduct_research()

# Generate report
report = await researcher.write_report()
print(report)

if __name__ == "__main__":
asyncio.run(main())

幕后原理:深度研究如何运作

查看代码库可以发现支撑GPT Researcher深度研究能力的复杂系统:

1. 查询生成与规划

系统首先会根据您的初始问题生成一组多样化的搜索查询:

async def generate_search_queries(self, query: str, num_queries: int = 3) -> List[Dict[str, str]]:
"""Generate SERP queries for research"""
messages = [
{"role": "system", "content": "You are an expert researcher generating search queries."},
{"role": "user",
"content": f"Given the following prompt, generate {num_queries} unique search queries to research the topic thoroughly. For each query, provide a research goal. Format as 'Query: <query>' followed by 'Goal: <goal>' for each pair: {query}"}
]

这一过程会生成有针对性的查询,每个查询都有特定的研究目标。例如,关于量子计算的查询可能会生成:

  • "2024-2025年最新量子计算突破"
  • "量子计算在金融领域的实际应用"
  • "量子纠错技术进展"

2. 并发研究执行

系统随后会并发执行这些查询,并采用智能资源管理:

# Process queries with concurrency limit
semaphore = asyncio.Semaphore(self.concurrency_limit)

async def process_query(serp_query: Dict[str, str]) -> Optional[Dict[str, Any]]:
async with semaphore:
# Research execution logic

这种方法在确保系统稳定性的同时最大化效率 - 就像有多位研究人员并行工作一样。

3. 递归探索

神奇之处在于递归探索:

# Continue deeper if needed
if depth > 1:
new_breadth = max(2, breadth // 2)
new_depth = depth - 1
progress.current_depth += 1

# Create next query from research goal and follow-up questions
next_query = f"""
Previous research goal: {result['researchGoal']}
Follow-up questions: {' '.join(result['followUpQuestions'])}
"""

# Recursive research
deeper_results = await self.deep_research(
query=next_query,
breadth=new_breadth,
depth=new_depth,
# Additional parameters
)

这会创建一种树状探索模式,沿着有前景的线索深入挖掘,同时保持覆盖的广度。

4. 上下文管理与综合

管理海量收集的信息需要复杂的追踪系统:

# Trim context to stay within word limits
trimmed_context = trim_context_to_word_limit(all_context)
logger.info(f"Trimmed context from {len(all_context)} items to {len(trimmed_context)} items to stay within word limit")

这确保了在尊重模型上下文限制的同时保留最相关的信息。

定制您的研究体验

GPT Researcher开源方法的关键优势之一是完全可定制性。您可以通过多种配置选项根据具体需求调整研究流程:

deep_research_breadth: 4    # Number of parallel research paths
deep_research_depth: 2 # How many levels deep to explore
deep_research_concurrency: 4 # Maximum concurrent operations
total_words: 2500 # Word count for final report

通过环境变量、配置文件或直接在代码中应用这些配置:

researcher = GPTResearcher(
query="your query",
report_type="deep",
config_path="path/to/config.yaml"
)

实时进度追踪

对于需要了解研究过程的应用,GPT Researcher提供详细进度跟踪:

class ResearchProgress:
current_depth: int # Current depth level
total_depth: int # Maximum depth to explore
current_breadth: int # Current number of parallel paths
total_breadth: int # Maximum breadth at each level
current_query: str # Currently processing query
completed_queries: int # Number of completed queries
total_queries: int # Total queries to process

这使您能够构建实时显示研究进度的界面 - 非常适合需要让用户了解流程细节的应用场景。

为何重要:深度研究的影响

通过GPT Researcher等开源工具实现深度研究能力的民主化,标志着我们处理和分析信息方式的范式转变。其优势包括:

  1. 更深入的洞察: 揭示表层研究会遗漏的关联与模式
  2. 节省时间: 将数小时甚至数天的手动研究自动化,缩短至几分钟
  3. 降低成本: 以极低成本获得企业级研究能力
  4. 可访问性: 为个人和小型组织提供先进的研究工具
  5. 透明度: 完全可见的研究方法和来源

立即开始使用

准备好体验深度研究为您的项目带来的强大力量了吗?以下是入门指南:

  1. 安装: pip install gpt-researcher
  2. API密钥: 为您选择的LLM提供商和搜索引擎设置API密钥
  3. 配置: 根据您的研究需求自定义参数
  4. 实现: 使用示例代码集成到您的应用中

更多详细说明和示例可在GPT Researcher文档中找到

无论您是正在构建下一代研究工具的开发者、寻求更深入见解的学者,还是需要全面分析的商业专业人士,GPT Researcher的深度研究能力都提供了一个可访问且强大的解决方案,其表现可与大型AI公司的产品相媲美——在许多方面甚至更胜一筹。

AI驱动研究的未来已经到来,而且是开源的。🎉

祝您研究愉快!

研究的未来是混合式的

· 8 min read
Assaf Elovic
Creator @ GPT Researcher and Tavily

Hyrbrid Research with GPT Researcher

过去几年,我们见证了旨在颠覆研究工作的新型AI工具爆发式增长。诸如ChatPDFConsensus专注于从文档中提取洞见,而Perplexity等工具则擅长从网络抓取信息。但关键在于:目前还没有任何工具能在统一的情境研究流程中同时整合网络和本地文档搜索功能。

这就是为什么我很高兴向大家介绍GPT Researcher的最新进展——现在能够对任何给定任务和文档进行混合研究。

网络驱动的研究往往缺乏具体情境,存在信息过载的风险,并可能包含过时或不可靠的数据。另一方面,本地驱动的研究仅限于历史数据和现有知识,可能形成组织内部的信息茧房,错失关键市场趋势或竞争对手动向。这两种方法若单独使用,都可能导致不完整或有偏见的见解,从而影响您做出全面知情决策的能力。

今天,我们将改变游戏规则。通过本指南的学习,您将掌握如何进行混合研究,结合网络与本地资源的双重优势,从而开展更全面、更相关且更具洞察力的研究工作。

为什么混合研究方法更有效

通过结合网络和本地资源,混合研究解决了这些限制并提供了几个关键优势:

  1. 基于本地文档的上下文: 本地文档提供了经过验证的、组织专属信息的基础。这使研究扎根于既定知识,降低了偏离核心概念或误解行业特定术语的风险。

    示例: 某制药公司在研究新药开发机会时,可以以其内部研究论文和临床试验数据为基础,然后通过网络补充最新的已发表研究和监管更新。

  2. 提高准确性:网络来源提供最新信息,而本地文档则提供历史背景。这种结合可以实现更准确的趋势分析和决策制定。

    示例:一家金融服务公司在分析市场趋势时,可以将其历史交易数据与实时市场新闻和社交媒体情绪分析相结合,从而做出更明智的投资决策。

  3. 减少偏见:通过同时利用网络和本地资源,我们降低了单一来源可能存在的偏见风险。

    示例:一家科技公司在评估其产品路线图时,可以平衡内部功能需求和使用数据与外部客户评价及竞争对手分析,确保获得全面的视角。

  4. 改进的规划和推理能力: 大型语言模型可以利用本地文档的上下文信息,更好地规划其网络研究策略,并对在线发现的信息进行推理。

    示例: 一个由AI驱动的市场研究工具可以利用公司过去的营销活动数据来指导其搜索当前市场趋势,从而获得更具相关性和可操作性的见解。

  5. 定制化洞察: 混合研究可以将专有信息与公共数据整合,从而产生独特的、针对特定组织的洞察。

    示例: 一家零售连锁企业可以将其销售数据与网络抓取的竞争对手定价和经济指标相结合,以优化其在不同地区的定价策略。

这些只是企业可以利用混合研究的几个用例示例,闲话少说——让我们开始构建吧!

构建混合研究助手

在深入细节之前,值得指出的是GPT Researcher具备开箱即用的混合研究能力!但为了真正理解其运作原理并让您更深入地了解整个过程,我们将剖析其内部机制。

GPT Researcher hybrid research

GPT Researcher根据本地文档自动生成的计划进行网络研究,如上图架构所示。然后从本地和网络数据中检索相关信息,生成最终的研究报告。

我们将探讨如何利用LangChain处理本地文档,这是GPT Researcher文档处理的核心组件。随后,我们将展示如何运用GPT Researcher开展混合研究,将网络搜索的优势与您的本地文档知识库相结合。

使用Langchain处理本地文档

LangChain提供了多种文档加载器,使我们能够处理不同类型的文件。在处理多样化的本地文档时,这种灵活性至关重要。以下是设置方法:

from langchain_community.document_loaders import (
PyMuPDFLoader,
TextLoader,
UnstructuredCSVLoader,
UnstructuredExcelLoader,
UnstructuredMarkdownLoader,
UnstructuredPowerPointLoader,
UnstructuredWordDocumentLoader
)
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma

def load_local_documents(file_paths):
documents = []
for file_path in file_paths:
if file_path.endswith('.pdf'):
loader = PyMuPDFLoader(file_path)
elif file_path.endswith('.txt'):
loader = TextLoader(file_path)
elif file_path.endswith('.csv'):
loader = UnstructuredCSVLoader(file_path)
elif file_path.endswith('.xlsx'):
loader = UnstructuredExcelLoader(file_path)
elif file_path.endswith('.md'):
loader = UnstructuredMarkdownLoader(file_path)
elif file_path.endswith('.pptx'):
loader = UnstructuredPowerPointLoader(file_path)
elif file_path.endswith('.docx'):
loader = UnstructuredWordDocumentLoader(file_path)
else:
raise ValueError(f"Unsupported file type: {file_path}")

documents.extend(loader.load())

return documents

# Use the function to load your local documents
local_docs = load_local_documents(['company_report.pdf', 'meeting_notes.docx', 'data.csv'])

# Split the documents into smaller chunks for more efficient processing
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(local_docs)

# Create embeddings and store them in a vector database for quick retrieval
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(documents=splits, embedding=embeddings)

# Example of how to perform a similarity search
query = "What were the key points from our last strategy meeting?"
relevant_docs = vectorstore.similarity_search(query, k=3)

for doc in relevant_docs:
print(doc.page_content)

使用GPT Researcher进行网络研究

既然我们已经学会了如何处理本地文档,现在让我们快速了解一下GPT Researcher的内部工作原理:

GPT Researcher Architecture

如上所示,GPT Researcher会根据给定的任务创建研究计划,通过生成潜在的研究查询来共同提供对该主题的客观且全面的概述。一旦生成这些查询,GPT Researcher会使用像Tavily这样的搜索引擎来查找相关结果。每个抓取的结果随后会被保存在向量数据库中。最后,检索与研究任务最相关的top k数据块以生成最终的研究报告。

GPT Researcher支持混合研究模式,该模式在检索最相关信息前会额外执行一个本地文档分块步骤(通过Langchain实现)。经过社区大量评估验证,我们发现混合研究能将最终结果的准确率提升40%以上!

使用GPT Researcher进行混合研究

现在您对混合研究的工作原理有了更深入的理解,让我们展示一下使用GPT Researcher可以多么轻松地实现这一目标。

步骤1:使用PIP安装GPT Researcher

pip install gpt-researcher

步骤2:设置环境

我们将使用OpenAI作为大语言模型供应商和Tavily作为搜索引擎来运行GPT Researcher。在继续之前,您需要获取两者的API密钥。然后,在您的CLI中按以下方式导出环境变量:

export OPENAI_API_KEY={your-openai-key}
export TAVILY_API_KEY={your-tavily-key}

步骤3:使用混合研究配置初始化GPT Researcher

GPT Researcher可以通过参数轻松初始化,以指示其进行混合研究。您可以开展多种形式的研究,前往文档页面了解更多信息。

要让GPT Researcher执行混合研究,您需要将所有相关文件包含在my-docs目录中(如果不存在则创建该目录),并如下所示将实例report_source设置为"hybrid"。一旦报告来源设置为混合模式,GPT Researcher将在my-docs目录中查找现有文档并将其纳入研究。如果不存在任何文档,它将忽略此操作。

from gpt_researcher import GPTResearcher
import asyncio

async def get_research_report(query: str, report_type: str, report_source: str) -> str:
researcher = GPTResearcher(query=query, report_type=report_type, report_source=report_source)
research = await researcher.conduct_research()
report = await researcher.write_report()
return report

if __name__ == "__main__":
query = "How does our product roadmap compare to emerging market trends in our industry?"
report_source = "hybrid"

report = asyncio.run(get_research_report(query=query, report_type="research_report", report_source=report_source))
print(report)

如上所示,我们可以运行以下示例的研究:

  • 研究任务:"我们的产品路线图与行业新兴市场趋势相比如何?"
  • 网络:当前市场趋势、竞争对手公告和行业预测
  • 本地:内部产品路线图文档和功能优先级列表

经过多次社区评估,我们发现这项研究的结果将调研质量和准确性提升了40%以上,并减少了50%的幻觉现象。更重要的是,如上所述,本地信息能帮助大语言模型改进规划推理能力,使其做出更优决策并调研更相关的网络资源。

但等等,还有更多!GPT Researcher还包含一个使用NextJS和Tailwind构建的时尚前端应用。要了解如何运行它,请查看文档页面。您可以轻松使用拖放文档功能来进行混合研究。

结论

混合研究代表了数据收集和决策制定领域的重大进步。通过利用GPT Researcher等工具,团队现在能够进行更全面、情境感知且可操作的研究。这种方法解决了单独使用网络或本地资源的局限性,提供了诸多优势,例如基于实境的上下文、更高的准确性、减少偏见、改进的规划与推理能力,以及定制化的洞察。

混合研究的自动化可以使团队做出更快、更数据驱动的决策,最终提高生产力,并在分析不断增长的非结构化和动态信息池中提供竞争优势。

如何构建终极研究多智能体助手

· 10 min read
Assaf Elovic
Creator @ GPT Researcher and Tavily

Header

学习如何使用LangGraph构建一个由专业AI智能体团队组成的自主研究助手

GPT Researcher 自首次发布仅过去一年,但构建、测试和部署智能体的方法已经发生了显著变化。这正是当前人工智能发展的本质和速度。从最初简单的零样本或少样本提示,迅速演变为智能体函数调用、RAG(检索增强生成),如今最终发展为智能体工作流(又称"流程工程")。

吴恩达最近表示:“我认为AI智能体工作流将在今年推动人工智能的重大进展——甚至可能超过下一代基础模型。这是一个重要趋势,我敦促所有从事AI工作的人都予以关注。”

在本文中,您将了解为什么多智能体工作流是当前的最佳标准,以及如何使用LangGraph构建最优的自主研究多智能体助手。

要跳过本教程,欢迎查看GPT Researcher x LangGraph的Github仓库。

LangGraph简介

LangGraph是LangChain的一个扩展,旨在创建智能体和多智能体流程。它增加了创建循环流程的能力,并内置了记忆功能——这两者对于构建智能体都是至关重要的特性。

LangGraph为开发者提供了高度的可控性,对于创建自定义智能体和流程至关重要。实际生产环境中几乎所有的智能体都会针对其试图解决的具体用例进行定制。LangGraph让您能够灵活创建任意自定义智能体,同时提供直观的开发者体验来实现这一目标。

寒暄到此为止,让我们开始构建吧!

构建终极自主研究智能体

通过利用LangGraph,研究过程的深度和质量可以得到显著提升,这得益于多个具备专业技能的智能体的协同工作。让每个智能体专注于并精通某一特定技能,能够实现更好的关注点分离、更高的可定制性,并随着项目规模的扩大而持续进行扩展开发。

受近期STORM论文的启发,本示例展示了AI智能体团队如何协作完成从规划到发布的给定主题研究。该示例还将利用领先的自主研究智能体GPT Researcher。

研究智能体团队

研究团队由七个LLM智能体组成:

  • 主编 — 监督研究过程并管理团队。这是使用LangGraph协调其他智能体的"主控"智能体。该智能体作为主要的LangGraph接口。
  • GPT Researcher — 一个专门化的自主智能体,能够对给定主题进行深入研究。
  • 编辑 — 负责规划研究大纲和结构。
  • 审阅者 — 根据给定标准验证研究结果的正确性。
  • 修订者 — 根据审阅者的反馈修订研究成果。
  • Writer — 负责编译和撰写最终报告。
  • 发布者 — 负责以多种格式发布最终报告。

架构

如下所示,自动化流程基于以下阶段:规划研究、数据收集与分析、审核与修订、撰写报告,最后发布:

Architecture

更具体地说,流程如下:

  • 浏览器 (gpt-researcher) — 根据给定的研究任务在互联网上进行初步调研。这一步骤对大型语言模型至关重要,使其能够基于最新相关信息规划研究流程,而不仅仅依赖预训练数据来处理特定任务或主题。

  • 编辑 — 根据初步研究规划报告大纲和结构。编辑还负责根据规划的大纲触发并行研究任务。

  • 针对每个大纲主题(并行处理):

    • 研究员 (gpt-researcher) — 对子主题进行深入研究并撰写初稿。该智能体底层使用GPT Researcher Python包,用于生成经过优化的、深入且基于事实的研究报告。
    • 审阅者 — 根据一组指南验证草稿的正确性,并向修订者提供反馈(如有需要)。
    • 修订者 — 根据评审反馈不断修改草稿,直至达到满意效果。
  • 撰写者 — 根据给定的研究发现,编译并撰写最终报告,包括引言、结论和参考文献部分。

  • 发布器 — 将最终报告发布为多种格式,如PDF、Docx、Markdown等。

  • 由于代码量庞大,我们不会深入探讨所有代码,而是主要聚焦于我发现的值得分享的有趣部分。

定义图状态

LangGraph最让我喜爱的功能之一是状态管理。在LangGraph中,状态通过结构化方法实现,开发者可以定义一个GraphState来封装应用程序的完整状态。图中的每个节点都可以修改这个状态,从而根据交互过程中不断变化的上下文生成动态响应。

就像任何技术设计的开始阶段,考虑整个应用程序的数据架构是关键。在本例中,我们将定义一个ResearchState如下:

class ResearchState(TypedDict):
task: dict
initial_research: str
sections: List[str]
research_data: List[dict]
# Report layout
title: str
headers: dict
date: str
table_of_contents: str
introduction: str
conclusion: str
sources: List[str]
report: str

如上所示,状态分为两个主要区域:研究任务和报告布局内容。当数据在智能体图中流转时,每个智能体会基于现有状态依次生成新数据,并更新状态以便后续与其他智能体在图中进行进一步处理。

然后我们可以用以下方式初始化图表:

from langgraph.graph import StateGraph
workflow = StateGraph(ResearchState)

使用LangGraph初始化图表 如上所述,多智能体开发的一大优势在于构建每个智能体使其具备专业化和限定范围的技能。让我们以使用GPT Researcher Python包的研究员智能体为例:

from gpt_researcher import GPTResearcher

class ResearchAgent:
def __init__(self):
pass

async def research(self, query: str):
# Initialize the researcher
researcher = GPTResearcher(parent_query=parent_query, query=query, report_type=research_report, config_path=None)
# Conduct research on the given query
await researcher.conduct_research()
# Write the report
report = await researcher.write_report()

return report

如上所示,我们已经创建了一个研究智能体的实例。现在假设我们对团队中的每个智能体都进行了同样的操作。在创建完所有智能体后,我们将使用LangGraph初始化图结构:

def init_research_team(self):
# Initialize skills
editor_agent = EditorAgent(self.task)
research_agent = ResearchAgent()
writer_agent = WriterAgent()
publisher_agent = PublisherAgent(self.output_dir)

# Define a Langchain StateGraph with the ResearchState
workflow = StateGraph(ResearchState)

# Add nodes for each agent
workflow.add_node("browser", research_agent.run_initial_research)
workflow.add_node("planner", editor_agent.plan_research)
workflow.add_node("researcher", editor_agent.run_parallel_research)
workflow.add_node("writer", writer_agent.run)
workflow.add_node("publisher", publisher_agent.run)

workflow.add_edge('browser', 'planner')
workflow.add_edge('planner', 'researcher')
workflow.add_edge('researcher', 'writer')
workflow.add_edge('writer', 'publisher')

# set up start and end nodes
workflow.set_entry_point("browser")
workflow.add_edge('publisher', END)

return workflow

如上所示,创建LangGraph图非常简单直接,主要由三个核心函数组成:add_node、add_edge和set_entry_point。通过这些主要函数,您可以先向图中添加节点,连接边,最后设置起始点。

重点检查:如果你一直在正确跟踪代码和架构,你会注意到上面的初始化中缺少了Reviewer和Reviser智能体。让我们深入探讨这个问题!

支持有状态并行化的图中图

这是我在使用LangGraph过程中最令人兴奋的部分!这个自主智能体的一个亮点功能是能够并行执行每项研究任务,并根据一组预定义的指导方针进行审查和修订。

了解如何在流程中利用并行工作是优化速度的关键。但如果所有智能体都向同一状态报告,该如何触发并行智能体工作?这可能导致最终数据报告中的竞争条件和不一致。为解决此问题,您可以创建一个子图,该子图将从主LangGraph实例触发。这个子图将为每次并行运行维护自己的状态,从而解决上述问题。

和之前一样,让我们定义LangGraph状态及其智能体。由于这个子图主要是审查和修改研究草稿,我们将用草稿信息来定义状态:

class DraftState(TypedDict):
task: dict
topic: str
draft: dict
review: str
revision_notes: str

正如DraftState所示,我们主要关注讨论的主题、审阅者以及修订说明,因为它们相互沟通以最终确定子主题研究报告。为了创建循环条件,我们将利用LangGraph的最后一个重要部分——条件边:

async def run_parallel_research(self, research_state: dict):
workflow = StateGraph(DraftState)

workflow.add_node("researcher", research_agent.run_depth_research)
workflow.add_node("reviewer", reviewer_agent.run)
workflow.add_node("reviser", reviser_agent.run)

# set up edges researcher->reviewer->reviser->reviewer...
workflow.set_entry_point("researcher")
workflow.add_edge('researcher', 'reviewer')
workflow.add_edge('reviser', 'reviewer')
workflow.add_conditional_edges('reviewer',
(lambda draft: "accept" if draft['review'] is None else "revise"),
{"accept": END, "revise": "reviser"})

通过定义条件边,如果审阅者存在审阅意见,图表将指向修订者,否则循环将以最终草案结束。如果回到我们构建的主图表,你会看到这个并行工作位于由ChiefEditor智能体调用的名为“researcher”的节点下。

运行研究助手 在确定智能体、状态和图表后,是时候运行我们的研究助手了!为了便于自定义,该助手通过给定的task.json文件运行:

{
"query": "Is AI in a hype cycle?",
"max_sections": 3,
"publish_formats": {
"markdown": true,
"pdf": true,
"docx": true
},
"follow_guidelines": false,
"model": "gpt-4-turbo",
"guidelines": [
"The report MUST be written in APA format",
"Each sub section MUST include supporting sources using hyperlinks. If none exist, erase the sub section or rewrite it to be a part of the previous section",
"The report MUST be written in spanish"
]
}

任务对象本身已经非常直观明了,但请注意如果follow_guidelines设为false,会导致图谱忽略修订步骤和已定义的指导原则。此外,max_sections字段定义了需要研究的子标题数量。设置较小的值将生成较短的报告。

运行该助手将生成最终的研究报告,支持Markdown、PDF和Docx等格式。

要下载并运行示例,请查看GPT Researcher与LangGraph的开源页面

下一步是什么?

展望未来,有许多令人兴奋的思考方向。人机协同是优化AI体验的关键。通过人类协助助手修订并聚焦于最恰当的研究计划、主题和提纲,将显著提升整体质量和体验。此外,在AI流程中始终注重人类干预,能确保结果的正确性、可控性和确定性。很高兴看到LangGraph已经原生支持这一功能,具体可参考此处。

此外,支持对网络和本地数据的研究对于许多商业和个人用例来说至关重要。

最后,可以投入更多努力来提升检索来源的质量,并确保最终报告以最优的故事线构建。

在LangGraph和多智能体协作领域向前迈进的一步将是助手能够根据给定任务动态规划和生成图。这一愿景将使助手能够仅为特定任务选择一部分智能体,并根据本文介绍的图基础规划其策略,从而开启一个充满可能性的全新世界。鉴于人工智能领域的创新速度,新一代颠覆性的GPT Researcher版本很快将会问世。期待未来带来的惊喜!

要了解该项目的持续进展和更新,请加入我们的Discord社区。一如既往,如果您有任何反馈或进一步的问题,请在下方留言!

如何构建一个具备互联网访问功能的OpenAI助手

· 6 min read
Assaf Elovic
Creator @ GPT Researcher and Tavily

OpenAI再次取得突破,通过一场开创性的开发者大会展示了其工具、产品和服务套件的最新改进。其中一个重要发布是全新的Assistants API,它让开发者能更轻松地构建具有目标导向、并能调用模型和工具的辅助型AI应用。

新的Assistants API目前支持三种工具类型:代码解释器(Code Interpreter)、检索(Retrieval)和函数调用(Function calling)。虽然您可能期望检索工具支持在线信息检索(例如搜索API或ChatGPT插件),但目前它仅支持原始数据,如文本或CSV文件。

这篇博客将展示如何利用最新的Assistants API,通过函数调用工具获取在线信息。

如果想跳过下面的教程,可以查看完整的Github Gist here

从高层次来看,Assistants API的典型集成包含以下步骤:

  • 在API中创建一个助手,通过定义其自定义指令并选择模型。如有需要,可启用诸如代码解释器、检索和函数调用等工具。
  • 当用户开始对话时创建一个Thread
  • 当用户提问时,将消息添加到对话线程中。
  • Run 在Thread上运行Assistant以触发响应。这将自动调用相关工具。

如下所示,一个助手对象包含用于存储和处理助手与用户之间会话的线程(Threads),以及用于在线程上调用助手的运行(Run)。

OpenAI Assistant Object

让我们一步步实现这些步骤吧!在这个示例中,我们将构建一个金融GPT,能够提供关于财务问题的见解。我们将使用OpenAI Python SDK v1.2Tavily Search API

首先,让我们定义助手的指令:

assistant_prompt_instruction = """You are a finance expert. 
Your goal is to provide answers based on information from the internet.
You must use the provided Tavily search API function to find relevant online information.
You should never use your own knowledge to answer questions.
Please include relevant url sources in the end of your answers.
"""

接下来,让我们完成第一步,使用最新的GPT-4 Turbo模型(128K上下文)创建一个助手,并通过Tavily网页搜索API调用功能:

# Create an assistant
assistant = client.beta.assistants.create(
instructions=assistant_prompt_instruction,
model="gpt-4-1106-preview",
tools=[{
"type": "function",
"function": {
"name": "tavily_search",
"description": "Get information on recent events from the web.",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "The search query to use. For example: 'Latest news on Nvidia stock performance'"},
},
"required": ["query"]
}
}
}]
)

步骤2和3相当直接,我们将启动一个新线程并用用户消息更新它:

thread = client.beta.threads.create()
user_input = input("You: ")
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content=user_input,
)

最后,我们将在线程上运行助手以触发函数调用并获取响应:

run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant_id,
)

到目前为止一切顺利!但接下来就有点混乱了。与常规的GPT API不同,Assistants API不会返回同步响应,而是返回一个状态。这使得可以跨智能体进行异步操作,但需要更多开销来获取状态并手动处理每个状态。

Status Diagram

为了管理这个状态生命周期,让我们构建一个可复用的函数,用于处理等待各种状态(如'requires_action')的情况:

# Function to wait for a run to complete
def wait_for_run_completion(thread_id, run_id):
while True:
time.sleep(1)
run = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run_id)
print(f"Current run status: {run.status}")
if run.status in ['completed', 'failed', 'requires_action']:
return run

该函数将持续休眠,直到运行状态最终确定,例如运行完成或需要函数调用采取行动时。

我们快完成了!最后,来处理一下当助手想要调用网页搜索API时的情况:

# Function to handle tool output submission
def submit_tool_outputs(thread_id, run_id, tools_to_call):
tool_output_array = []
for tool in tools_to_call:
output = None
tool_call_id = tool.id
function_name = tool.function.name
function_args = tool.function.arguments

if function_name == "tavily_search":
output = tavily_search(query=json.loads(function_args)["query"])

if output:
tool_output_array.append({"tool_call_id": tool_call_id, "output": output})

return client.beta.threads.runs.submit_tool_outputs(
thread_id=thread_id,
run_id=run_id,
tool_outputs=tool_output_array
)

如上所示,如果智能体已推理出应该触发函数调用,我们会提取给定的必需函数参数并传回可运行线程。我们捕获此状态并按如下方式调用函数:

if run.status == 'requires_action':
run = submit_tool_outputs(thread.id, run.id, run.required_action.submit_tool_outputs.tool_calls)
run = wait_for_run_completion(thread.id, run.id)

搞定!我们现在拥有了一个可运行的OpenAI智能体,能够利用实时在线信息回答金融问题。以下是完整的可执行代码:

import os
import json
import time
from openai import OpenAI
from tavily import TavilyClient

# Initialize clients with API keys
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])

assistant_prompt_instruction = """You are a finance expert.
Your goal is to provide answers based on information from the internet.
You must use the provided Tavily search API function to find relevant online information.
You should never use your own knowledge to answer questions.
Please include relevant url sources in the end of your answers.
"""

# Function to perform a Tavily search
def tavily_search(query):
search_result = tavily_client.get_search_context(query, search_depth="advanced", max_tokens=8000)
return search_result

# Function to wait for a run to complete
def wait_for_run_completion(thread_id, run_id):
while True:
time.sleep(1)
run = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run_id)
print(f"Current run status: {run.status}")
if run.status in ['completed', 'failed', 'requires_action']:
return run

# Function to handle tool output submission
def submit_tool_outputs(thread_id, run_id, tools_to_call):
tool_output_array = []
for tool in tools_to_call:
output = None
tool_call_id = tool.id
function_name = tool.function.name
function_args = tool.function.arguments

if function_name == "tavily_search":
output = tavily_search(query=json.loads(function_args)["query"])

if output:
tool_output_array.append({"tool_call_id": tool_call_id, "output": output})

return client.beta.threads.runs.submit_tool_outputs(
thread_id=thread_id,
run_id=run_id,
tool_outputs=tool_output_array
)

# Function to print messages from a thread
def print_messages_from_thread(thread_id):
messages = client.beta.threads.messages.list(thread_id=thread_id)
for msg in messages:
print(f"{msg.role}: {msg.content[0].text.value}")

# Create an assistant
assistant = client.beta.assistants.create(
instructions=assistant_prompt_instruction,
model="gpt-4-1106-preview",
tools=[{
"type": "function",
"function": {
"name": "tavily_search",
"description": "Get information on recent events from the web.",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "The search query to use. For example: 'Latest news on Nvidia stock performance'"},
},
"required": ["query"]
}
}
}]
)
assistant_id = assistant.id
print(f"Assistant ID: {assistant_id}")

# Create a thread
thread = client.beta.threads.create()
print(f"Thread: {thread}")

# Ongoing conversation loop
while True:
user_input = input("You: ")
if user_input.lower() == 'exit':
break

# Create a message
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content=user_input,
)

# Create a run
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant_id,
)
print(f"Run ID: {run.id}")

# Wait for run to complete
run = wait_for_run_completion(thread.id, run.id)

if run.status == 'failed':
print(run.error)
continue
elif run.status == 'requires_action':
run = submit_tool_outputs(thread.id, run.id, run.required_action.submit_tool_outputs.tool_calls)
run = wait_for_run_completion(thread.id, run.id)

# Print messages from the thread
print_messages_from_thread(thread.id)

助手可以通过使用额外的检索信息、OpenAI的代码解释器等进一步定制和改进。此外,您还可以添加更多功能工具,使助手更加智能。

如果您有任何其他问题,欢迎在下方留言!

我们如何构建GPT Researcher

· 7 min read
Assaf Elovic
Creator @ GPT Researcher and Tavily

AutoGPT发布后,我们立即进行了试用。首先想到的应用场景就是自主在线研究。对于人工研究任务来说,形成客观结论可能需要花费时间,有时甚至需要数周来寻找合适的资源和信息。看到AutoGPT如此出色地创建和执行任务,让我开始思考利用AI进行全面研究的巨大潜力,以及这对未来在线研究意味着什么。

但AutoGPT的问题是它通常会陷入无限循环,几乎每一步都需要人工干预,不断丢失进度跟踪,几乎从未真正完成任务。

尽管如此,在研究任务期间收集的信息和上下文丢失了(例如跟踪来源),有时还会产生幻觉。

出于对利用AI进行在线研究的热情以及我所发现的局限性,我踏上了一个使命:尝试解决这些问题,同时与世界分享我的工作。就在那时,我创建了GPT Researcher——一个用于在线全面研究的开源自主智能体。

在本文中,我们将分享引导我找到所提出解决方案的步骤。

从无限循环到确定性结果的转变

解决这些问题的第一步是寻求一种更具确定性的解决方案,最终保证在固定时间范围内完成任何研究任务,无需人工干预。

就在那时,我们偶然发现了近期发表的论文Plan and Solve。该论文旨在为上述挑战提供更好的解决方案。其思路相当简单,包含两个组成部分:首先制定计划将整个任务分解为较小的子任务,然后按照计划执行这些子任务。

Planner-Excutor-Model

在研究过程中,首先创建与任务相关的研究问题大纲,然后确定性地为每个大纲项执行一个智能体。这种方法通过将智能体步骤分解为确定性的有限任务集,消除了任务完成的不确定性。当所有任务完成后,智能体将结束研究。

遵循这一策略已将研究任务的完成可靠性提升至100%。现在的挑战在于,如何提高质量和速度?

追求客观公正的结果

The biggest challenge with LLMs is the lack of factuality and unbiased responses caused by hallucinations and out-of-date training sets (GPT is currently trained on datasets from 2021). But the irony is that for research tasks, it is crucial to optimize for these exact two criteria: factuality and bias.

为了应对这些挑战,我们做出了以下假设:

  • 大数定律 — 内容越多,结果偏差越小。特别是在正确收集的情况下。
  • 利用LLM进行事实信息摘要可以显著提高结果的整体事实准确性。

经过对大型语言模型(LLM)的长期实验后,我们可以得出结论:基础模型最擅长的领域在于对给定内容的总结和重写。因此从理论上说,如果LLM仅对给定内容进行审阅、总结和重写,将能显著减少幻觉现象的产生。

此外,假设给定内容是无偏见的,或者至少包含一个话题各方的观点和信息,那么改写后的结果也将是无偏见的。那么内容如何才能做到无偏见呢?大数定律。换句话说,如果抓取足够多包含相关信息的网站,偏见信息的可能性就会大大降低。因此,思路是抓取足够多的网站,从而对任何话题形成客观的看法。

太好了!听起来目前我们已经有了如何生成确定性、事实性且无偏见结果的思路。但速度问题怎么解决呢?

加速研究进程

AutoGPT的另一个问题是它以同步方式工作。其主要理念是创建一系列任务然后逐个执行。因此,假设一个研究任务需要访问20个网站,每个网站大约需要一分钟来抓取和总结,那么整个研究任务至少需要20分钟以上。这还是假设它最终会停止的情况下。但如果我们可以并行化智能体的工作呢?

通过利用asyncio等Python库,智能体任务已优化为并行工作,从而显著缩短研究时间。

# Create a list to hold the coroutine agent tasks
tasks = [async_browse(url, query, self.websocket) for url in await new_search_urls]

# Gather the results as they become available
responses = await asyncio.gather(*tasks, return_exceptions=True)

在上面的示例中,我们并行触发了所有URL的抓取操作,仅当所有操作完成后才继续执行任务。根据多次测试,平均研究任务耗时约三分钟(!!)。这比AutoGPT快了85%。

完成研究报告

最终,在尽可能多地收集关于给定研究任务的信息后,面临的挑战是撰写一份全面的报告。

在尝试了多个OpenAI模型甚至开源模型后,我得出结论:目前使用GPT-4能获得最佳效果。任务很简单——将所有汇总信息作为上下文提供给GPT-4,并要求它根据原始研究任务撰写详细报告。

提示内容如下:

"{research_summary}" Using the above information, answer the following question or topic: "{question}" in a detailed report — The report should focus on the answer to the question, should be well structured, informative, in depth, with facts and numbers if available, a minimum of 1,200 words and with markdown syntax and apa format. Write all source urls at the end of the report in apa format. You should write your report only based on the given information and nothing else.

结果相当令人印象深刻,只有极少数样本存在轻微幻觉,但可以合理预期随着GPT的持续改进,效果只会越来越好。

最终架构

既然我们已经回顾了GPT Researcher的必要步骤,现在让我们分解最终的架构,如下所示:

更具体地说:

  • 针对任何给定任务生成研究问题的大纲,以形成客观意见。
  • 针对每个研究问题,触发一个爬虫智能体,该智能体会从在线资源中抓取与给定任务相关的信息。
  • 对于每个抓取的资源,仅当其包含相关信息时才进行跟踪、过滤和总结。
  • 最后,汇总所有摘要来源并生成最终研究报告。

展望未来

在线研究自动化的未来正面临重大变革。随着人工智能技术的持续进步,AI智能体能够为我们日常需求执行全面研究任务只是时间问题。AI研究将颠覆金融、法律、学术、医疗和零售等领域,在日益增长的在线信息洪流中,将每次研究时间减少95%,同时优化事实性和无偏见的报告。

想象一下,如果AI最终能够理解和分析任何形式的在线内容——视频、图像、图表、表格、评论、文本、音频。再想象一下,如果它能在单个提示中支持并分析数十万字的聚合信息。甚至设想AI最终能在推理和分析方面不断进步,使其更适合得出新颖创新的研究结论。而它能在几分钟内(如果不是几秒钟的话)完成所有这些工作。

这一切都取决于时间,而这正是GPT Researcher的核心所在。