CloudBuilder.Topshelf/Utility/SpeakerAnalysisHelper.cs
owenchen 5f222a23b3 ow
2026-06-02 11:01:00 +08:00

235 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using CloudBuilder.AI.Entity;
using CloudBuilder.Core.DatabaseAccessor.Entity;
using CloudBuilder.Topshelf.Python;
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;
namespace CloudBuilder.Topshelf.Utility
{
public class SpeakerAnalysisHelper
{
public string GetPerson(Hanlp2 hanlp, string text)
{
string depRoot = hanlp.GetDepRoot(text);
List<NamedEntity> ners = hanlp.GetHanlpNer(text);
List<List<MeaningRepresentationParsingEntity>> srls = hanlp.GetHanlpSrl(text);
List<HanlpConstituencyNode> cons = hanlp.GetHanlpCon(text);
SpeakerAnalysisHelper speakerFeatureLearner = new SpeakerAnalysisHelper();
List<string> ps = new List<string>();
string arg1 = string.Empty;
string person = GetArg0(hanlp, depRoot, ners, srls, cons, ref arg1);
//同边同时有的,放在最前面
if (!string.IsNullOrEmpty(person) && ners != null && ners.Where(x => x.Type.Contains("PERSON")).Count() > 0)
{
if (ners.Where(x => x.Text.Contains(person)).Any()) ps.Add(person);
}
//如果前面的不一样,那么加入人名
if (ners != null && ners.Where(x => x.Type.Contains("PERSON")).Count() > 0)
{
foreach (string namedEntity in ners.Where(x => x.Type.Contains("PERSON")).Select(x => x.Text).Distinct().ToArray())
{
if (namedEntity.Length > 1)
{
if (!ps.Contains(namedEntity))
ps.Add(namedEntity);
}
else
{
HanlpConstituencyNode[] nodes;
HanlpConstituencyNode nodef;
string feature = null;
nodes = HanlpResultHelper.GetNodeByLabel(cons, namedEntity);
if (nodes == null || nodes.Length == 0) continue;
string[] nps = new string[] { "NP", "DNP" };
//如果存在找到父节点上的NP
foreach (HanlpConstituencyNode node in nodes)
{
nodef = HanlpResultHelper.GetNodeTopLabelById(cons, node.FatherId, nps);
if (nodef != null)
{
feature = HanlpResultHelper.GetNodeBottomLabelById(cons, nodef.ItemId, nps);
if (string.IsNullOrEmpty(feature)) continue;
}
else if (string.IsNullOrEmpty(feature))
{
feature = node.Label;
}
//如果下一个是“NP、DNP”可以串起来跟上面的GetNodeBottomLabelById类似
if (feature.Length == 1)
{
HanlpConstituencyNode[] nodesSon;
nodef = HanlpResultHelper.GetNodeById(cons, node.ItemId + 1);
if (nps.Contains(nodef.Label))
{
nodesSon = HanlpResultHelper.GetNodeSonById(cons, nodef.ItemId);
if (nodesSon != null && nodesSon.Where(x => x.Children == 0).Any())
{
feature += string.Concat(nodesSon.Select(x => x.Label));
}
}
}
if (feature.Length == 1)
{
var bs = HanlpResultHelper.GetNodeBrothersById(cons, node.ItemId);
if (bs != null && bs.Where(x => x.Children == 0).Any())
{
feature += string.Concat(bs.Select(x => x.Label));
}
}
if (feature.Contains(namedEntity) && !ps.Contains(feature)) ps.Add(feature);
}
}
}
}
//如果主语==动作发出者
//if (!string.IsNullOrEmpty(person) && !ps.Contains(person) && !ps.Contains(string.Format("[{0}]", person))) ps.Add(string.Format("[{0}]", person));
//动作接受者
//if (!string.IsNullOrEmpty(arg1) && !ps.Contains(arg1)) ps.Add(arg1);
person = QuotedString.ToDelimiteredList(ps.ToArray());
return person;
}
public string GetAgr0(Hanlp2 hanlp, string text)
{
string depRoot = hanlp.GetDepRoot(text);
List<NamedEntity> ners = hanlp.GetHanlpNer(text);
List<List<MeaningRepresentationParsingEntity>> srls = hanlp.GetHanlpSrl(text);
List<HanlpConstituencyNode> cons = hanlp.GetHanlpCon(text);
SpeakerAnalysisHelper speakerFeatureLearner = new SpeakerAnalysisHelper();
List<string> ps = new List<string>();
string arg1 = string.Empty;
return GetArg0(hanlp, depRoot, ners, srls, cons, ref arg1);
}
public string GetArg0(Hanlp2 hanlp, string depRoot, List<NamedEntity> ners, List<List<MeaningRepresentationParsingEntity>> srls, List<HanlpConstituencyNode> cons, ref string arg1)
{
string arg0 = string.Empty;
if (!string.IsNullOrEmpty(depRoot) && srls != null && srls.Count() > 0)
{
foreach (var srl in srls)
{
if (srl.Where(x => x.Text == depRoot).Any())
{
foreach (var mrp in srl)
{
if (mrp.Type.ToUpper() != "ARG0") continue;
if (ners != null && ners.Where(x => mrp.Text.Contains(x.Text)).Any() &&
ners.Where(x => mrp.Text.Contains(x.Text)).FirstOrDefault().Text.Length > 1)
return ners.Where(x => mrp.Text.Contains(x.Text)).FirstOrDefault().Text;
if (mrp.Text.Length > 4)
{
arg0 = GetAgr0(hanlp, mrp.Text);
}
else if (mrp.Text.Length > 1)
{
if (ners == null || ners.Where(x => x.Type.Contains("PERSON")).Count() == 0)
return mrp.Text;
}
}
}
foreach (var mrp in srl)
{
if (mrp.Type.ToUpper() != "ARG0") continue;
if (mrp.Text.Length > 4)
{
var temp = GetAgr0(hanlp, mrp.Text);
if (!string.IsNullOrEmpty(temp))
{
arg1 = temp;
return arg0;
}
}
else
{
arg1 = mrp.Text;
}
}
}
}
return arg0;
}
public void MatchPerson(AiSentenceViewEntity[] aiSentences, IRepository<AiSentenceEntity> repositoryAiSentenceEntity)
{
if (AiChapterPersons == null || AiChapterPersons.Length == 0) return;
AiSentenceEntity aiSentence;
string dialogueName = string.Empty;
foreach (AiSentenceViewEntity aiSentenceView in aiSentences)
{
dialogueName= string.Empty;
if (aiSentenceView.DialogueIndc != YesNoPolicy.YES) continue;
if (aiSentences.Where(x => x.ChapterId == aiSentenceView.ChapterId && x.ParagraphId == aiSentenceView.ParagraphId).Count() > 1)
{
if (AiChapterPersons.Where(x => x.ChapterId == aiSentenceView.ChapterId && x.ParagraphIndex == aiSentenceView.ParagraphId && aiSentenceView.SentenceIndex == x.SentenceIndex).Any())
{
dialogueName = AiChapterPersons.Where(x => x.ChapterId == aiSentenceView.ChapterId && x.ParagraphIndex == aiSentenceView.ParagraphId && aiSentenceView.SentenceIndex == x.SentenceIndex).FirstOrDefault().PersonName;
}
if (AiChapterPersons.Where(x => x.ChapterId == aiSentenceView.ChapterId && x.ParagraphIndex == aiSentenceView.ParagraphId && aiSentenceView.SentenceIndex != x.SentenceIndex && x.PersonName != dialogueName).Any())
{
aiSentenceView.PersonName = AiChapterPersons.Where(x =>x.ChapterId==aiSentenceView.ChapterId && x.ParagraphIndex == aiSentenceView.ParagraphId && aiSentenceView.SentenceIndex != x.SentenceIndex && x.PersonName != dialogueName).OrderBy(x => x.OrderIndex).FirstOrDefault().PersonName;
}
}
aiSentence = new AiSentenceEntity();
ObjectCopyHelper.Copy(aiSentenceView, aiSentence);
repositoryAiSentenceEntity.UpdateNow(aiSentence);
}
}
public AiSentenceEntity[] AiSentences { get; set; }
public AiChapterPersonEntity[] AiChapterPersons { get; set; }
}
}
/*
“文本解析→人物提取→上下文匹配→结果输出”
graph TD
A[对话行] --> B{规则1文本特征匹配};
B -->|匹配成功| C[直接赋值说话者];
B -->|匹配失败| D{规则2紧邻旁白匹配};
D -->|匹配成功| C;
D -->|匹配失败| E{规则3段落内最近人物};
E -->|匹配成功| C;
E -->|匹配失败| F[赋值默认值+标记异常];
*/