Flavio Casadei Della Chiesa commited on
Commit
0f09876
·
1 Parent(s): eb935f8

prima versione funzionante

Browse files
Files changed (4) hide show
  1. app.py +62 -15
  2. domandePNRR.xlsx +0 -0
  3. ragpipeline.py +99 -0
  4. textutils.py +1 -1
app.py CHANGED
@@ -3,6 +3,9 @@ import os
3
  from transformers import pipeline
4
  from HFBot import HFBot
5
  from textutils import ParagraphDocumentProcessor, WholeTextDocumentProcessor, SmallFragmentDocumentProcessor
 
 
 
6
  def main():
7
  modelliLLM = [
8
  'Almawave/Velvet-2B',
@@ -15,28 +18,36 @@ def main():
15
  UPLOAD_DIR="/tmp/"
16
  if "indice_creato" not in st.session_state:
17
  st.session_state["indice_creato"] = False
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
- testi = []
20
  modello_scelto = st.selectbox("Seleziona un modello:", modelliLLM, index=0)
21
  st.write(f"Hai selezionato: {modello_scelto}")
22
 
23
  LLM = HFBot(model_name=modello_scelto)
24
- domanda ="Valuta questo testo"
25
- Istruzioni = "Rispondi sinteticamente"
26
- frammenti = [
27
- "visto il DPR 445/2000" , "con sui si elegge il presidente della repubblica"
28
- ]
29
 
30
  #res = LLM.chat(domanda=domanda, istruzioni= Istruzioni, frammenti=frammenti)
31
  #st.write(f"Domanda {domanda} - risposta {res}")
32
  st.title("Suddivisione in paragrafi")
33
  docprocessor_options = {
34
  "ParagraphDocumentProcessor": ParagraphDocumentProcessor(),
35
- "WholeText": WholeTextDocumentProcessor(),
36
- "Small Fragments": SmallFragmentDocumentProcessor(),
37
  }
38
  selected_docprocessor = st.selectbox("Divisione in paragrafi", docprocessor_options.keys())
39
- docprocessor = docprocessor_options[selected_docprocessor]
40
  st.write(f"Hai selezionato: **{selected_docprocessor}**")
41
 
42
  if not st.session_state["indice_creato"]:
@@ -51,19 +62,55 @@ def main():
51
  save_path = os.path.join(UPLOAD_DIR, main_pdf.name)
52
  with open(save_path, "wb") as f:
53
  f.write(main_pdf.read())
 
54
  st.success(f"✅ Determinazione caricata con successo! File salvato in: `{save_path}`")
55
- testi= docprocessor.estrai_da_pdf(save_path)
56
- st.write(testi[:400])
57
- #ßragpipeline.aggiungi_file_pdf(save_path)
58
  st.session_state["indice_creato"] = True
59
  except Exception as e:
60
  st.error(f"❌ Errore nel salvataggio del file: {e}")
61
  else:
62
  st.warning("Nessun PDF di Determinazione caricato.")
63
  if st.session_state["indice_creato"]:
64
- st.write("Eseguo riassunto")
65
- summary = LLM.riassumi(testi)
66
- st.success(summary)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
  if __name__ == "__main__":
69
  main()
 
3
  from transformers import pipeline
4
  from HFBot import HFBot
5
  from textutils import ParagraphDocumentProcessor, WholeTextDocumentProcessor, SmallFragmentDocumentProcessor
6
+ import pandas as pd
7
+ from ragpipeline import RAGPipeline, Retriever
8
+
9
  def main():
10
  modelliLLM = [
11
  'Almawave/Velvet-2B',
 
18
  UPLOAD_DIR="/tmp/"
19
  if "indice_creato" not in st.session_state:
20
  st.session_state["indice_creato"] = False
21
+ if "faiss_builder" not in st.session_state:
22
+ ragpipeline = RAGPipeline( )
23
+ codice_tabella = f"<table><tr><td>💡AURA:</td><td> AI-Utilizzata per la Regolarità Amministrativa</td></tr></table>"
24
+ st.markdown(codice_tabella, unsafe_allow_html=True)
25
+ st.title("Cosa è AURA?")
26
+ st.write("""
27
+ Questo strumento, sperimentale, è stato realizzato per eseguire i controlli di
28
+ regolarità amministrativa ex art. 147-bis del D.Lgs 267/2000 relativamente agli atti del PNRR.
29
+ E' in continua evoluzione. Per testarne il funzionamento è suddiciente caricare un file PDF contenente una determinazione dirigenziale.
30
+ AURA risponderà in base ad una check list predefinita di domande.
31
+
32
+ """)
33
 
34
+ st.warning("Attenzione questo tool è sperimentale. AURA può sbagliare")
35
  modello_scelto = st.selectbox("Seleziona un modello:", modelliLLM, index=0)
36
  st.write(f"Hai selezionato: {modello_scelto}")
37
 
38
  LLM = HFBot(model_name=modello_scelto)
39
+
 
 
 
 
40
 
41
  #res = LLM.chat(domanda=domanda, istruzioni= Istruzioni, frammenti=frammenti)
42
  #st.write(f"Domanda {domanda} - risposta {res}")
43
  st.title("Suddivisione in paragrafi")
44
  docprocessor_options = {
45
  "ParagraphDocumentProcessor": ParagraphDocumentProcessor(),
46
+ # "WholeText": WholeTextDocumentProcessor(),
47
+ "Small Fragments (più veloce ma poco preciso)": SmallFragmentDocumentProcessor(),
48
  }
49
  selected_docprocessor = st.selectbox("Divisione in paragrafi", docprocessor_options.keys())
50
+ ragpipeline.docprocessor = docprocessor_options[selected_docprocessor]
51
  st.write(f"Hai selezionato: **{selected_docprocessor}**")
52
 
53
  if not st.session_state["indice_creato"]:
 
62
  save_path = os.path.join(UPLOAD_DIR, main_pdf.name)
63
  with open(save_path, "wb") as f:
64
  f.write(main_pdf.read())
65
+ ragpipeline.aggiungi_file_pdf(save_path)
66
  st.success(f"✅ Determinazione caricata con successo! File salvato in: `{save_path}`")
67
+ ragpipeline.crea_indice( )
68
+ st.success("Indice FAISS generato e caricato.")
 
69
  st.session_state["indice_creato"] = True
70
  except Exception as e:
71
  st.error(f"❌ Errore nel salvataggio del file: {e}")
72
  else:
73
  st.warning("Nessun PDF di Determinazione caricato.")
74
  if st.session_state["indice_creato"]:
75
+ st.write("Eseguo controlli")
76
+ csv_file ="domandePNRR.xlsx"
77
+
78
+
79
+ df = pd.read_excel(csv_file)
80
+ if "domanda" in df.columns:
81
+ domande = df["domanda"].tolist()
82
+ istruzioni = df["istruzioni"].tolist();
83
+ #print(f"ISTRUZIONI {istruzioni}")
84
+ st.success(f"Caricate {len(domande)} domande!")
85
+ if ragpipeline.indice is not None :
86
+ #cb = ChatBot(model_name="flaollama", model_orig=modello_scelto)
87
+ st.write("**Risposte automatiche per ciascuna domanda **:")
88
+ i = 0
89
+ for domanda in domande:
90
+ istruzione = istruzioni[i]
91
+ ret = Retriever (indice=ragpipeline.indice,
92
+ sentence_transformer_model=ragpipeline.sentence_transformer_model,
93
+ query=domanda ,
94
+ documenti=ragpipeline.documenti,
95
+ frammenti_indicizzati= ragpipeline.frammenti_indicizzati,
96
+ attributi_frammenti= ragpipeline.attributi_frammenti
97
+ )
98
+ ret.esegui_query( top_k=3 )
99
+ risposta = LLM.generate(query=domanda,
100
+ relevant_docs=ret.passaggi_rilevanti,attributi_frammenti_rilevanti=ret.attributi_rilevanti,
101
+ istruzioni=istruzione)
102
+ st.markdown(
103
+ f"<p><strong>Domanda:</strong> {domanda} Istruzioni: <em>{istruzione}</em><br/><br/>"
104
+ f"<strong>Risposta:</strong><em> {risposta}</em></p>",
105
+ unsafe_allow_html=True
106
+ )
107
+
108
+
109
+ i = i+1
110
+
111
+
112
+
113
+
114
 
115
  if __name__ == "__main__":
116
  main()
domandePNRR.xlsx ADDED
Binary file (7.32 kB). View file
 
ragpipeline.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from textutils import ParagraphDocumentProcessor, DocumentProcessor
2
+ from sentence_transformers import SentenceTransformer
3
+ from transformers import AutoTokenizer, AutoModel
4
+ import faiss
5
+ import os
6
+ import csv
7
+ import re
8
+ import pandas as pd
9
+
10
+
11
+ class RAGPipeline:
12
+ def __init__(self,
13
+ model_name: str = "flaollama",
14
+ model_orig: str = "mistral",
15
+ docprocessor = ParagraphDocumentProcessor(),
16
+ sentence_transformer_name: str = 'paraphrase-multilingual-MiniLM-L12-v2',
17
+ numero_frammenti = 10
18
+ ) :
19
+ self.model_name = model_name
20
+ self.model_orig = model_orig
21
+ self.docprocessor = docprocessor
22
+ self.sentence_transformer_name = sentence_transformer_name
23
+ self.sentence_transformer_model = SentenceTransformer( self.sentence_transformer_name )
24
+ self.numero_frammenti = numero_frammenti
25
+
26
+ self.documenti = []
27
+ self.files_pdf =[]
28
+ self.indice =False
29
+
30
+ ##attrributi_frammenti contiene una lista di frammenti con attribui es:
31
+ ##
32
+ ##
33
+ ##
34
+ self.attributi_frammenti = [] #elenco di dizionari di tutti i frammenti
35
+ ##LISTA DI FRAMMENTI INDICIZZATI (lista di testi)
36
+ self. frammenti_indicizzati = [] #sonoi testi dei vari frammenti
37
+ #print(f"NUMERODI FRAMMENTIIIII {self.numero_frammenti} param {numero_frammenti}")
38
+
39
+
40
+ def crea_indice(self):
41
+ # Converte i documenti in vettori
42
+ docId = 0
43
+ fraId = 0
44
+ for documento in self.documenti:
45
+ frammenti = self.docprocessor.scomponi_in_frammenti(documento, self.numero_frammenti )
46
+ for frammento in frammenti:
47
+ dizionario_frammenti = {
48
+ 'id': f"{docId}-{fraId}",
49
+ "documento": docId,
50
+ "frammento": fraId,
51
+
52
+ 'testo_frammento':frammento
53
+ }
54
+ self.attributi_frammenti.append( dizionario_frammenti )
55
+ self.frammenti_indicizzati.append(frammento)
56
+ fraId = fraId +1
57
+ docId = docId +1
58
+ self.doc_embeddings = self.sentence_transformer_model.encode(self.frammenti_indicizzati)
59
+ # Creazione dell'indice Faiss
60
+ dimension = self.doc_embeddings.shape[1]
61
+ self.indice = faiss.IndexFlatL2(dimension) # Indice L2 (distanza euclidea)
62
+ self.indice.add(self.doc_embeddings)
63
+
64
+ def aggiungi_file_pdf(self, filename: str) :
65
+ text= self.docprocessor.estrai_da_pdf(filename)
66
+ self.documenti.append(text)
67
+ self.files_pdf.append(filename)
68
+
69
+ class Retriever:
70
+ def __init__(self,
71
+ indice ,
72
+ sentence_transformer_model ,
73
+ query : str,
74
+ documenti =[],
75
+ frammenti_indicizzati = [], #tutti i frammenti ??
76
+ attributi_frammenti = [] ##elenco attrivuti frammenti
77
+
78
+ ):
79
+ self.indice = indice
80
+ self.sentence_transformer = sentence_transformer_model
81
+ self.query = query
82
+ self.documenti = documenti
83
+ self.frammenti_indicizzati = frammenti_indicizzati
84
+ self.attributi_frammenti = attributi_frammenti
85
+ self.passaggi_rilevanti = [] ## documenti rilevanti per la query (recuperati)
86
+ self.attributi_rilevanti = [] ## atteributi dei frammenti rilevanti
87
+
88
+ def esegui_query(self, top_k = 5):
89
+ # Embedding della query
90
+ query_embedding = self.sentence_transformer.encode([self.query])
91
+
92
+ # Recupero dei documenti più simili
93
+ distances, indices = self.indice.search(query_embedding, top_k)
94
+
95
+ # documenti rilevanti e passaggi rilevanti
96
+ self.passaggi_rilevanti = [self.frammenti_indicizzati[j] for j in indices[0]] #frammenti rilevanti
97
+ self.attributi_rilevanti = [self.attributi_frammenti[j] for j in indices[0]] #passaggi rilevanti
98
+
99
+
textutils.py CHANGED
@@ -151,7 +151,7 @@ class SmallFragmentDocumentProcessor(DocumentProcessor):
151
  def scomponi_in_frammenti(self, testo:str, numero_frammenti: int = 1):
152
  return self.dividi_testo_in_frammenti(testo)
153
 
154
- def dividi_testo_in_frammenti(self,testo, lunghezza_massima=500):
155
  frammenti = []
156
  inizio = 0
157
 
 
151
  def scomponi_in_frammenti(self, testo:str, numero_frammenti: int = 1):
152
  return self.dividi_testo_in_frammenti(testo)
153
 
154
+ def dividi_testo_in_frammenti(self,testo, lunghezza_massima=1000):
155
  frammenti = []
156
  inizio = 0
157