核心技术文档:轻量级语义加权检索算法 (L-SWA)
最近更新日期:2026-02-01 20:02:18
1. 算法背景
在不引入深度学习模型(Embedding)和向量数据库的情况下,本算法通过特征提取、语义扩张和多维评分三项核心技术,在本地端实现高度智能的文本召回。
2. 核心代码实现与逐行解析
以下是算法的核心方法 GetFilteredMemory 的完整代码及详细注释:
csharp
/// <summary>
/// 基于语义权重与近义词扩张的记忆检索算法
/// </summary>
/// <param name="allContents">数据库中的全量记忆数据</param>
/// <param name="userKeywords">从用户输入中提取的核心关键词</param>
/// <param name="topN">需要返回的结果数量</param>
public static List<tb_db_MemoryPalace_Content> GetFilteredMemory(
List<tb_db_MemoryPalace_Content> allContents,
List<string> userKeywords,
int topN)
{
// 【1. 容错处理】如果数据库为空,直接返回空列表,避免后续计算报错
if (allContents == null || allContents.Count == 0) return new List<tb_db_MemoryPalace_Content>();
// 【2. 构建查询字典】这是算法的“心脏”。Dictionary 提供 O(1) 的极速查找性能
// Key 为搜索词(原词或近义词),Value 为该词的权重衰减系数
var queryExpandMap = new Dictionary<string, double>(StringComparer.OrdinalIgnoreCase);
if (userKeywords != null)
{
foreach (var kw in userKeywords)
{
// 【3. 原词加权】原词是用户最直接的意图,权重系数设为 1.0 (不打折)
queryExpandMap[kw] = 1.0;
// 【4. 近义词自动扩张】调用辅助类获取该词的所有近义词
var syns = Utils_SynonymHelper.GetSynonyms(kw);
foreach (var syn in syns)
{
// 如果近义词不在字典中(避免覆盖原词),则将其加入
if (!queryExpandMap.ContainsKey(syn.Word))
{
// 【5. 权重衰减】近义词关联度稍低,赋予 0.8 的系数,确保排名在原词之后
queryExpandMap[syn.Word] = syn.WeightScale;
}
}
}
}
// 【6. 执行打分逻辑】利用 LINQ 的 Select 方法对数据库每一项进行评分映射
var scoredList = allContents.Select(item =>
{
double totalScore = 0; // 初始化该条数据的总得分
// --- 维度一:Triggers (强特征/标签匹配) ---
if (item.triggers != null && queryExpandMap.Count > 0)
{
foreach (var trig in item.triggers)
{
// 检查标签是否命中了用户的搜索词(含近义词)
if (queryExpandMap.TryGetValue(trig, out double scale))
{
// 【7. 标签加成】标签是人工设定的高价值特征,基础分给 15.0,极大拉开差距
totalScore += 15.0 * scale;
}
}
}
// --- 维度二:Content (语义特征/TF-IDF匹配) ---
if (!string.IsNullOrEmpty(item.content))
{
// 【8. TF-IDF 特征提取】利用 Jieba 提取内容中最重要的前 20 个词及其权重
var contentTags = Utils_SegmentText.ExtractKeywordsWithWeight(item.content, 20);
foreach (var tag in contentTags)
{
// 检查内容中的核心词是否出现在搜索意图字典中
if (queryExpandMap.TryGetValue(tag.Word, out double scale))
{
// 【9. 语义累加】得分 = 词自身的重要性(TF-IDF Weight) * 近义词衰减(Scale)
totalScore += tag.Weight * scale;
}
}
}
// 返回一个匿名对象,包含原始数据和最终计算出的总分
return new { Data = item, Score = totalScore };
}).ToList();
// 【10. 排序与保底输出】
// 优先级 1:Score 降序(最相关的排前面)
// 优先级 2:Weight 降序(相关度一样时,挑最优质的内容)
// Take(topN):即便所有项得分都是0,也会强行取前 N 个,实现“矮子里拔将军”
return [.. scoredList
.OrderByDescending(x => x.Score)
.ThenByDescending(x => x.Data.weight)
.Take(topN)
.Select(x => x.Data)];
}3. 技术原理解析
3.1 意图扩张 (Query Expansion)
传统搜索必须“字词完全一致”才能匹配。通过近义词库的引入,算法在搜索前将用户的单一词汇扩展为一个关联词簇。配合衰减权重系数(0.8),算法在拓宽搜索范围的同时,通过数学手段保护了检索的精准度。
3.2 特征降维 (TF-IDF Weighting)
通过 ExtractKeywordsWithWeight 接口,我们将一段长文本抽象为 20 个带有数值属性的点。这种处理方式模拟了向量模型中“特征提取”的过程,使得匹配不再是简单的“字符存在性”检测,而是“信息密度”的匹配。
3.3 启发式评分架构
算法采用了双轨评分机制:
- 强轨 (Triggers):解决“确定性”需求,适合标签过滤。
- 弱轨 (Content):解决“相关性”需求,适合语义模糊搜索。 两者通过加法融合,形成了最终的排序结果。