using JiebaNet.Analyser;
using JiebaNet.Segmenter;
namespace Service.AI;
///
/// 文本分词服务接口
///
public interface ITextSegmentService
{
///
/// 从文本中提取关键词
///
/// 待分析的文本
/// 返回前N个关键词,默认5个
/// 关键词列表
List ExtractKeywords(string text, int topN = 5);
///
/// 对文本进行分词
///
/// 待分词的文本
/// 分词结果列表
List Segment(string text);
}
///
/// 基于 JiebaNet 的文本分词服务实现
///
public class TextSegmentService : ITextSegmentService
{
private readonly JiebaSegmenter _segmenter;
private readonly TfidfExtractor _extractor;
private readonly ILogger _logger;
public TextSegmentService(ILogger logger)
{
_logger = logger;
_segmenter = new JiebaSegmenter();
_extractor = new TfidfExtractor();
// 仅添加JiebaNet词典中可能缺失的特定业务词汇
AddCustomWords();
}
///
/// 添加自定义词典 - 仅添加JiebaNet词典中可能缺失的特定词汇
///
private void AddCustomWords()
{
try
{
// 只添加可能缺失的特定业务词汇
// 大部分常用词(如"美团"、"支付宝"等)JiebaNet已内置
var customWords = new[]
{
"水电费", "物业费", "燃气费" // 复合词,确保作为整体识别 // TODO 做成配置文件 让 AI定期提取复合词汇填入到这边
};
foreach (var word in customWords)
{
_segmenter.AddWord(word);
}
if (customWords.Length > 0)
{
_logger.LogDebug("已加载 {Count} 个自定义词汇", customWords.Length);
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "添加自定义词典失败");
}
}
public List ExtractKeywords(string text, int topN = 5)
{
if (string.IsNullOrWhiteSpace(text))
{
return [];
}
try
{
// 使用 TF-IDF 算法提取关键词(已内置停用词过滤)
var keywords = _extractor.ExtractTags(text, topN, new List());
// 过滤单字,保留有意义的词
var filteredKeywords = keywords
.Where(k => k.Length >= 2)
.Distinct()
.ToList();
// 如果过滤后没有关键词,使用基础分词并选择最长的词
if (filteredKeywords.Count == 0)
{
var segments = Segment(text);
filteredKeywords = segments
.Where(s => s.Length >= 2)
.OrderByDescending(s => s.Length)
.Take(topN)
.Distinct()
.ToList();
}
// 如果还是没有,返回原文的前10个字符
if (filteredKeywords.Count == 0 && text.Length > 0)
{
filteredKeywords.Add(text.Length > 10 ? text.Substring(0, 10) : text);
}
_logger.LogDebug("从文本 '{Text}' 中提取关键词: {Keywords}",
text, string.Join(", ", filteredKeywords));
return filteredKeywords;
}
catch (Exception ex)
{
_logger.LogError(ex, "提取关键词失败,文本: {Text}", text);
// 降级处理:返回原文
return [text.Length > 10 ? text.Substring(0, 10) : text];
}
}
public List Segment(string text)
{
if (string.IsNullOrWhiteSpace(text))
{
return [];
}
try
{
// 执行分词
var segments = _segmenter.Cut(text).ToList();
// 过滤空白和停用词
var filteredSegments = segments
.Where(s => !string.IsNullOrWhiteSpace(s) && s.Trim().Length > 0)
.Select(s => s.Trim())
.ToList();
return filteredSegments;
}
catch (Exception ex)
{
_logger.LogError(ex, "分词失败,文本: {Text}", text);
return [text];
}
}
}