Spaces:
Runtime error
Runtime error
import pandas as pd | |
import gradio as gr | |
import stanza | |
import torch | |
from collections import Counter | |
import nltk | |
from thefuzz import process | |
from thefuzz import fuzz | |
import re | |
from sentence_transformers import SentenceTransformer | |
from keyphrase_vectorizers import KeyphraseCountVectorizer | |
from keybert import KeyBERT | |
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
print(DEVICE) | |
def get_fuzz_candidates(candidates): | |
result = [] | |
try: | |
for item in candidates: | |
if len(result) == 0: | |
result.append(item) | |
elif len(result) == 1: | |
extract = fuzz.token_sort_ratio(item, candidates[0]) | |
if extract < 85: | |
result.append(item) | |
else: | |
extract = process.extractOne(item, result, scorer=fuzz.token_sort_ratio) | |
if extract[1] < 85: | |
result.append(item) | |
except Exception as e: | |
print(str(e)) | |
def pre_proccess_text(text): | |
stopword = ['ada', 'adalah', 'adanya', 'adapun', 'agak', 'agaknya', 'agar', 'akan', 'akankah', 'akhir', 'akhiri', 'akhirnya', 'aku', 'akulah', 'amat', 'amatlah', 'anda', 'andalah', 'antar', 'antara', 'antaranya', 'apa', 'apaan', 'apabila', 'apakah', 'apalagi', 'apatah', 'artinya', 'asal', 'asalkan', 'atas', 'atau', 'ataukah', 'ataupun', 'awal', 'awalnya', 'bagai', 'bagaikan', 'bagaimana', 'bagaimanakah', 'bagaimanapun', 'bagi', 'bagian', 'bahkan', 'bahwa', 'bahwasanya', 'baik', 'bakal', 'bakalan', 'balik', 'banyak', 'bapak', 'baru', 'bawah', 'beberapa', 'begini', 'beginian', 'beginikah', 'beginilah', 'begitu', 'begitukah', 'begitulah', 'begitupun', 'bekerja', 'belakang', 'belakangan', 'belum', 'belumlah', 'benar', 'benarkah', 'benarlah', 'berada', 'berakhir', 'berakhirlah', 'berakhirnya', 'berapa', 'berapakah', 'berapalah', 'berapapun', 'berarti', 'berawal', 'berbagai', 'berdatangan', 'beri', 'berikan', 'berikut', 'berikutnya', 'berjumlah', 'berkali-kali', 'berkata', 'berkehendak', 'berkeinginan', 'berkenaan', 'berlainan', 'berlalu', 'berlangsung', 'berlebihan', 'bermacam', 'bermacam-macam', 'bermaksud', 'bermula', 'bersama', 'bersama-sama', 'bersiap', 'bersiap-siap', 'bertanya', 'bertanya-tanya', 'berturut', 'berturut-turut', 'bertutur', 'berujar', 'berupa', 'besar', 'betul', 'betulkah', 'biasa', 'biasanya', 'bila', 'bilakah', 'bisa', 'bisakah', 'boleh', 'bolehkah', 'bolehlah', 'buat', 'bukan', 'bukankah', 'bukanlah', 'bukannya', 'bulan', 'bung', 'cara', 'caranya', 'cukup', 'cukupkah', 'cukuplah', 'cuma', 'dahulu', 'dalam', 'dan', 'dapat', 'dari', 'daripada', 'datang', 'dekat', 'demi', 'demikian', 'demikianlah', 'dengan', 'depan', 'di', 'dia', 'diakhiri', 'diakhirinya', 'dialah', 'diantara', 'diantaranya', 'diberi', 'diberikan', 'diberikannya', 'dibuat', 'dibuatnya', 'didapat', 'didatangkan', 'digunakan', 'diibaratkan', 'diibaratkannya', 'diingat', 'diingatkan', 'diinginkan', 'dijawab', 'dijelaskan', 'dijelaskannya', 'dikarenakan', 'dikatakan', 'dikatakannya', 'dikerjakan', 'diketahui', 'diketahuinya', 'dikira', 'dilakukan', 'dilalui', 'dilihat', 'dimaksud', 'dimaksudkan', 'dimaksudkannya', 'dimaksudnya', 'diminta', 'dimintai', 'dimisalkan', 'dimulai', 'dimulailah', 'dimulainya', 'dimungkinkan', 'dini', 'dipastikan', 'diperbuat', 'diperbuatnya', 'dipergunakan', 'diperkirakan', 'diperlihatkan', 'diperlukan', 'diperlukannya', 'dipersoalkan', 'dipertanyakan', 'dipunyai', 'diri', 'dirinya', 'disampaikan', 'disebut', 'disebutkan', 'disebutkannya', 'disini', 'disinilah', 'ditambahkan', 'ditandaskan', 'ditanya', 'ditanyai', 'ditanyakan', 'ditegaskan', 'ditujukan', 'ditunjuk', 'ditunjuki', 'ditunjukkan', 'ditunjukkannya', 'ditunjuknya', 'dituturkan', 'dituturkannya', 'diucapkan', 'diucapkannya', 'diungkapkan', 'dong', 'dua', 'dulu', 'empat', 'enggak', 'enggaknya', 'entah', 'entahlah', 'guna', 'gunakan', 'hal', 'hampir', 'hanya', 'hanyalah', 'hari', 'harus', 'haruslah', 'harusnya', 'hendak', 'hendaklah', 'hendaknya', 'hingga', 'ia', 'ialah', 'ibarat', 'ibaratkan', 'ibaratnya', 'ibu', 'ikut', 'ingat', 'ingat-ingat', 'ingin', 'inginkah', 'inginkan', 'ini', 'inikah', 'inilah', 'itu', 'itukah', 'itulah', 'jadi', 'jadilah', 'jadinya', 'jangan', 'jangankan', 'janganlah', 'jauh', 'jawab', 'jawaban', 'jawabnya', 'jelas', 'jelaskan', 'jelaslah', 'jelasnya', 'jika', 'jikalau', 'juga', 'jumlah', 'jumlahnya', 'justru', 'kala', 'kalau', 'kalaulah', 'kalaupun', 'kalian', 'kami', 'kamilah', 'kamu', 'kamulah', 'kan', 'kapan', 'kapankah', 'kapanpun', 'karena', 'karenanya', 'kasus', 'kata', 'katakan', 'katakanlah', 'katanya', 'ke', 'keadaan', 'kebetulan', 'kecil', 'kedua', 'keduanya', 'keinginan', 'kelamaan', 'kelihatan', 'kelihatannya', 'kelima', 'keluar', 'kembali', 'kemudian', 'kemungkinan', 'kemungkinannya', 'kenapa', 'kepada', 'kepadanya', 'kesampaian', 'keseluruhan', 'keseluruhannya', 'keterlaluan', 'ketika', 'khususnya', 'kini', 'kinilah', 'kira', 'kira-kira', 'kiranya', 'kita', 'kitalah', 'kok', 'kurang', 'lagi', 'lagian', 'lah', 'lain', 'lainnya', 'lalu', 'lama', 'lamanya', 'lanjut', 'lanjutnya', 'lebih', 'lewat', 'lima', 'luar', 'macam', 'maka', 'makanya', 'makin', 'malah', 'malahan', 'mampu', 'mampukah', 'mana', 'manakala', 'manalagi', 'masa', 'masalah', 'masalahnya', 'masih', 'masihkah', 'masing', 'masing-masing', 'mau', 'maupun', 'melainkan', 'melakukan', 'melalui', 'melihat', 'melihatnya', 'memang', 'memastikan', 'memberi', 'memberikan', 'membuat', 'memerlukan', 'memihak', 'meminta', 'memintakan', 'memisalkan', 'memperbuat', 'mempergunakan', 'memperkirakan', 'memperlihatkan', 'mempersiapkan', 'mempersoalkan', 'mempertanyakan', 'mempunyai', 'memulai', 'memungkinkan', 'menaiki', 'menambahkan', 'menandaskan', 'menanti', 'menanti-nanti', 'menantikan', 'menanya', 'menanyai', 'menanyakan', 'mendapat', 'mendapatkan', 'mendatang', 'mendatangi', 'mendatangkan', 'menegaskan', 'mengakhiri', 'mengapa', 'mengatakan', 'mengatakannya', 'mengenai', 'mengerjakan', 'mengetahui', 'menggunakan', 'menghendaki', 'mengibaratkan', 'mengibaratkannya', 'mengingat', 'mengingatkan', 'menginginkan', 'mengira', 'mengucapkan', 'mengucapkannya', 'mengungkapkan', 'menjadi', 'menjawab', 'menjelaskan', 'menuju', 'menunjuk', 'menunjuki', 'menunjukkan', 'menunjuknya', 'menurut', 'menuturkan', 'menyampaikan', 'menyangkut', 'menyatakan', 'menyebutkan', 'menyeluruh', 'menyiapkan', 'merasa', 'mereka', 'merekalah', 'merupakan', 'meski', 'meskipun', 'meyakini', 'meyakinkan', 'minta', 'mirip', 'misal', 'misalkan', 'misalnya', 'mula', 'mulai', 'mulailah', 'mulanya', 'mungkin', 'mungkinkah', 'nah', 'naik', 'namun', 'nanti', 'nantinya', 'nyaris', 'nyatanya', 'oleh', 'olehnya', 'pada', 'padahal', 'padanya', 'pak', 'paling', 'panjang', 'pantas', 'para', 'pasti', 'pastilah', 'penting', 'pentingnya', 'per', 'percuma', 'perlu', 'perlukah', 'perlunya', 'pernah', 'persoalan', 'pertama', 'pertama-tama', 'pertanyaan', 'pertanyakan', 'pihak', 'pihaknya', 'pukul', 'pula', 'pun', 'punya', 'rasa', 'rasanya', 'rata', 'rupanya', 'saat', 'saatnya', 'saja', 'sajalah', 'saling', 'sama', 'sama-sama', 'sambil', 'sampai', 'sampai-sampai', 'sampaikan', 'sana', 'sangat', 'sangatlah', 'satu', 'saya', 'sayalah', 'se', 'sebab', 'sebabnya', 'sebagai', 'sebagaimana', 'sebagainya', 'sebagian', 'sebaik', 'sebaik-baiknya', 'sebaiknya', 'sebaliknya', 'sebanyak', 'sebegini', 'sebegitu', 'sebelum', 'sebelumnya', 'sebenarnya', 'seberapa', 'sebesar', 'sebetulnya', 'sebisanya', 'sebuah', 'sebut', 'sebutlah', 'sebutnya', 'secara', 'secukupnya', 'sedang', 'sedangkan', 'sedemikian', 'sedikit', 'sedikitnya', 'seenaknya', 'segala', 'segalanya', 'segera', 'seharusnya', 'sehingga', 'seingat', 'sejak', 'sejauh', 'sejenak', 'sejumlah', 'sekadar', 'sekadarnya', 'sekali', 'sekali-kali', 'sekalian', 'sekaligus', 'sekalipun', 'sekarang', 'sekarang', 'sekecil', 'seketika', 'sekiranya', 'sekitar', 'sekitarnya', 'sekurang-kurangnya', 'sekurangnya', 'sela', 'selain', 'selaku', 'selalu', 'selama', 'selama-lamanya', 'selamanya', 'selanjutnya', 'seluruh', 'seluruhnya', 'semacam', 'semakin', 'semampu', 'semampunya', 'semasa', 'semasih', 'semata', 'semata-mata', 'semaunya', 'sementara', 'semisal', 'semisalnya', 'sempat', 'semua', 'semuanya', 'semula', 'sendiri', 'sendirian', 'sendirinya', 'seolah', 'seolah-olah', 'seorang', 'sepanjang', 'sepantasnya', 'sepantasnyalah', 'seperlunya', 'seperti', 'sepertinya', 'sepihak', 'sering', 'seringnya', 'serta', 'serupa', 'sesaat', 'sesama', 'sesampai', 'sesegera', 'sesekali', 'seseorang', 'sesuatu', 'sesuatunya', 'sesudah', 'sesudahnya', 'setelah', 'setempat', 'setengah', 'seterusnya', 'setiap', 'setiba', 'setibanya', 'setidak-tidaknya', 'setidaknya', 'setinggi', 'seusai', 'sewaktu', 'siap', 'siapa', 'siapakah', 'siapapun', 'sini', 'sinilah', 'soal', 'soalnya', 'suatu', 'sudah', 'sudahkah', 'sudahlah', 'supaya', 'tadi', 'tadinya', 'tahu', 'tahun', 'tak', 'tambah', 'tambahnya', 'tampak', 'tampaknya', 'tandas', 'tandasnya', 'tanpa', 'tanya', 'tanyakan', 'tanyanya', 'tapi', 'tegas', 'tegasnya', 'telah', 'tempat', 'tengah', 'tentang', 'tentu', 'tentulah', 'tentunya', 'tepat', 'terakhir', 'terasa', 'terbanyak', 'terdahulu', 'terdapat', 'terdiri', 'terhadap', 'terhadapnya', 'teringat', 'teringat-ingat', 'terjadi', 'terjadilah', 'terjadinya', 'terkira', 'terlalu', 'terlebih', 'terlihat', 'termasuk', 'ternyata', 'tersampaikan', 'tersebut', 'tersebutlah', 'tertentu', 'tertuju', 'terus', 'terutama', 'tetap', 'tetapi', 'tiap', 'tiba', 'tiba-tiba', 'tidak', 'tidakkah', 'tidaklah', 'tiga', 'tinggi', 'toh', 'tunjuk', 'turut', 'tutur', 'tuturnya', 'ucap', 'ucapnya', 'ujar', 'ujarnya', 'umum', 'umumnya', 'ungkap', 'ungkapnya', 'untuk', 'usah', 'usai', 'waduh', 'wah', 'wahai', 'waktu', 'waktunya', 'walau', 'walaupun', 'wong', 'yaitu', 'yakin', 'yakni', 'yang'] | |
text_1 = text.lower().split() | |
text_1 = [x for x in text_1 if x not in stopword] | |
text_1 = " ".join(text_1) | |
return text_1 | |
def parser_text(doc, text): | |
grammar = "NP: {<NOUN>+}" | |
# grammar = "NP: {<NOUN>+}" | |
parser = nltk.RegexpParser(grammar) | |
# create word and POS tag pair | |
pairs = [] | |
for sentence in doc.sentences: | |
tagged = [] | |
for word in sentence.words: | |
tagged.append((word.text, word.upos)) | |
pairs.append(tagged) | |
candidates = [] | |
for sentence in pairs: | |
parse_tree = parser.parse(sentence) | |
for subtree in parse_tree.subtrees(): | |
if subtree.label() == 'NP' and (len(subtree.leaves()) >= 1 and len(subtree.leaves()) <= 3): # only consider bigram | |
words = [item[0] for item in subtree.leaves()] | |
keyword = ' '.join(words) | |
clean_keyword = re.sub('[^A-Za-z0-9]+', ' ', keyword) | |
if len(re.findall(clean_keyword, text, flags=re.IGNORECASE)) > 0: | |
candidates.append(clean_keyword) | |
return candidates | |
def sort_freq_candidates(self, candidates): | |
freq = Counter(candidates) | |
freq_used = freq.most_common(500) | |
for k,v in freq_used: | |
if k not in self.candidates: | |
self.candidates.append(k) | |
def keybert_keyword(text, candidate, diversity, result): | |
top_p = result | |
if result > len(candidate): | |
top_p = len(candidate) | |
# DEVICE = "cuda:0" | |
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
model_1 = 'paraphrase-multilingual-MiniLM-L12-v2' | |
model = SentenceTransformer(model_1, device=DEVICE) | |
kw_model = KeyBERT(model) | |
#vectorizer = KeyphraseCountVectorizer(pos_pattern='<J.*>*<N.*>+') | |
#vectorizer=vectorizer, | |
keyword = kw_model.extract_keywords(text, candidates=candidate, top_n=top_p, use_mmr=True, diversity=diversity) | |
keyword = parser_keyword(keyword, text) | |
return keyword | |
def parser_keyword(keywords, text): | |
clean_data = [] | |
for k, v in keywords: | |
data = {} | |
if v > 0.22 : | |
freq = len(re.findall(k, text, flags=re.IGNORECASE)) | |
if freq > 0: | |
data['keyword'] = k | |
data['score'] = v | |
data['freq'] = len(re.findall(k, text, flags=re.IGNORECASE)) | |
clean_data.append(data) | |
return sorted(clean_data, key=lambda k: k['score'], reverse=True) | |
def get_keyword(text, diversity, result, lang): | |
lang = lang | |
stanza.download(lang, processors='tokenize,pos') | |
nlp = stanza.Pipeline(lang=lang, processors='tokenize,pos', use_gpu=False) | |
list_candidates = [] | |
clean_text = pre_proccess_text(text) | |
nlp = nlp(clean_text.lower()) | |
candidates = parser_text(nlp, text) | |
#freq = Counter(candidates) | |
#freq_used = freq.most_common(500) | |
#for k,v in freq_used: | |
# if k not in list_candidates: | |
# list_candidates.append(k) | |
bert_keyword = keybert_keyword(text, candidates, diversity, result) | |
kw = pd.DataFrame(columns=['keyword', 'Score', 'Freq']) | |
kw = kw.append(bert_keyword, ignore_index=True) | |
kw = pd.DataFrame(data=bert_keyword) | |
return kw | |
ex1 ="Bitcoint is a digital asset and currency created by Satoshi Nakamoto. It was proposed in 2008 and implemented in 2009 as the first practical cryptocurrency. Bitcoint is based on the blockchain technology, which allows secure, decentralized transactions and control of the creation of new units." | |
ex2 = "Bitcoin adalah mata uang digital yang pertama kali diperkenalkan pada tahun 2009. Digunakan untuk membeli barang dan melakukan transaksi di internet. Bitcoin terdesentralisasi, artinya tidak tunduk pada kontrol pemerintah atau lembaga keuangan. Bitcoin telah disebut sebagai contoh terbaik dari proyek perangkat lunak sumber terbuka karena kodenya terus diperbarui dan ditingkatkan." | |
title = "SEO NLP - Bert Keyword Extractor" | |
description = "Demo penggunaan BERT models untuk meng-ekstrak keyword yang penting dari input artikel. Penjelasan dari SEO NLP di <a href='https://saungseo.com/' target='_blank'>saung seo</a>" | |
web = gr.Interface( | |
get_keyword, | |
inputs=[gr.Textbox(label="Artikel Text",lines=20), | |
gr.Slider(0.2,0.9,step=0.1,value=0.3,label="Diversity Keyword"), | |
gr.Slider(5,100,step=1,value=10,label="Max Result"), | |
gr.Dropdown(["id", "en", "es"])], | |
outputs=[ gr.outputs.Dataframe()], | |
examples=[[ex1,0.3,10,"en"],[ex2,0.3,10,"id"]], examples_per_page=2, live=False, | |
layout="horizontal", interpretation=None, title=title, | |
description=description | |
) | |
web.launch(debug=True) |