GPT Researcher 日志体系全解析:读懂 research 过程的 events、用户日志与开发者日志
GPT Researcher 日志体系全解析读懂 research 过程的 events、用户日志与开发者日志【免费下载链接】gpt-researcherAn autonomous agent that conducts deep research on any data using any LLM providers项目地址: https://gitcode.com/GitHub_Trending/gp/gpt-researcher导读gpt-researcher 在每次研究任务中都会沉淀三类日志——面向终端用户的 JSON 事件日志、面向开发者的.log文本日志与.json结构化日志。本文以仓库文档docs/docs/gpt-researcher/handling-logs/all-about-logs.md为骨架结合 logging_config.py、server_utils.py、actions/utils.py 等源码逐一拆解日志文件的存放位置、JSON 事件结构、26 类事件语义、日志的排障/透明化/复现价值以及面向开发者的日志类型与真实调用链帮助读者在排障、性能分析与流程追溯中准确使用这套日志体系。一、日志体系总览一份研究任务会产生哪些日志gpt-researcher 的日志体系分为用户日志User Logs与开发者日志Developer Logs两大阵营二者定位完全不同维度用户日志User Logs开发者日志Developer Logs存放位置outputs目录logs目录文件格式JSON.json带缩进、易读.log文本 .json结构化面向对象使用 Web 界面的终端用户开发者、调试者内容特征含 emoji 与通俗描述覆盖事件流、图片、来源、报告全文技术细节无 emoji、无简化语言聚焦子查询与数据量获取方式outputs目录内直接查看或报告页点击 Download Logs 按钮运行目录下的logs文件夹用户日志的文件名格式为task_{时间戳}_{任务哈希}.json。从 server_utils.py 的sanitize_filename实现可以看到任务哈希是任务文本的 MD5 前 10 位配合int(time.time())时间戳确保每次研究任务生成的日志文件名唯一且不含特殊字符便于在outputs目录中按任务定位。开发者日志的命名遵循research_{YYYYMMDD_HHMMSS}.log与research_{YYYYMMDD_HHMMSS}.json时间戳精确到秒同一时刻启动的.log与.json一一对应见 logging_config.py 的setup_research_logging。需要特别说明用户日志是增量实时写入的。Web 服务启动时会在 app.py 中os.makedirs(outputs, exist_okTrue)并挂载/outputs静态目录每次研究任务开始时CustomLogsHandler会先写入一个空的 JSON 骨架含timestamp、events、content三部分随后每产生一个事件就重写一次文件server_utils.py。这意味着研究进行中打开该 JSON 文件就能看到实时推进的事件流。二、用户日志 JSON 结构深度拆解用户日志是一个 JSON 文件包含一次研究任务中发生的所有事件events的列表。顶层结构如下{ timestamp: 2026-09-09T19:22:26.123456, events: [], content: { query: , sources: [], context: [], report: , costs: 0.0 } }这一骨架由 server_utils.py 初始化写入五个content字段在事件流推进过程中会被逐步填充query记录研究主问题sources记录被采纳的来源 URL 列表context记录最终聚合的研究上下文report存放生成的报告文本costs记录研究总成本。2.1 顶层字段说明timestamp格式为YYYY-MM-DDTHH:MM:SS.ffffff即 ISO 8601 格式。顶层timestamp表示日志文件本身的生成时间而events数组中每个事件各自的timestamp表示该事件实际发生的时间二者含义不同用于还原研究全程的时间线。events包含该研究任务所有已记录事件的数组每个事件对象结构如下{ timestamp: 2026-09-09T19:22:26.456789, type: event, data: { type: logs, content: scraping_content, output: Scraped 12 pages of content, metadata: null } }2.2 事件对象Event Object字段字段说明timestamp事件发生的具体时间ISO 格式用于按顺序追踪动作序列type目前恒为event是事件类型的占位标记data.type事件的广义类型目前主要为logsdata.content工具正在做什么的描述符例如starting_research、running_subquery_research、scraping_contentdata.output更详细的消息通常包含 emoji 等可视化指示会实时推送给用户data.metadata事件的附加数据可为null或包含相关信息数组如 URL 列表、子查询列表2.3 事件写入的源码依据事件对象由CustomLogsHandler.send_json在收到type logs的数据时追加写入其余类型如query、sources、report则更新到content区块server_utils.py。而事件数据的源头来自研究流程中的stream_output调用。其签名与核心逻辑见 actions/utils.pyasync def stream_output( type, content, output, websocketNone, output_logTrue, metadataNone ): if (not websocket or output_log) and type ! images: logger.info(f{output}) if websocket: await websocket.send_json( {type: type, content: content, output: output, metadata: metadata} )从源码可以推断当websocket被传入CustomLogsHandler实例时send_json会同时完成两件事——把数据实时推送给前端 WebSocket 显示并把type logs的事件落盘到outputs下的用户日志文件。这正是事件日志 前端实时进度条 可下载 JSON 日志双通道共享同一数据源的设计。三、26 类事件类型全解content 字段语义以下是文档中列出的全部content类型。按研究流程的阶段分组解读括号内为对应output/metadata行为3.1 研究启动与代理选择阶段content 值含义output / metadatastarting_research研究流程对给定任务正式启动output包含研究查询的完整文本agent_generated指示本次任务使用了哪个代理agentoutput显示代理名称planning_research工具先浏览以理解请求范围并开始规划output提示正在浏览或进行初始规划源码佐证在 researcher.py 中这三个事件在conduct_research阶段被依次发出starting_research携带用户查询原文agent_generated携带代理名称planning_research则由_plan_research_outline中get_search_results前后两次触发首次为Browsing the web...随后为Planning the research strategy...。3.2 子查询生成与执行阶段content 值含义output / metadatasubqueries工具已生成将用于研究的子查询output列出全部子查询metadata为子查询字符串数组running_subquery_research正在执行某个特定子查询的研究output显示正在运行的子查询源码佐证子查询生成后stream_output(logs, subqueries, ..., True, sub_queries)会把子查询列表同时写入output与metadataresearcher.py随后对每个子查询调用_get_context_by_subquery并在其中发出running_subquery_research事件researcher.py。3.3 来源采集与抓取阶段content 值含义output / metadataadded_source_url某 URL 被识别为相关信息来源output带勾选 emoji 的 URLmetadata包含实际添加的 URLresearching工具正在跨多个来源积极检索信息output为通用提示消息scraping_urls开始从一组 URL 抓取内容output提示将要抓取的 URL 数量scraping_content成功从 URL 抓取内容output显示成功抓取的页面数scraping_images抓取过程中识别并选择了图片output显示新选图片数与图片总数metadata为所选图片 URL 数组scraping_complete对 URL 的抓取过程已完成output提示抓取完成源码佐证added_source_url在_get_context_by_subquery中筛选出新 URL 后触发metadata携带该 URLresearcher.pyscraping_urls、scraping_content则由抓取函数在 browser.py 中发出scraping_content的 output 中即包含len(scraped_content)抓取成功页数。值得注意的是scraping_images事件与stream_output中type ! images的条件相互配合——图片数据不会写入控制台日志但仍会通过 WebSocket 推送并在用户日志中留下记录。3.4 上下文构建阶段content 值含义output / metadatafetching_query_content正在基于特定查询获取内容output显示正在获取内容的查询subquery_context_window为给定子查询创建上下文窗口辅助更细致的研究output提示子查询上下文窗口已创建research_step_finalized某一步骤的研究部分已定稿output提示研究完成并附研究总成本relevant_contents_context为相关内容创建了上下文窗口output提示相关内容上下文窗口已创建源码佐证research_step_finalized的 output 会附带 Total Research Costs: $xxx的成本信息researcher.py说明该事件同时承担了阶段成本汇报的功能。3.5 报告撰写阶段content 值含义output / metadatagenerating_subtopics/subtopics_generated生成/已完成生成报告子主题output分别提示生成中/已完成writing_introduction/introduction_written开始/完成撰写报告引言output分别提示开始/完成generating_draft_sections/draft_sections_generated开始/完成生成报告草稿章节output分别提示生成中/已完成fetching_relevant_written_content正在获取与报告相关的已写内容output提示正在获取相关内容writing_report/report_written开始/完成将研究编译为报告output分别提示生成已开始/已结束writing_conclusion/conclusion_written开始/完成撰写报告结论output分别提示撰写中/已完成源码佐证writing_report事件在 writer.py 中由write_report触发携带用户查询文本而在 agent.py 中报告撰写前后还会通过_log_event(research, stepwriting_report / report_completed, ...)记录existing_headers、context_source、available_images_count以及报告长度、嵌入图片数等开发者侧指标。3.6 用事件流还原一次完整研究结合时间戳上述事件按如下顺序串联出完整的研究流水线starting_research → agent_generated → planning_research → subqueries → (对每个子查询) running_subquery_research → added_source_url → scraping_urls → scraping_content → scraping_images → scraping_complete → subquery_context_window → research_step_finalized → generating_subtopics → subtopics_generated → writing_introduction → introduction_written → generating_draft_sections → draft_sections_generated → fetching_relevant_written_content → relevant_contents_context → writing_report → report_written → writing_conclusion → conclusion_written四、日志的四大实战用途文档明确了用户日志的四种核心用途对应不同角色与场景故障排查Troubleshooting当研究结果不符合预期时日志能帮你还原工具执行的确切步骤——用了哪些查询、访问了哪些来源、报告是如何生成的快速定位跑偏环节。过程透明Transparency日志完整记录了访问过的 URL、选中的图片、报告构建方式让每次研究行为可审计。流程理解Understanding the Process日志提供了工具整体工作流及各步骤形态的概览是新人理解 gpt-researcher 研究管线最直接的素材。可复现性Reproducibility通过时间戳与事件序列用户可以精确追溯整个研究过程复现同样的问题设定与来源路径。从 AccessReport.tsx 可确认前端报告结果页确实提供了 Download Logs 按钮aDownload Logs/a点击即可下载本次研究对应的用户日志 JSON 文件。五、开发者日志.log与.json双格式除了面向用户的日志文件应用还会为开发者生成两类日志均位于logs目录。其初始化逻辑集中在setup_research_logginglogging_config.py5.1 基础日志文件.log格式纯文本每行一条日志条目。内容毫秒级精度的时间戳日志级别通常为INFO复杂部署中可能包含DEBUG、WARNING、ERROR模块名如research各类流程的描述性消息覆盖研究任务开始与结束、正在执行的 Web 搜索、研究规划、生成的子查询及其结果、抓取数据的大小、子查询找到的内容大小、最终聚合的全部上下文大小。开发者用途实时监控随时观察工具活动调试通过操作的时间顺序与收集内容的体量定位问题性能分析利用时间戳量化特定操作的耗时识别瓶颈高层概览快速查看工具执行了哪些步骤及采集内容的规模。与用户日志的关键区别结构更松散适合开发者实时查看包含非开发用户通常不需要的技术信息没有 emoji 和简化语言不包含图片采集信息。源码佐证.log文件由logging.FileHandler写入格式化模板为%(asctime)s - %(name)s - %(levelname)s - %(message)s并同时挂载控制台StreamHandler实现文件 终端双输出research_logger.propagate False防止向根日志器重复传播logging_config.py。研究过程中的业务埋点通过logger.info或_log_event中的兜底research_logger.info(...)agent.py写入。5.2 JSON 日志文件.json格式结构化 JSON。内容与所有日志文件一致的时间戳type字段取值包括sub_query包含子查询字符串与scraped_data_size抓取数据大小content_found包含sub_query与content_size找到的内容大小content字段给出整体研究的快照可包含该任务研究得到的最终上下文与来源。开发者用途详细分析查看工具运行的细节尤其是子查询与其研究结果过程理解查看运行了哪些子查询、每个子查询生成了多少内容助力调试与理解数据检查审阅生成的查询与内容大小。与用户日志的关键区别高度结构化、聚焦子查询执行及其结果特别是采集信息的体量不包含简化语言、emoji 或高层解释不包含整体上下文与图片信息主要关注子查询过程。源码佐证JSONResearchHandler在初始化时即构建{timestamp, events, content}骨架log_event将事件追加到events数组并调用_save_json落盘update_content则更新content区logging_config.py。get_json_handler通过getattr(logging.getLogger(research), json_handler, None)获取处理器logging_config.py供研究者模块在子查询完成后记录scraped_data_size与content_size等体量指标。六、日志读取与解析速查结合测试验证仓库的测试用例 test_logging.py 直接验证了用户日志的写入契约可作为解析日志时的官方参考handler CustomLogsHandler(mock_websocket, test_query) test_data {type: logs, message: Test log message} await handler.send_json(test_data) # 读取日志文件验证 with open(handler.log_file, r) as f: log_data json.load(f) assert len(log_data[events]) 1 assert log_data[events][0][data] test_data测试同时验证了content更新行为当发送非logs类型数据如query、sources、report时会更新log_data[content]对应字段test_logging.py。据此可以总结出解析规则events数组 时间线遍历其中事件按data.content分类统计各阶段执行情况content区块 结果快照直接读取query、sources、context、report、costs获取研究成果按时间戳排序 流程还原将events[].timestamp按序排列即可复现研究步骤与耗时。七、日志体系常见问题与最佳实践7.1 找不到outputs/logs目录outputs与logs目录均在运行时按需创建outputs由 Web 服务启动时的os.makedirs(outputs, exist_okTrue)及CustomLogsHandler初始化创建server_utils.pylogs由setup_research_logging中的Path(logs).mkdir(exist_okTrue)创建logging_config.py。二者均为相对当前运行目录创建因此日志文件会出现在启动服务/运行脚本时的工作目录下。7.2 何时选择用户日志 vs 开发者日志排查研究结论为什么与预期不符、追溯访问了哪些 URL、确认图片选择情况 → 用outputs下的用户日志或报告页 Download Logs量化子查询抓取/内容体量、分析阶段耗时瓶颈、查看原始技术细节 → 用logs目录下的开发者日志.log看时序与级别.json看体量指标。7.3 实时监控技巧Web 界面研究过程中stream_output会同时把事件推送到前端并写入用户日志因此研究未结束时打开outputs下的 JSON 文件即可看到实时事件流开发者.log文件为追加写入FileHandler默认模式配合tail -f即可实时观察INFO/WARNING/ERROR级别的流程输出。7.4 关于文档与版本演进的提示文档明确提示随着新功能开发报告与事件类型可能随版本演进而变化。因此本文的事件清单26 类content以当前仓库源码为准在旧版本或未来版本中若遇到未收录的事件名应优先以日志中实际的data.content值和该版本源码中的stream_output调用点为准进行解读。八、小结gpt-researcher 的日志体系用一份用户日志 两份开发者日志覆盖了研究流程的可观测性需求用户日志outputs以 JSON 事件流的形式把从starting_research到conclusion_written的全过程透明化兼顾前端实时展示与事后下载追溯是排查研究为什么这样做的一手证据开发者日志logs以.log文本与.json结构化两种形态提供毫秒级时间戳、日志级别、模块名与子查询数据体量指标服务于实时监控、调试与性能分析事件流、content快照与测试契约test_logging.py共同构成了可靠的解析基础让研究者既能还原完整时间线也能一键获取最终查询、来源、上下文、报告与成本。理解这套日志体系后无论你是想排查一次失败的研究、分析某类报告类型的时间开销还是想复现某次调研的完整来源链都能在日志中快速找到答案。【免费下载链接】gpt-researcherAn autonomous agent that conducts deep research on any data using any LLM providers项目地址: https://gitcode.com/GitHub_Trending/gp/gpt-researcher创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考