#python #html #spacy
Вопрос:
Я работаю над инструментом для визуализации совпадений NER и пытаюсь устранить совпадения. Я использую displacy SpaCy в качестве шаблона, и моя идея состояла в том, чтобы добавить функцию после displacy.render()
того, как она изменит HTML-строку в соответствии с желаемым результатом, но я несколько застрял. Вот мой процесс до сих пор:
Допустим, у меня есть некоторые text
и некоторые entities
(идентифицированные ранее каким-либо методом):
text = "This is an example sentence with some super secret (and some text in between) stuff"
entities = [{"start": 38, "end": 43, "label": "SUPER"},
{"start": 38, "end": 50, "label": "SUPER SECRET"},
{"start": 78, "end": 83, "label": "STUFF"}]
Мы можем визуализировать их в формате HTML вручную, используя display:
from spacy import displacy
example = [{"text": text,
"ents": entities,
"title": None}]
html = displacy.render(example, style="ent", manual=True)
который возвращает
<div class="entities" style="line-height: 2.5; direction: ltr">This is an example sentence with some
<mark class="entity" style="background: #ddd; padding: 0.45em 0.6em; margin: 0 0.25em; line-height: 1; border-radius: 0.35em;">
super
<span style="font-size: 0.8em; font-weight: bold; line-height: 1; border-radius: 0.35em; vertical-align: middle; margin-left: 0.5rem">SUPER</span>
</mark>
<mark class="entity" style="background: #ddd; padding: 0.45em 0.6em; margin: 0 0.25em; line-height: 1; border-radius: 0.35em;">
super secret
<span style="font-size: 0.8em; font-weight: bold; line-height: 1; border-radius: 0.35em; vertical-align: middle; margin-left: 0.5rem">SUPER SECRET</span>
</mark>
(and some text in between)
<mark class="entity" style="background: #ddd; padding: 0.45em 0.6em; margin: 0 0.25em; line-height: 1; border-radius: 0.35em;">
stuff
<span style="font-size: 0.8em; font-weight: bold; line-height: 1; border-radius: 0.35em; vertical-align: middle; margin-left: 0.5rem">STUFF</span>
</mark>
</div>
Проблема здесь в том, что «супер» находится отдельно <mark>
от «суперсекрета». В идеале я бы хотел иметь что-то подобное:
<div class="entities" style="line-height: 2.5; direction: ltr">This is an example sentence with
<mark class="entity" style="background: #ddd; padding: 0.45em 0.6em; margin: 0 0.25em; line-height: 1; border-radius: 0.35em;">
<mark class="entity" style="background: #add; padding: 0.45em 0.6em; margin: 0 0.25em; line-height: 1; border-radius: 0.35em;">
super
<span style="font-size: 0.8em; font-weight: bold; line-height: 1; border-radius: 0.35em; vertical-align: middle; margin-left: 0.5rem">SUPER</span>
</mark>
secret
<span style="font-size: 0.8em; font-weight: bold; line-height: 1; border-radius: 0.35em; vertical-align: middle; margin-left: 0.5rem">SUPER SECRET</span>
</mark>
(and some text in between)
<mark class="entity" style="background: #ddd; padding: 0.45em 0.6em; margin: 0 0.25em; line-height: 1; border-radius: 0.35em;">
stuff
<span style="font-size: 0.8em; font-weight: bold; line-height: 1; border-radius: 0.35em; vertical-align: middle; margin-left: 0.5rem">STUFF</span>
</mark>
</div>
So my idea was to write an html_transform(starting_html: str) -> str
function that resolves overlapping entities and returns something like the bottom image. After writing some psuedocode though, I realised that this might be a too complicated approach and I’m still stuck with it. Does anyone know of better ways of approaching this? Any pointers would be appreciated!