|
|
"""
|
|
|
App principale Streamlit per l'anonimizzazione documenti.
|
|
|
"""
|
|
|
|
|
|
import streamlit as st
|
|
|
import json
|
|
|
import pandas as pd
|
|
|
from ui_components import (
|
|
|
setup_page_config, display_sidebar, display_entity_editor,
|
|
|
display_file_preview, display_analysis_results, display_crewai_result,
|
|
|
display_progress_metrics, display_examples_section, create_download_button
|
|
|
)
|
|
|
from utils import (
|
|
|
init_session_state, process_uploaded_files, run_anonymization,
|
|
|
run_ai_analysis, build_rag_knowledge_base, export_results_json,
|
|
|
get_confirmed_docs_count, reset_document_state, add_chat_message,
|
|
|
add_crewai_result, clear_crewai_history
|
|
|
)
|
|
|
|
|
|
def main():
|
|
|
"""Funzione principale dell'app"""
|
|
|
|
|
|
|
|
|
setup_page_config()
|
|
|
init_session_state()
|
|
|
|
|
|
|
|
|
st.title("π Anonimizzatore Documenti con NER, RAG e CrewAI")
|
|
|
st.markdown("---")
|
|
|
|
|
|
|
|
|
display_sidebar()
|
|
|
|
|
|
|
|
|
tab1, tab2, tab3, tab4, tab5 = st.tabs([
|
|
|
"π€ Upload",
|
|
|
"π Anonimizzazione",
|
|
|
"π Analisi",
|
|
|
"π¬ Chatbot RAG",
|
|
|
"π€ CrewAI"
|
|
|
])
|
|
|
|
|
|
|
|
|
with tab1:
|
|
|
upload_tab()
|
|
|
|
|
|
|
|
|
with tab2:
|
|
|
anonymization_tab()
|
|
|
|
|
|
|
|
|
with tab3:
|
|
|
analysis_tab()
|
|
|
|
|
|
|
|
|
with tab4:
|
|
|
rag_tab()
|
|
|
|
|
|
|
|
|
with tab5:
|
|
|
crewai_tab()
|
|
|
|
|
|
def upload_tab():
|
|
|
"""Tab per upload file"""
|
|
|
st.header("π€ Carica Documenti")
|
|
|
|
|
|
uploaded_files = st.file_uploader(
|
|
|
"Carica uno o piΓΉ file .txt",
|
|
|
type=['txt'],
|
|
|
accept_multiple_files=True,
|
|
|
help="Seleziona i file di testo da anonimizzare"
|
|
|
)
|
|
|
|
|
|
if uploaded_files:
|
|
|
if process_uploaded_files(uploaded_files):
|
|
|
st.success(f"Caricati {len(uploaded_files)} file")
|
|
|
st.rerun()
|
|
|
else:
|
|
|
st.info("Nessun nuovo file caricato.")
|
|
|
|
|
|
|
|
|
st.subheader("π File caricati")
|
|
|
for filename, file_data in st.session_state.uploaded_files.items():
|
|
|
display_file_preview(filename, file_data['content'])
|
|
|
|
|
|
def anonymization_tab():
|
|
|
"""Tab per anonimizzazione"""
|
|
|
st.header("π Anonimizzazione e Revisione")
|
|
|
|
|
|
if not st.session_state.uploaded_files:
|
|
|
st.warning("β οΈ Carica prima alcuni documenti nella tab 'Upload'")
|
|
|
return
|
|
|
|
|
|
|
|
|
if st.button("π Avvia Anonimizzazione", type="primary"):
|
|
|
run_anonymization()
|
|
|
st.rerun()
|
|
|
|
|
|
|
|
|
if st.session_state.anonymized_docs:
|
|
|
st.subheader("π Revisiona Documenti Anonimizzati")
|
|
|
|
|
|
for filename, doc_data in st.session_state.anonymized_docs.items():
|
|
|
with st.expander(
|
|
|
f"π {filename} {'β
' if doc_data['confirmed'] else 'β³'}",
|
|
|
expanded=not doc_data['confirmed']
|
|
|
):
|
|
|
|
|
|
col1, col2 = st.columns(2)
|
|
|
|
|
|
|
|
|
with col1:
|
|
|
st.write("**Testo Originale:**")
|
|
|
preview = doc_data['original'][:300]
|
|
|
if len(doc_data['original']) > 300:
|
|
|
preview += "..."
|
|
|
|
|
|
st.text_area(
|
|
|
"Originale",
|
|
|
value=preview,
|
|
|
height=200,
|
|
|
disabled=True,
|
|
|
key=f"orig_{filename}",
|
|
|
label_visibility="collapsed"
|
|
|
)
|
|
|
|
|
|
|
|
|
with col2:
|
|
|
st.write("**Testo Anonimizzato:**")
|
|
|
edited_text = st.text_area(
|
|
|
"Anonimizzato (modificabile)",
|
|
|
value=doc_data['anonymized'],
|
|
|
height=200,
|
|
|
key=f"anon_{filename}",
|
|
|
label_visibility="collapsed"
|
|
|
)
|
|
|
|
|
|
|
|
|
if edited_text != doc_data['anonymized']:
|
|
|
st.session_state.anonymized_docs[filename]['anonymized'] = edited_text
|
|
|
|
|
|
|
|
|
updated_entities = display_entity_editor(dict(doc_data['entities']), filename)
|
|
|
|
|
|
|
|
|
col_confirm, col_reset = st.columns(2)
|
|
|
|
|
|
with col_confirm:
|
|
|
if st.button(f"β
Conferma {filename}", key=f"confirm_{filename}"):
|
|
|
st.session_state.anonymized_docs[filename]['confirmed'] = True
|
|
|
st.session_state.anonymized_docs[filename]['entities'] = updated_entities
|
|
|
st.success(f"β
{filename} confermato!")
|
|
|
st.session_state.vector_store_built = False
|
|
|
st.rerun()
|
|
|
|
|
|
with col_reset:
|
|
|
if st.button(f"π Reset {filename}", key=f"reset_{filename}"):
|
|
|
reset_document_state(filename)
|
|
|
st.rerun()
|
|
|
|
|
|
|
|
|
display_progress_metrics()
|
|
|
|
|
|
def analysis_tab():
|
|
|
"""Tab per analisi AI"""
|
|
|
st.header("π Analisi AI")
|
|
|
|
|
|
confirmed_docs = {k: v for k, v in st.session_state.anonymized_docs.items()
|
|
|
if v.get('confirmed', False)}
|
|
|
|
|
|
if not confirmed_docs:
|
|
|
st.warning("β οΈ Conferma prima alcuni documenti anonimizzati")
|
|
|
return
|
|
|
|
|
|
st.write(f"Documenti confermati pronti: **{len(confirmed_docs)}**")
|
|
|
|
|
|
if st.button("π€ Avvia Analisi AI", type="primary"):
|
|
|
run_ai_analysis()
|
|
|
|
|
|
|
|
|
if st.session_state.processed_docs:
|
|
|
st.subheader("π Risultati Analisi")
|
|
|
|
|
|
for filename, result in st.session_state.processed_docs.items():
|
|
|
display_analysis_results(filename, result)
|
|
|
|
|
|
|
|
|
result_json = export_results_json({
|
|
|
'filename': filename,
|
|
|
'anonymized_text': result['anonymized_text'],
|
|
|
'analysis': result['analysis'],
|
|
|
'entities': result['entities'],
|
|
|
'entities_count': result['entities_count']
|
|
|
}, f"analisi_{filename}")
|
|
|
|
|
|
create_download_button(
|
|
|
result_json,
|
|
|
f"analisi_{filename}.json",
|
|
|
f"πΎ Scarica {filename}",
|
|
|
f"download_{filename}"
|
|
|
)
|
|
|
|
|
|
def rag_tab():
|
|
|
"""Tab per RAG chatbot"""
|
|
|
st.header("π¬ Chatta con i Documenti")
|
|
|
|
|
|
confirmed_docs = {k: v for k, v in st.session_state.anonymized_docs.items()
|
|
|
if v.get('confirmed', False)}
|
|
|
|
|
|
if not confirmed_docs:
|
|
|
st.warning("β οΈ Carica e conferma documenti per abilitare il chatbot")
|
|
|
return
|
|
|
|
|
|
|
|
|
if build_rag_knowledge_base():
|
|
|
st.info(f"Chatbot pronto per {len(confirmed_docs)} documenti")
|
|
|
|
|
|
|
|
|
for message in st.session_state.chat_history:
|
|
|
with st.chat_message(message["role"]):
|
|
|
st.markdown(message["content"])
|
|
|
|
|
|
|
|
|
if prompt := st.chat_input("Fai una domanda sui documenti..."):
|
|
|
|
|
|
add_chat_message("user", prompt)
|
|
|
with st.chat_message("user"):
|
|
|
st.markdown(prompt)
|
|
|
|
|
|
|
|
|
with st.chat_message("assistant"):
|
|
|
with st.spinner("Generando risposta..."):
|
|
|
response = st.session_state.rag_chatbot.answer_question(prompt)
|
|
|
st.markdown(response)
|
|
|
|
|
|
|
|
|
add_chat_message("assistant", response)
|
|
|
else:
|
|
|
st.error("Impossibile costruire knowledge base. Verifica configurazione Azure.")
|
|
|
|
|
|
def crewai_tab():
|
|
|
"""Tab per CrewAI"""
|
|
|
st.header("π€ Analisi Multi-Agente CrewAI")
|
|
|
|
|
|
confirmed_docs = {k: v for k, v in st.session_state.anonymized_docs.items()
|
|
|
if v.get('confirmed', False)}
|
|
|
|
|
|
if not confirmed_docs:
|
|
|
st.warning("β οΈ Conferma documenti per abilitare CrewAI")
|
|
|
return
|
|
|
|
|
|
if not st.session_state.crewai_manager.agents:
|
|
|
st.error("β CrewAI non configurato. Verifica Azure OpenAI.")
|
|
|
return
|
|
|
|
|
|
|
|
|
build_rag_knowledge_base()
|
|
|
|
|
|
st.success(f"π― CrewAI pronto per {len(confirmed_docs)} documenti")
|
|
|
|
|
|
|
|
|
st.subheader("βοΈ Configurazione Analisi")
|
|
|
|
|
|
col1, col2 = st.columns(2)
|
|
|
|
|
|
with col1:
|
|
|
analysis_type = st.selectbox(
|
|
|
"Tipo di Analisi",
|
|
|
options=["comprehensive", "document", "sentiment", "rag", "custom"],
|
|
|
format_func=lambda x: {
|
|
|
"comprehensive": "π Analisi Comprensiva",
|
|
|
"document": "π Analisi Documentale",
|
|
|
"sentiment": "π Sentiment Analysis",
|
|
|
"rag": "π Query RAG Avanzata",
|
|
|
"custom": "βοΈ Personalizzata"
|
|
|
}[x]
|
|
|
)
|
|
|
|
|
|
with col2:
|
|
|
if analysis_type == "custom":
|
|
|
selected_agents = st.multiselect(
|
|
|
"Agenti da utilizzare",
|
|
|
options=list(st.session_state.crewai_manager.agents.keys()),
|
|
|
default=["strategy_coordinator"],
|
|
|
format_func=lambda x: {
|
|
|
"document_analyst": "π Document Analyst",
|
|
|
"rag_specialist": "π RAG Specialist",
|
|
|
"strategy_coordinator": "π― Strategy Coordinator",
|
|
|
"sentiment_analyst": "π Sentiment Analyst"
|
|
|
}.get(x, x)
|
|
|
)
|
|
|
else:
|
|
|
selected_agents = []
|
|
|
|
|
|
|
|
|
st.subheader("β Query per l'Analisi")
|
|
|
query_input = st.text_area(
|
|
|
"Inserisci la tua domanda:",
|
|
|
placeholder="Es: Analizza i temi principali e identifica rischi operativi...",
|
|
|
height=100
|
|
|
)
|
|
|
|
|
|
|
|
|
if analysis_type == "custom":
|
|
|
custom_instructions = st.text_area(
|
|
|
"Istruzioni Personalizzate:",
|
|
|
placeholder="Istruzioni specifiche per gli agenti...",
|
|
|
height=80
|
|
|
)
|
|
|
else:
|
|
|
custom_instructions = ""
|
|
|
|
|
|
|
|
|
col_analyze, col_clear = st.columns(2)
|
|
|
|
|
|
with col_analyze:
|
|
|
if st.button("π Avvia Analisi CrewAI", type="primary", disabled=not query_input.strip()):
|
|
|
if analysis_type == "custom" and not selected_agents:
|
|
|
st.error("Seleziona almeno un agente")
|
|
|
else:
|
|
|
|
|
|
if analysis_type == "custom":
|
|
|
result = st.session_state.crewai_manager.create_custom_task(
|
|
|
query_input, selected_agents, custom_instructions
|
|
|
)
|
|
|
else:
|
|
|
result = st.session_state.crewai_manager.create_analysis_task(
|
|
|
query_input, analysis_type
|
|
|
)
|
|
|
|
|
|
|
|
|
add_crewai_result(query_input, analysis_type, result, selected_agents)
|
|
|
st.success("β
Analisi CrewAI completata!")
|
|
|
|
|
|
with col_clear:
|
|
|
if st.button("ποΈ Pulisci Cronologia"):
|
|
|
clear_crewai_history()
|
|
|
st.success("Cronologia pulita!")
|
|
|
st.rerun()
|
|
|
|
|
|
|
|
|
if st.session_state.crewai_history:
|
|
|
st.subheader("π Risultati Analisi CrewAI")
|
|
|
|
|
|
for i, analysis in enumerate(reversed(st.session_state.crewai_history)):
|
|
|
display_crewai_result(analysis, len(st.session_state.crewai_history) - i)
|
|
|
|
|
|
|
|
|
result_json = export_results_json(analysis, f"crewai_analysis_{i}")
|
|
|
create_download_button(
|
|
|
result_json,
|
|
|
f"crewai_analysis_{analysis['timestamp'].replace(':', '-').replace(' ', '_')}.json",
|
|
|
"πΎ Scarica Risultato",
|
|
|
f"download_crewai_{i}"
|
|
|
)
|
|
|
|
|
|
|
|
|
display_examples_section()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
main() |