实用提示:Dartboard RAG——当Top-K返回同一内容的三个版本时
《实用笔记》操作指南:Dartboard RAG——当Top-K返回同一内容的三个版本时,适用于采用该模式的团队的契约、校验机制及可直接插入的代码片段。
以下笔记为解决“Dartboard RAG:Top-K返回同一片段的三个版本”这一问题提供了实用路径。重点在于契约定义、校验机制以及可直接插入的代码占位符,而非动机性阐述。
重复上下文问题
在处理重复上下文问题阶段时,首先明确契约要求:所需输入、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续代码修改的规范性。 在功能结果旁记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。 在调整提示词之前,先使用固定问题集测试召回率。频繁更换提示词往往无法改善较差的检索效果。
Top 3:
1. "Greenhouse gases trap heat in the atmosphere, causing warming..." (sim 0.91)
2. "Atmospheric greenhouse gases are the primary driver of climate change..." (sim 0.89)
3. "The trapping of heat by greenhouse gases leads to rising temperatures..." (sim 0.88)
Dartboard类比
在处理“飞镖靶类比”阶段时,首先写下契约:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 将配置信息置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放,这样操作人员无需查看整个系统结构即可进行审计。 在调整提示词之前,先使用固定的问题集来衡量召回率。仅仅更换提示词往往无法解决检索效果不佳的问题。
Chunks plotted by relevance to query
(closer to center = higher cosine sim)
●●● ← cluster of near-duplicate chunks
●●● (all about "greenhouse gases")
● bull's-eye = QUERY
● ← chunk about deforestation
(relevant but different topic)
● ● ← chunks about agriculture, ocean carbon
● ● ← chunks about historical climate
STANDARD TOP-3 picks: DARTBOARD TOP-3 picks:
3 closest darts 1 closest, then darts that are also
= 3 darts in the same good but spread across the board
spot near bull's-eye = better coverage of relevant content
处理流程
在处理流程阶段时,首先写下相关契约:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及死信处理都是产品本身的组成部分,而非后续需要补充的功能。 在调整提示词之前,先使用固定的问题集来衡量检索的覆盖率。仅仅更换提示词很难解决检索效果不佳的问题。
第一步 — 使用 FAISS 进行过度检索
在执行“按阶段过度获取”这一第一步时,首先需明确相关约定:所需的输入参数、成功信号,以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 相较于庞大的脚本,应优先选择小型且可测试的单元。当某一步骤失败时,故障应指向单一的责任模块,而非复杂的流程链。 在调整提示词之前,需先使用固定的问题集来评估召回率。仅仅更换提示词往往无法解决检索效果不佳的问题。
fetch_k = self.k * self.oversampling # default: 5 × 3 = 15
candidates = vector_store.search(query_embedding, k=fetch_k)
第二步 — 计算距离矩阵
在处理“步骤2:计算距离”阶段时,首先需明确相关约定:所需输入、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改始终符合约定。 将此阶段视为输入与验证后输出之间的契约。为相关产物命名,定义成功检测标准,杜绝无声的半完成状态。 在调整提示词之前,先使用固定的问题集来衡量召回率。仅仅更换提示词往往无法改善较差的检索效果。 在处理“步骤2:计算距离”阶段时,首先需明确相关约定:所需输入、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改始终符合约定。 将配置信息置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放于一处,以便操作人员无需查看整个系统结构即可进行审计。
# Normalize all vectors so dot product = cosine similarity
query_norm = query_vec / np.linalg.norm(query_vec)
cand_norm = candidate_matrix / np.linalg.norm(candidate_matrix, axis=1, keepdims=True)
# Distance = 1 - cosine_similarity
query_distances = 1.0 - np.dot(query_norm, cand_norm.T) # (1, N)
document_distances = 1.0 - np.dot(cand_norm, cand_norm.T) # (N, N)
第3步 — 转换为对数正态概率
将第3步的“转换”流程视为可测量的表面来处理效果最佳。在扩大范围之前,先记录一个成功的测试用例、一个失败案例以及回滚说明。同时记录正常流程和恢复流程的文档。重试机制、人工审核环节以及死信处理都是产品本身的一部分,而非后续需要补充的内容。应将分块策略与检索策略分开,当质量指标发生变化时,修改其中一项不应强制要求重新编写另一项。
def lognorm(dist, sigma):
return -np.log(sigma) - 0.5 * np.log(2 * np.pi) - dist**2 / (2 * sigma**2)
第4步 — 贪心选择循环
第4步:贪婪阶段若被视为可度量的对象,效果最佳。在扩大范围之前,先记录一个成功的案例、一个失败案例以及回滚说明。 优先选择小型且可测试的单元,而非庞大的脚本。当某一步骤失败时,故障应指向单一责任点,而非复杂的流程链。 将分块策略与检索策略分开。当质量指标发生变化时,修改其中一项不应迫使重新编写另一项。
# Step 1: pick most relevant first
most_relevant_idx = np.argmax(query_probs)
selected_indices = [most_relevant_idx]
max_distances = doc_probs[most_relevant_idx].copy() # diversity tracker
# Step 2-6: iteratively add diverse + relevant chunks
while len(selected_indices) < num_results:
# For each candidate, compute "diversity from any selected"
updated_distances = np.maximum(max_distances, doc_probs)
# Combine relevance + diversity
combined = (diversity_weight * updated_distances
+ relevance_weight * query_probs[np.newaxis, :])
# Aggregate per candidate (logsumexp for numerical stability)
normalized = logsumexp(combined, axis=1)
# Mask already-selected
for idx in selected_indices:
normalized[idx] = -np.inf
# Pick the best
best_idx = np.argmax(normalized)
max_distances = updated_distances[best_idx]
selected_indices.append(best_idx)
数学模型究竟在做什么(直观理解)
“数学是什么”阶段若被视为可度量的对象,效果最佳。在扩大范围之前,需记录一份理想案例、一个失败案例以及回滚说明。 将此阶段视为输入与已验证输出之间的契约。为相关成果命名,明确成功标准,杜绝默许的半完成状态。 将分块策略与检索策略分开。当质量指标发生变化时,修改其中一项不应强制重新编写另一项。 “数学是什么”阶段若被视为可度量的对象,效果最佳。在扩大范围之前,需记录一份理想案例、一个失败案例以及回滚说明。 将配置置于应用程序代码之外。环境文件、密钥存储及功能开关应集中存放于一处,以便操作人员无需查看整个系统结构即可进行审计。
Relevance →
Low ●◯
● ● ← Standard top-k picks these 3
(highest relevance, regardless of diversity)
● ●
●●●●●● ● ● ● ← Many similar high-relevance chunks
High (cluster)
Diversity ↓
from
selected
↓
↓ ↓ ← Dartboard picks 1 from cluster,
then far-away ones with high relevance still
权重——各权重的作用
在修改代码之前,需明确每个阶段的权重、输入内容、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 需同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及错误处理都是产品本身的组成部分,而非后续需要补充的功能。 必须引用实际作为答案依据的段落。如果没有引用,操作人员就无法区分是幻觉内容还是索引缺失导致的错误。
relevance_weight = 1.0 # how much we care about chunks being close to query
diversity_weight = 1.0 # how much we care about chunks being different from each other
一个实际案例:重复语料库测试
对于经过验证的示例,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。相比冗长的脚本,更应采用小型且可测试的单元。当某个步骤失败时,故障原因应能指向单一责任主体,而非复杂的流程链。必须引用实际作为答案依据的段落;没有引用的话,操作人员就无法区分是虚假信息还是索引缺失所致。
1. "Greenhouse gases cause warming..." (sim 0.91)
2. "Greenhouse gases cause warming..." (sim 0.91) ← DUPLICATE
3. "Greenhouse gases cause warming..." (sim 0.91) ← DUPLICATE
4. "Greenhouse gases cause warming..." (sim 0.91) ← DUPLICATE
5. "Greenhouse gases cause warming..." (sim 0.91) ← DUPLICATE
Unique results: 1/5
1. "Greenhouse gases cause warming..." (highest relevance — wins first pick)
2. "Deforestation reduces the carbon sink..." (different chunk, still relevant)
3. "Industrial agriculture emits methane..." (third unique cause)
4. "Land-use changes alter surface albedo..." (fourth unique cause)
5. "Fossil fuel combustion is the largest CO₂ source..." (related to #1 but different angle)
Unique results: 5/5
几句话概括核心要点
对于“阶段核心”而言,在修改代码之前需明确输入参数、该步骤的负责人以及完成标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 应将此阶段视为输入与已验证输出之间的契约。为相关成果命名,定义成功判定标准,并拒绝默许的半完成状态。 必须引用实际作为答案依据的段落。没有引用的话,操作人员就无法区分幻觉内容与索引缺失的问题。
def dartboard_select(query_emb, candidate_embs, k=5, sigma=0.1):
# 1. Compute distance matrices
query_dist = 1 - cosine(query_emb, candidate_embs) # query→each
doc_dist = 1 - cosine(candidate_embs, candidate_embs) # each→each
# 2. Convert distances to log-probabilities
query_probs = lognorm(query_dist, sigma)
doc_probs = lognorm(doc_dist, sigma)
# 3. Pick most relevant first
selected = [np.argmax(query_probs)]
max_distances = doc_probs[selected[0]].copy()
# 4. Iteratively add diverse + relevant
while len(selected) < k:
updated = np.maximum(max_distances, doc_probs)
combined = updated + query_probs[np.newaxis, :] # equal weights = sum
scores = logsumexp(combined, axis=1)
for idx in selected:
scores[idx] = -np.inf # don't re-select
best = np.argmax(scores)
max_distances = updated[best]
selected.append(best)
return selected
对于“舞台上的精髓”这一概念,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 配置应置于应用程序代码之外。环境文件、密钥存储以及功能标志都应放在一个操作人员可以审核的位置,无需阅读整个流程图。
可调整的参数
在处理各个控件时,可以先写下契约:所需的输入参数、成功信号以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持一致性。 同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及死信处理都是产品本身的组成部分,而非后续需要补充的功能。 在调整提示词之前,先使用固定的问题集来衡量检索效果。仅仅更换提示词很难解决检索能力不足的问题。
这种方法的适用场景与局限性
在处理“该功能在何处获得执行阶段”这一问题时,首先需写下相关契约:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 相较于庞大的脚本,应优先选择小型且可测试的单元。当某个步骤失败时,故障应指向单一责任模块,而非复杂的流程链。 在调整提示词之前,先使用固定的问题集来衡量召回率。仅仅更换提示词很难解决检索效果不佳的问题。
值得牢记的核心理念
在处理“更有价值的整体思路”阶段时,首先要写明契约:所需的输入、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持透明。 将这一阶段视为输入与经过验证的输出之间的契约。为相关成果命名,明确成功检测标准,杜绝默许的部分完成情况。 在调整提示词之前,先使用固定的问题集来测试召回率。仅仅更换提示词很难解决检索效果不佳的问题。 在处理“更有价值的整体思路”阶段时,首先要写明契约:所需的输入、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持透明。 将配置信息置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放,以便操作人员无需查看整个系统结构即可进行审计。
最后的思考
“最终思考”阶段若被视为可度量的对象,效果会更好。在扩大范围之前,先记录一个成功的案例、一个失败案例以及回滚说明。同时将正常流程与恢复流程都记录下来。重试机制、人工审核环节以及死信处理都是产品本身的组成部分,而非后续需要补充的内容。应将分块策略与检索策略分开,当质量指标发生变化时,修改其中一项不应迫使另一项也重新编写。
操作检查清单
在“操作检查清单”阶段,修改代码之前需明确输入内容、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新执行该步骤,而无需猜测隐藏的状态。应在功能结果旁记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在流程从演示环境转向共享环境时出现意外费用。
请注明支撑答案的具体段落。没有引用的话,操作人员无法区分是幻觉内容还是索引缺失导致的错误。
编写一份简短的操作手册:说明如何轮换密钥、如何清空队列、以及如何回滚上一次的导入操作。
将配置信息置于应用程序代码之外。环境文件、密钥存储和功能开关应集中存放于一个位置,这样操作人员无需查看整个系统结构即可进行审计。
请注明支撑答案的具体段落。没有引用的话,操作人员无法区分是幻觉内容还是索引缺失导致的错误。
在升级整个系统之前,先冻结现有版本,为关键流程保存一份标准操作记录,并确认好回滚步骤。共享环境需要设置速率限制、进行租户验证,同时明确密钥轮换的责任人。与其追求华丽的临时演示,不如注重扎实的可靠性。
关于 fd4991fea9d9 的批量处理说明:不要将提供者密钥放入代码仓库,为每个会话设置令牌上限,并将转录内容存储在评估测试用例的旁边,以便后续更换模型时仍能保持可比性。