alegio98 commited on
Commit
f56e52a
Β·
1 Parent(s): 87756ed

fix con file ingest

Browse files
Files changed (2) hide show
  1. app.py +8 -16
  2. rag_ingest.py +254 -0
app.py CHANGED
@@ -11,25 +11,17 @@ st.title("πŸ€– RAG Chatbot – INSIEL")
11
 
12
  import os
13
  import streamlit as st
 
14
 
15
- # Esegue il notebook una volta se vectorstore non esiste
16
- def run_notebook_once():
17
  if not os.path.exists("vectorstore"):
18
- st.info("Inizializzazione: generazione vectorstore in corsoo...")
 
 
 
 
 
19
 
20
- import nbformat
21
- from nbconvert.preprocessors import ExecutePreprocessor
22
-
23
- with open("rag.ipynb") as f:
24
- nb = nbformat.read(f, as_version=4)
25
-
26
- ep = ExecutePreprocessor(timeout=600)
27
- ep.preprocess(nb, {"metadata": {"path": "./"}})
28
-
29
- st.success("Vectorstore generata correttamente βœ…")
30
-
31
- # Chiama la funzione prima di tutto
32
- run_notebook_once()
33
 
34
 
35
 
 
11
 
12
  import os
13
  import streamlit as st
14
+ import subprocess
15
 
16
+ def run_ingest_if_needed():
 
17
  if not os.path.exists("vectorstore"):
18
+ st.info("Inizializzazione: generazione vectorstore in corso...")
19
+ try:
20
+ subprocess.run(["python", "rag_ingest.py"], check=True)
21
+ st.success("Vectorstore generata correttamente βœ…")
22
+ except subprocess.CalledProcessError:
23
+ st.error("Errore durante la generazione della vectorstore.")
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
 
27
 
rag_ingest.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+
4
+ # In[1]:
5
+
6
+
7
+ get_ipython().system('pip install docling chromadb sentence-transformers')
8
+
9
+
10
+ # In[2]:
11
+
12
+
13
+ get_ipython().system('pip install pymupdf tqdm spacy')
14
+ get_ipython().system('python -m spacy download it_core_news_sm')
15
+
16
+
17
+ # In[3]:
18
+
19
+
20
+ get_ipython().system('pip install transformers')
21
+
22
+
23
+ # In[4]:
24
+
25
+
26
+ import fitz # PyMuPDF
27
+ from tqdm.auto import tqdm
28
+ import pandas as pd
29
+
30
+ def text_formatter(text: str) -> str:
31
+ # Pulizia semplice
32
+ import re
33
+ text = text.replace("\n", " ").strip()
34
+ text = re.sub(r"[ \t]{2,}", " ", text)
35
+ text = re.sub(r"\.{2,}", " ", text) # sostituisce ... con spazio
36
+ text = re.sub(r"Pagina\s+\d+\s+di\s+\d+", "", text, flags=re.IGNORECASE)
37
+ text = re.sub(r"Creazione VM su Cloud INSIEL","", text)
38
+ text = re.sub(r"IO_XX_00_XX ISTRUZIONE OPERATIVA 22/10/2024", "",text)
39
+ text = re.sub(r"IO_XX_00_XX ISTRUZIONE OPERATIVA 22/10/2024 ","",text)
40
+ return text.strip()
41
+
42
+ def open_and_read_pdf(pdf_path: str):
43
+ doc = fitz.open(pdf_path)
44
+ pages = []
45
+ for page_number, page in tqdm(enumerate(doc), total=len(doc), desc="πŸ“„ Lettura pagine PDF"):
46
+ text = text_formatter(page.get_text())
47
+ pages.append({
48
+ "page_number": page_number + 1,
49
+ "page_char_count": len(text),
50
+ "page_word_count": len(text.split()),
51
+ "page_token_estimate": len(text) // 4,
52
+ "text": text
53
+ })
54
+ return pages
55
+
56
+ pdf_path = "data/insiel.pdf" # Cambia se il tuo file Γ¨ altrove
57
+ pages_and_texts = open_and_read_pdf(pdf_path)
58
+
59
+
60
+ # In[5]:
61
+
62
+
63
+ import spacy
64
+ nlp = spacy.load("it_core_news_sm")
65
+
66
+ # Spezza il testo di ogni pagina in frasi
67
+ for page in tqdm(pages_and_texts, desc="βœ‚οΈ Split in frasi"):
68
+ doc = nlp(page["text"])
69
+ sentences = [sent.text.strip() for sent in doc.sents if sent.text.strip()]
70
+ page["sentence_chunks"] = []
71
+
72
+ CHUNK_SIZE = 10 # Gruppi da 5 frasi
73
+ for i in range(0, len(sentences), CHUNK_SIZE):
74
+ chunk = sentences[i:i + CHUNK_SIZE]
75
+ page["sentence_chunks"].append(chunk)
76
+
77
+
78
+ # In[6]:
79
+
80
+
81
+ pages_and_texts[65]
82
+
83
+
84
+ # In[7]:
85
+
86
+
87
+ df = pd.DataFrame(pages_and_texts)
88
+ df["chunk_id"] = df.index.astype(str)
89
+
90
+ # Mostra i primi
91
+ df.tail()
92
+
93
+
94
+ # In[8]:
95
+
96
+
97
+ df.shape
98
+
99
+
100
+ # In[9]:
101
+
102
+
103
+ df[df['page_token_estimate'] < 60].count()
104
+
105
+
106
+ # In[10]:
107
+
108
+
109
+ final = df[df['page_token_estimate'] > 60]
110
+
111
+
112
+ # In[11]:
113
+
114
+
115
+ final.describe().round(2)
116
+
117
+
118
+ # In[12]:
119
+
120
+
121
+ get_ipython().system('pip install sentence-transformers chromadb')
122
+
123
+
124
+ # In[13]:
125
+
126
+
127
+ from sentence_transformers import SentenceTransformer
128
+ from tqdm.notebook import tqdm
129
+
130
+ embedding_model = SentenceTransformer("sentence-transformers/distiluse-base-multilingual-cased-v1")
131
+
132
+ texts = final["text"].tolist()
133
+ chunk_ids = final["chunk_id"].tolist()
134
+ metadatas = [{"page": int(p)} for p in final["page_number"]]
135
+
136
+ embeddings = embedding_model.encode(texts, show_progress_bar=True)
137
+
138
+
139
+ # In[14]:
140
+
141
+
142
+ import chromadb
143
+
144
+ # nuovo client
145
+ client = chromadb.PersistentClient(path="./vectorstore")
146
+
147
+ # collection
148
+ collection = client.get_or_create_collection("insiel_chunks")
149
+
150
+ # aggiunta
151
+ collection.add(
152
+ documents=texts,
153
+ embeddings=embeddings.tolist(),
154
+ metadatas=metadatas,
155
+ ids=chunk_ids
156
+ )
157
+
158
+
159
+ # In[16]:
160
+
161
+
162
+ """query = input("Domanda: ")
163
+ query_embedding = embedding_model.encode([query])
164
+ """
165
+ results = collection.query(
166
+ query_embeddings=query_embedding,
167
+ n_results=3 # puoi aumentare a 5, 10, ecc.
168
+ )
169
+
170
+
171
+ # In[17]:
172
+
173
+
174
+ """for i, (doc, meta) in enumerate(zip(results["documents"][0], results["metadatas"][0])):
175
+ print(f"\nπŸ”Ή RISULTATO {i+1} (pagina {meta['page']}):")
176
+ print(doc[:500] + "...\n---")
177
+ """
178
+
179
+
180
+ # In[18]:
181
+
182
+
183
+ import torch
184
+ from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
185
+
186
+ model_id = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
187
+
188
+ tokenizer = AutoTokenizer.from_pretrained(model_id)
189
+ model = AutoModelForCausalLM.from_pretrained(model_id).to(torch.device("cpu"))
190
+
191
+ rag_chat = pipeline("text-generation", model=model, tokenizer=tokenizer, max_new_tokens=200, device=-1)
192
+
193
+
194
+ # In[ ]:
195
+
196
+
197
+ def generate_rag_response_local(query, retrieved_chunks):
198
+ context = "\n\n".join(retrieved_chunks)
199
+
200
+ prompt = f"""[INST] Usa solo le informazioni fornite nel contesto qui sotto per rispondere alla domanda, la risposta deve finire sempre con un punto.
201
+ Se la risposta non Γ¨ presente, di' chiaramente che non Γ¨ specificato nel documento.
202
+
203
+ Contesto:
204
+ {context}
205
+
206
+ Domanda: {query}
207
+ Risposta: [/INST]
208
+ """
209
+ result = rag_chat(prompt)[0]["generated_text"]
210
+ return result.split("Risposta:")[-1].strip()
211
+
212
+
213
+ # In[ ]:
214
+
215
+
216
+ # 🧠 Inserisci la domanda
217
+ query = input("Domanda: ")
218
+
219
+ # πŸ”Ž Ottieni l'embedding della query (usa sentence-transformers, NON il modello generativo!)
220
+ query_embedding = embedding_model.encode([query])
221
+
222
+ # πŸ” Retrieval dei chunk piΓΉ simili da Chroma
223
+ results = collection.query(
224
+ query_embeddings=query_embedding,
225
+ n_results=3
226
+ )
227
+
228
+ # 🧱 Estrai i chunk di contesto
229
+ retrieved_chunks = results["documents"][0]
230
+
231
+ # πŸ€– Genera la risposta usando il modello open-source locale
232
+ response = generate_rag_response_local(query, retrieved_chunks)
233
+
234
+ # πŸ–¨οΈ Mostra la risposta
235
+ print("πŸ€– Risposta:\n", response)
236
+
237
+
238
+ # In[ ]:
239
+
240
+
241
+ retrieved_chunks
242
+
243
+
244
+ # In[ ]:
245
+
246
+
247
+ results
248
+
249
+
250
+ # In[ ]:
251
+
252
+
253
+
254
+