petrsovadina commited on
Commit
928f226
1 Parent(s): e4e334b

Update presidio_streamlit.py

Browse files
Files changed (1) hide show
  1. presidio_streamlit.py +61 -229
presidio_streamlit.py CHANGED
@@ -1,4 +1,3 @@
1
- """Streamlit app pro anonymizaci českých textů s využitím Presidio."""
2
  import logging
3
  import os
4
  import traceback
@@ -20,6 +19,14 @@ from presidio_helpers import (
20
  analyzer_engine,
21
  )
22
 
 
 
 
 
 
 
 
 
23
  st.set_page_config(
24
  page_title="Presidio demo pro české texty",
25
  layout="wide",
@@ -29,255 +36,94 @@ st.set_page_config(
29
  },
30
  )
31
 
32
- dotenv.load_dotenv()
33
- logger = logging.getLogger("presidio-streamlit")
34
-
35
- allow_other_models = os.getenv("ALLOW_OTHER_MODELS", False)
36
 
37
  # Sidebar
38
- st.sidebar.header(
39
- """
40
- Anonymizace osobních údajů v českých textech s [Microsoft Presidio](https://microsoft.github.io/presidio/)
41
- """
42
- )
43
-
44
- model_help_text = """
45
- Vyberte model pro rozpoznávání pojmenovaných entit (NER) pro detekci osobních údajů v českých textech.
46
- Presidio podporuje různé NER balíčky, jako jsou spaCy, Huggingface, Stanza a Flair,
47
- stejně jako služby jako Azure Text Analytics PII.
48
- """
49
- st_ta_key = st_ta_endpoint = ""
50
 
 
 
51
  model_list = [
52
- "spacy/en_core_web_sm",
53
  "iiiorg/piiranha-v1-detect-personal-information",
54
  "FacebookAI/xlm-roberta-large-finetuned-conll03-english",
55
  ]
56
  if not allow_other_models:
57
  model_list.pop()
58
- # Výběr modelu
59
- st_model = st.sidebar.selectbox(
60
- "NER model",
61
- model_list,
62
- index=1,
63
- help=model_help_text,
64
- )
65
 
66
- # Extrakce balíčku modelu
67
- st_model_package = st_model.split("/")[0]
68
 
69
- # Odstranění prefixu balíčku (pokud je potřeba)
70
- st_model = (
71
- st_model
72
- if st_model_package.lower() not in ("spacy", "iiiorg")
73
- else "/".join(st_model.split("/")[1:])
74
- )
75
-
76
- if st_model == "Other":
77
- st_model_package = st.sidebar.selectbox(
78
- "NER model OSS balíček", options=["spacy", "iiiorg"]
79
- )
80
- st_model = st.sidebar.text_input(f"Název NER modelu", value="")
81
-
82
- st.sidebar.warning("Poznámka: Stažení modelů může chvíli trvat.")
83
 
 
84
  analyzer_params = (st_model_package, st_model, st_ta_key, st_ta_endpoint)
85
  logger.debug(f"analyzer_params: {analyzer_params}")
86
 
 
87
  st_operator = st.sidebar.selectbox(
88
  "Přístup k anonymizaci",
89
  ["redact", "replace", "synthesize", "highlight", "mask", "hash", "encrypt"],
90
  index=1,
91
- help="""
92
- Vyberte způsob úpravy textu po identifikaci osobních údajů.\n
93
- - Redact: Kompletně odstranit osobní údaj\n
94
- - Replace: Nahradit osobní údaj konstantou, např. <OSOBA>\n
95
- - Synthesize: Nahradit falešnými hodnotami (vyžaduje OpenAI klíč)\n
96
- - Highlight: Zobrazí původní text se zvýrazněnými osobními údaji\n
97
- - Mask: Nahradí požadovaný počet znaků hvězdičkou (nebo jiným znakem)\n
98
- - Hash: Nahradí hashem osobního údaje\n
99
- - Encrypt: Nahradí AES šifrováním osobního údaje, umožňující reverzní proces
100
- """,
101
  )
 
 
102
  st_mask_char = "*"
103
  st_number_of_chars = 15
104
  st_encrypt_key = "WmZq4t7w!z%C&F)J"
105
-
106
  open_ai_params = None
107
 
108
- logger.debug(f"st_operator: {st_operator}")
109
-
110
- def set_up_openai_synthesis():
111
- """Nastavení OpenAI API klíče a modelu pro syntézu textu."""
112
-
113
- if os.getenv("OPENAI_TYPE", default="openai") == "Azure":
114
- openai_api_type = "azure"
115
- st_openai_api_base = st.sidebar.text_input(
116
- "Azure OpenAI base URL",
117
- value=os.getenv("AZURE_OPENAI_ENDPOINT", default=""),
118
- )
119
- openai_key = os.getenv("AZURE_OPENAI_KEY", default="")
120
- st_deployment_id = st.sidebar.text_input(
121
- "Název nasazení", value=os.getenv("AZURE_OPENAI_DEPLOYMENT", default="")
122
- )
123
- st_openai_version = st.sidebar.text_input(
124
- "OpenAI verze",
125
- value=os.getenv("OPENAI_API_VERSION", default="2023-05-15"),
126
- )
127
- else:
128
- openai_api_type = "openai"
129
- st_openai_version = st_openai_api_base = None
130
- st_deployment_id = ""
131
- openai_key = os.getenv("OPENAI_KEY", default="")
132
- st_openai_key = st.sidebar.text_input(
133
- "OPENAI_KEY",
134
- value=openai_key,
135
- help="Více informací na https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key",
136
- type="password",
137
- )
138
- st_openai_model = st.sidebar.text_input(
139
- "OpenAI model pro syntézu textu",
140
- value=os.getenv("OPENAI_MODEL", default="gpt-3.5-turbo-instruct"),
141
- help="Více informací zde: https://platform.openai.com/docs/models/",
142
- )
143
- return (
144
- openai_api_type,
145
- st_openai_api_base,
146
- st_deployment_id,
147
- st_openai_version,
148
- st_openai_key,
149
- st_openai_model,
150
- )
151
-
152
  if st_operator == "mask":
153
- st_number_of_chars = st.sidebar.number_input(
154
- "počet znaků", value=st_number_of_chars, min_value=0, max_value=100
155
- )
156
- st_mask_char = st.sidebar.text_input(
157
- "Znak pro maskování", value=st_mask_char, max_chars=1
158
- )
159
  elif st_operator == "encrypt":
160
  st_encrypt_key = st.sidebar.text_input("AES klíč", value=st_encrypt_key)
161
  elif st_operator == "synthesize":
162
- (
163
- openai_api_type,
164
- st_openai_api_base,
165
- st_deployment_id,
166
- st_openai_version,
167
- st_openai_key,
168
- st_openai_model,
169
- ) = set_up_openai_synthesis()
170
 
171
- open_ai_params = OpenAIParams(
172
- openai_key=st_openai_key,
173
- model=st_openai_model,
174
- api_base=st_openai_api_base,
175
- deployment_id=st_deployment_id,
176
- api_version=st_openai_version,
177
- api_type=openai_api_type,
178
- )
179
-
180
- st_threshold = st.sidebar.slider(
181
- label="Práh přijetí",
182
- min_value=0.0,
183
- max_value=1.0,
184
- value=0.35,
185
- help="Definujte práh pro přijetí detekce jako osobní údaj.",
186
- )
187
 
188
- st_return_decision_process = st.sidebar.checkbox(
189
- "Přidat vysvětlení analýzy k nálezům",
190
- value=False,
191
- help="Přidá rozhodovací proces do výstupní tabulky. "
192
- "Více informací najdete zde: https://microsoft.github.io/presidio/analyzer/decision_process/",
193
- )
194
 
195
  # Povolené a zakázané seznamy
196
- st_deny_allow_expander = st.sidebar.expander(
197
- "Povolené a zakázané seznamy",
198
- expanded=False,
199
- )
200
-
201
- with st_deny_allow_expander:
202
- st_allow_list = st_tags(
203
- label="Přidat slova do povoleného seznamu", text="Zadejte slovo a stiskněte enter."
204
- )
205
- st.caption(
206
- "Povolené seznamy obsahují slova, která nejsou považována za osobní údaje, ale jsou jako takové detekována."
207
- )
208
-
209
- st_deny_list = st_tags(
210
- label="Přidat slova do zakázaného seznamu", text="Zadejte slovo a stiskněte enter."
211
- )
212
- st.caption(
213
- "Zakázané seznamy obsahují slova, která jsou považována za osobní údaje, ale nejsou jako takové detekována."
214
- )
215
 
216
- # Hlavní panel
217
  with st.expander("O této ukázce", expanded=False):
218
- st.info(
219
- """Presidio je open source přizpůsobitelný framework pro detekci a anonymizaci osobních údajů.
220
- \n\n[Kód](https://aka.ms/presidio) |
221
- [Tutoriál](https://microsoft.github.io/presidio/tutorial/) |
222
- [Instalace](https://microsoft.github.io/presidio/installation/) |
223
- [FAQ](https://microsoft.github.io/presidio/faq/) |
224
- [Zpětná vazba](https://forms.office.com/r/9ufyYjfDaY) |"""
225
- )
226
-
227
- st.info(
228
- """
229
- Použijte tuto ukázku k:
230
- - Experimentování s různými hotovými modely a NLP balíčky.
231
- - Prozkoumání různých možností anonymizace, včetně redakce, maskování, šifrování a dalších.
232
- - Generování syntetického textu s Microsoft Presidio a OpenAI.
233
- - Konfiguraci povolených a zakázaných seznamů.
234
-
235
- Tato ukázková webová stránka ukazuje některé z možností Presidio.
236
- [Navštivte naši webovou stránku](https://microsoft.github.io/presidio) pro více informací,
237
- ukázek a možností nasazení.
238
- """
239
- )
240
-
241
- st.markdown(
242
- "[![Pypi Downloads](https://img.shields.io/pypi/dm/presidio-analyzer.svg)](https://img.shields.io/pypi/dm/presidio-analyzer.svg)" # noqa
243
- "[![MIT license](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)"
244
- "![GitHub Repo stars](https://img.shields.io/github/stars/microsoft/presidio?style=social)"
245
- )
246
-
247
- analyzer_load_state = st.info("Spouštění Presidio analyzátoru...")
248
-
249
- analyzer_load_state.empty()
250
 
251
  # Načtení výchozího textu
252
  with open("demo_text.txt", "r", encoding="utf-8") as f:
253
  demo_text = f.read()
254
 
255
- # Vytvoření dvou sloupců pro před a po
256
  col1, col2 = st.columns(2)
257
 
258
- # Před:
259
- col1.subheader("Vstup")
260
- st_text = col1.text_area(
261
- label="Zadejte text", value=demo_text, height=400, key="text_input"
262
- )
263
 
264
  try:
265
- # Výběr entit
266
  st_entities_expander = st.sidebar.expander("Vyberte entity k vyhledání")
267
  st_entities = st_entities_expander.multiselect(
268
  label="Které entity hledat?",
269
  options=get_supported_entities(*analyzer_params),
270
  default=list(get_supported_entities(*analyzer_params)),
271
- help="Omezte seznam detekovaných osobních údajů. "
272
- "Tento seznam je dynamický a závisí na NER modelu a registrovaných rozpoznávačích. "
273
- "Více informací najdete zde: https://microsoft.github.io/presidio/analyzer/adding_recognizers/",
274
  )
275
 
276
- # Před
277
- analyzer_load_state = st.info("Spouštění Presidio analyzátoru...")
278
- analyzer = analyzer_engine(*analyzer_params)
279
- analyzer_load_state.empty()
280
-
281
  st_analyze_results = analyze(
282
  *analyzer_params,
283
  text=st_text,
@@ -289,10 +135,10 @@ try:
289
  deny_list=st_deny_list,
290
  )
291
 
292
- # Po
293
- if st_operator not in ("highlight", "synthesize"):
294
- with col2:
295
- st.subheader(f"Výstup")
296
  st_anonymize_results = anonymize(
297
  text=st_text,
298
  operator=st_operator,
@@ -301,33 +147,20 @@ try:
301
  encrypt_key=st_encrypt_key,
302
  analyze_results=st_analyze_results,
303
  )
304
- st.text_area(
305
- label="Anonymizováno", value=st_anonymize_results.text, height=400
306
- )
307
- elif st_operator == "synthesize":
308
- with col2:
309
- st.subheader(f"OpenAI Generovaný výstup")
310
- fake_data = create_fake_data(
311
- st_text,
312
- st_analyze_results,
313
- open_ai_params,
314
- )
315
  st.text_area(label="Syntetická data", value=fake_data, height=400)
316
- else:
317
- st.subheader("Zvýrazněno")
318
- annotated_tokens = annotate(text=st_text, analyze_results=st_analyze_results)
319
- annotated_text(*annotated_tokens)
320
 
321
- # tabulka výsledků
322
- st.subheader(
323
- "Nálezy"
324
- if not st_return_decision_process
325
- else "Nálezy s rozhodovacími faktory"
326
- )
327
  if st_analyze_results:
328
  df = pd.DataFrame.from_records([r.to_dict() for r in st_analyze_results])
329
  df["text"] = [st_text[res.start : res.end] for res in st_analyze_results]
330
-
331
  df_subset = df[["entity_type", "text", "start", "end", "score"]].rename(
332
  {
333
  "entity_type": "Typ entity",
@@ -338,7 +171,6 @@ try:
338
  },
339
  axis=1,
340
  )
341
- df_subset["Text"] = [st_text[res.start : res.end] for res in st_analyze_results]
342
  if st_return_decision_process:
343
  analysis_explanation_df = pd.DataFrame.from_records(
344
  [r.analysis_explanation.to_dict() for r in st_analyze_results]
@@ -349,10 +181,10 @@ try:
349
  st.text("Žádné nálezy")
350
 
351
  except Exception as e:
352
- print(e)
353
- traceback.print_exc()
354
- st.error(e)
355
 
 
356
  components.html(
357
  """
358
  <script type="text/javascript">
 
 
1
  import logging
2
  import os
3
  import traceback
 
19
  analyzer_engine,
20
  )
21
 
22
+ # Načtení proměnných prostředí
23
+ dotenv.load_dotenv()
24
+
25
+ # Konfigurace loggeru
26
+ logging.basicConfig(level=logging.INFO)
27
+ logger = logging.getLogger("presidio-streamlit")
28
+
29
+ # Nastavení stránky Streamlit
30
  st.set_page_config(
31
  page_title="Presidio demo pro české texty",
32
  layout="wide",
 
36
  },
37
  )
38
 
39
+ # Načtení konfiguračních proměnných
40
+ allow_other_models = os.getenv("ALLOW_OTHER_MODELS", "False").lower() == "true"
 
 
41
 
42
  # Sidebar
43
+ st.sidebar.header("Anonymizace osobních údajů v českých textech s Microsoft Presidio")
 
 
 
 
 
 
 
 
 
 
 
44
 
45
+ # Výběr modelu
46
+ model_help_text = "Vyberte model pro rozpoznávání pojmenovaných entit (NER) pro detekci osobních údajů."
47
  model_list = [
48
+ "spacy/cs_core_news_sm",
49
  "iiiorg/piiranha-v1-detect-personal-information",
50
  "FacebookAI/xlm-roberta-large-finetuned-conll03-english",
51
  ]
52
  if not allow_other_models:
53
  model_list.pop()
 
 
 
 
 
 
 
54
 
55
+ st_model = st.sidebar.selectbox("NER model", model_list, index=1, help=model_help_text)
 
56
 
57
+ # Zpracování výběru modelu
58
+ st_model_package = st_model.split("/")[0]
59
+ st_model = "/".join(st_model.split("/")[1:]) if st_model_package.lower() in ("spacy", "iiiorg") else st_model
 
 
 
 
 
 
 
 
 
 
 
60
 
61
+ st_ta_key = st_ta_endpoint = "" # Placeholder pro případné použití Text Analytics
62
  analyzer_params = (st_model_package, st_model, st_ta_key, st_ta_endpoint)
63
  logger.debug(f"analyzer_params: {analyzer_params}")
64
 
65
+ # Výběr metody anonymizace
66
  st_operator = st.sidebar.selectbox(
67
  "Přístup k anonymizaci",
68
  ["redact", "replace", "synthesize", "highlight", "mask", "hash", "encrypt"],
69
  index=1,
70
+ help="Vyberte způsob úpravy textu po identifikaci osobních údajů."
 
 
 
 
 
 
 
 
 
71
  )
72
+
73
+ # Nastavení pro jednotlivé metody anonymizace
74
  st_mask_char = "*"
75
  st_number_of_chars = 15
76
  st_encrypt_key = "WmZq4t7w!z%C&F)J"
 
77
  open_ai_params = None
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  if st_operator == "mask":
80
+ st_number_of_chars = st.sidebar.number_input("Počet znaků", value=st_number_of_chars, min_value=0, max_value=100)
81
+ st_mask_char = st.sidebar.text_input("Znak pro maskování", value=st_mask_char, max_chars=1)
 
 
 
 
82
  elif st_operator == "encrypt":
83
  st_encrypt_key = st.sidebar.text_input("AES klíč", value=st_encrypt_key)
84
  elif st_operator == "synthesize":
85
+ # Implementace nastavení pro OpenAI syntézu
86
+ pass
 
 
 
 
 
 
87
 
88
+ # Nastavení prahu důvěry
89
+ st_threshold = st.sidebar.slider("Práh přijetí", min_value=0.0, max_value=1.0, value=0.35)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
+ # Volba pro zobrazení rozhodovacího procesu
92
+ st_return_decision_process = st.sidebar.checkbox("Přidat vysvětlení analýzy k nálezům", value=False)
 
 
 
 
93
 
94
  # Povolené a zakázané seznamy
95
+ with st.sidebar.expander("Povolené a zakázané seznamy", expanded=False):
96
+ st_allow_list = st_tags(label="Přidat slova do povoleného seznamu", text="Zadejte slovo a stiskněte enter.")
97
+ st_deny_list = st_tags(label="Přidat slova do zakázaného seznamu", text="Zadejte slovo a stiskněte enter.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
+ # Hlavní část aplikace
100
  with st.expander("O této ukázce", expanded=False):
101
+ st.info("Presidio je open source přizpůsobitelný framework pro detekci a anonymizaci osobních údajů.")
102
+ # Další informace o aplikaci...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  # Načtení výchozího textu
105
  with open("demo_text.txt", "r", encoding="utf-8") as f:
106
  demo_text = f.read()
107
 
108
+ # Vytvoření dvou sloupců pro vstup a výstup
109
  col1, col2 = st.columns(2)
110
 
111
+ # Vstupní text
112
+ with col1:
113
+ st.subheader("Vstup")
114
+ st_text = st.text_area(label="Zadejte text", value=demo_text, height=400, key="text_input")
 
115
 
116
  try:
117
+ # Výběr entit k detekci
118
  st_entities_expander = st.sidebar.expander("Vyberte entity k vyhledání")
119
  st_entities = st_entities_expander.multiselect(
120
  label="Které entity hledat?",
121
  options=get_supported_entities(*analyzer_params),
122
  default=list(get_supported_entities(*analyzer_params)),
123
+ help="Omezte seznam detekovaných osobních údajů."
 
 
124
  )
125
 
126
+ # Analýza textu
 
 
 
 
127
  st_analyze_results = analyze(
128
  *analyzer_params,
129
  text=st_text,
 
135
  deny_list=st_deny_list,
136
  )
137
 
138
+ # Zobrazení výsledků
139
+ with col2:
140
+ st.subheader("Výstup")
141
+ if st_operator not in ("highlight", "synthesize"):
142
  st_anonymize_results = anonymize(
143
  text=st_text,
144
  operator=st_operator,
 
147
  encrypt_key=st_encrypt_key,
148
  analyze_results=st_analyze_results,
149
  )
150
+ st.text_area(label="Anonymizováno", value=st_anonymize_results.text, height=400)
151
+ elif st_operator == "synthesize":
152
+ fake_data = create_fake_data(st_text, st_analyze_results, open_ai_params)
 
 
 
 
 
 
 
 
153
  st.text_area(label="Syntetická data", value=fake_data, height=400)
154
+ else:
155
+ st.subheader("Zvýrazněno")
156
+ annotated_tokens = annotate(text=st_text, analyze_results=st_analyze_results)
157
+ annotated_text(*annotated_tokens)
158
 
159
+ # Zobrazení tabulky s výsledky
160
+ st.subheader("Nálezy" if not st_return_decision_process else "Nálezy s rozhodovacími faktory")
 
 
 
 
161
  if st_analyze_results:
162
  df = pd.DataFrame.from_records([r.to_dict() for r in st_analyze_results])
163
  df["text"] = [st_text[res.start : res.end] for res in st_analyze_results]
 
164
  df_subset = df[["entity_type", "text", "start", "end", "score"]].rename(
165
  {
166
  "entity_type": "Typ entity",
 
171
  },
172
  axis=1,
173
  )
 
174
  if st_return_decision_process:
175
  analysis_explanation_df = pd.DataFrame.from_records(
176
  [r.analysis_explanation.to_dict() for r in st_analyze_results]
 
181
  st.text("Žádné nálezy")
182
 
183
  except Exception as e:
184
+ logger.error(f"Došlo k chybě: {str(e)}", exc_info=True)
185
+ st.error(f"Došlo k chybě při zpracování: {str(e)}")
 
186
 
187
+ # Přidání skriptu pro sledování využití (volitelné)
188
  components.html(
189
  """
190
  <script type="text/javascript">