在实施 DeepResearch 时,至少有两个地方需要生成多样化的查询。首先,你必须根据用户输入生成网络搜索查询(直接将用户输入扔进搜索引擎并不是一个好主意)。其次,许多 DeepResearch 系统包含一个 “研究计划器”,将原始问题分解为子问题,并发调用代理独立解决这些子问题,然后合并它们的结果。无论是处理查询还是子问题,我们的期望都保持不变:它们必须与原始输入相关,并且足够多样化,以提供独特的视角。通常,我们需要限制查询的数量,以避免在不必要地请求搜索引擎或使用代理的词元上浪费金钱。
虽然理解查询生成的重要性,但大多数开源 DeepResearch 实现并没有认真对待这种优化。它们只是直接提示这些约束。有些可能会要求 大模型 额外进行一轮评估并使查询多样化。以下是大多数实现方法的基本示例:

gemini-2.5-flash 作为 大模型,原始查询是 "embeddings and rerankers"。在本文中,我想演示一种更严格的方法,使用句子 向量模型 和次模优化来解决最佳查询生成问题。早在我的博士期间,次模优化就是我最喜欢的技术之一,与 L-BFGS 并列。我将展示如何应用它来生成一组在基数约束下的多样化查询,这可以显着提高 DeepResearch 系统的整体质量。
tag通过提示词生成查询
首先,我们想检查提示词是否是生成多样化查询的有效方法。我们还想了解复杂的提示词是否比简单的提示词更有效。让我们运行一个实验,比较以下两个提示词,以找出答案:
You are an expert at generating diverse search queries. Given any input topic, generate {num_queries} different search queries that explore various angles and aspects of the topic.简单提示词
You are an expert research strategist. Generate an optimal set of diverse search queries that maximizes information coverage while minimizing redundancy.
Task: Create exactly {num_queries} search queries from any given input that satisfy:
- Relevance: Each query must be semantically related to the original input
- Diversity: Each query should explore a unique facet with minimal overlap
- Coverage: Together, the queries should comprehensively address the topic
Process:
1. Decomposition: Break down the input into core concepts and dimensions
2. Perspective Mapping: Identify distinct angles (theoretical, practical, historical, comparative, etc.)
3. Query Formulation: Craft specific, searchable queries for each perspective
4. Diversity Check: Ensure minimal semantic overlap between queries结构化提示词
我们使用 gemini-2.5-flash 作为 大模型,原始查询为 "embeddings and rerankers",并测试简单和结构化提示词,以迭代生成从 1 到 20 个查询。然后,我们使用带有 text-matching 任务的 jina-embeddings-v3 来测量原始查询和生成的查询之间的句子相似度,以及生成的查询本身的相似度。以下是可视化结果。

查看右侧的两个图,可以看出简单和结构化的提示词都表现出余弦相似度得分的较大方差,许多达到 0.7-0.8 的相似度,表明某些生成的查询几乎相同。此外,随着生成更多查询,两种方法都难以保持多样性。我们没有看到相似度随着查询数量的增加而明显下降的趋势,而是观察到相对稳定(且较高)的相似度水平,表明额外的查询经常复制现有的视角。
一种解释是 Wang 等人 (2025) 发现 大模型 经常不成比例地反映主要群体的观点,即使使用提示词引导,也表明存在对常见视角的偏见。这是因为 大模型 的训练数据可能过度代表某些观点,导致模型生成与这些普遍观点一致的变体。Abe 等人 (2025) 还发现,基于 大模型 的查询扩展倾向于流行的解释,而忽略了其他解释。例如,“人工智能的好处是什么?” 可能会产生常见的益处,如自动化、效率、伦理,但会错过不太明显的益处,如药物发现。


tag问题公式化
有人可能认为我们之前的实验没有定论,我们应该改进提示词并再次尝试。虽然提示词肯定可以在某种程度上改变结果,但更重要的是我们已经学到了一些东西:简单地增加生成的查询数量使我们更有可能获得多样化的查询。坏消息是,我们也会得到一堆重复的查询作为副产品。
但是,既然生成大量查询很便宜,最终会产生一些好的查询,为什么我们不将其视为子集选择问题呢?
在数学中,我们可以这样描述这个问题:给定一个原始输入 ,一组由大模型使用提示词工程生成的候选查询 。选择一个子集 ,包含 个查询,以最大化覆盖范围并最小化冗余。
不幸的是,从 个候选项中找到 个查询的最佳子集需要检查 种组合,这是一个指数级的复杂度。仅仅对于 20 个候选和 来说,就有 15,504 种组合。
tag次模函数
在尝试暴力解决子集选择问题之前,让我向读者介绍一下次模性和次模函数这两个术语。对很多人来说,它们可能听起来很陌生,但你很可能听说过“收益递减”的概念——嗯,次模性就是对它的数学表示。
考虑在一个大型建筑物中放置 Wi-Fi 路由器以提供互联网覆盖。你安装的第一个路由器提供了巨大的价值——它覆盖了以前没有覆盖的很大一片区域。第二个路由器也增加了相当大的价值,但它的一些覆盖区域与第一个路由器重叠,因此边际效益低于第一个。当你继续添加路由器时,每个额外的路由器覆盖的新区域越来越少,因为大多数空间已经被现有路由器覆盖。最终,第 10 个路由器可能提供的额外覆盖范围非常小,因为建筑物已经被很好地覆盖了。
这种直觉抓住了次模性的本质。数学上,一个集合函数 是次模的,如果对于所有 和任何元素 :
用通俗易懂的语言来说:将一个元素添加到一个较小的集合所带来的好处,至少与将同一个元素添加到一个包含该较小集合的较大集合所带来的好处一样多。
现在让我们将这个概念应用于我们的查询生成问题。人们可能会立即意识到,查询选择表现出自然的收益递减:
- 我们选择的第一个查询覆盖了全新的语义空间
- 第二个查询应该覆盖不同的方面,但一些重叠是不可避免的
- 当我们添加更多查询时,每个额外的查询覆盖的新领域越来越少

tag基于向量模型的次模函数设计
设 是查询 的向量模型,使用句子向量模型(例如,jina-embeddings-v3)获得。设计目标函数主要有两种方法:
tag方法 1:设施选址(基于覆盖)
此函数衡量所选集合 对所有候选查询的“覆盖”程度,其中:
- 是余弦相似度
- 确保与原始查询的相关性
- 衡量所选集合 对候选 的覆盖程度
需要注意的是,此函数仅隐式地鼓励多样性。它不会明确地惩罚所选集合 内的相似性。多样性的出现是因为选择相似的查询会提供递减的覆盖回报。
tag方法 2:显式覆盖 + 多样性
为了更直接地控制多样性,我们可以将覆盖范围和显式多样性项结合起来:
其中,多样性分量可以表示为:
此多样性项衡量所选查询和未选择查询之间的总相似度——当我们选择与剩余候选查询不同的查询时,它会最大化(一种图割函数的形式)。
tag两种方法之间的区别
两种公式都保持了次模性。
设施选址函数是一个众所周知的次模函数。由于 max 运算,它表现出次模性:当我们向所选集合添加一个新查询 时,每个候选查询 都会被我们集合中的“最佳”查询(具有最高相似度的查询)覆盖。与添加到较大的集合 相比,将 添加到较小的集合 更有可能改善各种候选查询的覆盖范围,因为在较大的集合中,许多候选查询已经被很好地覆盖。
在图割多样性函数中,多样性项 是次模的,因为它衡量了所选集合和未选择集合之间的“割”。与添加到较大的所选集合相比,将新查询添加到较小的所选集合会创建更多与未选择查询的新连接。
设施选址方法依赖于通过覆盖竞争实现的隐式多样性,而显式方法直接衡量和优化多样性。因此,两者都是有效的,但显式方法使你可以更直接地控制相关性-多样性的权衡。
tag实现
完整的实现可以在 Github 上找到:
由于我们的函数是次模的,我们可以使用贪婪算法,该算法提供了 的近似保证:
这是优化设施选址(基于覆盖)的代码——具有隐式多样性的代码。
def greedy_query_selection(candidates, embeddings, original_embedding, k, alpha=0.3):
"""
用于次模查询选择的贪婪算法
Args:
candidates: 候选查询字符串列表
embeddings: 查询向量模型矩阵 (n x d)
original_embedding: 原始查询的向量模型 (d,)
k: 要选择的查询数
alpha: 相关性权重参数
"""
n = len(candidates)
selected = []
remaining = set(range(n))
# 预计算相关性得分
relevance_scores = cosine_similarity(original_embedding, embeddings)
for _ in range(k):
best_gain = -float('inf')
best_query = None
for i in remaining:
# 计算添加查询 i 的边际收益
gain = compute_marginal_gain(i, selected, embeddings,
relevance_scores, alpha)
if gain > best_gain:
best_gain = gain
best_query = i
if best_query is not None:
selected.append(best_query)
remaining.remove(best_query)
return [candidates[i] for i in selected]
def compute_marginal_gain(new_idx, selected, embeddings, relevance_scores, alpha):
"""计算将 new_idx 添加到所选集合的边际收益"""
if not selected:
# 第一个查询:收益是所有相关性得分的总和
return sum(max(alpha * relevance_scores[j],
cosine_similarity(embeddings[new_idx], embeddings[j]))
for j in range(len(embeddings)))
# 计算当前覆盖范围
current_coverage = [
max([alpha * relevance_scores[j]] +
[cosine_similarity(embeddings[s], embeddings[j]) for s in selected])
for j in range(len(embeddings))
]
# 计算添加附加查询后的新覆盖范围
new_coverage = [
max(current_coverage[j],
cosine_similarity(embeddings[new_idx], embeddings[j]))
for j in range(len(embeddings))
]
return sum(new_coverage) - sum(current_coverage)
平衡参数 控制相关性和多样性之间的权衡:
- 高 (例如,0.8):优先考虑与原始查询的相关性,可能会牺牲多样性
- 低 (例如,0.2):优先考虑所选查询之间的多样性,可能会偏离原始意图
- 中等 (例如,0.4-0.6):平衡的方法,通常在实践中效果很好
tag惰性贪婪算法
你可能会在上面的代码中注意到:
for i in remaining:
# 计算添加查询 i 的边际收益
gain = compute_marginal_gain(i, selected, embeddings,
relevance_scores, alpha)我们在每次迭代中计算所有剩余候选查询的边际收益。我们可以做得更好。
惰性贪婪算法是一种巧妙的优化,它利用次模性来避免不必要的计算。关键的见解是:如果在迭代 中元素 A 的边际收益高于元素 B,那么在迭代 中,A 的边际收益仍然高于 B(由于次模性)。
import heapq
def lazy_greedy_query_selection(candidates, embeddings, original_embedding, k, alpha=0.3):
"""
Lazy greedy algorithm for submodular query selection
More efficient than standard greedy by avoiding unnecessary marginal gain computations
"""
n = len(candidates)
selected = []
# Precompute relevance scores
relevance_scores = cosine_similarity(original_embedding, embeddings)
# Initialize priority queue: (-marginal_gain, last_updated, query_index)
# Use negative gain because heapq is a min-heap
pq = []
for i in range(n):
gain = compute_marginal_gain(i, [], embeddings, relevance_scores, alpha)
heapq.heappush(pq, (-gain, 0, i))
for iteration in range(k):
while True:
neg_gain, last_updated, best_idx = heapq.heappop(pq)
# If this gain was computed in current iteration, it's definitely the best
if last_updated == iteration:
selected.append(best_idx)
break
# Otherwise, recompute the marginal gain
current_gain = compute_marginal_gain(best_idx, selected, embeddings,
relevance_scores, alpha)
heapq.heappush(pq, (-current_gain, iteration, best_idx))
return [candidates[i] for i in selected]惰性贪婪算法的工作原理如下:
- 维护一个按边际收益排序的元素优先级队列
- 仅重新计算顶部元素的边际收益
- 如果在重新计算后它仍然是最高的,则选择它
- 否则,将其重新插入到正确的位置并检查下一个顶部元素
由于我们避免了重新计算明显不会被选中的元素的边际收益,因此这可以显著提高速度。
tag结果
让我们再次运行实验。我们使用相同的简单 提示词 生成 1 到 20 个不同的查询,并执行与之前相同的余弦相似度测量。对于子模优化,我们从 20 个生成的候选项中使用不同的 k 值选择查询,并像以前一样测量相似度。结果表明,通过子模优化选择的查询更加多样化,并且显示出更低的集合内相似度。

"embeddings and rerankers"
"generative ai"
"geopolitics USA and China"
"google 2025 revenue breakdown"tag最终问题:为什么子模公式很重要
您可能想知道:为什么还要费力地将其表述为子模优化问题呢?为什么不使用启发式或其他优化方法呢?
简而言之,子模公式将临时的“选择多样化查询”启发式转换为具有可证明的保证、高效的算法和可衡量的目标的严格优化问题。
tag保证效率
一旦我们证明了我们的目标函数是子模的,我们就可以获得强大的理论保证和高效的算法。与检查组合相比,在时间内运行的贪婪算法实现了对最优解的近似。这意味着我们的贪婪解始终至少与最佳可能解一样好 63%。没有启发式方法可以保证这一点。
此外,由于子模函数的数学结构,惰性贪婪算法在实践中要快得多。加速来自收益递减:在早期迭代中表现不佳的元素不太可能在以后成为好的选择。因此,惰性贪婪通常只需要重新计算前几个候选项的收益,而不是检查所有个候选项。
tag无需手工制作的启发式方法
如果没有一个有原则的框架,您可能会求助于诸如“确保查询的余弦相似度 < 0.7”或“平衡不同的关键字类别”之类的临时规则。这些规则很难调整并且不具有通用性。子模优化为您提供了一种有原则的、数学上可靠的方法。您可以使用验证集系统地调整超参数,并在生产系统中监控解决方案质量。当系统产生不良结果时,您可以获得明确的指标来调试出了什么问题。
最后,子模优化是一个经过深入研究的领域,拥有数十年的研究经验,允许您利用贪婪算法之外的高级算法(如加速贪婪或局部搜索),关于某些公式何时效果最佳的理论见解,以及处理额外约束(如预算限制或公平性要求)的扩展。

对于那些对子模优化感兴趣的人,我建议您访问此站点以了解更多信息。








