from annotated_text import annotated_text, parameters, annotation from razdel import tokenize from transformers import AutoTokenizer, AutoModelForTokenClassification, pipeline import streamlit as st import torch # add the caching decorator and use custom text for spinner @st.cache_resource(show_spinner = "Loading the model...") def label_text(text): if text != "": tokenizer = AutoTokenizer.from_pretrained("yeshpanovrustem/xlm-roberta-large-ner-kazakh") model = AutoModelForTokenClassification.from_pretrained("yeshpanovrustem/xlm-roberta-large-ner-kazakh") nlp = pipeline("ner", model = model, tokenizer = tokenizer) labels_dict = {0: 'O', 1: 'B-ADAGE', 2: 'I-ADAGE', 3: 'B-ART', 4: 'I-ART', 5: 'B-CARDINAL', 6: 'I-CARDINAL', 7: 'B-CONTACT', 8: 'I-CONTACT', 9: 'B-DATE', 10: 'I-DATE', 11: 'B-DISEASE', 12: 'I-DISEASE', 13: 'B-EVENT', 14: 'I-EVENT', 15: 'B-FACILITY', 16: 'I-FACILITY', 17: 'B-GPE', 18: 'I-GPE', 19: 'B-LANGUAGE', 20: 'I-LANGUAGE', 21: 'B-LAW', 22: 'I-LAW', 23: 'B-LOCATION', 24: 'I-LOCATION', 25: 'B-MISCELLANEOUS', 26: 'I-MISCELLANEOUS', 27: 'B-MONEY', 28: 'I-MONEY', 29: 'B-NON_HUMAN', 30: 'I-NON_HUMAN', 31: 'B-NORP', 32: 'I-NORP', 33: 'B-ORDINAL', 34: 'I-ORDINAL', 35: 'B-ORGANISATION', 36: 'I-ORGANISATION', 37: 'B-PERSON', 38: 'I-PERSON', 39: 'B-PERCENTAGE', 40: 'I-PERCENTAGE', 41: 'B-POSITION', 42: 'I-POSITION', 43: 'B-PRODUCT', 44: 'I-PRODUCT', 45: 'B-PROJECT', 46: 'I-PROJECT', 47: 'B-QUANTITY', 48: 'I-QUANTITY', 49: 'B-TIME', 50: 'I-TIME'} single_sentence_tokens = [_.text for _ in list(tokenize(text))] tokenized_input = tokenizer(single_sentence_tokens, is_split_into_words = True, return_tensors = "pt") tokens = tokenized_input.tokens() output = model(**tokenized_input).logits predictions = torch.argmax(output, dim = 2) # convert label IDs to label names word_ids = tokenized_input.word_ids(batch_index = 0) previous_word_id = None labels = [] for token, word_id, prediction in zip(tokens, word_ids, predictions[0].numpy()): # # Special tokens have a word id that is None. We set the label to -100 so they are # # automatically ignored in the loss function. if word_id is None or word_id == previous_word_id: continue elif word_id != previous_word_id: labels.append(labels_dict[prediction]) previous_word_id = word_id assert len(single_sentence_tokens) == len(labels), "Mismatch between input token and label sizes!" sentence_tokens = [] sentence_labels = [] token_list = [] label_list = [] previous_token = "" previous_label = "" for token, label in zip(single_sentence_tokens, labels): current_token = token current_label = label # starting loop if previous_label == "": previous_token = current_token previous_label = current_label # collecting compound named entities elif (previous_label.startswith("B-")) and (current_label.startswith("I-")): token_list.append(previous_token) label_list.append(previous_label) elif (previous_label.startswith("I-")) and (current_label.startswith("I-")): token_list.append(previous_token) label_list.append(previous_label) elif (previous_label.startswith("I-")) and (not current_label.startswith("I-")): token_list.append(previous_token) label_list.append(previous_label) sentence_tokens.append(token_list) sentence_labels.append(label_list) token_list = [] label_list = [] # collecting single named entities: elif (not previous_label.startswith("I-")) and (not current_label.startswith("I-")): token_list.append(previous_token) label_list.append(previous_label) sentence_tokens.append(token_list) sentence_labels.append(label_list) token_list = [] label_list = [] previous_token = current_token previous_label = current_label token_list.append(previous_token) label_list.append(previous_label) sentence_tokens.append(token_list) sentence_labels.append(label_list) output = [] for sentence_token, sentence_label in zip(sentence_tokens, sentence_labels): if len(sentence_label[0]) > 1: if len(sentence_label) > 1: output.append((" ".join(sentence_token), sentence_label[0].split("-")[1])) else: output.append((sentence_token[0], sentence_label[0].split("-")[1])) else: # output.append((sentence_token[0], sentence_label[0])) output.append(sentence_token[0]) modified_output = [] for element in output: if not isinstance(element, tuple): if element.isalnum(): modified_output.append(' ' + element + ' ') else: modified_output.append(' ' + element + ' ') else: tuple_first = f" {element[0]} " tuple_second = element[1] new_tuple = (tuple_first, tuple_second) modified_output.append(new_tuple) else: return st.markdown("

EN: PLEASE INSERT YOUR TEXT
ҚАЗ: МӘТІНДІ ОРНАЛАСТЫРЫҢЫЗ
РУС: ВСТАВЬТЕ ТЕКСТ

", unsafe_allow_html = True) return annotated_text(modified_output) ######################### #### CREATE SIDEBAR ##### ######################### with open("style.css") as f: css = f.read() languages = ['🇬🇧', '🇰🇿', '🇷🇺'] language = st.sidebar.radio("", options = languages, horizontal = True) st.sidebar.markdown(f'', unsafe_allow_html = True) if language == languages[0]: st.sidebar.markdown("

Kazakh NER

", unsafe_allow_html = True) st.sidebar.markdown("

Named entity classes

", unsafe_allow_html = True) with st.sidebar.expander("ADAGE"): st.write("Well-known Kazakh proverbs and sayings") with st.sidebar.expander("ART"): st.write("Titles of books, songs, television programmes, etc.") with st.sidebar.expander("CARDINAL"): st.write("Cardinal numbers, including whole numbers, fractions, and decimals") with st.sidebar.expander("CONTACT"): st.write("Addresses, emails, phone numbers, URLs") with st.sidebar.expander("DATE"): st.write("Dates or periods of 24 hours or more") with st.sidebar.expander("DISEASE"): st.write("Diseases or medical conditions") with st.sidebar.expander("EVENT"): st.write("Named events and phenomena") with st.sidebar.expander("FACILITY"): st.write("Names of man-made structures") with st.sidebar.expander("GPE"): st.write("Names of geopolitical entities") with st.sidebar.expander("LANGUAGE"): st.write("Named languages") with st.sidebar.expander("LAW"): st.write("Named legal documents") with st.sidebar.expander("LOCATION"): st.write("Names of geographical locations other than GPEs") with st.sidebar.expander("MISCELLANEOUS"): st.write("Entities of interest but hard to assign a proper tag to") with st.sidebar.expander("MONEY"): st.write("Monetary values") with st.sidebar.expander("NON_HUMAN"): st.write("Names of pets, animals or non-human creatures") with st.sidebar.expander("NORP"): st.write("Adjectival forms of GPE and LOCATION; named religions, etc.") with st.sidebar.expander("ORDINAL"): st.write("Ordinal numbers, including adverbials") with st.sidebar.expander("ORGANISATION"): st.write("Names of companies, government agencies, etc.") with st.sidebar.expander("PERCENTAGE"): st.write("Percentages") with st.sidebar.expander("PERSON"): st.write("Names of persons") with st.sidebar.expander("POSITION"): st.write("Names of posts and job titles") with st.sidebar.expander("PRODUCT"): st.write("Names of products") with st.sidebar.expander("PROJECT"): st.write("Names of projects, policies, plans, etc.") with st.sidebar.expander("QUANTITY"): st.write("Length, distance, etc. measurements") with st.sidebar.expander("TIME"): st.write("Times of day and time duration less than 24 hours") elif language == languages[1]: st.sidebar.markdown("

Атаулы мәндерді анықтау

", unsafe_allow_html = True) st.sidebar.markdown("

Атаулы мән түрлері

", unsafe_allow_html = True) with st.sidebar.expander("ADAGE >> НАҚЫЛ СӨЗ"): st.write("Қазақ мақал-мәтелдері") with st.sidebar.expander("ART >> ТУЫНДЫ"): st.write("Өнер туындылары, теледидар бағдарламалары, ғылыми мәтіндер атаулары") with st.sidebar.expander("CARDINAL >> ЕСЕПТІК САН"): st.write("Бүтін сандар мен (ондық) бөлшектер") with st.sidebar.expander("CONTACT >> БАЙЛАНЫС ДЕРЕКТЕРІ"): st.write("Мекенжайлар, телефон нөмірлері, сілтемелер және электрондық пошта адрестері") with st.sidebar.expander("DATE >> ДАТА"): st.write("Даталар, күндер, апталар, айлар, атауы бар белгілі кезеңдер, мезгілдер, жылдар") with st.sidebar.expander("DISEASE >> АУРУ"): st.write("Ауру немесе бұзылу атаулары") with st.sidebar.expander("EVENT >> ОҚИҒА"): st.write("Атауы бар оқиғалар мен табиғи құбылыстар") with st.sidebar.expander("FACILITY >> ҚҰРЫЛЫС"): st.write("Адам қолымен жасалынған құрылымдардың атаулары") with st.sidebar.expander("GPE >> ГӘС"): st.write("Географиялық әкімшілік бірліктерінің атаулары") with st.sidebar.expander("LANGUAGE >> ТІЛ"): st.write("Тіл атаулары") with st.sidebar.expander("LAW >> ЗАҢ"): st.write("Заңдастырылған құжаттар атаулары") with st.sidebar.expander("LOCATION >> МЕКЕН"): st.write("GPE атаулы мәніне жатпайтын географиялық нысандардың атаулары") with st.sidebar.expander("MISCELLANEOUS >> АРАЛАС"): st.write("Атаулы мәнді анықтауға қиыншылық тудыратын сөздер, фразалар") with st.sidebar.expander("MONEY >> АҚША БІРЛІГІ"): st.write("Құрамында сан және ақша бірлігі айқын берілген фразалар.") with st.sidebar.expander("NON_HUMAN >> АДАМ ЕМЕС"): st.write("Жануарлардың және ойдан шығарылған жануар-кейіпкерлердің лақап аттары") with st.sidebar.expander("NORP >> ҰДСҚ"): st.write("GPE және LOCATION атаулы мәндеріне қатыстылықты білдіретін сөздер") with st.sidebar.expander("ORDINAL >> РЕТТІК САН"): st.write("Реттік сандар және реттік сандардан құрылған сын есімдер мен қыстырма сөздер") with st.sidebar.expander("ORGANISATION >> ҰЙЫМ"): st.write("Ұйым атаулары") with st.sidebar.expander("PERCENTAGE >> ПАЙЫЗ"): st.write("Құрамында сан және пайыз, процент сөздері немесе % белгісі бар фразалар") with st.sidebar.expander("PERSON >> АДАМ"): st.write("Адам есімі, фамилиясы, әкесінің аты") with st.sidebar.expander("POSITION >> ОРЫН"): st.write("Адамның белгілі бір ұйымның иерархиялық жүйесіндегі орны немесе атқаратын қызметі") with st.sidebar.expander("PRODUCT >> ӨНІМ"): st.write("Өнім атаулары") with st.sidebar.expander("PROJECT >> ЖОБА"): st.write("Жобалар, жоспарлар, бастамалар, стратегиялардың атаулары") with st.sidebar.expander("QUANTITY >> ӨЛШЕМ"): st.write("Құрамында сан және өлшем бірлігі айқын берілген фразалар") with st.sidebar.expander("TIME >> УАҚЫТ"): st.write("Бір тәуліктен қысқа кезеңдер") elif language == languages[2]: st.sidebar.markdown("

Распознавание именованных сущностей

", unsafe_allow_html = True) st.sidebar.markdown("

Именованные сущности

", unsafe_allow_html = True) with st.sidebar.expander("ADAGE >> ПОСЛОВИЦА"): st.write("Известные казахские пословицы и поговорки") with st.sidebar.expander("ART >> ИСКУССТВО"): st.write("Названия книг, песен, телевизионных и радиопрограмм и др.") with st.sidebar.expander("CARDINAL >> КОЛИЧ. ЧИСЛ."): st.write("Количественные числительные (целые числа, дроби и десятичные дроби)") with st.sidebar.expander("CONTACT >> КОНТ. ДАННЫЕ"): st.write("Адреса, номера телефонов, URL-адреса и др") with st.sidebar.expander("DATE >> ДАТА"): st.write("Даты или периоды, продолжительность которых составляет 24 часа и более") with st.sidebar.expander("DISEASE >> БОЛЕЗНЬ"): st.write("Названия болезней, заболеваний, различных расстройств и недомоганий") with st.sidebar.expander("EVENT >> СОБЫТИЕ"): st.write("Названия мероприятий и природных явлений") with st.sidebar.expander("FACILITY >> СООРУЖЕНИЕ"): st.write("Названия зданий и сооружений, созданных руками человека") with st.sidebar.expander("GPE >> ГПС"): st.write("Названия геополитических объектов") with st.sidebar.expander("LANGUAGE >> ЯЗЫК"): st.write("Наименования и самоназвания языков") with st.sidebar.expander("LAW >> ЗАКОН"): st.write("Наименования юридических документов") with st.sidebar.expander("LOCATION >> МЕСТО"): st.write("Названия географических местоположений, отличных от GPE") with st.sidebar.expander("MISCELLANEOUS >> РАЗНОЕ"): st.write("Сущности, представляющие сложность при классификации") with st.sidebar.expander("MONEY >> ДЕНЬГИ"): st.write("Номинал и наименования денежных единиц") with st.sidebar.expander("NON_HUMAN >> НЕЧЕЛОВЕК"): st.write("Имена и клички домашних животных, зверей, вымышленных созданий") with st.sidebar.expander("NORP >> НОРП"): st.write("Прилагательные, образованные от сущностей GPE и LOCATION") with st.sidebar.expander("ORDINAL >> ПОРЯД. ЧИСЛ."): st.write("Порядковые числительные") with st.sidebar.expander("ORGANISATION >> ОРГАНИЗАЦИЯ"): st.write("Наименования компаний, правительственных учреждений и т. д.") with st.sidebar.expander("PERCENTAGE >> ПРОЦЕНТ"): st.write("Обозначение процентных соотношений") with st.sidebar.expander("PERSON >> ЧЕЛОВЕК"): st.write("Имена людей") with st.sidebar.expander("POSITION >> ДОЛЖНОСТЬ"): st.write("Наименования должностей") with st.sidebar.expander("PRODUCT >> ПРОДУКТ"): st.write("Названия продуктов/изделий различных видов производства") with st.sidebar.expander("PROJECT >> ПРОЕКТ"): st.write("Наименования проектов, планов, стратегий, кампаний, референдумов и др") with st.sidebar.expander("QUANTITY >> ВЕЛИЧИНА"): st.write("Наименования единиц измерения (длина, расстояние, вес, напряжение, др.)") with st.sidebar.expander("TIME >> ВРЕМЯ"): st.write("Обозначение времени, продолжительность которого менее 24 часов") ###################### #### CREATE FORM ##### ###################### if language == languages[0]: text_field = st.text_area('Insert your text here') submit = st.button("Submit", type = 'primary') st.markdown('Press **Submit** to have your text labelled') elif language == languages[1]: text_field = st.text_area('Мәтінді орналастырыңыз') submit = st.button("Анықтау", type = "primary") st.markdown('Мәтінді белгілеу үшін **Анықтау** батырмасын басыңыз') elif language == languages[2]: text_field = st.text_area('Вставьте текст') submit = st.button("Распознать", type = "primary") st.markdown('Нажмите кнопку **Распознать**, чтобы разметить текст') if submit: label_text(text_field)