跳到主要内容

05 · 深入:精华、边界、对比

这一章是「带走的东西」:哪些设计值得抄、它刻意不做什么、会在哪崩、和别的深度研究实现比有什么不同。

5.1 巧妙之处(可借鉴)

① 滚动摘要 = 用状态当记忆,省上下文。 摘要节点只读最新一轮资料(web_research_results[-1],graph.py:284),历史全部沉淀进 running_summary。这样上下文长度不随轮数线性膨胀——本地小模型上下文窗口小,这个设计是刚需。妙在它把「记忆压缩」外包给了 LLM 自己(每轮重写摘要)。

② 不确定性收口到一个函数。 所有「模型可能不听话」的处理都锁在 generate_search_query_with_structured_output(graph.py:44),每条失败路都通向同一个兜底查询。上层图逻辑因此可以假装结构化输出永远成功。参见 03 章

③ 搜索后端多态。 四个后端被抹平成同一结果形状(见 04 章),web_research 里只是 if/elif 选一个,下游完全无感。加第五个后端只需写一个返回统一形状的函数。

④ 配置三级优先级。 Configuration.from_runnable_config(configuration.py:63-81)按「环境变量 > UI 传入的 configurable > 类默认值」取值:对每个字段先读 os.environ.get(name.upper()),拿不到再退到 configurable,最后是 Field 默认。一行 dict 推导 + 过滤 None 就实现了(configuration.py:73-79)。这让同一份图既能用 .env 部署、又能在 Studio 里现场调参。

5.2 边界与局限(诚实)

每轮只有一条线性查询,没有并行分支。 尽管 README 说灵感来自 IterDRAG 的「子问题分解」,实现上并没有真的把问题拆成多个子问题并行检索——每一轮就一条 search_query,串行推进(见 01 章的数据流)。所以它是「迭代加深」,不是「树状展开」。

没有对搜索结果做相关性排序或质量过滤。 搜到什么就喂什么(仅按 URL 去重),来源好坏全靠搜索引擎和 LLM 的判断力。

兜底会静默降级。 结构化输出失败时退回 Tell me more about {topic}(graph.py:186),这一轮就变成泛泛搜索,且不会告知用户发生了降级。小模型上这可能悄悄拉低质量。

Tavily 每轮只取 1 条结果(graph.py:217,硬编码),来源覆盖面比其他后端窄。

循环次数比直觉多一次。 max_web_research_loops=3 实际搜 4 次(route_research<= + 先搜后计数,见 01 章 §1.4)。

摘要质量强依赖本地模型。 整个「读—写—反思」都压在一个本地 LLM 上;小模型可能反思出低质量的追问,或摘要时丢关键信息。README 自己就点名 R1 1.5B/7B 有 JSON 困难(README.md:151)。

无持久化/无缓存。 没有 checkpointer、不缓存搜索结果,每次从头跑;graph = builder.compile()(graph.py:465)未传 checkpointer。

5.3 横向对比

把它放到「深度研究 agent」这一类里看,它的定位是最小、最本地的那一端:

维度Local Deep Researcher典型「重型」深度研究 agent
编排LangGraph 固定 5 节点状态机常见多 agent / 动态规划
查询结构每轮单条线性查询常并行拆多个子问题
模型本地 Ollama/LMStudio多为云端大模型
记忆单段滚动摘要常有向量库/多文档存储
代码量7 个文件,可一晚读完通常大得多

它的价值不在「最强」,而在「最好懂、可完全本地、可当深度研究骨架的教学样板」。README 也提到有一个 TypeScript 移植版(README.md:190)。

同 shelf 可对照阅读: 本 shelf(ai-agent-reference / deep-research)下其他深度研究实现,重点看它们如何处理「查询分解是单条还是多路」「记忆用摘要还是向量库」「是否有反思环」这三点差异——本项目在这三点上都选了最简形态。

5.4 总代码地图(全项目导航)

你想看文件符号
整张图怎么连、循环判停src/ollama_deep_researcher/graph.pybuilder / route_research
共享状态与累加字段src/ollama_deep_researcher/state.pySummaryState
生成查询 / 反思节点src/ollama_deep_researcher/graph.pygenerate_query / reflect_on_summary
滚动摘要节点src/ollama_deep_researcher/graph.pysummarize_sources
收尾去重src/ollama_deep_researcher/graph.pyfinalize_summary
结构化输出兜底src/ollama_deep_researcher/graph.pygenerate_search_query_with_structured_output
LLM 装配(4 种)src/ollama_deep_researcher/graph.pyget_llm
LMStudio 适配src/ollama_deep_researcher/lmstudio.pyChatLMStudio
搜索后端 + 去重格式化src/ollama_deep_researcher/utils.pyduckduckgo_search / deduplicate_and_format_sources
剥离推理标记src/ollama_deep_researcher/utils.pystrip_thinking_tokens
配置与三级优先级src/ollama_deep_researcher/configuration.pyConfiguration / from_runnable_config
五段提示词 + 两套结构化指令src/ollama_deep_researcher/prompts.pyquery_writer_instructions
Studio 入口注册langgraph.jsongraphs.ollama_deep_researcher