MatteoScript commited on
Commit
293ffb8
·
verified ·
1 Parent(s): 6931600

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -556
app.py CHANGED
@@ -1,563 +1,69 @@
1
  import streamlit as st
2
-
3
- from chat_client import chat
4
- from google_function import leggi_gmail
5
- from google_function import scrivi_bozza_gmail
6
- from google_function import leggi_calendario_google
7
- from google_function import connetti_google
8
- from google_function import crea_documento_google
9
  import time
10
- import os
11
- from dotenv import load_dotenv
12
- from sentence_transformers import SentenceTransformer
13
- import requests
14
- from langchain_community.vectorstores import Chroma
15
- from langchain_community.embeddings import HuggingFaceEmbeddings
16
- import json
17
- from googlesearch import search
18
- from bs4 import BeautifulSoup
19
- import PyPDF2
20
- import pytesseract
21
  from PIL import Image
22
- from youtube_transcript_api import YouTubeTranscriptApi
23
- import webbrowser
24
- from streamlit_javascript import st_javascript
25
- import datetime
26
- from openai import OpenAI
27
-
28
- load_dotenv()
29
- EFFETTUA_LOGIN_GOOGLE = os.getenv('EFFETTUA_LOGIN_GOOGLE')=="1"
30
- URL_APP_SCRIPT = os.getenv('URL_APP_SCRIPT')
31
- URL_PROMPT = URL_APP_SCRIPT + '?IdFoglio=1cLw9q70BsPmxMBj9PIzgXtq6sm3X-GVBVnOB5wE8jr8'
32
- URL_DOCUMENTI = URL_APP_SCRIPT + '?IdSecondoFoglio=1cLw9q70BsPmxMBj9PIzgXtq6sm3X-GVBVnOB5wE8jr8'
33
- SYSTEM_PROMPT = ["Sei BonsiAI e mi aiuterai nelle mie richieste (Parla in ITALIANO)", "Esatto, sono BonsiAI. Di cosa hai bisogno?"]
34
- CHAT_BOTS = {
35
- "Mixtral 8x7B v0.1": {
36
- "model": "mistralai/Mixtral-8x7B-Instruct-v0.1",
37
- "description": "Un modello avanzato di chatbot con architettura 8x7B sviluppato da Mistral AI. Supporta fino a 30 pagine di input e costa zero",
38
- "pagine_contesto": 30,
39
- "richiede_api_key": False
40
- },
41
- "Mistral 7B v0.2": {
42
- "model": "mistralai/Mistral-7B-Instruct-v0.2",
43
- "description": "Una versione più leggera del modello Mistral, con architettura 7B, sviluppato da Mistral AI. Supporta fino a 8 pagine di input e costa zero",
44
- "pagine_contesto": 8,
45
- "richiede_api_key": False
46
- },
47
- "Gpt 3.5 Turbo": {
48
- "model": "gpt-3.5-turbo",
49
- "description": "Una versione ottimizzata e performante del modello GPT-3.5 di OpenAI. Supporta 16 Pagine di input e costa 2$ ogni 1000 Pagine",
50
- "pagine_contesto": 16,
51
- "richiede_api_key": True
52
- },
53
- "Gpt 4 Turbo": {
54
- "model": "gpt-4-turbo",
55
- "description": "Una versione avanzata e potenziata del famoso modello GPT-4 di OpenAI, ottimizzata per prestazioni superiori. Supporta fino a 120 Pagine di input e costa 30$ ogni 1000 Pagine",
56
- "pagine_contesto": 120,
57
- "richiede_api_key": True
58
- },
59
- "Gpt 4-o": {
60
- "model": "gpt-4o",
61
- "description": "L'ultimissima versione di GPT! Supporta fino a 120 Pagine di input e costa 20$ ogni 1000 Pagine (meno di GPT 4 Turbo)",
62
- "pagine_contesto": 120,
63
- "richiede_api_key": True
64
- }
65
- }
66
- option_personalizzata = {'Personalizzata': {'systemRole': 'Tu sei BONSI AI, il mio assistente personale della scuola superiore del Bonsignori. Aiutami in base alle mie esigenze',
67
- 'systemStyle': 'Firmati sempre come BONSI AI. (scrivi in italiano)',
68
- 'instruction': '',
69
- 'tipo': '',
70
- 'RAG': False}
71
- }
72
- option_leggiemail = {'Leggi Gmail': {'systemRole': 'Tu sei BONSI AI, il mio assistente personale della scuola superiore del Bonsignori. Effettua l operazione richiesta sulla base delle seguenti email: ',
73
- 'systemStyle': 'Firmati sempre come BONSI AI. (scrivi in italiano)',
74
- 'instruction': '',
75
- 'tipo': 'EMAIL',
76
- 'RAG': False}
77
- }
78
- option_leggicalendar = {'Leggi Calendar': {'systemRole': 'Tu sei BONSI AI, il mio assistente personale della scuola superiore del Bonsignori. Effettua l operazione richiesta sulla base dei seguenti eventi di calendario: ',
79
- 'systemStyle': 'Firmati sempre come BONSI AI. (scrivi in italiano)',
80
- 'instruction': '',
81
- 'tipo': 'CALENDAR',
82
- 'RAG': False}
83
- }
84
- # ----------------------------------------------------------- Interfaccia --------------------------------------------------------------------
85
- st.set_page_config(page_title="Bonsi A.I.", page_icon="🏫")
86
-
87
- def init_state() :
88
- if "messages" not in st.session_state:
89
- st.session_state.messages = []
90
-
91
- if "temp" not in st.session_state:
92
- st.session_state.temp = 0.8
93
-
94
- if "history" not in st.session_state:
95
- st.session_state.history = [SYSTEM_PROMPT]
96
-
97
- if "top_k" not in st.session_state:
98
- st.session_state.top_k = 5
99
-
100
- if "repetion_penalty" not in st.session_state :
101
- st.session_state.repetion_penalty = 1
102
-
103
- if "api_key" not in st.session_state :
104
- st.session_state.api_key = ""
105
-
106
- if "chat_bot" not in st.session_state :
107
- st.session_state.chat_bot = "Mixtral 8x7B v0.1"
108
-
109
- if 'loaded_data' not in st.session_state:
110
- st.session_state.loaded_data = False
111
-
112
- if "split" not in st.session_state:
113
- st.session_state.split = 30
114
-
115
- if "enable_history" not in st.session_state:
116
- st.session_state.enable_history = True
117
-
118
- if "audio_bytes" not in st.session_state:
119
- st.session_state.audio_bytes = False
120
-
121
- if "cerca_online" not in st.session_state:
122
- st.session_state.cerca_online = False
123
-
124
- if "numero_siti" not in st.session_state:
125
- st.session_state.numero_siti = 3
126
-
127
- if "suddividi_siti" not in st.session_state:
128
- st.session_state.suddividi_siti = 1
129
-
130
- if "cerca_dominio" not in st.session_state:
131
- st.session_state.cerca_dominio = False
132
-
133
- if "numero_generazioni" not in st.session_state:
134
- st.session_state.numero_generazioni = 1
135
-
136
- if "numero_elementi" not in st.session_state:
137
- st.session_state.numero_elementi = 5
138
-
139
- if "data_inizio" not in st.session_state:
140
- st.session_state.data_inizio = None
141
-
142
- if "data_inizio" not in st.session_state:
143
- st.session_state.data_inizio = None
144
-
145
- if "testo_documenti" not in st.session_state:
146
- st.session_state.testo_documenti = ''
147
-
148
- if "uploaded_files" not in st.session_state:
149
- st.session_state.uploaded_files = None
150
-
151
- if "client" not in st.session_state:
152
- st.session_state.client = None
153
-
154
- if "urls" not in st.session_state:
155
- st.session_state.urls = [""] * 5
156
-
157
- if "creds" not in st.session_state:
158
- st.session_state.creds = None
159
-
160
- if "login_effettuato" not in st.session_state:
161
- st.session_state.login_effettuato = False
162
-
163
- if "ultimo_messaggio" not in st.session_state:
164
- st.session_state.ultimo_messaggio = ""
165
-
166
- if "tutti_messaggi" not in st.session_state:
167
- st.session_state.tutti_messaggi = ""
168
-
169
- if "tbs_options" not in st.session_state:
170
- st.session_state.tbs_options = {
171
- "Sempre": "0",
172
- "Ultimo anno": "qdr:y",
173
- "Ultimo mese": "qdr:m",
174
- "Ultima settimana": "qdr:w",
175
- "Ultimo giorno": "qdr:d"
176
- }
177
-
178
- if not st.session_state.loaded_data and (st.session_state.login_effettuato == True or EFFETTUA_LOGIN_GOOGLE == False):
179
- place=st.empty()
180
- place=st.empty()
181
- with place:
182
- with st.status("Caricamento in corso...", expanded=True) as status:
183
- st.write("Inizializzazione Ambiente")
184
- time.sleep(1)
185
- st.write("Inizializzazione Prompt")
186
- URL_REDIRECT = os.getenv('URL_REDIRECT')
187
- options = {}
188
- if URL_REDIRECT != "http://localhost:8501/":
189
- options = requests.get(URL_PROMPT).json()
190
- st.write("Inizializzazione Documenti")
191
- documenti = {}
192
- if URL_REDIRECT != "http://localhost:8501/":
193
- documenti = requests.get(URL_DOCUMENTI).json()
194
- st.session_state.options = {**option_personalizzata, **options}
195
- if EFFETTUA_LOGIN_GOOGLE:
196
- st.session_state.options.update(option_leggiemail)
197
- st.session_state.options.update(option_leggicalendar)
198
- st.session_state.documenti = documenti
199
- st.session_state.loaded_data = True
200
- status.update(label="Caricamento Completato", state="complete", expanded=False)
201
- place.empty()
202
 
203
- def read_text_from_file(file):
204
- text = ""
205
- if file.name.endswith(".txt"):
206
- text = file.read().decode("utf-8")
207
- elif file.name.endswith(".pdf"):
208
- pdf_reader = PyPDF2.PdfReader(file)
209
- for page_num in range(len(pdf_reader.pages)):
210
- page = pdf_reader.pages[page_num]
211
- text += page.extract_text()
212
- else:
213
  try:
214
- image = Image.open(file)
215
- text = pytesseract.image_to_string(image)
216
- except:
217
- st.write(f"Non è possibile leggere il testo dal file '{file.name}'.")
218
- return text
219
-
220
- def open_new_tab(url):
221
- placeholder = st.empty()
222
- with placeholder:
223
- placeholder.empty()
224
- new_tab_js = f'''<script type="text/javascript">window.open("{url}", "_blank");</script>'''
225
- st.components.v1.html(new_tab_js, height=1)
226
- time.sleep(0.3)
227
- placeholder.empty()
228
-
229
- def esporta_testo(tipo, ultimo_messaggio):
230
- testo = st.session_state.ultimo_messaggio if ultimo_messaggio else st.session_state.tutti_messaggi
231
- if tipo == 'Bozza Email':
232
- url = scrivi_bozza_gmail(testo)
233
- open_new_tab(url)
234
- if tipo == 'Google Documenti':
235
- url = crea_documento_google(testo)
236
- open_new_tab(url)
237
-
238
- def sidebar():
239
- def retrieval_settings() :
240
- st.markdown("# Impostazioni Prompt")
241
- st.session_state.selected_option_key = st.selectbox('Azione', list(st.session_state.options.keys()))
242
- st.session_state.selected_option = st.session_state.options.get(st.session_state.selected_option_key, {})
243
-
244
- if st.session_state.options.get(st.session_state.selected_option_key, {})["tipo"]=='DOCUMENTO':
245
- st.session_state.selected_documento_key = st.selectbox('Documento', list(st.session_state.documenti.keys()))
246
- st.session_state.selected_documento = st.session_state.documenti.get(st.session_state.selected_documento_key, {})
247
- st.session_state.instruction = st.session_state.selected_documento.get('instruction', '')['Testo']
248
- else:
249
- st.session_state.instruction = st.session_state.selected_option.get('instruction', '')
250
-
251
-
252
-
253
- st.session_state.systemRole = st.session_state.selected_option.get('systemRole', '')
254
- st.session_state.systemRole = st.text_area("Descrizione", st.session_state.systemRole, help='Ruolo del chatbot e descrizione dell\'azione che deve svolgere')
255
- st.session_state.systemStyle = st.session_state.selected_option.get('systemStyle', '')
256
- st.session_state.systemStyle = st.text_area("Stile", st.session_state.systemStyle, help='Descrizione dello stile utilizzato per generare il testo')
257
- if st.session_state.selected_option["tipo"]=='EMAIL':
258
- st.session_state.numero_elementi = st.slider(label="Numero Email", min_value=1, max_value=100, value=10)
259
- st.session_state.data_inizio = st.date_input("Email dal", value=datetime.date.today()-datetime.timedelta(days=7), format='DD/MM/YYYY')
260
- st.session_state.data_fine = st.date_input("Email al", value=datetime.date.today(), format='DD/MM/YYYY')
261
- if st.session_state.selected_option["tipo"]=='CALENDAR':
262
- st.session_state.numero_elementi = st.slider(label="Numero Eventi Calendario", min_value=1, max_value=100, value=10)
263
- st.session_state.data_inizio = st.date_input("Eventi dal", value=datetime.date.today(), format='DD/MM/YYYY')
264
- st.session_state.data_fine = st.date_input("Eventi al", value=datetime.date.today()+datetime.timedelta(days=7), format='DD/MM/YYYY')
265
- st.session_state.rag_enabled = st.session_state.selected_option.get('tipo', '')=='RAG'
266
- if st.session_state.selected_option_key == 'Decreti':
267
- st.session_state.top_k = st.slider(label="Documenti da ricercare", min_value=1, max_value=20, value=4, disabled=not st.session_state.rag_enabled)
268
- st.session_state.decreti_escludere = st.multiselect(
269
- 'Decreti da escludere',
270
- ['23.10.2 destinazione risorse residue pnrr DGR 1051-2023_Destinazione risorse PNRR Duale.pdf', '23.10.25 accompagnatoria Circolare Inail assicurazione.pdf', '23.10.26 circolare Inail assicurazione.pdf', '23.10.3 FAQ in attesa di avviso_.pdf', '23.11.2 avviso 24_24 Decreto 17106-2023 Approvazione Avviso IeFP 2023-2024.pdf', '23.5.15 decreto linee inclusione x enti locali.pdf', '23.6.21 Circolare+esplicativa+DGR+312-2023.pdf', '23.7.3 1° Decreto R.L. 23_24 .pdf', '23.9 Regolamento_prevenzione_bullismo_e_cyberbullismo__Centro_Bonsignori.pdf', '23.9.1 FAQ inizio anno formativo.pdf', '23.9.15 DECRETO VERIFICHE AMMINISTR 15-09-23.pdf', '23.9.4 modifica decreto GRS.pdf', '23.9.8 Budget 23_24.pdf', '24.10.2022 DECRETO loghi N.15176.pdf', 'ALLEGATO C_Scheda Supporti al funzionamento.pdf', 'ALLEGATO_ B_ Linee Guida.pdf', 'ALLEGATO_A1_PEI_INFANZIA.pdf', 'ALLEGATO_A2_PEI_PRIMARIA.pdf', 'ALLEGATO_A3_PEI_SEC_1_GRADO.pdf', 'ALLEGATO_A4_PEI_SEC_2_GRADO.pdf', 'ALLEGATO_C_1_Tabella_Fabbisogni.pdf', 'Brand+Guidelines+FSE+.pdf', 'Decreto 20797 del 22-12-2023_Aggiornamento budget PNRR.pdf', 'Decreto 20874 del 29-12-2023 Avviso IeFP PNRR 2023-2024_file unico.pdf'],
271
- [])
272
- st.session_state.uploaded_files = st.file_uploader("Importa file", accept_multiple_files=True)
273
- st.session_state.testo_documenti = ''
274
- for uploaded_file in st.session_state.uploaded_files:
275
- text_doc = read_text_from_file(uploaded_file)
276
- st.session_state.testo_documenti += text_doc
277
- print(st.session_state.testo_documenti)
278
- st.markdown("---")
279
- st.markdown("# Ricerca Online")
280
- st.session_state.cerca_online = st.toggle("Attivata", value=False)
281
- with st.popover("Siti Specifici", disabled=not st.session_state.cerca_online,use_container_width=True):
282
- st.markdown("#### Inserisci Siti Web ")
283
- st.session_state.cerca_dominio = st.toggle("Cerca nel dominio", value=False, help="Se disattivo, cerca SOLO all'interno dell'url per esempio se digito www.ansa.it, cerca solo nella HOME PAGE di ansa, altrimenti cerca all'interno di tutto il DOMINIO ansa.it")
284
- for i in range(5):
285
- if (i<2) or ((i>1) and (st.session_state.urls[i-2] != "")):
286
- st.session_state.urls[i] = st.text_input(f"URL Sito {i+1}", placeholder='Sito Web...', help='è possibile specificare anche il link di un video Youtube, in tal caso verrà restituita la trascrizione del video')
287
- st.session_state.selected_tbs = st.selectbox("Periodo:", list(st.session_state.tbs_options.keys()), disabled=(not st.session_state.cerca_online) or (st.session_state.urls[0]!="" and not st.session_state.cerca_dominio))
288
- st.session_state.tbs_value = st.session_state.tbs_options[st.session_state.selected_tbs]
289
- st.session_state.numero_siti = st.slider(label="Risultati", min_value = 1, max_value=20, value=3, disabled=(not st.session_state.cerca_online) or (st.session_state.urls[0]!="" and not st.session_state.cerca_dominio))
290
- st.session_state.suddividi_siti = st.slider(label="Scomponi Ricerca", min_value = 1, max_value=10, value=1, disabled=(not st.session_state.cerca_online) or (st.session_state.urls[0]!="" and not st.session_state.cerca_dominio))
291
- st.markdown("---")
292
-
293
- def model_settings():
294
- st.markdown("# Modello")
295
- st.session_state.chat_bot = st.sidebar.selectbox('Tipo', list(CHAT_BOTS.keys()))
296
- if CHAT_BOTS[st.session_state.chat_bot]["richiede_api_key"] == True:
297
- st.session_state.api_key = st.text_input('Api Key', type = 'password', label_visibility='collapsed', placeholder='Inserisci la chiave API')
298
- st.session_state.client = OpenAI(api_key=st.session_state.api_key)
299
- print('xxxxxxx')
300
- st.write(CHAT_BOTS[st.session_state.chat_bot]["description"])
301
- st.session_state.split = st.slider(label="Pagine Suddivisione", min_value=1, max_value=CHAT_BOTS[st.session_state.chat_bot]["pagine_contesto"], value=CHAT_BOTS[st.session_state.chat_bot]["pagine_contesto"], help='Se il documento ha 100 pagine e suddivido per 20 pagine elaborerà la risposta 5 volte. Più alto è il numero e meno volte elaborerà ma la risposta sarà più imprecisa')
302
- st.session_state.numero_generazioni = st.slider(label="Generazioni", min_value = 1, max_value=10, value=1)
303
- st.session_state.enable_history = st.toggle("Storico Messaggi", value=True)
304
- st.session_state.temp = st.slider(label="Creatività", min_value=0.0, max_value=1.0, step=0.1, value=0.9)
305
- st.session_state.max_tokens = st.slider(label="Lunghezza Output", min_value = 2, max_value=4096, step= 32, value=1024)
306
- st.markdown("---")
307
-
308
- def export_settings():
309
- st.markdown("# Esportazione")
310
- st.session_state.export_type = st.selectbox('Tipologia', ('Non Esportare', 'Google Documenti', 'Bozza Email'), help='Seleziona la tipologia di esportazione del testo generato')
311
- st.session_state.export_all = st.toggle("Considera tutte le chat", value=False)
312
- if st.button("Esporta", type="primary", use_container_width=True):
313
- esporta_testo(st.session_state.export_type, st.session_state.export_all)
314
- st.markdown("---")
315
-
316
- with st.sidebar:
317
- retrieval_settings()
318
- model_settings()
319
- if EFFETTUA_LOGIN_GOOGLE:
320
- export_settings()
321
- st.markdown("""> **Creato da Matteo Bergamelli **""")
322
-
323
- def header() :
324
- st.title("Bonsi A.I.", anchor=False)
325
- with st.expander("Cos'è BonsiAI?"):
326
- st.info("""BonsiAI Chat è un ChatBot personalizzato basato su un database vettoriale, funziona secondo il principio della Generazione potenziata da Recupero (RAG).
327
- La sua funzione principale ruota attorno alla gestione di un ampio repository di documenti BonsiAI e fornisce agli utenti risposte in linea con le loro domande.
328
- Questo approccio garantisce una risposta più precisa sulla base della richiesta degli utenti.""")
329
-
330
- def chat_box() :
331
- for message in st.session_state.messages:
332
- with st.chat_message(message["role"]):
333
- st.markdown(message["content"])
334
-
335
- def formattaPrompt(prompt, systemRole, systemStyle, instruction):
336
- if st.session_state.cerca_online:
337
- systemRole += '. Ti ho fornito una lista di materiali nelle instruction. Devi rispondere sulla base delle informazioni fonrnite!'
338
- input_text = f'''
339
- {{
340
- "input": {{
341
- "role": "system",
342
- "content": "{systemRole}",
343
- "style": "{systemStyle} "
344
- }},
345
- "messages": [
346
- {{
347
- "role": "instructions",
348
- "content": "{instruction} ({systemStyle})"
349
- }},
350
- {{
351
- "role": "user",
352
- "content": "{prompt}"
353
- }}
354
- ]
355
- }}
356
- '''
357
- return input_text
358
-
359
- def gen_augmented_prompt(prompt, top_k) :
360
- links = ""
361
- embedding = HuggingFaceEmbeddings(model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")
362
- db = Chroma(persist_directory='./DB_Decreti', embedding_function=embedding)
363
- docs = db.similarity_search(prompt, k=top_k)
364
- links = []
365
- context = ''
366
- NomeCartellaOriginariaDB = 'Documenti_2\\'
367
- for doc in docs:
368
- testo = doc.page_content.replace('\n', ' ')
369
- context += testo + '\n\n\n'
370
- reference = doc.metadata["source"].replace(NomeCartellaOriginariaDB, '') + ' (Pag. ' + str(doc.metadata["page"]) + ')'
371
- links.append((reference, testo))
372
- return context, links
373
-
374
- def get_search_results_int(url):
375
- result = {'title': '', 'description': '', 'url': '', 'body': ''}
376
- try:
377
- if "www.youtube.com" in url:
378
- video_id = url.split("=")[1]
379
- title = 'Video Youtube'
380
- description = ''
381
- transcript = YouTubeTranscriptApi.get_transcript(video_id)
382
- body_content = " ".join([segment["text"] for segment in transcript])
383
- print(video_id)
384
- print(body_content)
385
- result = {'title': title, 'description': body_content, 'url': url, 'body': body_content}
386
  else:
387
- response = requests.get(url)
388
- soup = BeautifulSoup(response.text, 'html.parser')
389
- title = soup.title.string if soup.title else "N/A"
390
- description = soup.find('meta', attrs={'name': 'description'})['content'] if soup.find('meta', attrs={'name': 'description'}) else "N/A"
391
- body_content = soup.find('body').get_text() if soup.find('body') else "N/A"
392
- result = {'title': title, 'description': description, 'url': url, 'body': body_content}
393
- except Exception as e:
394
- print(f"Error fetching data from {url}: {e}")
395
- return result
396
-
397
- def get_search_results(query, top_k):
398
- results = []
399
- if st.session_state.urls[0] != "":
400
- for i in range(5):
401
- dominio = st.session_state.urls[i]
402
- if dominio != "":
403
- if st.session_state.cerca_dominio:
404
- for url in search(query + ' site:' + dominio, num=top_k, stop=top_k, tbs=st.session_state.tbs_value):
405
- results.append(get_search_results_int(url))
406
- else:
407
- results.append(get_search_results_int(dominio))
408
- else:
409
- for url in search(query, num=top_k, stop=top_k, tbs=st.session_state.tbs_value):
410
- results.append(get_search_results_int(url))
411
- return results
412
-
413
- def gen_online_prompt(prompt, top_k) :
414
- links = []
415
- context = ''
416
- if st.session_state.suddividi_siti > 1:
417
- prompt_suddivisione = f'''Genera un elenco PUNTATO di {st.session_state.suddividi_siti} PAROLE CHIAVE in ITALIANO ottimizzate per il WEB e l'indicizzazione SEO.
418
- Attenzione, restituisci solo le KEYWORD e non scrivere nulla prima o dopo!
419
- Genera le PAROLE CHIAVE a partire da questo argomento, mi raccomando devono essere un elenco PUNTATO in ITALIANO: "{prompt}" '''
420
- chat_stream = generate_chat_stream(prompt_suddivisione)
421
- risposta = stream_handler(chat_stream, None)
422
- sottoricerche = risposta.strip().split('\n')
423
- for sottoricerca in sottoricerche:
424
- with st.spinner('Sottoricerca: ' + sottoricerca):
425
- results = get_search_results(sottoricerca, top_k)
426
- for i, result in enumerate(results, start=1):
427
- st.toast(result['title'], icon = '🗞️' )
428
- context += result['title'] + '\n' + result['description'] + '\n' + '\n\n' + result['body'].replace('\n','.') + '\n\n------------------------------------------------------------'
429
- links.append((str(i) + '. ' + result['title'], result['description'] + '\n\n' + result['url']))
430
- else:
431
- results = get_search_results(prompt, top_k)
432
- for i, result in enumerate(results, start=1):
433
- st.toast(result['title'])
434
- context += result['title'] + '\n' + result['description'] + '\n' + '\n\n' + result['body'].replace('\n','.') + '\n\n------------------------------------------------------------'
435
- links.append((str(i) + '. ' + result['title'], result['description'] + '\n\n' + result['url']))
436
- if context == '':
437
- context = "Non sono state trovate informazioni sul Web in merito all'argomento specificato. Riprova con un altra ricerca o modifica i parametri"
438
- return context, links
439
-
440
- def generate_chat_stream(prompt):
441
- chat_stream = chat(prompt, st.session_state.history,chat_client=CHAT_BOTS[st.session_state.chat_bot]["model"],
442
- temperature=st.session_state.temp, max_new_tokens=st.session_state.max_tokens, client_openai = st.session_state.client)
443
- return chat_stream
444
-
445
- def inserisci_istruzioni(prompt_originale):
446
- links = []
447
- if st.session_state.cerca_online:
448
- with st.spinner("Ricerca Online...."):
449
- time.sleep(1)
450
- st.session_state.instruction, links = gen_online_prompt(prompt=prompt_originale, top_k=st.session_state.numero_siti)
451
- if st.session_state.rag_enabled :
452
- with st.spinner("Ricerca nei Decreti...."):
453
- time.sleep(1)
454
- st.session_state.instruction, links = gen_augmented_prompt(prompt=prompt_originale, top_k=st.session_state.top_k)
455
- if st.session_state.selected_option["tipo"]=='EMAIL':
456
- with st.spinner("Ricerca nelle Email...."):
457
- time.sleep(1)
458
- st.session_state.instruction, links = leggi_gmail(max_results=st.session_state.numero_elementi, data_inizio = st.session_state.data_inizio, data_fine = st.session_state.data_fine)
459
- if st.session_state.selected_option["tipo"]=='CALENDAR':
460
- with st.spinner("Ricerca nel Calendario...."):
461
- time.sleep(1)
462
- st.session_state.instruction, links = leggi_calendario_google(max_results=st.session_state.numero_elementi, data_inizio = st.session_state.data_inizio, data_fine = st.session_state.data_fine)
463
- with st.spinner("Generazione in corso...") :
464
- time.sleep(1)
465
- #st.session_state.instruction = instruction_originale + '\n----------------------------------------------\n' + st.session_state.instruction
466
- return links
467
-
468
- def stream_handler(chat_stream, placeholder):
469
- full_response = ''
470
- for chunk in chat_stream :
471
- if CHAT_BOTS[st.session_state.chat_bot]["model"][:3] == 'gpt':
472
- if chunk.choices[0].delta and chunk.choices[0].delta.content:
473
- full_response += chunk.choices[0].delta.content
474
  else:
475
- if chunk.token.text!='</s>' :
476
- full_response += chunk.token.text
477
- if placeholder:
478
- placeholder.markdown(full_response + "▌")
479
- if placeholder:
480
- placeholder.markdown(full_response)
481
- return full_response
482
-
483
- def show_source(links) :
484
- with st.expander("Mostra fonti") :
485
- for link in links:
486
- reference, testo = link
487
- st.info('##### ' + reference.replace('_', ' ') + '\n\n'+ testo)
488
-
489
- def split_text(text, chunk_size):
490
- testo_suddiviso = []
491
- if text == '':
492
- text = ' '
493
- if chunk_size < 100:
494
- chunk_size = 60000
495
- for i in range(0, len(text), chunk_size):
496
- testo_suddiviso.append(text[i:i+chunk_size])
497
- return testo_suddiviso
498
-
499
- init_state()
500
- if not st.session_state.login_effettuato and EFFETTUA_LOGIN_GOOGLE:
501
- connetti_google()
502
-
503
- if st.session_state.login_effettuato or not EFFETTUA_LOGIN_GOOGLE:
504
- st_javascript("localStorage.removeItem('token');")
505
- init_state()
506
- sidebar()
507
- header()
508
- chat_box()
509
-
510
- if prompt := st.chat_input("Chatta con BonsiAI..."):
511
- prompt_originale = prompt
512
- links = inserisci_istruzioni(prompt_originale)
513
- st.session_state.instruction+= ' \n\n' + st.session_state.testo_documenti
514
- instruction_suddivise = split_text(st.session_state.instruction, st.session_state.split*2000)
515
- ruolo_originale = st.session_state.systemRole
516
- ruoli_divisi = ruolo_originale.split("&&")
517
- parte=1
518
- i=1
519
- risposta_completa = ''
520
- full_response = ''
521
- errore_generazione = False
522
- for ruolo_singolo in ruoli_divisi:
523
- for instruction_singola in instruction_suddivise:
524
- for numgen in range(1, st.session_state.numero_generazioni+1):
525
- if i==1:
526
- st.chat_message("user").markdown(prompt_originale + (': Parte ' + str(parte) if i > 1 else ''))
527
- i+=1
528
- prompt = formattaPrompt(prompt_originale, ruolo_singolo, st.session_state.systemStyle, instruction_singola)
529
- print('------------------------------------------------------------------------------------')
530
- print(prompt)
531
- st.session_state.messages.append({"role": "user", "content": prompt_originale})
532
- try:
533
- chat_stream = generate_chat_stream(prompt)
534
- with st.chat_message("assistant"):
535
- placeholder = st.empty()
536
- full_response = stream_handler(chat_stream, placeholder)
537
- if st.session_state.rag_enabled or st.session_state.cerca_online or st.session_state.selected_option["tipo"]=='EMAIL' or st.session_state.selected_option["tipo"]=='CALENDAR':
538
- show_source(links)
539
- if st.session_state.options.get(st.session_state.selected_option_key, {})["tipo"]=='DOCUMENTO':
540
- with st.expander("Mostra Documento") :
541
- st.info('##### ' + st.session_state.selected_documento_key + ' (Parte ' + str(parte) +')'+ '\n\n\n' + instruction_singola)
542
- parte+=1
543
- st.session_state.messages.append({"role": "assistant", "content": full_response})
544
- risposta_completa = risposta_completa + '\n' + full_response
545
- except Exception as e:
546
- print(str(e))
547
- errore_generazione = True
548
- if CHAT_BOTS[st.session_state.chat_bot]["model"][:3] == 'gpt':
549
- st.error('Inserisci una CHIAVE API valida e controlla il CREDITO residuo: https://platform.openai.com/api-keys')
550
- else:
551
- st.error('Errore nella generazione riprova o utilizza un altro modello AI')
552
-
553
- if errore_generazione == False:
554
- st.session_state.ultimo_messaggio = full_response
555
- st.session_state.tutti_messaggi += '\n\n' + full_response
556
- if st.session_state.enable_history:
557
- st.session_state.history.append([prompt_originale, full_response])
558
- else:
559
- st.session_state.history.append(['', ''])
560
- st.success('Generazione Completata')
561
- payload = {"domanda": prompt_originale, "risposta": risposta_completa}
562
- json_payload = json.dumps(payload)
563
- response = requests.post(URL_APP_SCRIPT, data=json_payload)
 
1
  import streamlit as st
 
 
 
 
 
 
 
2
  import time
3
+ import base64
4
+ import io
 
 
 
 
 
 
 
 
 
5
  from PIL import Image
6
+ from together import Together
7
+ import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
+ # Funzione per generare le immagini, con gestione errori e retry dopo 10 secondi
10
+ def generate_image(prompt, max_retries=5):
11
+ api_key = os.getenv('API_REPLIACATE')
12
+ client = Together(api_key = api_key)
13
+ retries = 0
14
+ while retries < max_retries:
 
 
 
 
15
  try:
16
+ response = client.images.generate(
17
+ prompt=prompt,
18
+ model="black-forest-labs/FLUX.1-schnell-Free",
19
+ width=960,
20
+ height=1440,
21
+ steps=4,
22
+ n=1,
23
+ response_format="b64_json"
24
+ )
25
+ return response.data # Una lista di oggetti con attributo b64_json
26
+ except Exception as e:
27
+ st.error(f"Errore durante la generazione delle immagini: {e}. Riprovo tra 10 secondi...")
28
+ time.sleep(10)
29
+ retries += 1
30
+ st.error("Numero massimo di tentativi raggiunto. Impossibile generare le immagini.")
31
+ return None
32
+
33
+ def generate_images(prompt, num_immagini):
34
+ for numero in range(num_immagini):
35
+ images_data = generate_image(prompt)
36
+ if images_data is not None:
37
+ for i, img_obj in enumerate(images_data):
38
+ try:
39
+ image_bytes = base64.b64decode(img_obj.b64_json)
40
+ image = Image.open(io.BytesIO(image_bytes))
41
+ st.image(image, caption="")
42
+ except Exception as e:
43
+ st.error(f"Errore nella visualizzazione dell'immagine {i+1}: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  else:
45
+ st.error("Non è stato possibile generare le immagini. Riprova più tardi.")
46
+ time.sleep(5)
47
+ st.success("Immagini generate con successo!")
48
+
49
+ def main():
50
+ st.title("AI Imaging")
51
+ st.sidebar.header("Impostazioni")
52
+ stile_default = "Highly detailed, painterly style with a historical yet stylized aesthetic. Rich textures, ornate patterns, and a color palette dominated by imperial gold, deep red, and aged marble tones. Inspired by ancient Roman mosaics, frescoes, and classical sculpture, with a balanced mix of realism and stylization. Elegant, decorative card borders with intricate engravings and antique flourishes. Designed for a tabletop card game, ensuring clarity, readability, and a visually immersive experience."
53
+ stile_immagine = st.sidebar.text_area("Stile Immagine", stile_default, disabled=False)
54
+ prompt_input = st.sidebar.text_area("Prompt Immagine")
55
+ num_immagini = st.sidebar.slider("Variazioni", min_value=1, max_value=6, value=2)
56
+ submit_button = st.sidebar.button(label="Genera Immagine", type = "primary", use_container_width=True)
57
+ st.write("Inserisci il **Prompt** (che verrà unito allo stile) e clicca su *Genera Immagine*.")
58
+ if submit_button:
59
+ if not prompt_input.strip():
60
+ st.error("Per favore, inserisci un prompt per l'immagine!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  else:
62
+ # Combiniamo il prompt inserito con lo stile fisso
63
+ prompt_completo = f"{prompt_input}, {stile_immagine}"
64
+
65
+ st.info("Generazione in corso, attendere...")
66
+ generate_images(prompt_completo, num_immagini)
67
+
68
+ if __name__ == "__main__":
69
+ main()