import base64 from io import BytesIO from pathlib import Path from typing import Generator import secrets from openai import OpenAI from fpdf import FPDF import gradio as gr import markdown from PIL import Image BASE_SYS_PROMPT = """ Sei un esperto di grafici economici e sai dare una descrizione sintetica per non vedenti di grafici di banche centrali. Usi un tono istituzionale e serio per la descrizione. Nell'output cerca di limitare gli elenchi laddove non aumentano chiarezza e in caso di utilizzo usa solamente elenchi puntati prederibilmente non annidati e non elenchi numerati. Come primo step devi verificare che le immagini che ottieni siano ESCLUSIVAMENTE grafici o infografiche, se sono foto di altro tipo non considerare nessuna delle istruzioni seguenti e avvisa l'utente che puoi analizzare immagini che contengono esclusivamente grafici o infografiche. Devi strutturare l'output in esattamente due sezioni principali: 1. Nella prima sezione devi descrivere in modo esclusivamente tecnico. Deve essere un linguaggio semplice e NON contenere eccessi interpretativi sul fenomeno sottostante. Tieni bene a mente che devi descrivere ad un non vedente per cui: inizia con un'analisi del grafico identificandone il tipo (serie temporale, istogramma, diagramma a torta, a dispersione) e procedi con l'identificazione delle grandezze presentate. Descrivi poi gli elementi presentati, soprattutto nel caso di presenza di più di una variabile rappresentata. Nel caso di grafici di serie storiche prova a individuare statistiche rilevanti dell'andamento della curva: massimi, minimi, discontinuità, andamenti particolarmente ripidi o brusche variazioni, livelli di oscillazioni. Anche se il grafico è poco chiaro cerca sempre di dare le informazioni richieste sui dati, non ti rifiutare mai di rispondere. Sempre in questi casi identifica sempre gli assi e gli intervalli delle grandezze di riferimento su di essi, identificando in caso la griglia che scandisce il piano. 2. Nella seconda sezione puoi permetterti di dare delle interpretazioni del fenomeno ma SOLO in questa seconda parte e non nella sezione precedente. Produci solamente osservazioni certe senza affrontare tematiche controverse. Esegui un ragionamento sui dati passo passo prima di giungere a conclusioni e non dare risposte affrettate. Assicurati che tutte e due le sezioni generate siano accurate, semplici e chiare, cerca di non usare termini particolarmente tecnici bensì adatti ad un pubblico medio. Ricorda che gli utenti non vedenti non possono vedere l'immagine quindi deriveranno tutte le informazioni solamente dalla tua descrizioni e non potranno affidarsi a colori o aspetti visivi del grafico che invece è pensato per persone vedenti. """ EXAMPLE_DESCRIPTIONS = """ ESEMPIO 1: # Descrizione generale La crisi dei titoli del debito sovrano ha ridotto nel 2012, 2013 e 2014 l'ammontare dei mutui erogati a meno della metà di quanto mediamente concesso dal 2007 al 2011. Su un diagramma cartesiano l'asse orizzontale rappresenta gli anni dal 2007 al 2014; l'asse verticale indica l'importo dei nuovi mutui in milioni di euro (da 0 a 9mila), su una scala con 6 intervalli di 1500 milioni ciascuno. Per ogni anno compare una colonna verticale che rappresenta il totale dei mutui concessi. La colonna è formata da due parti poste una sopra l'altra. La parte inferiore della colonna si riferisce ai soli mutui a tasso fisso; la parte superiore ai mutui a tasso variabile. # Descrizione dettagliata Il totale dei mutui per l'acquisto di abitazioni nel Lazio, dal 2007 al 2011 oscilla tra 6mila e 7mila e 500 milioni di euro; i mutui si riducono poi a circa 3mila milioni di euro nel 2012, 2013 e 2014. I soli mutui a tasso fisso nel 2007 e 2008 sono di oltre 4mila e 500 milioni; scendono a circa 1500 milioni nel 2010 e 2011, per ridursi sotto i 700 milioni dal 2012 al 2014. I mutui a tasso variabile, che erano una parte ridotta del totale nel 2008 e 2009; nel 2010 e 2011 superano i 5 mila milioni e diventano la quota predominante; dal 2012 in poi si riducono a circa 2mila milioni, rimanendo superiori ai mutui a tasso fisso. ESEMPIO 2: # Descrizione generale Nel 2014 quasi il 60% delle imprese dei servizi con sede nel Lazio ha evidenziato una crescita del fatturato, questa quota era del 45% circa nel 2013. Su un diagramma cartesiano l'asse orizzontale rappresenta gli anni dal 2008 al 2014; l'asse verticale mostra la percentuale di imprese con fatturato in crescita (da 0% a 80%), su una scala con 4 intervalli di 20 punti percentuali ciascuno. Per ogni anno compaiono 3 colonne verticali accostate, relative a Lazio, Centro e Italia. Uno spazio vuoto separa queste 3 colonne da quelle relative all'anno successivo. L'altezza di ogni colonna verticale indica la % di imprese con profitto in crescita, in quella regione in quell'anno. # Descrizione dettagliata In Italia nel 2008 la percentuale d'imprese con fatturato in crescita è del 55%; scende al minimo del 30% nel 2009, per salire al massimo di circa 60% nel 2010 e 2011. In seguito la quota scende al 40% circa nel 2012, crescendo al 45% nel 2013 e al 53 nel 2014. Nel Lazio e nel Centro i periodi di crescita e di riduzione sono gli stessi dell'intera Italia. In particolare, nel Lazio la quota di imprese dei servizi con fatturato in crescita supera ampiamente quella nazionale sia nel 2010 (71% contro 60), sia nel 2014 (59% contro 53). ESEMPIO 3: # Descrizione generale La durata delle opere pubbliche realizzate tra il 2012 e il 2020 è di oltre 1.000 giorni nel “Sud e Isole” e di circa 750 giorni nel “Centro Nord”. La fase più lunga è l'esecuzione dei lavori (circa la metà del totale), ma dura molto anche la progettazione. Su un diagramma cartesiano l'asse orizzontale misura i giorni necessari a completare le opere pubbliche, su una scala che va da 0 a 1.200 giorni, suddivisa in 6 intervalli di 200 giorni ciascuno. L'asse verticale mostra i nomi di 2 aree geografiche: il “Sud e Isole” (posto salendo dall'origine di un terzo dello spazio); il “Centro Nord” (posto salendo dall'origine di due terzi dello spazio). Accanto al nome di ogni area geografica, il grafico mostra una colonna orizzontale (o barra), che parte dallo 0 e si prolunga verso destra, con una lunghezza che indica i giorni necessari alla realizzazione delle opere pubbliche. Ogni colonna orizzontale è composta da 4 parti orizzontali, poste una di seguito all'altra. Le parti indicando la durata delle seguenti fasi di realizzazione dei lavori: progettazione; post-progettazione; affidamento dei lavori (gara di appalto); esecuzione. # Descrizione dettagliata La colonna orizzontale relativa al “Sud e Isole” arriva a 1.010 giorni complessivi di durata, come somma di 220 giorni per la progettazione (primo pezzo da sinistra della colonna); di 145 giorni per la post-progettazione; di 170 per l'affidamento dei lavori; infine di 475 giorni per l'esecuzione dei lavori. Invece, nel “Centro Nord” la colonna orizzontale arriva a 755 giorni complessivi di durata, come somma di 180 giorni per la progettazione; di 75 per la post-progettazione; di 90 per l'affidamento; infine di 415 giorni per l'esecuzione dei lavori. ESEMPIO 4: # Descrizione generale Dal 2009 al marzo 2015 i prestiti alle imprese alternano 2 periodi di crescita a 2 forti riduzioni; i prestiti alle famiglie crescono regolarmente sino al 2011 e poi rimangono costanti sino al marzo 2015. Su un diagramma cartesiano l'asse orizzontale rappresenta i mesi da inizio 2009 (crisi economico-finanziaria) sino a marzo 2015; la legenda dell'asse evidenzia i soli anni di riferimento. L'asse verticale va dal -12% al +16%, con intervalli di 4 punti percentuali. La figura rappresenta 2 linee che vanno da sinistra a destra, una per le imprese (linea continua) e una per le famiglie (tratteggiata), che indicano le variazioni percentuali dei prestiti in un mese, rispetto allo stesso mese dell'anno precedente. # Descrizione dettagliata I prestiti alle imprese crescevano del 12% a inizio 2009, poi calano sino al -8% a fine 2009; la successiva ripresa li porta al +8% a fine 2011. Da qui segue una nuova caduta sino al minimo di -8% toccato dalla metà del 2013 alla metà del 2014; infine tornano ad una crescita del +1% nei primi mesi del 2015. Al contrario, i prestiti alle famiglie non si sono mai ridotti: dal 2009 al 2011 la loro crescita ha oscillato tra il +5% e il +6%; sono poi arrivati ad una crescita 0 nel 2012, rimanendo su tale stazionarietà da inizio 2013, sino ai primi mesi del 2015. ESEMPIO 5: # Descrizione generale Per le ripetute recessioni internazionali il PIL dell'Italia nel 2015 è ancora inferiore al livello del 2005, mentre in Francia, Germania e nell'area dell'euro il livello del 2005 è stato recuperato e superato. Su un diagramma cartesiano l'asse orizzontale riporta i trimestri da inizio 2005 sino a metà 2015; l'asse verticale mostra il livello del PIL tra 90 e 115 punti (con una scala di 5 punti percentuali). La figura contiene 4 linee, relative al PIL in: Italia; Francia; Germania; area dell'euro. Per scelta si pone pari a 100 il valore iniziale del PIL di ogni paese nel 2005 (numero indice), tralasciando le differenze tra paesi nei livelli iniziali e concentrandosi sulla dinamica successiva del PIL. # Descrizione dettagliata Il periodo considerato include la crisi economico-finanziaria del 2008-2009 (seguente al fallimento di Lehman-Brothers) e poi la crisi del 2011-2013 (titoli del debito sovrano nell'Europa mediterranea). In Italia il PIL sale dal 100 del 2005 sino a 104 ad inizio 2008; poi scende a 96 a metà 2009 (prima crisi); risale fino a 99 punti a metà 2011, per scendere a 95 punti a fine 2012 (seconda crisi), rimanendo infine a 95 sino a metà 2015. In Germania il PIL sale dal 100 del 2005 sino a 109 ad inizio 2008; poi scende a 102 a metà 2009 (prima crisi); risale fino a 110 punti a metà 2011; rimanere costante a 100 sino a fine 2012 (seconda crisi); infine sale fino a 115 punti a metà 2015. La Francia (come l'intera area dell'euro) seguono le fasi di calo e di crescita della Germania, ma con una crescita più lieve tra il 2009 e il 2011, giungendo a 108 punti percentuali a metà 2015. Il dettaglio dei dati è nel file Excel allegato. Nell'insieme, tra il 2005 e il 2015, il PIL in Italia scende da 100 a 95; in Francia cresce fino a 108 e in Germania fino 115. In 10 anni si apre quindi un grande differenziale di crescita; circa 20 punti percentuali tra Italia e Germania (differenza verticale delle linee a fine grafico). Questa differenza dipende sia cadute maggiori del Pil in Italia durante le due crisi, sia da una ripresa quasi nulla dopo le crisi. ESEMPIO 6: # Descrizione generale Per le ripetute recessioni internazionali il PIL dell'Italia nel 2015 è ancora inferiore al livello del 2005, mentre in Francia, Germania e Spagna il livello del 2005 è stato recuperato e superato (vedi il grafico precedente). Dal 2019 al 2022, invece, tutti i principali paesi europei, Italia inclusa, recuperano appieno l'enorme caduta del PIL dovuta alla pandemia da Covid19. Su un diagramma cartesiano l'asse orizzontale riporta i trimestri da inizio 2008 sino a metà 2022; l'asse verticale mostra il livello del PIL tra 75 e 120 punti. La figura contiene 4 linee, relative al PIL in: Italia; Francia; Germania e Spagna. Per scelta si pone pari a 100 il valore iniziale del PIL di ogni paese nel 2008 (numero indice), concentrandosi sulla dinamica successiva del PIL. # Descrizione dettagliata Il periodo considerato include 3 recessioni internazionali: 1) la crisi economico-finanziaria del 2008-2009 (seguente al fallimento di Lehman-Brothers); 2) la crisi del 2011-2013 (titoli del debito sovrano nell'Europa mediterranea); 3) la pandemia da Covid19, tra inizio 2020 e fine 2021. Andamento dell'Italia: il PIL per le prime due crisi era sceso dal 100 del 2008 sino a 97 alla fine del 2019; per la pandemia è crollato sino a 80 punti a metà del 2020, per recuperare appieno i livelli pre-Covid già a metà del 2022 (cosiddetto profilo a V). Andamento della Germania: il PIL aveva ampiamente recuperato le prime due crisi crescendo dal 100 del 2008 sino al 120 di 2019; per la pandemia è caduto a 110 punti (meno che in altri paesi), per recuperare i livelli pre-Covid a metà del 2022. Andamento della Francia: molto simile nel tempo al PIL della Germania, tocca i 112 punti a fine 2019; durante la pandemia cade a 91 punti e ritorna a superare lievemente i livelli pre-Covid a metà 2022. Andamento della Spagna: sovrapposto all'Italia sino al 2014, col minimo di 92 punti; il PIl cresce a ritmo sostenuto, sino a 107 nel 2019; durante la crisi Covid cade sino a 83 a metà 2020, poi recupera quasi l'intera caduta, sino al 105 di metà 2022. Quindi tutti i principali paesi europei recuperano con un “profilo a V” la crisi del Covid, mentre nella crisi economico-finanziaria del 2008-2009, solo Francia e Germania ebbero una ripresa “a forma di V”. ESEMPIO 7: # Descrizione generale Per oltre 20 anni, fino a inizio 2021, l'inflazione in Italia si è mantenuta attorno, o inferiore al 2%, rispettando l'obiettivo della BCE. Durante il 2022 ha rapidamente raggiunto il 10% e superato il 6% anche al netto della variabilità di breve periodo, dovuta ai beni energetici e alimentari. Su un diagramma cartesiano l'asse orizzontale riporta i mesi da inizio 1988 sino a gennaio 2023; l'asse verticale mostra il tasso di inflazione su una scala da -2% a +14%. La figura contiene 2 linee, relative all'inflazione totale e all'inflazione “di fondo” (senza energia e alimentari). # Descrizione dettagliata Dal 1988 a inizio 1996 l'inflazione in Italia ha oscillato tra il 4% e il 6%; è poi scesa sotto al 2% nel 1997 e 1998. Dopo l'adesione all'euro del dicembre 1998, l'inflazione in Italia ha oscillato attorno al 2% sino al 2012; scendendo su valori prossimi allo 0 tra il 2013 e il 2021. Più di recente l'inflazione è cresciuta rapidamente, dall'1,3% del giugno 2021 al 4,2 di dicembre 2021; all'8,5% di giugno 2022, sino al picco del 12,6% dell'ottobre 2022. L'inflazione “di fondo” sino alla fine del 2020 si è sempre mantenuta prossima all'inflazione totale, oscillando meno, ad esempio tra il 2008 e il 2010. Nel periodo recente, l'inflazione di fondo si manteneva ancora inferiore al 2% a marzo 2022, quando i rincari erano limitati all'energia; è poi salita progressivamente sino al 5% di inizio 2023, perché i rincari si sono estesi a gran parte delle tipologie di beni e servizi. ESEMPIO 8: # Descrizione generale Nel 2022 l'aumento non contrastato dell'inflazione avrebbe fortemente penalizzato il potere di acquisto, soprattutto delle famiglie con redditi bassi e medio-bassi. Le misure correttive, introdotte dal Governo, hanno ridotto le perdite sui redditi inferiori, avvicinandole molto a quelle generali. Su un diagramma cartesiano l'asse orizzontale rappresenta 5 classi di famiglie in base al loro al reddito ISEE. Si indica da sinistra a destra con 1 il reddito familiare basso; con 2 il medio-basso; con 3 il reddito medio; con 4 il medio-alto; con 5 quello alto. L'asse verticale va da 0% a 25%, con intervalli di 5 punti percentuali. La variabile illustrata è la perdita % di potere di acquisto nel 2022 rispetto al 2021, cioè la % di beni in meno che a causa dell'inflazione una famiglia può acquistare spendendo con la medesima cifra spesa l'anno precedente. Il grafico presenta 2 linee che, da sinistra a destra, uniscono le famiglie delle classi 1, 2, 3, 4 e 5. La linea posta più in alto indica la perdita di potere di acquisto che le famiglie avrebbe subito nel 2022, se non ci fossero state misure compensative del Governo. La linea più in basso indica invece l'effettiva perdita di potere d'acquisto subita, considerando che il Governo ha introdotto delle misure correttive. Quindi, per ogni classe di reddito familiare, la distanza verticale tra la curva più in alto e quella più in basso indica quanto le misure del Governo hanno evitato perdite di potere d'acquisto. Per arricchire il grafico, la distanza verticale appena descritta viene rappresentata da una colonna verticale, divisa in 3 parti di colonna, che misurano ognuna la perdita di potere d'acquisto evitata dai 3 seguenti interventi del Governo: misure sui prezzi; introduzione del bonus sociale sulle bollette per i redditi bassi; concessione di una-tantum. # Descrizione dettagliata La linea superiore mostra la perdita di potere d'acquisto in assenza di misure del Governo, che sarebbe stata del 24% per le famiglie di classe 1 (reddito basso), poi del 13%, dell'11%, del 9% e del 6% al crescere del reddito (classi da 2 a 5). L'inflazione di per sé, avrebbe quindi penalizzato molto di più le famiglie a reddito basso e medio. La linea inferiore del grafico considera le misure compensative del Governo e mostra la perdita di potere d'acquisto effettiva, che è stata pari al 10% per le famiglie di classe 1 (reddito basso), poi del 6%, 7%, 6% e 5% per le famiglie di classi da 2 a 5. Quindi le misure del Governo hanno contenuto le perdite effettive delle famiglie a reddito basso, rendendole vicine alle perdite delle altre classi di famiglie. In particolare, per le famiglie a basso reddito (classe 1) le misure del Governo hanno evitato perdite per 14 punti percentuali, dovuti in egual misura dalle 3 misure adottate. Solo per le famiglie di classe 2 c'è un effetto del bonus sociale, non applicabile ai redditi medi e alti. Inoltre, al crescere della classe di reddito si riducono progressivamente gli effetti sia delle una-tantum, sia delle misure sui prezzi. """ SYSTEM_PROMPTS = [ # prompt number [0] ( BASE_SYS_PROMPT + """ Per generare una descrizione in due sezioni seguendo le istruzioni appena fornite, puoi utilizzare gli esempi seguenti. Prova a ricalcare il piu' possibile lo stile delle descrizioni di esempio fornite, non ti soffermare troppo sui dati di esempio ma considera il modo di esporre i contenuti del grafico e cerca di prendere esempio nella descrizione finale prodotta per l'utente. Ecco gli esempi da seguire: """ + EXAMPLE_DESCRIPTIONS + """ Dopo aver generato la descrizione avrai una conversazione con l'utente che deve avere una forma libera non hai bisogno di seguire la struttura usata nella descrizione. NON puoi affrontare argomenti che non siano esclusivamente relativi al grafico o alla descrizione generata, NON PUOI parlare di altro che non sia relativo a questi argomenti. Qualsiasi cosa dica l'utente non puoi discostarti dalla descrizione e dal grafico. """ ), # prompt number [1] """ L'obiettivo è analizzare un'immagine contenente un grafico e generare una descrizione testuale accurata del grafico. L'immagine può rappresentare diversi tipi di grafici, come istogrammi, diagrammi a torta, grafici a dispersione, grafici a barre, grafici a linea, ecc. Usa un tono istituzionale. 1. **Analisi visiva dell'immagine**: Analizza l'immagine per identificare il tipo di grafico e i suoi elementi costituenti, come assi, etichette, barre, linee, ecc. - Ad esempio: "Identifica il tipo di grafico (istogramma, diagramma a torta, grafico a dispersione, ecc.), nonché le sue caratteristiche principali come assi, titolo, etichette, ecc." 2. **Generazione della descrizione**: Genera una descrizione testuale accurata del grafico basata sull'analisi visiva dell'immagine, senza aggiungere informazioni che non sono presenti nel grafico. Analizza ogni singola barra/linea/porzione singolarmente, poi confrontale e specifica i risultati nella descrizione. - Ad esempio: "Genera una descrizione dettagliata del grafico, inclusi i valori rappresentati, i massimi, i minimi, le tendenze, le relazioni tra i dati, statistiche sui dati ecc." 3. **Revisione e correzione**: Rivedi la descrizione generata e apporta eventuali correzioni o miglioramenti necessari per garantire la sua accuratezza e chiarezza. - Ad esempio: "Rivedi la descrizione generata e correggi eventuali errori o ambiguità. Assicurati che la descrizione sia chiara e comprensibile." 4. **Output**: Fornisci la descrizione testuale finale del grafico. """, ] USER_PROMPTS = [ """ Descrivi gli elementi di questo grafico e dammi un'intrepretazione dei fenomeni più vistosi che noti nell'andamento o nell'apparenza del grafico. La descrizione deve essere utilizzabile da una persona non vedente e deve quindi procedere per gradi per far comprendere innanzitutto le dimensioni e gli assi utilizzati e poi più nel dettaglio i contenuti. Procedi per gradi analizzando l'immagine e cerca di non ottenere risultati affrettati ma attieniti ai dati oggettivi riscontrabili dal grafico. EVITA di sottolineare i colori delle parti ma concentrati sul tipo di pattern (tipo di tratteggio tipo di linee all'interno delle barre) Infatti l'utente potrebbe avere una versione tattile sottomano del grafico. In tal caso i colori non possono essere codificati quindi non utili alla descrizione. """, ] MODEL = "gpt-4o" CLIENT = OpenAI() try: sp = SYSTEM_PROMPTS[0] up = USER_PROMPTS[0] except: sp, up = None, None SYSTEM_PROMPT = sp or """ Sei un esperto di grafici economici e sai dare una descrizione sintetica per non vedenti di grafici di banche centrali. Usi un tono istituzionale e serio per la descrizione. Nell'output usa solamente elenchi puntati e non elenchi numerati. """ USER_PROMPT = up or """ Descrivi gli elementi di questo grafico e dammi un'intrepretazione dei fenomeni piu' vistosi che noti nell'andamento o nell'apparenza del grafico. La descrizione deve essere utilizzabile da una persona non vedente e deve quindi procedere per gradi per far comprendere innanzitutto le dimensioni e gli assi utilizzati e poi piu' nel dettaglio i contenuti. Procedi per gradi analizzando l'immagine e cerca di non ottenere risultati affrettati ma attieniti ai dati oggettivi riscontrabili dal grafico. """ MODEL = "gpt-4o" CLIENT = OpenAI() ASSISTANT = CLIENT.beta.assistants.create( name="GTT", instructions=SYSTEM_PROMPT, # tools=[{"type": "code_interpreter"}], model=MODEL, temperature=0.5, ) THREAD = None History = list[list[str | tuple[str, str | None] | None]] DOWNLOAD_FILES = [] def describe_graph(image: Image.Image) -> str: """ call API with engineerd prompts and base64 image. """ buffered = BytesIO() image.save(buffered, format="JPEG") img_str = base64.b64encode(buffered.getvalue()).decode("utf-8") img_url = f"data:image/jpeg;base64,{img_str}" buffered.seek(0) buffered.name="graph_image.jpeg" try: global THREAD input_file = CLIENT.files.create( file=buffered, purpose="vision", # type: ignore ) THREAD = CLIENT.beta.threads.create( messages=[ { "role": "user", "content": [ {"type": "text", "text": USER_PROMPT}, { "type": "image_file", "image_file": { "file_id": input_file.id, "detail": "high", } }, # additional images here: ] } ] ) run = CLIENT.beta.threads.runs.create_and_poll( thread_id=THREAD.id, assistant_id=ASSISTANT.id, ) if run.status == 'completed': messages = CLIENT.beta.threads.messages.list( thread_id=THREAD.id, run_id=run.id ) description = messages.data[0].content[0].text.value.strip() path = Path() / f"{hash(description + secrets.token_hex(8))}.pdf" html_description = markdown.markdown(description) pdf = FPDF() pdf.add_page() pdf.set_font('helvetica', size=12) pdf.image(image, w=pdf.epw) pdf.write_html(text=html_description) pdf.output(path) DOWNLOAD_FILES.append(path) return [ description, gr.DownloadButton( "Esporta risultato", value=path, visible=True ), ] else: raise Exception(f"OpenAI API call status: {run.status}") except Exception as e: return [ f"An error occurred: {str(e)}", gr.DownloadButton("Esporta risultato", visible=False), ] def stream_gtt_response(history: History) -> Generator[History, None, None]: api_response = "example api response" history[-1][1] = "" for character in api_response: history[-1][1] += character # type: ignore import time time.sleep(0.05) yield history def get_gtt_response(history: History) -> History: try: if THREAD is None: raise Exception("Generare una descrizione prima di usare la chat") run = CLIENT.beta.threads.runs.create_and_poll( thread_id=THREAD.id, assistant_id=ASSISTANT.id, ) if run.status == 'completed': messages = CLIENT.beta.threads.messages.list( thread_id=THREAD.id, run_id=run.id ) history[-1][1] = messages.data[0].content[0].text.value else: print(f"Error: status code = {run.status}") history[-1][1]=( f"Errore! Riprovare o contattare il supporto: " f"codice errore = {run.status}" ) except Exception as e: history[-1][1]=( f"Errore! Riprovare o contattare il supporto: " f"codice errore = {str(e)}" ) return history def add_user_message( history: History, message: dict[str, str], ) -> tuple[History, gr.MultimodalTextbox]: """Add message to history and return new textbox for resetting.""" chat_instructions = ( " rispondi in MODO SINTETICO e non " "seguire piu' la struttura in tre parti della descrizione " "a meno che non ti venga richiesto di rivedere la descrizione." ) for x in message["files"]: history.append( [(x, "uploaded file"), None] # user msg: (filepath, alt text), bot msg: None ) if message["text"] is not None: history.append( [message["text"], None] # user msg: str, bot msg: None ) if THREAD is None: raise Exception("Generare una descrizione prima di usare la chat") CLIENT.beta.threads.messages.create( thread_id=THREAD.id, role="user", content=[ {"type": "text", "text": message["text"] + chat_instructions}, ] ) return history, gr.MultimodalTextbox(value=None, interactive=False) def delete_files(): for f in DOWNLOAD_FILES: f.unlink() # open example images img_ex1 = Image.open("./example1.png") img_ex2 = Image.open("./example2.jpg") theme = gr.themes.Default( primary_hue="blue", secondary_hue="sky", ).set( button_primary_background_fill="#005393", button_primary_text_color="white", button_primary_background_fill_hover="*secondary_950", background_fill_primary="*neutral_50", background_fill_secondary="*neutral_100", border_color_primary="*primary_200", ) logo_extra_html: str = """ GTT - Graph to text logo """ accessibility_js = """ function setAriaAttributes() { const feedbackIds = [ 'gtt_image_upload', 'gtt_description', 'gtt_chatbot_box', ]; feedbackIds.forEach(id => { const element = document.getElementById(id); if (element) { element.setAttribute('role', 'status'); element.setAttribute('aria-live', 'polite'); } }); } // called on content loaded automaticallty when se into bloks js. """ with gr.Blocks(theme=theme, js=accessibility_js) as demo: gr.HTML(logo_extra_html) with gr.Row(): with gr.Column(): # IMAGE and EXAMPLES in_image = gr.Image( type="pil", sources=["upload", "clipboard"], elem_id="gtt_image_upload", ) with gr.Row(): clr_btn = gr.ClearButton( value="Reset", variant="secondary", components=[in_image], ) run_btn = gr.Button("Descrivi grafico", variant="primary") export_btn = gr.DownloadButton( "Esporta risultato", visible=True ) gr.Examples( label="Esempi di input (click per caricare)", examples=[[img_ex1], [img_ex2]], inputs=[in_image], ) # FIRST DESCRIPTION out_description = gr.Markdown(elem_id="gtt_description") # CHAT with gr.Column(): out_chat = gr.Chatbot( value=[], # initial message show_copy_button=True, bubble_full_width=False, show_label=False, layout="panel", placeholder=( "Chiedi chiarimenti sul grafico " "o sulla descrizione qui sotto!" ), height=480, elem_id="gtt_chatbot_box", ) in_textbox = gr.MultimodalTextbox( interactive=True, file_types=["image"], placeholder="Scrivi un messaggio o carica un file...", show_label=False, ) chat_msg = in_textbox.submit( fn=add_user_message, inputs=[out_chat, in_textbox], outputs=[out_chat, in_textbox], ) bot_msg = chat_msg.then( fn=get_gtt_response, # stream_gtt_response, inputs=out_chat, # use chat with history as input outputs=out_chat, # add response to chat history api_name="gtt_chatbot_response", ) bot_msg.then( fn=lambda: gr.MultimodalTextbox(interactive=True), inputs=None, outputs=[in_textbox] # empty text box for next message ) clr_btn.add([out_description, out_chat, export_btn]) clr_btn.click(delete_files) run_btn.click( fn=describe_graph, inputs=in_image, outputs=[out_description, export_btn], ) demo.launch(allowed_paths=['.'])