local-deep-research 死代码归档分析:PR #3205 中 entity-aware 策略与问题生成器的删除决策及其设计遗产
【免费下载链接】local-deep-research~95% on SimpleQA (e.g. Qwen3.6-27B on a 3090). Supports all local and cloud LLMs (llama.cpp, Ollama, Google, ...). 10+ search engines - arXiv, PubMed, your private documents. Everything Local & Encrypted.项目地址: https://gitcode.com/GitHub_Trending/lo/local-deep-research
这篇技术归档解读围绕 local-deep-research 仓库中 pr-3205-entity-aware.md 展开,它记录了 PR #3205 如何删除两个零可达组件 ——EntityAwareSourceStrategy与EntityAwareQuestionGenerator,并保留其中值得复用、但未被验证过的设计想法。读完本文,你将理解该仓库"删除死代码"的决策方法论(可达性分析、后继组件识别、恢复路径设计),掌握 17 关键词实体分类器与朴素大写词 NER 的缺陷教训,并能在未来需要实体识别型搜索时,直接沿用文档沉淀的 prompt 模板与恢复建议,而无需重走弯路。
一、背景:这篇归档文档在仓库中的位置与作用
local-deep-research 在src/local_deep_research/advanced_search_system/下长期演化出大量搜索策略(strategies)与问题生成器(question generators)。当 PR 删除其中任意.py文件时,一个名为require-strategy-deletion-docs的 pre-commit 钩子(见 require-strategy-deletion-docs.py)会强制开发者在本目录新增或更新归档说明。归档目录的规则由 docs/strategies/deleted/README.md 定义:
- 目的:git 已保存删除前的代码与历史,归档文档的职责是解释"被删组件的新颖之处与删除原因"—— 这是
git blame无法重建的散文信息; - 命名:每个删除 PR 一个文件,格式
pr-<number>-<short-slug>.md,如pr-3205-entity-aware.md; - 结构:若一个 PR 删除多个组件,按
## Component:一节一个组件组织。
PR #3205 恰好属于"一个 PR 删除两个组件"的情况:EntityAwareSourceStrategy(实体感知搜索策略)与EntityAwareQuestionGenerator(实体感知问题生成器)。两者的共同命运是:在删除时点都已不可达—— 前者未注册进search_system_factory.py,后者唯一的调用方就是前者,因此删掉策略后问题生成器自然成了孤儿。
二、Component 1:EntityAwareSourceStrategy的解剖
2.1 基本档案
| 维度 | 内容 |
|---|---|
| 删除文件 | src/local_deep_research/advanced_search_system/strategies/entity_aware_source_strategy.py |
| 删除时规模 | 139 行 |
| 可达性 | 未出现在search_system_factory.py;未从 strategies/init.py 导出;仅被自身纯逻辑测试与STRATEGY_IMPORTS引用 |
| 删除时最近的可达后继者 | BrowseCompEntityStrategy(factory key"browsecomp-entity"),面向约束驱动的实体研究 |
| 纯字符串实体 ID 查询的回退路径 | SourceBasedSearchStrategy+StandardQuestionGenerator或BrowseCompQuestionGenerator |
验证当前仓库可见:strategies/__init__.py目前仅导出BaseSearchStrategy、FocusedIterationStrategy、SourceBasedSearchStrategy三个类,印证了归档文档对"未从__init__导出"的判断;当前strategies/目录清单中也已不存在entity_aware_source_strategy.py。值得注意的是,文档所说的后继者browsecomp_entity_strategy.py在当前strategies/目录中同样已不存留(根据同目录下的 pr-remove-experimental-search-strategies.md 记载,这批实验策略后来也被清理),但 search_system.py 第 115 行仍保留"browsecomp-entity"策略键的语义说明("Entity-focused search for BrowseComp questions with knowledge graph building"),可作为追溯该能力设计的线索。
2.2 删除前版本中有价值的想法(已记录,未验证)
归档文档特别保留了两条"思想遗产",明确提示后人不要盲目复刻,但可作为未来实现参考:
(1)17 关键词实体查询分类器
策略及其问题生成器在判断"查询是否在找实体"时,采用了一个朴素规则:只要小写化后的查询中出现下列 17 个关键词中的任意一个,即判定为实体查询:
who / what / which / identify / name / character / person / place organization / company / author / scientist / inventor / city country / book / movie文档明确指出该方案的硬伤:实践中误报率很高——who、what、which会命中绝大多数研究类查询,导致几乎任何问题都会被误判为实体查询。它的价值定位是"如果有人日后构建真正的分类器,这份关键词表可以作为起点",而非可直接投产的成品。
(2)朴素大写词 NER
_format_search_results_as_context方法把每个长度大于 2 的大写词首 token当作候选实体,并截取 ±2 词的上下文窗口作为实体描述。该文件自身的 TODO 注释就已标注这是 placeholder(占位实现)。归档文档记录它的教训是:这种启发式会误匹配章节标题、句首单词、标题大小写格式的杂项内容,属于"有人试过且被证明不充分"的捷径。
2.3 为什么删除是安全的
归档文档给出的结论是:零用户可达路径 + 零算法新颖性。该策略相对其父类SourceBasedSearchStrategy只增加了两件事 —— 一次问题生成器替换(把标准生成器换成EntityAwareQuestionGenerator)和上文那套朴素 NER —— 没有引入任何新的搜索算法或提示工程。真正有技术含量的提示工程部分在问题生成器里(见第三节),策略本身只是个 139 行的薄包装。
2.4 值得注意的接口缺口
归档文档记录了一个"删除后留下"的能力空白:BrowseCompEntityStrategy要求调用方预先构造好Constraint对象;而EntityAwareSourceStrategy是当时唯一(虽然不可达)接受纯字符串实体 ID 查询的路径。也就是说,"用户直接输入一个实体 ID 字符串"的用例在生产环境中从未被服务过。文档对此的结论是:这不是回滚的理由,而是一个未来功能需求—— 如果它重要,应当作为新特性提出,而非恢复旧代码。
2.5 恢复路径(Recovery Path)
归档文档给出的官方恢复建议非常明确:
不要恢复这 139 行的包装类。
如果纯字符串实体 ID 查询确实重要,正确做法是:
- 编写一个辅助函数,从自由文本查询中提取
Constraint对象(复用现成的ConstraintAnalyzer,见 constraint_analyzer.py); - 将提取结果路由到
BrowseCompEntityStrategy。
这条建议与仓库现状高度吻合 ——ConstraintAnalyzer至今仍是约束分析的核心实现,说明"复用约束提取器 + 路由到约束驱动策略"的路径在当前架构下依然成立。
三、Component 2:EntityAwareQuestionGenerator的解剖
3.1 基本档案
| 维度 | 内容 |
|---|---|
| 删除文件 | src/local_deep_research/advanced_search_system/questions/entity_aware_question.py |
| 删除时规模 | 178 行 |
| 可达性 | 唯一消费者是EntityAwareSourceStrategy;策略删除后成为孤儿;同时从 questions/init.py 的__all__中移除 |
| 删除时最近的可达后继者 | BrowseCompQuestionGenerator(browsecomp_question.py) |
与策略不同,问题生成器承载了真正的提示工程价值。当前 questions/init.py 仍导出BrowseCompQuestionGenerator,其类文档(browsecomp_question.py 第 14-23 行)明确描述其设计要点:提取具体实体(日期、数字、人名、地点)、生成渐进式搜索组合、先宽后窄、聚焦可验证事实 —— 这正是归档文档所说"以算法方式覆盖实体组合查询"的后继能力。
3.2 删除前版本中有价值的两条遗产
(1)多约束引号搜索的 prompt 模板
generate_questions与generate_sub_questions是整个代码库中仅有的两个显式教模型"把多个标识约束组合进单个引号搜索"的 prompt,并附带一个具体的完整示例 —— 一个虚构的、活跃于 1960s-1980s、会打破第四面墙的电视角色。归档文档的评价是:如果你日后需要为实体 ID 查询写 prompt,应从这两个模板出发而非重新发明,它们是合理的初版("reasonable first cut"),只是从未被验证过。
(2)复活时必须规避的陷阱
generate_questions存在一个致命回退逻辑:当 17 关键词门控未命中时,它直接返回空列表,这会彻底中断非实体查询的后续研究流程。归档文档明确警告:复活该生成器时绝不能重新引入这个空列表回退。
3.3 为什么删除是安全的
原因非常直接:EntityAwareSourceStrategy被删除后,该生成器没有任何剩余消费者。删除它不会影响任何可达代码路径。
3.4 恢复路径
如果这套 prompt 工程日后被证明有价值,官方建议是子类化BrowseCompQuestionGenerator(或为其添加可选模式),而不是恢复一个平行的生成器类;同时务必去掉空列表回退。
四、从仓库源码印证归档结论
以上所有结论都可以在当前仓库中找到直接证据:
- 可达性结论:
strategies/__init__.py与questions/__init__.py的导出清单中均无被删组件;strategies/目录与questions/目录下也没有entity_aware_*.py文件 —— 与文档"删除后无残留"一致; - 后继者存在性:
SourceBasedSearchStrategy(source_based_strategy.py)、StandardQuestionGenerator(standard_question.py)、BrowseCompQuestionGenerator均在仓库中正常存在,构成实体类查询的回退与替代路径; - 约束提取能力:
ConstraintAnalyzer(constraint_analyzer.py)作为文档建议复用的核心组件持续在库,支撑"从自由文本提取约束"的恢复方案; - 删除纪律:docs/strategies/deleted/README.md 与 require-strategy-deletion-docs.py 共同构成制度保障,确保任何删除
advanced_search_system/下组件的提交都必须留下这种"新颖性说明",让今天的分析对未来的维护者有据可查。
五、总结:这次删除给我们的决策清单
PR #3205 的归档记录浓缩了 local-deep-research 处理死代码的一套可复用决策流程:
- 先做可达性分析:是否被工厂注册、是否被
__init__.py导出、是否被其他组件或测试引用 —— 三条都查过才敢动刀; - 判断是否有算法新颖性:纯包装、无新逻辑的组件可以安全删除(策略本身),有价值的部分要单独识别并归档(prompt 模板);
- 记录接口缺口:删除后是否留下能力空白(纯字符串实体 ID 查询),若空白已长期无人服务,则视为"未来特性"而非"回滚理由";
- 给出明确恢复路径:不恢复旧类,而是复用
ConstraintAnalyzer提取约束后路由到BrowseCompEntityStrategy,或子类化BrowseCompQuestionGenerator; - 标注已知陷阱:17 关键词分类器的高误报、朴素大写词 NER 的占位性质、空列表回退会中断后续研究 —— 这些教训随归档文档一同保留,防止后人重蹈覆辙。
对于想要在 local-deep-research 上扩展实体感知搜索能力的开发者,这份归档就是最好的起点:保留遗产、规避陷阱、按官方恢复路径在ConstraintAnalyzer+BrowseCompEntityStrategy的方向上构建新能力,而不是回到 139 行 + 178 行的旧实现。
【免费下载链接】local-deep-research~95% on SimpleQA (e.g. Qwen3.6-27B on a 3090). Supports all local and cloud LLMs (llama.cpp, Ollama, Google, ...). 10+ search engines - arXiv, PubMed, your private documents. Everything Local & Encrypted.项目地址: https://gitcode.com/GitHub_Trending/lo/local-deep-research
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考