import logging import os import traceback import dotenv import pandas as pd import streamlit as st import streamlit.components.v1 as components from annotated_text import annotated_text from streamlit_tags import st_tags from openai_fake_data_generator import OpenAIParams from presidio_helpers import ( get_supported_entities, analyze, anonymize, annotate, create_fake_data, analyzer_engine, ) # Načtení proměnných prostředí dotenv.load_dotenv() # Konfigurace loggeru logging.basicConfig(level=logging.INFO) logger = logging.getLogger("presidio-streamlit") # Nastavení stránky Streamlit st.set_page_config( page_title="Presidio demo pro české texty", layout="wide", initial_sidebar_state="expanded", menu_items={ "About": "https://microsoft.github.io/presidio/", }, ) # Načtení konfiguračních proměnných allow_other_models = os.getenv("ALLOW_OTHER_MODELS", "False").lower() == "true" # Sidebar st.sidebar.header("Anonymizace osobních údajů v českých textech s Microsoft Presidio") # Výběr modelu model_help_text = "Vyberte model pro rozpoznávání pojmenovaných entit (NER) pro detekci osobních údajů." model_list = [ "spacy/cs_core_news_sm", "iiiorg/piiranha-v1-detect-personal-information", "FacebookAI/xlm-roberta-large-finetuned-conll03-english", ] if not allow_other_models: model_list.pop() st_model = st.sidebar.selectbox("NER model", model_list, index=1, help=model_help_text) # Zpracování výběru modelu st_model_package = st_model.split("/")[0] st_model = "/".join(st_model.split("/")[1:]) if st_model_package.lower() in ("spacy", "iiiorg") else st_model st_ta_key = st_ta_endpoint = "" # Placeholder pro případné použití Text Analytics analyzer_params = (st_model_package, st_model, st_ta_key, st_ta_endpoint) logger.debug(f"analyzer_params: {analyzer_params}") # Výběr metody anonymizace st_operator = st.sidebar.selectbox( "Přístup k anonymizaci", ["redact", "replace", "synthesize", "highlight", "mask", "hash", "encrypt"], index=1, help="Vyberte způsob úpravy textu po identifikaci osobních údajů." ) # Nastavení pro jednotlivé metody anonymizace st_mask_char = "*" st_number_of_chars = 15 st_encrypt_key = "WmZq4t7w!z%C&F)J" open_ai_params = None if st_operator == "mask": st_number_of_chars = st.sidebar.number_input("Počet znaků", value=st_number_of_chars, min_value=0, max_value=100) st_mask_char = st.sidebar.text_input("Znak pro maskování", value=st_mask_char, max_chars=1) elif st_operator == "encrypt": st_encrypt_key = st.sidebar.text_input("AES klíč", value=st_encrypt_key) elif st_operator == "synthesize": # Implementace nastavení pro OpenAI syntézu pass # Nastavení prahu důvěry st_threshold = st.sidebar.slider("Práh přijetí", min_value=0.0, max_value=1.0, value=0.35) # Volba pro zobrazení rozhodovacího procesu st_return_decision_process = st.sidebar.checkbox("Přidat vysvětlení analýzy k nálezům", value=False) # Povolené a zakázané seznamy with st.sidebar.expander("Povolené a zakázané seznamy", expanded=False): st_allow_list = st_tags(label="Přidat slova do povoleného seznamu", text="Zadejte slovo a stiskněte enter.") st_deny_list = st_tags(label="Přidat slova do zakázaného seznamu", text="Zadejte slovo a stiskněte enter.") # Hlavní část aplikace with st.expander("O této ukázce", expanded=False): st.info("Presidio je open source přizpůsobitelný framework pro detekci a anonymizaci osobních údajů.") # Další informace o aplikaci... # Načtení výchozího textu with open("demo_text.txt", "r", encoding="utf-8") as f: demo_text = f.read() # Vytvoření dvou sloupců pro vstup a výstup col1, col2 = st.columns(2) # Vstupní text with col1: st.subheader("Vstup") st_text = st.text_area(label="Zadejte text", value=demo_text, height=400, key="text_input") try: # Výběr entit k detekci st_entities_expander = st.sidebar.expander("Vyberte entity k vyhledání") st_entities = st_entities_expander.multiselect( label="Které entity hledat?", options=get_supported_entities(*analyzer_params), default=list(get_supported_entities(*analyzer_params)), help="Omezte seznam detekovaných osobních údajů." ) # Analýza textu st_analyze_results = analyze( *analyzer_params, text=st_text, entities=st_entities, language="cs", score_threshold=st_threshold, return_decision_process=st_return_decision_process, allow_list=st_allow_list, deny_list=st_deny_list, ) # Zobrazení výsledků with col2: st.subheader("Výstup") if st_operator not in ("highlight", "synthesize"): st_anonymize_results = anonymize( text=st_text, operator=st_operator, mask_char=st_mask_char, number_of_chars=st_number_of_chars, encrypt_key=st_encrypt_key, analyze_results=st_analyze_results, ) st.text_area(label="Anonymizováno", value=st_anonymize_results.text, height=400) elif st_operator == "synthesize": fake_data = create_fake_data(st_text, st_analyze_results, open_ai_params) st.text_area(label="Syntetická data", value=fake_data, height=400) else: st.subheader("Zvýrazněno") annotated_tokens = annotate(text=st_text, analyze_results=st_analyze_results) annotated_text(*annotated_tokens) # Zobrazení tabulky s výsledky st.subheader("Nálezy" if not st_return_decision_process else "Nálezy s rozhodovacími faktory") if st_analyze_results: df = pd.DataFrame.from_records([r.to_dict() for r in st_analyze_results]) df["text"] = [st_text[res.start : res.end] for res in st_analyze_results] df_subset = df[["entity_type", "text", "start", "end", "score"]].rename( { "entity_type": "Typ entity", "text": "Text", "start": "Začátek", "end": "Konec", "score": "Důvěryhodnost", }, axis=1, ) if st_return_decision_process: analysis_explanation_df = pd.DataFrame.from_records( [r.analysis_explanation.to_dict() for r in st_analyze_results] ) df_subset = pd.concat([df_subset, analysis_explanation_df], axis=1) st.dataframe(df_subset.reset_index(drop=True), use_container_width=True) else: st.text("Žádné nálezy") except Exception as e: logger.error(f"Došlo k chybě: {str(e)}", exc_info=True) st.error(f"Došlo k chybě při zpracování: {str(e)}") # Přidání skriptu pro sledování využití (volitelné) components.html( """ """ )