Spaces:
Sleeping
Sleeping
Flavio Casadei Della Chiesa
commited on
Commit
·
0f09876
1
Parent(s):
eb935f8
prima versione funzionante
Browse files- app.py +62 -15
- domandePNRR.xlsx +0 -0
- ragpipeline.py +99 -0
- 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 |
-
|
| 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 |
-
|
| 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 |
-
|
| 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 |
-
|
| 56 |
-
st.
|
| 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
|
| 65 |
-
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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=
|
| 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 |
|