gliner_multi-v2.1 / src /example.py
cimo001's picture
update
336795c
Raw
History Blame Contribute Delete
5.83 kB
import sys
sys.dont_write_bytecode = True
import re
import unicodedata
import numpy
import sentencepiece
from sentencepiece import sentencepiece_model_pb2 as sentencepieceModel
from helper import onnxSessionBuild
pathModel = "./"
glinerTypeAllowList = ["person", "organization", "place", "category", "event"]
glinerScoreMin = 0.4
glinerEntId = 250103
glinerSepId = 250104
glinerClsId = 1
glinerEosId = 2
glinerMaxWidth = 12
glinerMaxLength = 384
proto = sentencepieceModel.ModelProto()
with open(f"{pathModel}spm.model", "rb") as file:
proto.ParseFromString(file.read())
proto.normalizer_spec.add_dummy_prefix = False
sentencepieceGliner = sentencepiece.SentencePieceProcessor()
sentencepieceGliner.LoadFromSerializedProto(proto.SerializeToString())
onnxSessionGliner = onnxSessionBuild(f"{pathModel}onnx/model.onnx")
def wideCheck(character):
return character != "" and unicodedata.east_asian_width(character) in ("W", "F")
def tokenizeWord(text):
resultList = []
for segment in re.findall(r"\d|\D+", text):
for tokenId in sentencepieceGliner.encode(segment, out_type=int):
resultList.append(tokenId)
return resultList
def wordSplit(text):
resultList = []
for match in re.finditer(r"\w+(?:[-_]\w+)*|[^\w\s]", text):
word = match.group(0)
start = match.start()
segment = ""
segmentStart = start
for a in range(len(word)):
if wideCheck(word[a]):
if segment != "":
resultList.append({"text": segment, "start": segmentStart, "end": segmentStart + len(segment)})
segment = ""
resultList.append({"text": word[a], "start": start + a, "end": start + a + 1})
segmentStart = start + a + 1
else:
if segment == "":
segmentStart = start + a
segment += word[a]
if segment != "":
resultList.append({"text": segment, "start": segmentStart, "end": segmentStart + len(segment)})
return resultList
def predict(text):
resultList = []
wordList = wordSplit(text)
if len(wordList) > glinerMaxLength:
wordList = wordList[0:glinerMaxLength]
numWords = len(wordList)
if numWords == 0:
return resultList
inputIdList = [glinerClsId]
wordsMaskList = [0]
for a in range(len(glinerTypeAllowList)):
inputIdList.append(glinerEntId)
wordsMaskList.append(0)
for tokenId in tokenizeWord(glinerTypeAllowList[a]):
inputIdList.append(tokenId)
wordsMaskList.append(0)
inputIdList.append(glinerSepId)
wordsMaskList.append(0)
for a in range(numWords):
subwordList = tokenizeWord(wordList[a]["text"])
for b in range(len(subwordList)):
inputIdList.append(subwordList[b])
wordsMaskList.append(a + 1 if b == 0 else 0)
inputIdList.append(glinerEosId)
wordsMaskList.append(0)
inputIds = numpy.array([inputIdList], dtype=numpy.int64)
attentionMask = numpy.ones((1, len(inputIdList)), dtype=numpy.int64)
wordsMask = numpy.array([wordsMaskList], dtype=numpy.int64)
textLengths = numpy.array([[numWords]], dtype=numpy.int64)
spanIdxList = []
spanMaskList = []
for a in range(numWords):
for b in range(glinerMaxWidth):
end = a + b
spanIdxList.append([a, end])
spanMaskList.append(end <= numWords - 1)
spanIdx = numpy.array([spanIdxList], dtype=numpy.int64)
spanMask = numpy.array([spanMaskList], dtype=bool)
feedObject = {
"input_ids": inputIds,
"attention_mask": attentionMask,
"words_mask": wordsMask,
"text_lengths": textLengths,
"span_idx": spanIdx,
"span_mask": spanMask
}
logits = onnxSessionGliner.run(["logits"], feedObject)[0]
probability = 1.0 / (1.0 + numpy.exp(-logits[0]))
candidateList = []
for a in range(numWords):
for b in range(glinerMaxWidth):
end = a + b
if end > numWords - 1:
continue
for c in range(len(glinerTypeAllowList)):
score = float(probability[a][b][c])
if score > glinerScoreMin:
candidateList.append({
"wordStart": a,
"wordEnd": end,
"label": glinerTypeAllowList[c],
"score": score
})
candidateList.sort(key=lambda candidate: candidate["score"], reverse=True)
takenList = []
for a in range(len(candidateList)):
candidate = candidateList[a]
isOverlap = False
for b in range(len(takenList)):
taken = takenList[b]
if candidate["wordStart"] <= taken["wordEnd"] and taken["wordStart"] <= candidate["wordEnd"]:
isOverlap = True
break
if isOverlap == False:
takenList.append(candidate)
charStart = wordList[candidate["wordStart"]]["start"]
charEnd = wordList[candidate["wordEnd"]]["end"]
resultList.append({
"start": charStart,
"end": charEnd,
"text": text[charStart:charEnd],
"label": candidate["label"],
"score": candidate["score"]
})
resultList.sort(key=lambda entity: entity["start"])
return resultList
text = unicodedata.normalize("NFKC", "Linus Torvalds created Linux in Helsinki and later joined the Linux Foundation, while 田中太郎 works at 東京大学 in Tokyo.")
entityList = predict(text)
for a in range(len(entityList)):
print(f"{entityList[a]['score']:.6f} | {entityList[a]['label']} | {entityList[a]['text']}")