import streamlit as st
import sparknlp
import os
import pandas as pd
from sparknlp.base import *
from sparknlp.annotator import *
from pyspark.ml import Pipeline
from sparknlp.pretrained import PretrainedPipeline
from annotated_text import annotated_text
# Page configuration
st.set_page_config(
layout="wide",
initial_sidebar_state="auto"
)
# CSS for styling
st.markdown("""
""", unsafe_allow_html=True)
@st.cache_resource
def init_spark():
return sparknlp.start()
@st.cache_resource
def create_pipeline(model):
documentAssembler = DocumentAssembler() \
.setInputCol("text") \
.setOutputCol("document")
sentence_detector = SentenceDetector() \
.setInputCols(["document"]) \
.setOutputCol("sentence")
tokenizer = Tokenizer() \
.setInputCols(["sentence"]) \
.setOutputCol("token")
word_embeddings = WordEmbeddingsModel.pretrained("hebrew_cc_300d", "he") \
.setInputCols(["sentence", "token"]) \
.setOutputCol("embeddings")
ner = NerDLModel.pretrained("hebrewner_cc_300d", "he") \
.setInputCols(["sentence", "token", "embeddings"]) \
.setOutputCol("ner")
ner_converter = NerConverter().setInputCols(["sentence", "token", "ner"]).setOutputCol("ner_chunk")
pipeline = Pipeline(stages=[documentAssembler, sentence_detector, tokenizer, word_embeddings, ner, ner_converter])
return pipeline
def fit_data(pipeline, data):
empty_df = spark.createDataFrame([['']]).toDF('text')
pipeline_model = pipeline.fit(empty_df)
model = LightPipeline(pipeline_model)
result = model.fullAnnotate(data)
return result
def annotate(data):
document, chunks, labels = data["Document"], data["NER Chunk"], data["NER Label"]
annotated_words = []
for chunk, label in zip(chunks, labels):
parts = document.split(chunk, 1)
if parts[0]:
annotated_words.append(parts[0])
annotated_words.append((chunk, label))
document = parts[1]
if document:
annotated_words.append(document)
annotated_text(*annotated_words)
# Set up the page layout
st.markdown('
Recognize entities in Persian text
', unsafe_allow_html=True)
st.markdown("""
Named Entity Recognition (NER) models identify and categorize important entities in a text. This page details a word embeddings-based NER model for Hebrew texts, using the hebrew_cc_300d
word embeddings. The model is pretrained and available for use with Spark NLP.
""", unsafe_allow_html=True)
# Sidebar content
model = st.sidebar.selectbox(
"Choose the pretrained model",
["hebrewner_cc_300d"],
help="For more info about the models visit: https://sparknlp.org/models"
)
# Reference notebook link in sidebar
link = """
"""
st.sidebar.markdown('Reference notebook:')
st.sidebar.markdown(link, unsafe_allow_html=True)
# Load examples
examples = [
"""והתוצאה : ספרו הפך לרב מכר ענק ובסיס לוויכוחים תיאולוגיים ודיונים נזעמים , כמו גם התקפות והאשמות כלפי בראון מחוגי הכנסייה כפי שמעולם לא התעוררו כתוצאה מספריהם של וואלאס או לאדלום , ואף גרם לסופר מצליח בזכות עצמו , דן בורסטין , לערוך את הספר " הסודות שמאחורי צופן דה וינצ'י " , שבו הוא בודק אחת לאחת את העובדות וההנחות שעליהן מסתמך בראון על ידי שפע של מאמרים , חלקם מקוריים וחלקם לקוחים מספרים , כתבי עת וראיונות עם חוקרים שונים .""",
"""בגלל קוצר היריעה לא נתעסק כאן בכל הנושאים המגוונים שבהם דן הספר , כמו למשל דמותה של מרים המגדלית , הדעות האזוטריות של ליאונרדו דה וינצי וכן הלאה , אלא נתמקד בנושא אחד - באגודת הסתר " מסדר ציון " - מסדר חשאי הקיים כביכול מזה אלף שנה , ותפקידו להגן על צאצאי השושלת המ ֶרוב ּינגית הקדומה של צרפת , שהם למעשה צאצאי ישוע ומרים המגדלית , ולפיכך הם , לדעת חברי המסדר , השושלת המלכותית הלגיטימית של צרפת , מה שאומר כמובן שמלכי צרפת הם ממוצא יהודי .""",
"""ב 32 באוקטובר התפעלה ממנו בעלת טור בעיתון " בוסטון גלוב " במלים היאות למעריצה בת 21 : " הוא עשה בחודשים אחדים למען צחות הדיבור מה שלקח לחברה שנים כדי לעשות למען טלוויזיה צבעונית ... אם דיבור היה ספורט אולימפי , הוא היה זוכה במדליית הזהב ... סילבר כה טוב , עד שהוא גורם לאנגלית להישמע כמו צרפתית ... אם ייבחר , תהיה לכולנו ההזדמנות ללמוד ממנו להיות סטודנטים בכיתתו הענקית , הנקראת מסצוסטס " .""",
"""לא מינה ולא מקצתה ! הרי שם סיפרתי על ההגעה בקרונות החנק , על המתים שטואטאו מהקרונות , על " קומנדו קנדה " , על אנשי הס"ס וכלביהם האמתניים , על אלומות האור מנקרות העיניים ששלחו הזרקורים , על בכי ילדים שנקרעו מזרועות אמותיהם , ולעתים נשארו האמהות הצעירות בחיים , ואתה מותיר רק מלים בודדות על ה"סלקציה " .""",
"""שוויד חושף את תמחורי המוצרים היציבים של החברה: " המחירים נותרו זהים : 70 דולר לאבטחת עסק קטן , 300 דולר לאבטחת רשת בעסק קטן , בין 1,500 ל - 3,500 דולר לאבטחת חברות גדולות עם אתר ראשי ועד 500 מחשבים , באמצעות מוצרי הצ'ק פוינט אקספרס , ובין 15,000 ל - 20,000 דולר לעסק עם 3 עד 4 אתרים , חברות גדולות עם מחזורי מכירות משמעותיים ."""
]
selected_text = st.selectbox("Select an example", examples)
custom_input = st.text_input("Try it with your own Sentence!")
text_to_analyze = custom_input if custom_input else selected_text
st.subheader('Full example text')
HTML_WRAPPER = """{}
"""
st.markdown(HTML_WRAPPER.format(text_to_analyze), unsafe_allow_html=True)
# Initialize Spark and create pipeline
spark = init_spark()
pipeline = create_pipeline(model)
output = fit_data(pipeline, text_to_analyze)
# Display matched sentence
st.subheader("Processed output:")
results = {
'Document': output[0]['document'][0].result,
'NER Chunk': [n.result for n in output[0]['ner_chunk']],
"NER Label": [n.metadata['entity'] for n in output[0]['ner_chunk']]
}
annotate(results)
with st.expander("View DataFrame"):
df = pd.DataFrame({'NER Chunk': results['NER Chunk'], 'NER Label': results['NER Label']})
df.index += 1
st.dataframe(df)