Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -19,6 +19,20 @@ import fitz
|
|
| 19 |
import re
|
| 20 |
import io
|
| 21 |
from collections import Counter
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
GENERATION_CONFIG = settings_ai.GENERATION_CONFIG
|
| 24 |
SYSTEM_INSTRUCTION = settings_ai.SYSTEM_INSTRUCTION
|
|
@@ -324,13 +338,12 @@ def parse_invoice_to_documento_azure(result) -> Documento:
|
|
| 324 |
|
| 325 |
# Front-End con Streamlit
|
| 326 |
def main():
|
| 327 |
-
st.set_page_config(page_title="Import Fatture AI", page_icon="✨")
|
| 328 |
-
st.title("Import Fatture AI ✨")
|
| 329 |
st.sidebar.title("Caricamento File")
|
| 330 |
uploaded_files = st.sidebar.file_uploader("Seleziona uno o più PDF", type=["pdf", "jpg", "jpeg", "png"], accept_multiple_files=True)
|
| 331 |
-
model_ai = st.sidebar.selectbox("Modello", ['Gemini Flash 2.0']) #'Azure Intelligence'])
|
| 332 |
use_azure = True if model_ai == 'Azure Intelligence' else False
|
| 333 |
-
number_pages_split = st.sidebar.slider('Split Pagine', 1, 30, 2)
|
| 334 |
if st.sidebar.button("Importa", type="primary", use_container_width=True):
|
| 335 |
if not uploaded_files:
|
| 336 |
st.warning("Nessun file caricato!")
|
|
@@ -383,4 +396,50 @@ def main():
|
|
| 383 |
os.remove(file_path)
|
| 384 |
|
| 385 |
if __name__ == "__main__":
|
| 386 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
import re
|
| 20 |
import io
|
| 21 |
from collections import Counter
|
| 22 |
+
from streamlit_google_auth import Authenticate
|
| 23 |
+
|
| 24 |
+
secret_json_str = os.getenv("JSON_GOOGLE_SECRET")
|
| 25 |
+
if secret_json_str:
|
| 26 |
+
secret_data = json.loads(secret_json_str)
|
| 27 |
+
with open("secret-account.json", "w") as f:
|
| 28 |
+
f.write(secret_json_str)
|
| 29 |
+
|
| 30 |
+
authenticator = Authenticate(
|
| 31 |
+
secret_credentials_path = 'secret-account.json',
|
| 32 |
+
cookie_name='my_cookie_name',
|
| 33 |
+
cookie_key='this_is_secret',
|
| 34 |
+
redirect_uri = 'http://localhost:8501',
|
| 35 |
+
)
|
| 36 |
|
| 37 |
GENERATION_CONFIG = settings_ai.GENERATION_CONFIG
|
| 38 |
SYSTEM_INSTRUCTION = settings_ai.SYSTEM_INSTRUCTION
|
|
|
|
| 338 |
|
| 339 |
# Front-End con Streamlit
|
| 340 |
def main():
|
| 341 |
+
#st.set_page_config(page_title="Import Fatture AI", page_icon="✨")
|
|
|
|
| 342 |
st.sidebar.title("Caricamento File")
|
| 343 |
uploaded_files = st.sidebar.file_uploader("Seleziona uno o più PDF", type=["pdf", "jpg", "jpeg", "png"], accept_multiple_files=True)
|
| 344 |
+
model_ai = st.sidebar.selectbox("Modello", ['Gemini Flash 2.0']) # 'Azure Intelligence'])
|
| 345 |
use_azure = True if model_ai == 'Azure Intelligence' else False
|
| 346 |
+
number_pages_split = st.sidebar.slider('Split Pagine', 1, 30, 2, help="Numero suddivisione pagine del PDF. Più il numero è basso e più il modello AI è preciso, più è alto più è veloce")
|
| 347 |
if st.sidebar.button("Importa", type="primary", use_container_width=True):
|
| 348 |
if not uploaded_files:
|
| 349 |
st.warning("Nessun file caricato!")
|
|
|
|
| 396 |
os.remove(file_path)
|
| 397 |
|
| 398 |
if __name__ == "__main__":
|
| 399 |
+
st.title("Import Fatture AI ✨")
|
| 400 |
+
with st.expander("Guida completa"):
|
| 401 |
+
st.write("""Questa applicazione Python, basata su Streamlit, integra servizi di intelligenza artificiale di Gemini per automatizzare l'estrazione e la validazione dei dati dalle fatture. Il sistema gestisce documenti in vari formati (PDF, immagini) e li elabora in maniera modulare per facilitare la conversione e la verifica delle informazioni.
|
| 402 |
+
|
| 403 |
+
## Funzionalità Principali
|
| 404 |
+
|
| 405 |
+
- **Caricamento e Gestione dei Documenti**
|
| 406 |
+
- Supporta il caricamento di file PDF, JPG, JPEG e PNG tramite un’interfaccia Streamlit.
|
| 407 |
+
- Se il file è un PDF con più pagine, viene suddiviso in sezioni (configurabile tramite uno slider) per una gestione più efficace. Più il numero è basso più il risultato è preciso.
|
| 408 |
+
|
| 409 |
+
- **Conversione dei Dati**
|
| 410 |
+
- **Upload e Inoltro a Gemini**: I file vengono caricati e inviati al rispettivo servizio AI.
|
| 411 |
+
- **Estrazione dei Dati**: Il sistema invia il documento a un modello di generazione AI per ottenere una rappresentazione JSON contenente i dati (ad es. numero di documento, data, totale imponibile e articoli).
|
| 412 |
+
|
| 413 |
+
- **Validazione e Verifica**
|
| 414 |
+
- **Validazione JSON**: Utilizza Pydantic per verificare la correttezza della struttura e dei dati estratti. In caso di errori, il documento viene riprocessato fino a 3 volte per cercare di correggere le anomalie.
|
| 415 |
+
- **Verifica Incrociata dei Contenuti**: Per i PDF, viene estratto il testo con PyPDF2 e confrontato con i codici articolo per assicurarsi che i dati siano effettivamente presenti nel documento.
|
| 416 |
+
- **Filtraggio Articoli**: Vengono mantenuti solo gli articoli compatibili con i criteri specifici (codici articolo e importi non nulli).
|
| 417 |
+
|
| 418 |
+
- **Visualizzazione e Highlighting**
|
| 419 |
+
- I dati validati vengono mostrati in formato tabellare e in JSON.
|
| 420 |
+
- Se il documento è un PDF, il sistema evidenzia graficamente (con rettangoli rossi) i testi relativi agli articoli compatibili, semplificando il controllo visivo.
|
| 421 |
+
|
| 422 |
+
## Avvertenze per l'Operatore
|
| 423 |
+
|
| 424 |
+
- **Controllo Manuale Obbligatorio**:
|
| 425 |
+
L'operatore **deve sempre verificare** i dati elaborati.
|
| 426 |
+
Nonostante il riprocessamento automatico in caso di errori, è fondamentale controllare la correttezza dei dati estratti e la validità degli articoli.
|
| 427 |
+
|
| 428 |
+
- **Validazione dei Dati**:
|
| 429 |
+
L'operazione di validazione tramite Pydantic e la verifica incrociata sul contenuto del PDF sono cruciali.
|
| 430 |
+
Assicurarsi che non vi siano discrepanze, specialmente nei casi in cui alcuni articoli risultino non verificati.
|
| 431 |
+
""")
|
| 432 |
+
|
| 433 |
+
st.write("📄 **Legge più PDF:** Carica più file PDF contemporaneamente")
|
| 434 |
+
st.write("🤖 **Sfrutta l'AI di Gemini:** Per ogni documento, estrae i dati in formato JSON e in formato tabellare.")
|
| 435 |
+
st.write("✅ **Mostra Articoli Compatibili:** Filtra e visualizza solo gli articoli che rispettano i criteri richiesti.")
|
| 436 |
+
st.write("🔍 **Anteprima Documento:** Visualizza un'anteprima del documento evidenziando gli articoli compatibili.")
|
| 437 |
+
authenticator.check_authentification()
|
| 438 |
+
authenticator.login()
|
| 439 |
+
if st.session_state['connected']:
|
| 440 |
+
st.divider()
|
| 441 |
+
main()
|
| 442 |
+
else:
|
| 443 |
+
with st.sidebar:
|
| 444 |
+
st.title("Login")
|
| 445 |
+
st.write("Seleziona l'account aziendale per accedere")
|