340 lines
16 KiB
Python
340 lines
16 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""Flair_NER_Inference .ipynb
|
||
|
||
Automatically generated by Colaboratory.
|
||
|
||
Original file is located at
|
||
https://colab.research.google.com/drive/1e-Q1bzMvm1mtRuxwnZBeXRfb-E39hxKu
|
||
"""
|
||
from general_functions import normalize_content
|
||
from funcs import separated_date_format_finder
|
||
from flair.data import Sentence
|
||
from flair.models import SequenceTagger
|
||
from flair.nn import Classifier
|
||
from transformers import AutoTokenizer, AutoModelForMaskedLM
|
||
from transformers import AutoTokenizer, AutoModelForTokenClassification
|
||
import torch
|
||
from transformers import AutoTokenizer
|
||
from flair.embeddings import TransformerWordEmbeddings
|
||
from find_law import find_related_law
|
||
|
||
# from train import model
|
||
trained_model = 'unknown'
|
||
|
||
model = "./taggers/final-model.pt"
|
||
print('model read')
|
||
tagger = SequenceTagger.load(model)
|
||
print('tagger initialized')
|
||
|
||
def save_to_file(result):
|
||
with open('./data/test_result.txt', 'a+', encoding='utf-8') as file:
|
||
previous_result = ''
|
||
try:
|
||
previous_result = file.read()
|
||
except:
|
||
pass
|
||
file.write(previous_result
|
||
+ '\n' + 50*'*'
|
||
+ '\n' + result
|
||
+ '\n' + 50*'*' + '\n')
|
||
|
||
def read_file():
|
||
with open('./data/law.txt', 'r', encoding='utf-8') as file:
|
||
text = ''
|
||
try:
|
||
text = str(file.read())
|
||
except:
|
||
pass
|
||
return text
|
||
|
||
|
||
# import nltk
|
||
import re
|
||
# from num2words import num2words
|
||
|
||
def extract_quoted_values(content):
|
||
|
||
ner_vlaue = re.findall(r'"(.*?)"', content)
|
||
|
||
return ner_vlaue
|
||
|
||
def convert_persian_numbers_to_english(text):
|
||
persian_numbers = {'۰': '0', '۱': '1', '۲': '2', '۳': '3', '۴': '4', '۵': '5', '۶': '6', '۷': '7', '۸': '8', '۹': '9'}
|
||
for persian, english in persian_numbers.items():
|
||
text = text.replace(persian, english)
|
||
return text
|
||
|
||
def convert_numbers_to_persian(text):
|
||
persian_numbers = {'0': '۰', '1': '۱', '2': '۲', '3': '۳', '4': '۴', '5': '۵', '6': '۶', '7': '۷', '8': '۸', '9': '۹'}
|
||
for english, persian in persian_numbers.items():
|
||
text = text.replace(english, persian)
|
||
return text
|
||
|
||
def find_quoted_values_in_text(text, ner_values):
|
||
"""
|
||
این تابع مقادیر استخراج شده را در یک متن دیگر جستجو میکند و اگر یافت شدند، محل آنها را نشان میدهد.
|
||
|
||
:param text: متنی که میخواهید در آن جستجو انجام شود.
|
||
:param quoted_values: لیستی از مقادیر استخراج شده که میخواهید در متن جستجو کنید.
|
||
"""
|
||
#tokens = nltk.word_tokenize(text)
|
||
tokens = text.split()
|
||
ner_token_index_list = []
|
||
for value in ner_values:
|
||
#value_tokens = nltk.word_tokenize(value)
|
||
# print(value[0])
|
||
value_tokens = value[0].split()
|
||
value_len = len(value_tokens)
|
||
found = False
|
||
for i in range(len(tokens) - value_len + 1):
|
||
if tokens[i:i + value_len] == value_tokens:
|
||
print(f'{i + 1}:{i + value_len}|{value[0]}')
|
||
ner_token_index_list.append(f'{i + 1}:{i + value_len}|{value[0]}')
|
||
found = True
|
||
break
|
||
if not found:
|
||
print(f'"{value[0]}" در جمله یافت نشد.')
|
||
return ner_token_index_list
|
||
|
||
def find_ner_values_in_text(text, ner_values):
|
||
text_temp = text
|
||
text_tokens = text.split()
|
||
ner_obj = []
|
||
difference = 0
|
||
for raw_item in ner_values:
|
||
raw_ner = raw_item['value']
|
||
ner = re.findall(r'"(.*?)"', raw_ner)[0]
|
||
# جلوگیری از مقادیر نامعتبر در خروجی
|
||
if ner == ')' or ner == '(' or ner == '/' or ner == 'قانون تغییر' or ner == 'قانون':
|
||
continue
|
||
ner_parts = raw_ner.split(ner)[1]
|
||
ner_parts = ner_parts.lstrip('"/')
|
||
ner_type = ner_parts.strip()
|
||
ner_score = raw_item['score'].strip()
|
||
ner_type = ner_type.strip()
|
||
ner_score = ner_score.strip()
|
||
ner = normalize_content(ner)
|
||
# پیدا کردن موجودیت نامدار بالا در متن
|
||
matched_ner = [(m.start(), m.end()) for m in re.finditer(re.escape(ner), text_temp)]
|
||
if matched_ner:
|
||
matched_ner_start = matched_ner[0][0]
|
||
matched_ner_end = matched_ner[0][1]
|
||
before_ner_text = ''
|
||
|
||
if matched_ner_start > 1:
|
||
before_ner_text = text_temp[0:matched_ner_start-1]
|
||
difference = len(before_ner_text.split())
|
||
|
||
ner_start_token = difference
|
||
ner_end_token = len(ner.split()) + difference
|
||
#after_ner_text = text_temp[matched_ner_end:]
|
||
#$after_ner_text_tokens = [text_tokens[t] for t in range (ner_end_token, len(text_tokens))]
|
||
#after_ner_text = ' '.join(after_ner_text_tokens)
|
||
ner_tokens = [text_tokens[t] for t in range (ner_start_token,ner_end_token)]
|
||
|
||
# برای جلوگیری از خطای منطقی در هنگامی که مقدار
|
||
# ner
|
||
#ما بیشتر از یکبار در متن وجود دارد، موجودیت بررسی شده را با کاراکتر های خنثی جایگزین می کنیم
|
||
for t in range (ner_start_token,ner_end_token):
|
||
text_tokens[t] = '#####'
|
||
text_temp = ' '.join(text_tokens)
|
||
text_temp = text_temp.strip()
|
||
if matched_ner_start == 0:
|
||
difference = len(ner.split())
|
||
#region Evaluate NER Format
|
||
# law_id = 0
|
||
if ner_type == 'HALFREFERENCE':
|
||
ner_type = 'H_REF'
|
||
if ner_type == 'REFERENCE':
|
||
ner_type = 'REF'
|
||
if not (ner.strip()).startswith('قانون'):
|
||
continue
|
||
##################################
|
||
# پیدا کردن شناسه متناظر با این قانون
|
||
# law_id = find_related_law(ner.strip())
|
||
##################################
|
||
if ner_type == 'DATE2':# تاریخ در سه توکن
|
||
# # در این فرمت از تاریخ اگر تعداد توکن های تاریخ، برابر با سه نباشد، تشخیص ماشین اشتباه بوده
|
||
# if len(ner_tokens) != 3:
|
||
# continue
|
||
date_ner = ' '.join(ner_tokens).strip()
|
||
# بررسی فرمت صحیح تاریخ با رگولار
|
||
result = separated_date_format_finder(date_ner)
|
||
if not result:
|
||
continue
|
||
if ner_type == 'DATE3':# تاریخ در یک توکن
|
||
date_ner = ' '.join(ner_tokens).strip()
|
||
# بررسی فرمت صحیح تاریخ با رگولار
|
||
result = separated_date_format_finder(date_ner)
|
||
if not result:
|
||
continue
|
||
#endregion
|
||
ner_obj.append({
|
||
'ner_value' : ner.strip(),
|
||
'ner_start_token': ner_start_token,
|
||
'ner_end_token' : ner_end_token,
|
||
# 'ner_tokens' : ner_tokens,
|
||
'ner_key' : ner_type.strip(),
|
||
'ner_score' : ner_score.strip()
|
||
})
|
||
# if law_id != 0:
|
||
# ner_obj[len(ner_obj)-1]['ner_law_id']= law_id
|
||
|
||
return ner_obj
|
||
|
||
def ner_values_token_finder(ner_values):
|
||
# ner_value_list = []
|
||
# for ner_value in ner_values:
|
||
# ner_value_list.append(extract_quoted_values(ner_value['value']))
|
||
|
||
text = read_file()
|
||
text = normalize_content(text)
|
||
# تبدیل اعداد فارسی به اعداد انگلیسی
|
||
#text = convert_persian_numbers_to_english(text)
|
||
|
||
return find_ner_values_in_text(text, ner_values)
|
||
|
||
def inference_main(trained_model,input_sentence):
|
||
if(input_sentence == ''):
|
||
input_sentence = read_file()
|
||
input_sentence = normalize_content(input_sentence)
|
||
# p = len(input_sentence)
|
||
# print(p)
|
||
# # نام مدل
|
||
# model_name = "./data/xlm-roberta-base.pt"
|
||
|
||
# # بارگذاری توکنایزر
|
||
# tokenizer = AutoTokenizer.from_pretrained(model)
|
||
|
||
# # جمله مورد نظر
|
||
# sentence = input_sentence
|
||
|
||
# # توکنسازی جمله
|
||
# inputs = tokenizer(sentence, return_tensors="pt")
|
||
|
||
# from transformers import AutoModel
|
||
|
||
# # بارگذاری مدل
|
||
# model = AutoModel.from_pretrained(model_name)
|
||
|
||
# # اجرای مدل
|
||
# outputs = model(**inputs)
|
||
|
||
# hidden_states = outputs.last_hidden_state
|
||
|
||
#model = "./data/final-model.pt"
|
||
# model = "./data/final-model_01.pt"
|
||
|
||
'''model = "./taggers/final-model.pt"
|
||
# tokenizer = AutoTokenizer.from_pretrained('./taggers')
|
||
# tokens = tokenizer.tokenize(input_sentence)
|
||
# for index, token in enumerate(tokens):
|
||
# print(index + ' - ' + token)
|
||
|
||
#model = "/home/gpu/tnlp/jokar/Models/HooshvareLab--bert-base-parsbert-ner-uncased/train 01/final-model.pt"
|
||
# model = "./data/HooshvareLab--distilbert-fa-zwnj-base-ner"
|
||
#model = "./jokar/Models/HooshvareLab-bert-fa-base-uncased-finetuned-2-pt"
|
||
print('model read')
|
||
|
||
# embeddings = TransformerWordEmbeddings(allow_long_sentences=True )
|
||
# tagger = SequenceTagger(embeddings=embeddings)
|
||
tagger = SequenceTagger.load(model)
|
||
print('tagger initialized')'''
|
||
|
||
# tokenizer = AutoTokenizer.from_pretrained('./data')
|
||
# model = AutoModelForTokenClassification.from_pretrained("./data", num_labels=5)
|
||
|
||
result = []
|
||
# if(len(input_sentence>511)):
|
||
# sentence = Sentence(input_sentence)
|
||
# tagger.predict(sentence)
|
||
# for span in sentence.get_spans():
|
||
# result.append(span)
|
||
if len(input_sentence.split()) > 256 :
|
||
sentence_parts = input_sentence.split('.')
|
||
for part in sentence_parts:
|
||
sentence = Sentence(part)
|
||
|
||
tagger.predict(sentence)
|
||
|
||
for span in sentence.get_spans():
|
||
result.append(span)
|
||
else:
|
||
sentence = Sentence(input_sentence)
|
||
tagger.predict(sentence)
|
||
for span in sentence.get_spans():
|
||
result.append(span)
|
||
|
||
from datetime import datetime
|
||
final_result = ''
|
||
result_header = 100*'#' + '\n' + 'Model Name: ' + trained_model + '\n' + 'Found Entity Count: ' + str(len(result)) + '\n' + 'inference time: ' + str(datetime.now()) + '\n' + 100*'#'
|
||
ner_values = []
|
||
if result:
|
||
for item in result:
|
||
value = item.annotation_layers['ner'][0].labeled_identifier
|
||
score = round(item.score, 2)
|
||
score = str(score)
|
||
final_result = final_result + '\n' + value + ' /%/ ' + score
|
||
ner_values.append({
|
||
'value':value,
|
||
'score':score
|
||
})
|
||
|
||
# text = read_file()
|
||
text = input_sentence
|
||
text = normalize_content(text)
|
||
ner_obj_list = find_ner_values_in_text(text, ner_values)
|
||
ner_addresses = ''
|
||
for ner_val in ner_obj_list:
|
||
ner_addresses = ner_addresses + '\n' + str(ner_val)
|
||
ner_addresss = '\n'+ '$'*70 + '\n' + ner_addresses + '\n' + '$'*70
|
||
save_to_file(result_header + final_result + ner_addresss)
|
||
return final_result
|
||
|
||
|
||
|
||
# tagger: SequenceTagger = SequenceTagger.load("./data/final-model.pt")
|
||
# # tagger: SequenceTagger = SequenceTagger.load(model)
|
||
# tagger: SequenceTagger = SequenceTagger.load("xlm-roberta-base")
|
||
# # sentence = Sentence(input_sentence)
|
||
# load the NER tagger
|
||
# tagger = Classifier.load('ner')
|
||
# tagger : Classifier = Classifier.load("sentiment")
|
||
#tagger = Classifier.load('sentiment')
|
||
|
||
# # tagger.predict(sentence)
|
||
|
||
# # for span in sentence.get_spans():
|
||
# # print(span)
|
||
|
||
# print()
|
||
# print(' <--- Predict Operation Finished! ---> ')
|
||
# print()
|
||
|
||
if __name__ == "__main__":
|
||
text = """ماده 26
|
||
در موضوعات صلاحیت قضایی در رابطه با شرکت کنندگان در رزمایش از طرف فرستنده، آن طرف باید از اصول زیر تبعیت نماید:
|
||
پرونده های جرایمی که شرکت کنندگان در رزمایش علیه طرف فرستنده یا شهروندان آن مرتکب شده اند و جرایمی که آن ها در حین انجام وظیفه مرتکب شده اند، در صلاحیت طرف فرستنده خواهد بود.
|
||
موارد جرایم ارتکابی توسط شرکت کنندگان در رزمایش غیر از موارد مشمول بند دوم این ماده در صلاحیت طرف میزبان یا طرف گذر(ترانزیت) خواهد بود.
|
||
طرف فرستنده می تواند تحقیقات مقدماتی را در مورد افراد ناشناس که علیه طرف فرستنده یا شرکت کنندگان رزمایش در مکان های استقرار شرکت کنندگان در رزمایش مرتکب تخلف می شوند، انجام دهد. در تعیین متخلف، رویه مشخص شده در این موافقت نامه اعمال خواهد شد.
|
||
مقام های ذی صلاح طرف های مجاز به انجام دادرسی باید مستقیماً تعامل داشته باشند و در تحقیقات، جمع آوری و تهیه شواهد مربوط به جرایم، در یافتن (جستجو)، دستگیری و بازداشت شرکت کنندگان در رزمایش مظنون یا متهم به یکدیگر کمک کنند.
|
||
حق برقراری روابط مستقیم نیز متعلق به سران شرکت کنندگان در رزمایش طرف ها در حوزه صلاحیت آن ها خواهد بود.
|
||
طرف فرستنده باید فوراً طرف گیرنده را از بازداشت شرکت کنندگان در رزمایش طرف میزبان و سایر افراد مطلع کند.
|
||
طرف میزبان باید فوراً طرف فرستنده را از بازداشت شرکت کنندگان رزمایش طرف فرستنده مطلع کند.
|
||
در جریان دستگیری، بازداشت و سایر اقدامات قانونی، و همچنین انتقال شرکت کنندگان در رزمایش مظنون به ارتکاب جرم یا کمک حقوقی، طرف ها باید تحت نظارت معاهدات بین المللی که عضو آن هستند و قوانین ملی عمل کنند.
|
||
در هر مورد هنگامی که شرکت کنندگان در رزمایش طرف فرستنده توسط طرف میزبان تحت تعقیب کیفری قرار می گیرند، نماینده طرف فرستنده حق دارد در محاکمه حضور داشته باشد، در حالی که شخص تحت تعقیب از حقوق ذیل برخوردار خواهد بود:
|
||
تحقیقات و محاکمه فوری و سریع؛
|
||
دریافت اطلاعات مربوط به اتهامات خاص علیه وی در ابتدای روند قضایی؛
|
||
رویا رویی با شاهدان دادستان و سایر شرکت کنندگان در دادرسی کیفری؛
|
||
حضور شهود برای دفاع در صورتی که تحت صلاحیت قضایی طرف میزبان باشند؛
|
||
وکیل حقوقی به انتخاب خود، یا مشاور حقوقی رایگان؛
|
||
وجود خدمات ترجمه؛
|
||
ارتباط با نماینده طرف فرستنده.
|
||
طرف ها می توانند درخواست هایی مبنی بر انتقال یا پذیرش پرونده های جنایی مربوط به جرایم ارتکابی توسط شرکت کنندگان در رزمایش را به یکدیگر ارجاع دهند. چنین درخواست هایی باید فورا مورد بررسی قرار گیرد.
|
||
مقام های ذی صلاح طرف ها که مجاز به انجام دادرسی هستند، طبق معاهدات بین المللی که عضو آن می باشند و قوانین طرف های آن ها، باید نتایج تحقیقات و دادرسی کلیه پرونده های جنایی را که طرف ها در رابطه با آن ها در حوزه های قضایی رقابت دارند، به اطلاع یکدیگر برسانند.
|
||
"""
|
||
print("do inf ... ")
|
||
inference_main('pourmand1376/NER_Farsi',text)
|
||
|
||
|