Spaces:
Sleeping
Sleeping
| import os | |
| import sys | |
| import streamlit as st | |
| from dotenv import load_dotenv, find_dotenv | |
| from huggingface_hub import snapshot_download # type: ignore | |
| import spacy | |
| from spacy_streamlit import visualize_spans | |
| import plotly.graph_objects as go | |
| import json | |
| from io import StringIO | |
| load_dotenv(find_dotenv()) | |
| FILTERED_OUT_CONCEPTS = [ | |
| "Präsenzpflicht", "Flexible und gestaltbare Dienstpläne und Schichtmodelle", "Finanzielle Unterstützung", "Unterstützung bei der Pflegeverantwortung" | |
| ] | |
| ANFORDERUNGEN = [ | |
| # "Präsenzpflicht", | |
| "Räumliche Flexibilität", | |
| "Zeitliche Flexibilität", | |
| "Schichtdienst", | |
| "Flexibiltät (SK) = Flexibilität (Soft Skill)", | |
| ] | |
| ANGEBOTE = [ | |
| "Planbarkeit und Verlässlichkeit", | |
| # "Flexible und gestaltbare Dienstpläne und Schichtmodelle", | |
| "flexible und gestaltbare Arbeitszeiten", | |
| "Wahl des Arbeitszeitumfangs", | |
| "Job-Sharing", | |
| "Vereinbarkeit", | |
| "Unterstützung bei der Kinderbetreuung", | |
| "wohnortnahe Einsätze", | |
| # "Finanzielle Unterstützung", | |
| "Familiäre und anlassbezogene Freistellung", | |
| # "Unterstützung bei der Pflegeverantwortung", | |
| ] | |
| ALL_CONCEPTS = ( | |
| ANFORDERUNGEN | |
| + ANGEBOTE | |
| + [ | |
| "Anforderungen an Bewerber:innen", | |
| "Anforderungen an Arbeitsort", | |
| "Zeitliche", | |
| "Flexibilität", | |
| "Angebote an Bewerber:innen", | |
| "Zeitsouveränität", | |
| "Familienfreundliche Konzepte", | |
| ] | |
| ) | |
| PARENTS = [ | |
| # "Anforderungen an Arbeitsort", | |
| "Anforderungen an Arbeitsort", | |
| "Zeitliche", | |
| "Zeitliche", | |
| "Flexibilität", | |
| "Zeitsouveränität", | |
| # "Zeitsouveränität", | |
| "Zeitsouveränität", | |
| "Zeitsouveränität", | |
| "Zeitsouveränität", | |
| "Familienfreundliche Konzepte", | |
| # "Familienfreundliche Konzepte", | |
| "Familienfreundliche Konzepte", | |
| # "Familienfreundliche Konzepte", | |
| "Familienfreundliche Konzepte", | |
| "Familienfreundliche Konzepte", | |
| "", | |
| "Anforderungen an Bewerber:innen", | |
| "Anforderungen an Bewerber:innen", | |
| "Anforderungen an Bewerber:innen", | |
| "", | |
| "Angebote an Bewerber:innen", | |
| "Angebote an Bewerber:innen", | |
| ] | |
| fig = go.Figure( | |
| go.Treemap( | |
| labels=ALL_CONCEPTS, | |
| parents=PARENTS, | |
| textinfo="label", | |
| ) | |
| ) | |
| # ig.update_traces(root_color="lightblue") | |
| fig.update_layout(margin=dict(t=50, l=25, r=25, b=25)) | |
| fig.update_layout(height=600, width=1400, template="plotly") | |
| model_name = "de_core_news_sm" | |
| if not spacy.util.is_package(model_name): | |
| # Download the model if not present | |
| os.system(f"python -m spacy download {model_name}") | |
| path = snapshot_download( | |
| cache_dir="tmp/", | |
| repo_id="and-effect/family-compatibility-extractor-copy", | |
| revision="main", | |
| token=os.getenv("HF_TOKEN"), | |
| ) | |
| sys.path.append(path) | |
| from pipeline import PipelineWrapper # noqa: E402 | |
| def load_pipeline(repo_path: str) -> PipelineWrapper: | |
| """Load the pipeline""" | |
| return PipelineWrapper(path=repo_path) | |
| def load_app_init() -> None: | |
| """Load the app initialisation""" | |
| st.title("Family Compatibility Extractor") | |
| st.markdown( | |
| """ | |
| <style> | |
| .font { | |
| font-size:20px !important; | |
| } | |
| </style> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| st.markdown( | |
| """ | |
| <style> | |
| .prediction { | |
| font-size:10px !important; | |
| } | |
| </style> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| st.markdown( | |
| """ <p class="font">Der Family Compatibility Extractor ist ein | |
| Sprachmodell, das aus den Texten von Jobanzeigen Anforderungen und | |
| Angebote an bzw. für Bewerbende extrahiert, die im Zusammenhang mit | |
| Familienkompatibilität stehen. | |
| Die Grafik unten zeigt die Taxonomie der extrahierten Konzepte. | |
| Hier wird die Taxonomie angezeigt wie sie in der Studie und deren Analysen benutzt wird. | |
| Die Konzepte 'Präsenzpflicht', 'Flexible und gestaltbare Dienstpläne und Schichtmodelle', | |
| 'Finanzielle Unterstützung' und 'Unterstützung bei der Pflegeverantwortung' wurden dafür nicht berücksichtigt.""", | |
| unsafe_allow_html=True, | |
| ) | |
| # taxonomy table einfügen | |
| st.plotly_chart(fig) | |
| st.header("Untersuche das Family Compatibility Modell") | |
| st.markdown( | |
| """ <p class="font">Lade den Text einer Jobanzeige hoch oder gebe ihn | |
| in das Eingabefeld ein und drücke den jeweiligen Extrahieren- | |
| Button, um die vorhergesagten Familienkompatibilitätskonzepte und die | |
| dazugehörigen Erklärungen zu sehen. | |
| Klicke auf den Beispieltext rechts um das Eingabefeld damit zu füllen | |
| und das Modell zu testen.</p>""", | |
| unsafe_allow_html=True, | |
| ) | |
| st.set_page_config(layout="wide") | |
| load_app_init() | |
| pipeline = load_pipeline(repo_path=path) | |
| # we need to keep button status in session state | |
| if "clicked" not in st.session_state: | |
| st.session_state.clicked = {1: False, 2: False, 3: False} | |
| def clicked(button: int) -> None: | |
| """updates session state variable when an example | |
| job title button is clicked | |
| Parameters | |
| ---------- | |
| button : int | |
| The number of the button that was clicked | |
| """ | |
| st.session_state.clicked[button] = True | |
| st.session_state.clicked[(button + 1) % 3] = False | |
| st.session_state.clicked[(button + 2) % 3] = False | |
| def reset_buttons() -> None: | |
| """resets the session state variable for the example | |
| job title buttons when the user types in a job title | |
| """ | |
| st.session_state.clicked = {1: False, 2: False, 3: False} | |
| st.markdown( | |
| """ | |
| <style> | |
| /* Style columns */ | |
| [data-testid="column"] { | |
| border-radius: 15px; | |
| background-color: white; | |
| box-shadow: 0 0 10px #eee; | |
| border: 1px solid #ddd; | |
| padding: 1rem;; | |
| } | |
| /* Style containers */ | |
| [data-testid="stVerticalBlock"] > | |
| [style*="flex-direction: column;"] > [data-testid="stVerticalBlock"] { | |
| border-radius: 15px; | |
| background-color: white; | |
| box-shadow: 0 0 10px #eee; | |
| border: 1px solid #ddd; | |
| padding: 1rem;; | |
| } | |
| </style> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| st.markdown( | |
| """ | |
| <style> | |
| .example { | |
| font-size:24px !important; | |
| } | |
| </style> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| left_column, middle_column, right_column = st.columns(3) | |
| with right_column: | |
| st.markdown( | |
| '<p class="example">Beispiel</p>', | |
| unsafe_allow_html=True, | |
| ) | |
| st.markdown( | |
| """ <p class="font">Klicke auf die Beispielausschreibung, um die | |
| extrahierten Konzepte anzuzeigen.</p>""", | |
| unsafe_allow_html=True, | |
| ) | |
| st.button( | |
| """\n## Stellendetails zu: Mitarbeiter in der Produktion (m/w/d)\n\n### Mitarbeiter | |
| in der Produktion (m/w/d)\n\nHelfer/in - Elektro \nVer\u00f6ffentlicht: | |
| XX.XX.2023\n\n#### Mitarbeiter in der Produktion (m/w/d)\n\nXXXX | |
| GmbH\n\n#### Typ:\n\nArbeit\n\n#### Arbeitszeit:\n\nVollzeit\n\n#### | |
| Eintrittsdatum:\n\nab sofort\n\n#### Arbeitsort:\n\XXXX\n\n### | |
| Stellenbeschreibung\n\nOrt: XXX Arbeitszeitmodell: Vollzeit | |
| Vertragsart: Arbeitnehmer\u00fcberlassung mit \u00dcbernahmeoption | |
| Branche: Elektro Startzeitpunkt: ab sofort Die XXXX GmbH ist Ihr | |
| Dienstleister im Gro\u00dfraum XXXX f\u00fcr eine faire, professionelle | |
| Umsetzung Ihrer neuen beruflichen Herausforderungen. Gestalten auch Sie | |
| Ihre berufliche Zukunft mit uns! Zum n\u00e4chstm\u00f6glichen Zeitpunkt | |
| suchen wir die ideale Besetzung f\u00fcr die Position: Mitarbeiter in der | |
| Produktion (m/w/d) Langfristige Besch\u00e4ftigungsoption Ihre Vorteile: | |
| *All-in-One: Umfassende Beratung und unkomplizierter Bewerbungsprozess mit | |
| XXXX * Bezahlung: Attraktives Gehalt mit Zusatzleistungen (z.B. | |
| Weihnachtsgeld) *Sicherheit: Vermittlung in einen zukunftssicheren | |
| Arbeitsplatz* Work-Life-Balance: Geregelte Arbeitszeiten *Onboarding: | |
| Umfangreiche und gr\u00fcndliche Einarbeitung* Abwechslung: Vielseitige | |
| und spannende Aufgaben *Arbeitsumgebung: Flache Hierarchien, modernes | |
| Arbeitsumfeld und ein aufgeschlossenes Team* Was wir von BS \nimmer bieten | |
| k\u00f6nnen: Pers\u00f6nlicher Ansprechpartner, gro\u00dfes | |
| Unternehmensnetzwerk, kostenlose Arbeitskleidung sowie eine zeitnahe | |
| R\u00fcckmeldung zum Bewerbungsstatus Ihre Aufgaben: *Montage von | |
| Elektronik-Komponenten* Konfektionierung einzelner Komponenten | |
| *Verpackungst\u00e4tigkeiten Ihr Profil:* Berufserfahrung: Idealerweise | |
| erste Berufserfahrung in einer vergleichbaren Position *Hard Skills: | |
| Fingerfertigkeit und technisches Grundverst\u00e4ndnis* Soft Skills: | |
| Teambewusstsein und eine gute Kommunikationsf\u00e4higkeit * Arbeitsweise: | |
| Sorgf\u00e4ltig und strukturiert\n\n### Anforderungen an den Bewerber\n\n | |
| #### Berufserfahrung:\n\nMit Berufserfahrung\n\n#### F\u00e4higkeiten:\n\n* | |
| ##### Transport, Verkehr \nGrundkenntnisse \nLagerarbeit, Transport\n* | |
| ##### Produktion, Verarbeitung, Technik \nGrundkenntnisse | |
| \nBest\u00fccken, Maschinenf\u00fchrung, Anlagenf\u00fchrung, | |
| -bedienung, Montage (Elektrotechnik)\n\n#### Pers\u00f6nliche | |
| St\u00e4rken:\n\n* Selbst\u00e4ndiges Arbeiten\n* Sorgfalt/Genauigkeit\n* | |
| Motivation/ Leistungsbereitschaft\n* Zuverl\u00e4ssigkeit\n* | |
| Lernbereitschaft\n\n#### Sprachen:\n\n* Grundkenntnisse \nDeutsch\n\n | |
| #### Fahrzeug erforderlich:\n\nNein\n\n#### Reise-/Montagebereitschaft: | |
| \n\nNicht erforderlich\n\n### Arbeitsorte\n\n* XXXX \n\n### | |
| Arbeitgeber\n\nXXX GmbH\n\n#### Firmenadresse:\n\n | |
| XXXX\n\n#### Branchengruppe:\n\n | |
| Arbeitnehmer\u00fcberlassung, Zeitarbeit\n\n#### Branche:\n\nBefristete | |
| \u00dcberlassung von Arbeitskr\u00e4ften\n\n### Weitere Informationen | |
| \n\nDas Stellenangebot wird durch den Arbeitgeber selbst verwaltet.\n\n | |
| Stelle im Rahmen der Arbeitnehmer\u00fcberlassung.\n\n#### Tarifvertrag: | |
| \n\nIGZ\n\n#### Befristung:\n\nUnbefristet\n\n#### Anzahl freier Stellen: | |
| \n\n1\n\n#### Arbeitszeitmodell:\n\n* Vollzeit\n\n#### Quelle des | |
| Stellenangebots:\n\narbeitsagentur.de\n\n#### Referenznummer:\n | |
| \nXXXX\n""", | |
| on_click=clicked, | |
| args=[1], | |
| ) | |
| # st.button( | |
| # "Nur Vollzeit", | |
| # on_click=clicked, | |
| # args=[2], | |
| # ) | |
| # st.button("Famillienfreundlich", on_click=clicked, args=[3]) | |
| with left_column: | |
| st.markdown( | |
| '<p class="example">Lade eine Datei mit einem Anzeigentext hoch.</p>', | |
| unsafe_allow_html=True, | |
| ) | |
| st.markdown( | |
| """ <p class="font">(.txt, .json mit key "full_text")</p>""", | |
| unsafe_allow_html=True, | |
| ) | |
| uploaded_file = st.file_uploader("Datei hochladen", type=["txt", "json"]) | |
| if uploaded_file is not None: | |
| if uploaded_file.type == "text/plain": | |
| stringio = StringIO(uploaded_file.getvalue().decode("utf-8")) | |
| uploaded_jobdescription = stringio.read() | |
| elif uploaded_file.type == "application/json": | |
| file_contents = json.load(uploaded_file) | |
| uploaded_jobdescription = file_contents["full_text"] | |
| else: | |
| st.write("Bitte lade eine .txt oder .json Datei hoch.") | |
| if st.button("Extrahieren", key="extract_file_based"): | |
| if uploaded_jobdescription: | |
| query = [{"posting_id": "aaaa", "text": uploaded_jobdescription}] | |
| output, docs = pipeline(query) | |
| concept = [output[i]["concept"] for i in range(len(output))] | |
| if output[0]["concept"] is not None: | |
| st.markdown( | |
| '<p class="example">Gefundene Konzepte:</p>', | |
| unsafe_allow_html=True, | |
| ) | |
| for c in output: | |
| if c["concept"] in ANFORDERUNGEN: | |
| st.write(f" - Anforderung: {c['concept']}") | |
| elif c["concept"] in ANGEBOTE: | |
| st.write(f" - Angebot: {c['concept']}") | |
| elif c["concept"] in FILTERED_OUT_CONCEPTS: | |
| st.write(f" - Konzept in der Taxonomie {c['concept']} aber nicht für die Datenanalyse benutzt") | |
| else: | |
| st.write(f" - Konzept nicht in der Taxonomie {c['concept']}") | |
| # add explanations | |
| options = {key: "#ef553b" for key in ANFORDERUNGEN} | { | |
| key: "#636efa" for key in ANGEBOTE | |
| } | |
| st.markdown( | |
| '<p class="example">Erklärungen:</p>', | |
| unsafe_allow_html=True, | |
| ) | |
| visualize_spans( | |
| docs[0], | |
| spans_key="ruler", | |
| title="", | |
| show_table=False, | |
| displacy_options={"colors": options}, | |
| ) | |
| else: | |
| st.write("Es wurde kein Konzept für diese Jobanzeige extrahiert.") | |
| else: | |
| st.write("Bitte lade eine Datei hoch.") | |
| with middle_column: | |
| tabs_font_css = """ | |
| <style> | |
| div[class*="stTextInput"] label p { | |
| font-size: 2px; | |
| } | |
| </style> | |
| """ | |
| st.markdown( | |
| '<p class="example">Gebe den Text einer Jobanzeige ein.</p>', | |
| unsafe_allow_html=True, | |
| ) | |
| # get to know if the example job title buttons were clicked | |
| selected_job_text = "" | |
| if st.session_state.clicked[1]: | |
| selected_job_text = """\n## Stellendetails zu: Mitarbeiter in der Produktion (m/w/d)\n\n### Mitarbeiter | |
| in der Produktion (m/w/d)\n\nHelfer/in - Elektro \nVer\u00f6ffentlicht: | |
| XX.XX.2023\n\n#### Mitarbeiter in der Produktion (m/w/d)\n\n XXXX | |
| GmbH\n\n#### Typ:\n\nArbeit\n\n#### Arbeitszeit:\n\nVollzeit\n\n#### | |
| Eintrittsdatum:\n\nab sofort\n\n#### Arbeitsort:\n\XXXX\n\n### | |
| Stellenbeschreibung\n\nOrt: XXXX Arbeitszeitmodell: Vollzeit | |
| Vertragsart: Arbeitnehmer\u00fcberlassung mit \u00dcbernahmeoption | |
| Branche: Elektro Startzeitpunkt: ab sofort Die XXXX GmbH ist Ihr | |
| Dienstleister im Gro\u00dfraum XXXX f\u00fcr eine faire, professionelle | |
| Umsetzung Ihrer neuen beruflichen Herausforderungen. Gestalten auch Sie | |
| Ihre berufliche Zukunft mit uns! Zum n\u00e4chstm\u00f6glichen Zeitpunkt | |
| suchen wir die ideale Besetzung f\u00fcr die Position: Mitarbeiter in der | |
| Produktion (m/w/d) Langfristige Besch\u00e4ftigungsoption Ihre Vorteile: | |
| *All-in-One: Umfassende Beratung und unkomplizierter Bewerbungsprozess mit | |
| XXXX * Bezahlung: Attraktives Gehalt mit Zusatzleistungen (z.B. | |
| Weihnachtsgeld) *Sicherheit: Vermittlung in einen zukunftssicheren | |
| Arbeitsplatz* Work-Life-Balance: Geregelte Arbeitszeiten *Onboarding: | |
| Umfangreiche und gr\u00fcndliche Einarbeitung* Abwechslung: Vielseitige | |
| und spannende Aufgaben *Arbeitsumgebung: Flache Hierarchien, modernes | |
| Arbeitsumfeld und ein aufgeschlossenes Team* Was wir von BS \nimmer bieten | |
| k\u00f6nnen: Pers\u00f6nlicher Ansprechpartner, gro\u00dfes | |
| Unternehmensnetzwerk, kostenlose Arbeitskleidung sowie eine zeitnahe | |
| R\u00fcckmeldung zum Bewerbungsstatus Ihre Aufgaben: *Montage von | |
| Elektronik-Komponenten* Konfektionierung einzelner Komponenten | |
| *Verpackungst\u00e4tigkeiten Ihr Profil:* Berufserfahrung: Idealerweise | |
| erste Berufserfahrung in einer vergleichbaren Position *Hard Skills: | |
| Fingerfertigkeit und technisches Grundverst\u00e4ndnis* Soft Skills: | |
| Teambewusstsein und eine gute Kommunikationsf\u00e4higkeit * Arbeitsweise: | |
| Sorgf\u00e4ltig und strukturiert\n\n### Anforderungen an den Bewerber\n\n | |
| #### Berufserfahrung:\n\nMit Berufserfahrung\n\n#### F\u00e4higkeiten:\n\n* | |
| ##### Transport, Verkehr \nGrundkenntnisse \nLagerarbeit, Transport\n* | |
| ##### Produktion, Verarbeitung, Technik \nGrundkenntnisse | |
| \nBest\u00fccken, Maschinenf\u00fchrung, Anlagenf\u00fchrung, | |
| -bedienung, Montage (Elektrotechnik)\n\n#### Pers\u00f6nliche | |
| St\u00e4rken:\n\n* Selbst\u00e4ndiges Arbeiten\n* Sorgfalt/Genauigkeit\n* | |
| Motivation/ Leistungsbereitschaft\n* Zuverl\u00e4ssigkeit\n* | |
| Lernbereitschaft\n\n#### Sprachen:\n\n* Grundkenntnisse \nDeutsch\n\n | |
| #### Fahrzeug erforderlich:\n\nNein\n\n#### Reise-/Montagebereitschaft: | |
| \n\nNicht erforderlich\n\n### Arbeitsorte\n\n* XXXX \n\n### | |
| Arbeitgeber\n\nXXX GmbH\n\n#### Firmenadresse:\n\n | |
| XXXX\n\n#### Branchengruppe:\n\n | |
| Arbeitnehmer\u00fcberlassung, Zeitarbeit\n\n#### Branche:\n\nBefristete | |
| \u00dcberlassung von Arbeitskr\u00e4ften\n\n### Weitere Informationen | |
| \n\nDas Stellenangebot wird durch den Arbeitgeber selbst verwaltet.\n\n | |
| Stelle im Rahmen der Arbeitnehmer\u00fcberlassung.\n\n#### Tarifvertrag: | |
| \n\nIGZ\n\n#### Befristung:\n\nUnbefristet\n\n#### Anzahl freier Stellen: | |
| \n\n1\n\n#### Arbeitszeitmodell:\n\n* Vollzeit\n\n#### Quelle des | |
| Stellenangebots:\n\narbeitsagentur.de\n\n#### Referenznummer:\n | |
| \nXXXX\n""" | |
| # create a text input for the user to type in a job title | |
| st.text_area( | |
| "---", | |
| value=selected_job_text, | |
| key="typed_job_text", | |
| height=500, | |
| on_change=reset_buttons, # noqa: E501 | |
| ) | |
| if selected_job_text: | |
| query = [{"posting_id": "aaaa", "text": selected_job_text}] | |
| else: | |
| query = [ | |
| {"posting_id": "aaaa", "text": ' ' + st.session_state.typed_job_text} | |
| ] # noqa: E501 | |
| # predicts the occupation of the job title when predict button is clicked | |
| if st.button("Extrahieren", key="extract_text_based"): | |
| output, docs = pipeline(query) | |
| concept = [output[i]["concept"] for i in range(len(output))] | |
| if output[0]["concept"] is not None: | |
| st.markdown( | |
| '<p class="example">Gefundene Konzepte:</p>', | |
| unsafe_allow_html=True, | |
| ) | |
| for c in output: | |
| if c["concept"] in ANFORDERUNGEN: | |
| st.write(f" - Anforderung: {c['concept']}") | |
| elif c["concept"] in ANGEBOTE: | |
| st.write(f" - Angebot: {c['concept']}") | |
| elif c["concept"] in FILTERED_OUT_CONCEPTS: | |
| st.write(f" - Konzept in der Taxonomie {c['concept']} aber nicht für die Datenanalyse benutzt") | |
| else: | |
| st.write(f" - Konzept nicht in der Taxonomie {c['concept']}") | |
| # add explanations | |
| options = {key: "#ef553b" for key in ANFORDERUNGEN} | { | |
| key: "#636efa" for key in ANGEBOTE | |
| } | |
| st.markdown( | |
| '<p class="example">Erklärungen:</p>', | |
| unsafe_allow_html=True, | |
| ) | |
| visualize_spans( | |
| docs[0], | |
| spans_key="ruler", | |
| title="", | |
| show_table=False, | |
| displacy_options={"colors": options}, | |
| ) | |
| else: | |
| st.write("Es wurde kein Konzept für diese Jobanzeige extrahiert.") | |
| st.markdown("#") | |