RAG 检索结果的排序与过滤相似度最高的不一定是最有用的一、检索结果排序的常见误区是只按相似度降序排列RAG 检索的默认排序方式是按向量相似度从高到低排列。相似度最高的分块排在第一位依次递减。这种排序的逻辑是最相似的应该最相关。但在生活数据场景下这个逻辑不完全成立。相似度衡量的是向量方向的接近程度。两段文本描述了相似的概念向量就接近。但相似的概念不一定是最有用的信息。用户搜索上周心情不好的原因相似度最高的分块可能是最近一次心情不好的日记因为它和查询的情感描述最匹配但真正有用的答案可能是上周日记中提到的具体事件比如工作压力增加、睡眠变差——这段文本的相似度可能低于情感描述分块但它才是用户想找到的信息。排序应该结合相似度、时间权重和内容类型权重。最近的记录时间权重高事件描述内容类型权重高。相似度只是排序的一个维度而非唯一维度。二、多维度排序的权重组合策略检索结果的排序应该由相似度权重、时间权重和内容类型权重三者组合决定。flowchart TD A[检索结果初始列表] -- B[维度权重计算] B -- C[相似度权重向量距离归一化到0-1] B -- D[时间权重越近的记录权重越高] B -- E[内容类型权重事件描述情感总结日常流水] C -- F[加权求和0.4*相似度0.3*时间0.3*类型] D -- F E -- F F -- G[按综合权重排序] G -- H[取前5条结果]权重比例需要根据具体场景调整。日记检索时时间权重更重要用户通常想找特定时间段的内容技术文档检索时类型权重更重要用户想找具体参数而非泛泛描述。固定权重比例只适合特定场景不同数据类型应该有不同的权重配置。三、多维度排序的实现type SearchResult { content: string; score: number; // 向量相似度分数 timestamp: string; // 记录时间 contentType: string; // 内容类型标签 metadata: Recordstring, unknown; }; type SortWeights { similarity: number; // 相似度权重 recency: number; // 时间权重 contentType: number; // 内容类型权重 }; // 不同数据类型的权重配置 const defaultWeights: Recordstring, SortWeights { diary: { similarity: 0.4, recency: 0.35, contentType: 0.25 }, technical: { similarity: 0.5, recency: 0.1, contentType: 0.4 }, chat: { similarity: 0.3, recency: 0.5, contentType: 0.2 }, }; export function sortSearchResults( results: SearchResult[], dataType: string, queryTime?: string ): SearchResult[] { const weights defaultWeights[dataType] ?? defaultWeights.diary; const scored results.map((result) { const simNorm normalizeSimilarity(result.score); const recNorm normalizeRecency(result.timestamp, queryTime ?? new Date().toISOString()); const typeNorm normalizeContentType(result.contentType); // 加权求和综合排序分数 const composite weights.similarity * simNorm weights.recency * recNorm weights.contentType * typeNorm; return { result, compositeScore: composite }; }); scored.sort((a, b) b.compositeScore - a.compositeScore); return scored.map((s) s.result).slice(0, 5); } function normalizeSimilarity(rawScore: number): number { // 归一化到0-1假设原始分数范围在0.5-1.0之间 return Math.max(0, Math.min(1, (rawScore - 0.5) / 0.5)); } function normalizeRecency(timestamp: string, queryTime: string): number { // 越近的记录分数越高7天内满分30天外接近零分 const daysDiff (Date.now() - new Date(timestamp).getTime()) / (86400000); if (daysDiff 7) return 1; if (daysDiff 30) return 1 - (daysDiff - 7) / 23; return 0.1; } function normalizeContentType(type: string): number { // 内容类型权重事件描述最高流水最低 const typeWeights: Recordstring, number { event: 1.0, insight: 0.8, emotion: 0.6, routine: 0.3, }; return typeWeights[type] ?? 0.5; }归一化函数是关键细节。相似度、时间和类型三个维度的原始分数范围不同直接加权求和会导致某个维度主导排序。归一化后所有维度都在0-1范围内权重才能真正控制各维度的贡献比例。四、排序策略不能替代检索质量优化多维度排序是检索结果的二次优化不能替代检索质量的根本提升。如果初始检索结果里就没有包含有用信息的分块排序再优化也无济于事。排序的另一个限制是权重比例需要持续调整。不同用户对时间权重和类型权重的偏好不同。有人习惯看最近的内容有人习惯看最相关的。产品应该允许用户调整权重偏好而不是强制使用默认比例。但这增加了配置复杂度需要在灵活性和简洁性之间权衡。结果数量也要控制。取前5条结果比取前10条更实用。5条结果足够覆盖不同维度的最优候选10条结果里后面5条的边际价值很低。少展示结果还能让每条结果的位置更突出用户更容易注意到不同类型的信息。五、总结RAG 检索结果排序应结合相似度、时间和内容类型三个维度。日记检索时间权重高技术文档类型权重高聊天记录时间权重最高。三个维度归一化到0-1范围后加权求和权重比例根据数据类型配置。取前5条结果而非前10条减少低边际价值的展示。权重比例可允许用户微调但默认配置应覆盖大多数场景。