
/** * 执行标准的 RAG 检索评估修正为 Macro-Precision */ public EvaluationResult evaluate() { int k 5; int totalQueries goldTestSet.size(); // 统计变量用于 Macro 平均 double sumPrecision 0.0; // 每个问题独立计算出的精确率之和 double sumRecall 0.0; // double sumMrr 0.0; int hitQueries 0; // 全局统计仅用于参考 int totalRelevantDocsInSystem 0; int totalRetrievedRelevantDocs 0; for (TestQuery testQuery : goldTestSet) { // 获取当前问题的标准相关文档集合 SetString relevantDocIds testQuery.getRelevantDocIds(); totalRelevantDocsInSystem relevantDocIds.size(); // 执行检索 // retrievedDocs 查询到的关联文档列表 ListDocument retrievedDocs retrieveTopK(testQuery.question, k); // retrievedDocIds 关联文档id ListString retrievedDocIds retrievedDocs.stream() .map(doc - doc.getId()) .collect(Collectors.toList()); // 1. 计算当前查询的命中匹配数 long matchedCount retrievedDocIds.stream() .filter(relevantDocIds::contains) .count(); // totalRetrievedRelevantDocs 全部的命中匹配数 totalRetrievedRelevantDocs matchedCount; // 2. 计算当前查询的 Precision (Macro 累加) double precisionPerQuery (double) matchedCount / k; // 单个问题的精确率 sumPrecision precisionPerQuery; // 3. 计算当前查询的 Recall (Macro 累加) // 注意如果相关文档总量为0该查询无意义通常跳过或记0 double recallPerQuery relevantDocIds.isEmpty() ? 0 : (double) matchedCount / relevantDocIds.size(); sumRecall recallPerQuery; // 4. 计算 MRR OptionalInt firstMatchIndex IntStream.range(0, retrievedDocIds.size()) .filter(i - relevantDocIds.contains(retrievedDocIds.get(i))) .findFirst(); if (firstMatchIndex.isPresent()) { sumMrr 1.0 / (firstMatchIndex.getAsInt() 1); hitQueries; // 命中 } } // 计算最终指标宏平均 Macro Average double macroPrecisionAtK sumPrecision / totalQueries; // TopK 的平均精确率 每个问题独立计算出的精确率之和 / 问题总数 double macroRecallAtK sumRecall / totalQueries; // TopK 的平均召回率 每个问题召回率之和 / 问题总数 double mrr sumMrr / totalQueries; // TopK 的平均倒数排名 每个问题第一个相关文档排名的倒数之和 / 问题总数 double hitRate (double) hitQueries / totalQueries; // TopK 的平均命中率 每个问题的命中率之和 / 问题总数 // 微平均指标作为辅助参考不用于决策 // double microPrecision (double) totalRetrievedRelevantDocs / (totalQueries * k); // double microRecall (double) totalRetrievedRelevantDocs / totalRelevantDocsInSystem; System.out.println( 核心指标宏平均 ); System.out.println(PrecisionK: macroPrecisionAtK); System.out.println(RecallK: macroRecallAtK); System.out.println(MRR: mrr); System.out.println(Hit Rate: hitRate); return new EvaluationResult(macroPrecisionAtK, macroRecallAtK, mrr, hitRate); }