149 lines
8.2 KiB
C#
149 lines
8.2 KiB
C#
using CloudBuilder.Topshelf.Python;
|
||
using Microsoft.VisualBasic;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Reflection.Metadata;
|
||
using System.Runtime.Intrinsics.Arm;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace CloudBuilder.Topshelf.Task.Novel.Process
|
||
{
|
||
public class SpeakerFeatureLearner
|
||
{
|
||
private readonly List<SpeakerRule> _rules;
|
||
public SpeakerFeatureLearner()
|
||
{
|
||
_rules = new List<SpeakerRule>();
|
||
InitializeDefaultRules();
|
||
}
|
||
|
||
private void InitializeDefaultRules()
|
||
{
|
||
//AddRule("银月", "少妇");
|
||
}
|
||
public void AutoLearnFromText(string text)
|
||
{
|
||
|
||
}
|
||
public void AutoLearnFromText(string depRoot, List<NamedEntity> ners, List<List<MeaningRepresentationParsingEntity>> srls, List<HanlpConstituencyNode> cons)
|
||
{
|
||
|
||
|
||
if (ners == null || !ners.Where(x => x.Type.Trim().ToUpper().Contains("PERSON")).Any()) return;
|
||
|
||
HanlpConstituencyNode[] nodes;
|
||
HanlpConstituencyNode nodef;
|
||
string feature = null;
|
||
foreach (NamedEntity namedEntity in ners.Where(x => x.Type.Trim().ToUpper().Contains("PERSON")).ToArray())
|
||
{
|
||
nodes = HanlpResultHelper.GetNodeByLabel(cons, namedEntity.Text);
|
||
if (nodes == null || nodes.Length == 0) continue;
|
||
|
||
//如果存在,找到父节点上的NP
|
||
foreach (HanlpConstituencyNode node in nodes)
|
||
{
|
||
nodef = HanlpResultHelper.GetNodeTopLabelById(cons, node.FatherId, "NP");
|
||
if (nodef == null) continue;
|
||
feature = HanlpResultHelper.GetNodeBottomLabelById(cons, nodef.ItemId, "NP");
|
||
if (string.IsNullOrEmpty(feature)) continue;
|
||
if (namedEntity.Text == feature) continue;
|
||
|
||
AddRule(namedEntity.Text, feature);
|
||
}
|
||
}
|
||
|
||
//自学创建特征
|
||
//NR->NP->NP->IP
|
||
//NN->NP(称呼、职业)
|
||
|
||
//完整汉语句法树库核心标签对照表(含 TOP/ NP / IP / CLP)
|
||
//按 “核心层级 / 短语类型” 分类整理,覆盖 90 % 以上高频标注:
|
||
//1.顶层 / 句子级标签
|
||
//标签 英文全称 中文名称 定义 示例
|
||
//TOP Top - level Phrase 顶层短语 句法树的根节点,包含整个句子的最高层级结构 所有句子的根节点均标注为 TOP
|
||
//IP Inflectional Phrase / Simple Clause 简单从句 句子级核心短语(含主谓结构),是 TOP 的直接子节点 “我吃饭” 整体标注为 IP
|
||
//CP Complement Clause 补语从句 带补语标记(的 / 吗 / 呢)的从句 / 复句成分 “我买的书” 中 “我买的” 标注为 CP
|
||
//2.名词类短语
|
||
//标签 英文全称 中文名称 定义 示例
|
||
//NP Noun Phrase 名词短语 以名词为核心的短语(可含定语 / 量词) “苹果”“我的手机”“三本书”
|
||
//DNP XP+DEG Phrase “的” 字短语 由 “XP + 的” 构成的名词性短语 “红色的”“我喜欢的”
|
||
//NNP Proper Noun Phrase 专有名词短语 人名 / 地名 / 机构名等专有名词构成的短语 “北京大学”“张三”“北京市”
|
||
//3.动词类短语
|
||
//标签 英文全称 中文名称 定义 示例
|
||
//VP Verb Phrase 动词短语 以动词为核心的短语(可含宾语 / 状语) “吃饭”“快速跑步”“看电影”
|
||
//VV Verb Phrase(Verb Core) 动词核心短语 纯动词构成的短语(无附加成分) “跑”“思考”“购买”
|
||
//VCP Verb Complement Phrase 动补短语 动词 +补语构成的短语 “吃完”“跑快”“看明白”
|
||
//4.数量 / 量词类短语
|
||
//标签 英文全称 中文名称 定义 示例
|
||
//CLP Classifier Phrase 量词短语 以量词为核心的短语(数词 + 量词 / 指示词 + 量词) “三个”“这本”“那些”
|
||
//QP Quantifier Phrase 量化短语 以数量为核心的短语(涵盖数词 / 量词 / 数量整体) “三”“若干”“三本”“许多”
|
||
//DP Determiner Phrase 指示词短语 以指示词(这 / 那 / 此)为核心的短语 “这个”“那些”“此问题”
|
||
//5.介词 / 方位类短语
|
||
//标签 英文全称 中文名称 定义 示例
|
||
//PP Prepositional Phrase 介词短语 以介词为核心的短语 “在学校”“关于这件事”“把书”
|
||
//LCP Locative Complement Phrase 方位补语短语 含方位词的短语 “桌子上”“房间里”“马路边”
|
||
//LOC Locative Phrase 方位短语 纯方位名词构成的短语(LCP 的简化版) “上面”“左边”“内部”
|
||
//6.形容词 / 副词类短语
|
||
//标签 英文全称 中文名称 定义 示例
|
||
//AP Adjective Phrase 形容词短语 以形容词为核心的短语 “漂亮”“非常开心”“红色的”
|
||
//ADVP Adverb Phrase 副词短语 以副词为核心的短语 “快速地”“很”“非常”
|
||
//7.其他功能类短语
|
||
//标签 英文全称 中文名称 定义 示例
|
||
//INTJ Interjection Phrase 感叹语短语 感叹词 / 语气词构成的短语 “啊”“哦”“哎呀”
|
||
//CONJP Conjunction Phrase 连词短语 连词构成的短语 “和”“但是”“因为”
|
||
//PRN Parenthetical Phrase 插入语短语 插入句子的附加成分 “换句话说”“总的来说”
|
||
//总结
|
||
//CLP 核心是量词短语,以量词为核心(如 “三本”“这本”),是数量表达的核心标注标签;
|
||
//TOP / IP 是句子层级标签(根节点 / 核心从句),NP / VP 是核心短语标签(名词 / 动词为核心);
|
||
//不同工具(CTB / HanLP / 北大树库)对标签的细分略有差异(如 CLP 是否归为 QP),但核心含义一致,优先以宾州中文树库(CTB)规范为准。
|
||
}
|
||
|
||
public void AddRule(string speaker, params string[] keywords)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(speaker))
|
||
throw new ArgumentException("说话者名称不能为空", nameof(speaker));
|
||
|
||
if (keywords == null || keywords.Length == 0)
|
||
throw new ArgumentException("至少需要提供一个关键词", nameof(keywords));
|
||
|
||
_rules.Add(new SpeakerRule(speaker, keywords));
|
||
}
|
||
|
||
public string MatchSpeaker(string dialogue)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(dialogue))
|
||
return null;
|
||
|
||
foreach (var rule in _rules)
|
||
{
|
||
if (rule.Match(dialogue))
|
||
{
|
||
return rule.Speaker;
|
||
}
|
||
}
|
||
|
||
return dialogue;
|
||
}
|
||
}
|
||
|
||
public class SpeakerRule
|
||
{
|
||
public string Speaker { get; }
|
||
public string[] Keywords { get; }
|
||
|
||
public SpeakerRule(string speaker, string[] keywords)
|
||
{
|
||
Speaker = speaker;
|
||
Keywords = keywords;
|
||
}
|
||
|
||
public bool Match(string dialogue)
|
||
{
|
||
return Keywords.Any(keyword =>
|
||
dialogue.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0);
|
||
}
|
||
}
|
||
}
|