Spaces:
Sleeping
Sleeping
| """ | |
| Componenti UI riutilizzabili per Streamlit. | |
| """ | |
| import streamlit as st | |
| import pandas as pd | |
| from typing import Dict | |
| from config import Config | |
| def setup_page_config(): | |
| """Configura la pagina Streamlit""" | |
| st.set_page_config( | |
| page_title="Anonimizzatore Documenti", | |
| page_icon="🔒", | |
| layout="wide" | |
| ) | |
| def display_sidebar(): | |
| """Mostra sidebar con configurazioni""" | |
| with st.sidebar: | |
| st.header("⚙️ Configurazione") | |
| # Status Azure | |
| if Config.AZURE_API_KEY and Config.AZURE_ENDPOINT: | |
| st.success("✅ Azure OpenAI configurato") | |
| st.info(f"Chat Model: {Config.DEPLOYMENT_NAME}") | |
| st.info(f"Embedding Model: {Config.AZURE_EMBEDDING_DEPLOYMENT_NAME}") | |
| else: | |
| st.error("❌ Azure OpenAI non configurato") | |
| st.write("Configura le variabili d'ambiente:") | |
| st.code(""" | |
| AZURE_ENDPOINT=your_endpoint | |
| AZURE_API_KEY=your_api_key | |
| AZURE_ENDPOINT_EMB=your_embedding_endpoint | |
| AZURE_API_KEY_EMB=your_embedding_api_key | |
| """) | |
| st.markdown("---") | |
| # Statistiche documenti | |
| if 'uploaded_files' in st.session_state and st.session_state.uploaded_files: | |
| st.subheader("📊 Statistiche") | |
| uploaded_count = len(st.session_state.uploaded_files) | |
| anonymized_count = len(st.session_state.get('anonymized_docs', {})) | |
| confirmed_count = sum(1 for doc in st.session_state.get('anonymized_docs', {}).values() | |
| if doc.get('confirmed', False)) | |
| st.metric("File caricati", uploaded_count) | |
| st.metric("Anonimizzati", anonymized_count) | |
| st.metric("Confermati", confirmed_count) | |
| if confirmed_count > 0: | |
| if st.session_state.get('vector_store_built', False): | |
| st.success("✅ Knowledge Base pronto") | |
| else: | |
| st.info("🔄 Knowledge Base da costruire") | |
| st.markdown("---") | |
| # Reset button | |
| if st.button("🔄 Reset sessione"): | |
| for key in list(st.session_state.keys()): | |
| del st.session_state[key] | |
| st.rerun() | |
| def display_entity_editor(entities: Dict, doc_key: str): | |
| """Editor per entità rilevate""" | |
| if not entities: | |
| st.info("Nessuna entità sensibile rilevata.") | |
| return entities | |
| st.subheader("🔍 Entità rilevate") | |
| st.write("Verifica e modifica le entità sensibili:") | |
| current_entities_list = list(entities.items()) | |
| updated_entities_dict = {} | |
| deleted_placeholders = set() | |
| for i, (placeholder, original_value) in enumerate(current_entities_list): | |
| col1, col2, col3 = st.columns([2, 3, 1]) | |
| with col1: | |
| st.write(f"**{placeholder}**") | |
| with col2: | |
| new_value = st.text_input( | |
| "Valore originale", | |
| value=original_value, | |
| key=f"{doc_key}_{placeholder}_value_{i}" | |
| ) | |
| updated_entities_dict[placeholder] = new_value | |
| with col3: | |
| if st.button("🗑️", key=f"{doc_key}_{placeholder}_delete_{i}", help="Rimuovi"): | |
| deleted_placeholders.add(placeholder) | |
| # Gestisci cancellazioni | |
| if deleted_placeholders: | |
| final_entities = {k: v for k, v in updated_entities_dict.items() | |
| if k not in deleted_placeholders} | |
| st.session_state.anonymized_docs[doc_key]['entities'] = final_entities | |
| # Re-anonimizza testo | |
| from anonymizer import NERAnonimizer | |
| anonymizer = NERAnonimizer() | |
| st.session_state.anonymized_docs[doc_key]['anonymized'], _ = anonymizer.anonymize( | |
| st.session_state.anonymized_docs[doc_key]['original'] | |
| ) | |
| st.session_state.vector_store_built = False | |
| st.rerun() | |
| return updated_entities_dict | |
| def display_file_preview(filename: str, content: str, max_chars: int = 500): | |
| """Mostra anteprima file""" | |
| with st.expander(f"📄 {filename} ({len(content)} caratteri)"): | |
| preview_text = content[:max_chars] | |
| if len(content) > max_chars: | |
| preview_text += "..." | |
| st.text_area( | |
| "Contenuto", | |
| value=preview_text, | |
| height=150, | |
| disabled=True, | |
| key=f"preview_{filename}", | |
| label_visibility="collapsed" | |
| ) | |
| def display_analysis_results(filename: str, result: Dict): | |
| """Mostra risultati analisi""" | |
| with st.expander(f"📊 Analisi: {filename}"): | |
| # Metriche | |
| col1, col2, col3 = st.columns(3) | |
| col1.metric("Caratteri testo", len(result['anonymized_text'])) | |
| col2.metric("Entità trovate", result['entities_count']) | |
| col3.metric("Stato", "✅ Completato") | |
| # Testo anonimizzato | |
| st.subheader("📄 Testo Anonimizzato") | |
| st.text_area( | |
| "Testo processato", | |
| value=result['anonymized_text'], | |
| height=150, | |
| disabled=True, | |
| key=f"analysis_text_{filename}" | |
| ) | |
| # Analisi AI | |
| st.subheader("🤖 Analisi AI") | |
| st.markdown(result['analysis']) | |
| # Entità | |
| if result['entities']: | |
| st.subheader("🔍 Entità Anonimizzate") | |
| entities_df = pd.DataFrame([ | |
| { | |
| 'Placeholder': k, | |
| 'Valore Originale': v, | |
| 'Tipo': k.split('_')[0].replace('[', '') | |
| } | |
| for k, v in result['entities'].items() | |
| ]) | |
| st.dataframe(entities_df, use_container_width=True) | |
| def display_crewai_result(analysis: Dict, index: int): | |
| """Mostra risultato analisi CrewAI""" | |
| with st.expander( | |
| f"🤖 Analisi {index}: {analysis['analysis_type'].upper()} - {analysis['timestamp']}" | |
| ): | |
| # Info header | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.metric("Tipo Analisi", analysis['analysis_type'].capitalize()) | |
| with col2: | |
| st.metric("Timestamp", analysis['timestamp']) | |
| with col3: | |
| agents_used = analysis.get('agents_used', 'auto') | |
| if agents_used == 'auto': | |
| agent_count = "Automatico" | |
| elif isinstance(agents_used, list): | |
| agent_count = f"{len(agents_used)} agenti" | |
| else: | |
| agent_count = str(agents_used) | |
| st.metric("Agenti", agent_count) | |
| # Query e risultato | |
| st.subheader("❓ Query Originale") | |
| st.info(analysis['query']) | |
| st.subheader("🎯 Risultato Analisi") | |
| st.markdown(analysis['result']) | |
| def display_progress_metrics(): | |
| """Mostra metriche di progresso""" | |
| if 'anonymized_docs' in st.session_state: | |
| confirmed_count = sum(1 for doc in st.session_state.anonymized_docs.values() | |
| if doc.get('confirmed', False)) | |
| total_count = len(st.session_state.anonymized_docs) | |
| if total_count > 0: | |
| st.metric( | |
| "Progresso Conferme", | |
| f"{confirmed_count}/{total_count}", | |
| delta=f"{(confirmed_count/total_count)*100:.1f}%" | |
| ) | |
| def display_examples_section(): | |
| """Mostra esempi di query CrewAI""" | |
| with st.expander("💡 Esempi di Query per CrewAI"): | |
| st.markdown(""" | |
| **Analisi Comprensiva:** | |
| - "Fornisci un'analisi completa dei documenti identificando rischi, opportunità e raccomandazioni strategiche" | |
| - "Analizza la comunicazione aziendale e suggerisci miglioramenti nella gestione clienti" | |
| **Analisi Documentale:** | |
| - "Classifica i documenti per tipologia e identifica pattern ricorrenti" | |
| - "Analizza la struttura e organizzazione delle informazioni nei documenti" | |
| **Sentiment Analysis:** | |
| - "Valuta il sentiment generale nelle comunicazioni e identifica aree di miglioramento" | |
| - "Analizza le emozioni e i trend nei feedback dei clienti" | |
| **Query RAG Avanzata:** | |
| - "Trova tutte le menzioni di problemi operativi e le relative soluzioni proposte" | |
| - "Estrai informazioni su scadenze, deadline e milestone importanti" | |
| **Personalizzata:** | |
| - Combina agenti specifici per analisi mirate alle tue esigenze | |
| """) | |
| def create_download_button(data: str, filename: str, label: str, key: str): | |
| """Crea bottone download con dati""" | |
| st.download_button( | |
| label=label, | |
| data=data, | |
| file_name=filename, | |
| mime="application/json", | |
| key=key | |
| ) |