|
@@ -146,7 +146,7 @@ public class RetrieverService {
|
|
|
return "drug_query";
|
|
return "drug_query";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /** 检索主入口:2025 优先,2025 结果不足时降级到全部版本(含 2020 补充) */
|
|
|
|
|
|
|
+ /** 检索:仅 2025 年版药典,AI 兜底补充 */
|
|
|
public List<Map<String, Object>> search(String query, String intent, int topK) {
|
|
public List<Map<String, Object>> search(String query, String intent, int topK) {
|
|
|
List<Float> vec = embedWithCache(query);
|
|
List<Float> vec = embedWithCache(query);
|
|
|
String vecStr = vec.stream()
|
|
String vecStr = vec.stream()
|
|
@@ -154,22 +154,7 @@ public class RetrieverService {
|
|
|
.collect(Collectors.joining(",", "[", "]"));
|
|
.collect(Collectors.joining(",", "[", "]"));
|
|
|
|
|
|
|
|
String drugName = extractDrugName(query);
|
|
String drugName = extractDrugName(query);
|
|
|
-
|
|
|
|
|
- // ============================================================
|
|
|
|
|
- // 第一轮:限定 2025 年版
|
|
|
|
|
- // ============================================================
|
|
|
|
|
- List<Map<String, Object>> results = searchWithVersion(vecStr, drugName, "2025年版", topK);
|
|
|
|
|
-
|
|
|
|
|
- // ============================================================
|
|
|
|
|
- // 如果 2025 结果不足(<3 条 或 最高相似度 <0.4),降级到全部版本
|
|
|
|
|
- // ============================================================
|
|
|
|
|
- if (results.size() < 3 || maxSimilarity(results) < 0.4) {
|
|
|
|
|
- List<Map<String, Object>> fallback = searchWithVersion(vecStr, drugName, null, topK);
|
|
|
|
|
- // 合并:2025 结果排在前面,2020 补充排在后面,去重
|
|
|
|
|
- results = mergeResults(results, fallback, topK);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return results;
|
|
|
|
|
|
|
+ return searchWithVersion(vecStr, drugName, "2025年版", topK);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 带版本过滤的向量检索。version 为 null 时不限制版本。 */
|
|
/** 带版本过滤的向量检索。version 为 null 时不限制版本。 */
|
|
@@ -227,34 +212,6 @@ public class RetrieverService {
|
|
|
return jdbc.queryForList(sql, params);
|
|
return jdbc.queryForList(sql, params);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /** 合并两轮结果:2025 在前,去重,不超过 topK */
|
|
|
|
|
- private List<Map<String, Object>> mergeResults(
|
|
|
|
|
- List<Map<String, Object>> first, List<Map<String, Object>> second, int topK) {
|
|
|
|
|
- Set<String> seen = new HashSet<>();
|
|
|
|
|
- List<Map<String, Object>> merged = new ArrayList<>();
|
|
|
|
|
-
|
|
|
|
|
- for (Map<String, Object> r : first) {
|
|
|
|
|
- String key = (String) r.getOrDefault("drug_id", "") + "|" + r.getOrDefault("section", "");
|
|
|
|
|
- if (seen.add(key)) merged.add(r);
|
|
|
|
|
- }
|
|
|
|
|
- for (Map<String, Object> r : second) {
|
|
|
|
|
- String key = (String) r.getOrDefault("drug_id", "") + "|" + r.getOrDefault("section", "");
|
|
|
|
|
- if (seen.add(key)) merged.add(r);
|
|
|
|
|
- }
|
|
|
|
|
- return merged.subList(0, Math.min(topK, merged.size()));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private double maxSimilarity(List<Map<String, Object>> results) {
|
|
|
|
|
- return results.stream()
|
|
|
|
|
- .mapToDouble(r -> toDouble(r.get("similarity")))
|
|
|
|
|
- .max().orElse(0.0);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private double toDouble(Object o) {
|
|
|
|
|
- if (o instanceof Number n) return n.doubleValue();
|
|
|
|
|
- return 0.0;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
// 剂型后缀(长后缀优先,避免"缓释胶囊"被错误截断为"缓释")
|
|
// 剂型后缀(长后缀优先,避免"缓释胶囊"被错误截断为"缓释")
|
|
|
private static final List<String> FORMULATION_SUFFIXES = List.of(
|
|
private static final List<String> FORMULATION_SUFFIXES = List.of(
|
|
|
"缓释胶囊", "缓释片", "肠溶胶囊", "肠溶片", "分散片", "咀嚼片",
|
|
"缓释胶囊", "缓释片", "肠溶胶囊", "肠溶片", "分散片", "咀嚼片",
|