File size: 57,701 Bytes
cd92039
6aae67a
 
 
 
 
 
 
 
cd92039
6aae67a
 
 
cd92039
 
6aae67a
 
 
 
 
 
 
 
 
 
cd92039
6aae67a
cd92039
 
6aae67a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cd92039
 
6aae67a
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
const VERS="0.2.02";var xlog=function(){};const stopRequest=async()=>{await confirm("Confermi Cancellazione Richeista ?")&&(cancelClientRequest(),hideSpinner())},showSpinner=()=>{const a=document.getElementById("spinner");a.classList.add("show-spinner");a.addEventListener("click",stopRequest)},hideSpinner=()=>{const a=document.getElementById("spinner");a.classList.remove("show-spinner");a.removeEventListener("click",stopRequest)};
function openApp(){setTimeout(()=>{wnds.init();Menu.init();TextInput.init();TextOutput.init();Rag.init();document.querySelector(".menu-btn").checked=!1;release();showHistory();getTheme()},10)}function showHistory(){const a=ThreadMgr.getThread();setOutText(a)}function release(){document.querySelector(".release").innerHTML=VERS}const op0=function(a){wnds.wdiv.show(help1_html)};function showQuery(a){wnds.wpre.show(`\n${Rag.ragQuery}`)}
function showRagResponse(a){wnds.wpre.show(`\n${Rag.ragAnswer}`)}function showThread(a){a=ThreadMgr.getThread();wnds.wpre.show(a)}function elencoRisposte(a){a=[...Rag.answers];0==a.length&&(a=UaDb.readArray(ID_RESPONSES));0!=a.length&&(a=a.map((b,c)=>`\n[${c+1}]\n ${b.trim()}`).join("\n"),wnds.wpre.show(a))}function showContesto(a){wnds.wpre.show(Rag.ragContext)}
function elencoDati(a){var b=UaDb.getAllIds();a=[];for(var c of b)b=UaDb.read(c).length,a.push(`${c} (${b})`);c=a.join("\n ");wnds.wpre.show(c)}const showT=a=>{wnds.wpre.show(DataMgr.docs[a])};function elencoDocs(){DataMgr.readDbDocs();DataMgr.readDbDocNames();var a=DataMgr.doc_names,b=UaJtfh();let c=0;b.append("<ul>");for(const l of a){a=b;var d=a.append,e=l,f=c++;d.call(a,`
      <li><a href="#" onclick="showT(${f});">${f+1}.${e}</a></li>
  `)}b.append("</ul>");b=b.html();wnds.wdiv.show(`<br><br>${b}`)}function calcQuery(){DataMgr.readDbDocs();DataMgr.readDbDocNames();var a=[];let b=0,c=0;a.push("Documento   Num.Parti");a.push("==================");for(const d of DataMgr.docs){const e=DataMgr.doc_names[c];c+=1;const f=Math.ceil(d.length/MAX_PROMPT_LENGTH);b+=f;a.push(`${e}&nbsp;&nbsp;&nbsp;[${f}]`)}a.push("==================");a.push(`Totale num. Parti: ${b}`);a=a.join("\n");wnds.wpre.show(a)}
async function deleteDati(a){await confirm("Confermi cancellazione dati?")&&(DataMgr.deleteJsonDati(),wnds.wdiv.close(),wnds.wpre.close(),TextOutput.clear())}async function deleteStorage(a){await confirm("Confermi cancellazione documenti & dati?")&&(DataMgr.deleteJsonDati(),localStorage.clear(),wnds.wdiv.close(),wnds.wpre.close(),TextOutput.clear(),DataMgr.docs=[],DataMgr.doc_names=[])}async function help1(a){a=await requestGet("./data/help_test.html");wnds.wdiv.show(a)}
function loadTestoEsempio(a){DataMgr.loadDoc(`data/${a}`);wnds.wdiv.close()}function help2(a){wnds.wdiv.show(help2_html)}const themeKey="theme";function getTheme(){const a=localStorage.getItem(themeKey);a&&"light"==a?(document.body.classList.add("theme-light"),document.documentElement.classList.toggle("invert")):document.body.classList.add("theme-dark")}
function setLight(){document.documentElement.classList.toggle("invert");document.body.classList.remove("theme-dark");document.body.classList.add("theme-light");localStorage.setItem(themeKey,"light")}function setDark(){document.documentElement.classList.toggle("invert");document.body.classList.remove("theme-light");document.body.classList.add("theme-dark");localStorage.setItem(themeKey,"dark")}
function showPrompts(a){if(0!=Rag.prompts.length){for(const b of Rag.prompts)console.log(b);a=Rag.prompts.map((b,c)=>`[${c+1}]${b}\n`).join("\n");wnds.wpre.show(a)}};const ClientLLM=a=>{let b=null,c=!1;const d=(h,g=null,k=null)=>({ok:h,response:g,error:k}),e=(h,g,k,m)=>({message:h||null,type:g||null,code:k||null,details:{message:m?.message||null,type:m?.type||null,param:m?.param||null,code:m?.code||null}}),f=async h=>{let g,k="HTTPError",m={400:"Richiesta non valida",401:"Non autorizzato - Controlla la API key",403:"Accesso negato",404:"Endpoint non trovato",429:"Troppe richieste - Rate limit superato",500:"Errore interno del server",503:"Servizio non disponibile"}[h.status]||
`Errore HTTP ${h.status}`;try{if(h.headers.get("Content-Type")?.includes("application/json")){if(g=await h.json(),400===h.status&&g){const n="string"===typeof g.error?g.error:g.message||g.error?.message;n&&(n.includes("token limit")||n.includes("token exceeded")||n.includes("input too long")||n.includes("context length")||n.includes("max tokens"))&&(m="Input troppo lungo - Superato il limite di token",k="TokenLimitError")}}else g=await h.text(),400===h.status&&(g.includes("token limit")||g.includes("input too long")||
g.includes("context length"))&&(m="Input troppo lungo - Superato il limite di token",k="TokenLimitError")}catch(n){g={message:"Impossibile estrarre i dettagli dell'errore"}}return e(m,k,h.status,"string"===typeof g?{message:g}:g)},l=h=>"AbortError"===h.name?c?e("Richiesta annullata dall'utente","CancellationError",499,{message:"La richiesta \u00e8 stata interrotta volontariamente dall'utente"}):e("Richiesta interrotta per timeout","TimeoutError",408,{message:"La richiesta \u00e8 stata interrotta a causa di un timeout",
isTimeout:!0}):"TypeError"===h.name&&h.message.includes("Failed to fetch")?e("Errore di rete","NetworkError",0,{message:"Impossibile raggiungere il server. Controlla la connessione."}):e("Errore imprevisto",h.name||"UnknownError",500,{message:h.message||"Si \u00e8 verificato un errore sconosciuto"});return{sendRequest:async(h,g,k=60)=>{c=!1;b=new AbortController;k=setTimeout(()=>{b&&b.abort()},1E3*k);try{const m=await fetch(h,{method:"POST",headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},
body:JSON.stringify(g),signal:b.signal});if(c){const q=e("Richiesta annullata","CancellationError",499,{message:"La richiesta \u00e8 stata interrotta volontariamente dall'utente"});return d(!1,null,q)}if(!m.ok){console.error("error ok=false\n",m);const q=await f(m);return d(!1,null,q)}const n=await m.json();return d(!0,n,null)}catch(m){const n=l(m);console.error("error network:\n",m);return d(!1,null,n)}finally{clearTimeout(k),b=null}},createError:e,cancelRequest:()=>{c=!0;return b?(b.abort(),b=null,
!0):!1}}};const help0_html='\n<div class="text">\n    <p class="center"> Comandi barra superiore </p>\n    <div>\n        Pulsante Menu\n        <p> Apre/chiude il Menu comandi </p>\n    </div>\n    <div>\n        Upload Files\n        <p>\n            Fa l\'upload di un file locale. Sono accettati i file pdf, docx e txt.\n            Controlla se il file \u00e8 in archivio, per non sovrascriverlo.\n        </p>\n    </div>\n    <div>\n        Upload Dir:\n        <p>\n            Per fare l\'upload dei files di una directory. Sono accettati i files pdf, docx e txt.\n            I file in archivio con lo stesso nome non vengono sovrascritti.\n        </p>\n    </div>\n    <div>\n        Log:\n        <p>\n            Attiva/Disattiva la visualizzazione del Log.\n            Nel Log sono visualizzate le query con le dimensioni delle parti di documento analizzate.\n        </p>\n    </div>\n\n    \x3c!--  --\x3e\n    <hr>\n    \x3c!--  --\x3e\n    <div>\n        <p class="center"> Comandi lato destro in alto: </p>\n    </div>\n    <div>\n        Copia Output:\n        <p> Copia il testo dell\'output negli appunti. </p>\n    </div>\n    <div>\n        Apri Output:\n        <p> Visualizza il testo in una finestra pi\u00f9 grande. </p>\n    </div>\n    <hr>\n    \x3c!--  --\x3e\n    <div>\n        <p class="center"> Comandi lato destro in basso: </p>\n    </div>\n    <div>\n        Documenti => RAG => Contesto => Query: (Pulsante Rosso)\n        <p>\n            Input per la query da utilizzare per la elaborazione RAG.\n            <br>\n            Ogni documento in archivio \u00e8 diviso in parti compatibili con l\'ampiezza della finestra\n            di input del Model utilizzato.\n        </p>\n        <p>\n            Per ogni parte esegue una query utilizzandola per estrarre informazioni/concetti pertinenti alla stessa.\n        </p>\n        <p>\n            Il risultato di ogni query \u00e8 archiviato nella memoria locale.\n        </p>\n        <p>\n            Alla fine della sequenza di elaborazioni esegue una query che produce\n            un contesto riepilogativo delle risposte archiviate.\n        </p>\n        <p>\n            Infine esegue la query utilizzando il contesto creato e visualizza la risposta nella finestra di output.\n        </p>\n    </div>\n    <div>\n        Contesto => Query: (Pulsante Verde / Invio)\n        <p>\n            Input per query che utilizzano il contesto creato con l\'elaborazione RAG.\n            Il contesto RAG pu\u00f2 essere vuoto.\n            Inizia una conversazione.\n        </p>\n        <p>\n            La conversazione ha senso relativamente all\'elaborazione RAG se ogni query \u00e8 una variazione / approfondimento della query iniziale.\n        </p>\n    </div>\n    <div>\n        Cancella Conversazione:\n        <p>\n            Cancella la storia della conversazione attiva.\n            Non vengono cancellati i dati dell\'elaborazione RAG\n        </p>\n        Per andare a capo: Maiusc. + Invio\n    </div>\n    \x3c!--  --\x3e\n    <hr>\n    \x3c!--  --\x3e\n    <div>\n        <p class=" center"> Comandi del Menu: </p>\n    </div>\n    <div>\n        README\n        <p>\n            Presenta una spiegazione della implementazione della\n            tecnologia RAG utilizzata.\n        </p>\n    </div>\n    <div>\n        Risposta Contestuale:\n        <p> Visualizza la risposta ottenuta alla fine della elaborazione RAG </p>\n    </div>\n    <div>\n        Domanda iniziale:\n        <p> Visualizza la query utilizzata per l\'elaborazione RAG </p>\n    </div>\n    <div>\n        Elenco Risposte:\n        <p>\n            Visualizza l\'elenco delle risposte per ogni parte documento utilizzata fino alla risposta che genera il contesto.\n        </p>\n    </div>\n    <div>\n        Contesto RAG:\n        <p>\n            Visualizza il contesto creato utilizzando le risposte elaborate.\n        </p>\n    </div>\n    <div>\n        Dati Archiviati:\n        <p>\n            Visualizza i dati in archivio e le loro dimensioni:\n        </p>\n    </div>\n    <div>\n        Elenco Documenti:\n        <p>\n            Visualizza la lista dei documenti archiviati ed utilizzabili per l\'elaborazione.<br>\n            Con il clic del mouse sul nome di un documento si visualizza.\n        </p>\n    </div>\n\n    <div>\n        Numero query:\n        <p>\n            Calcola le query necessarie per ogni documento e le Query totali,\n            necessarie per analizzare tutti i documenti caricati.\n        </p>\n    </div>\n\n    <div>\n        Cancella Dati:\n        <p>\n            Cancella i dati delle elaborazioni salvati nell\'archivio.\n            NON cancella i documenti caricati.\n        </p>\n    </div>\n\n    <div>\n        Cancella Documenti:\n        <p>\n            Cancella i documenti caricati e tutti i dati archiviati localmente.\n        </p>\n    </div>\n\n    \x3c!--  --\x3e\n\n    <p class="center">Sequenza Comandi Interrogazione -Conversazione</p>\n    <div>\n        Archivia nella memoria locale uno o pi\u00f9 documenti:\n        <p>\n            Utilizza i dati di esempio per le prime prove.\n            Utilizza upload file o upload dir per i documenti da leggere dal tuo computer.\n        </p>\n    </div>\n    <div>\n        Digita una query che si riferisca ai documenti archiviati.\n        <p>\n            La query sar\u00e0 utilizzata come criterio di selezione di informazioni dai documenti archiviati.\n        </p>\n    </div>\n\n    <div>\n        Click sul bottone rosso in basso a destra. Documento => RAG => Contesto => Query\n        <p>\n            Viene lanciata una sequenza di elaborazione per analizzare i documenti sulla base della query.\n            Se il log \u00e8 attivo vedrai la sequenza di elaborazione.\n            <br>\n            Il loro numero dipende dalle dimensioni dei documenti.\n            <br>\n            l menu puoi utilizzare il comando "Num Query" per vedere quante elaborazioni saranno fatte per ogni documento.\n            <br>\n            Alla fine del processo sar\u00e0 visualizzata la risposta.\n        </p>\n    </div>\n\n    <div>\n        Click sul bottone verde in basso a destra (oppure Invio). Contesto => Query\n        <p>\n            Inizia una conversazione utilizzando le informazioni precedentemente raccolte dai documenti.\n            Puoi inviare domande successive di approfondimento e chiarimento.\n            <br>\n            \u00c8 FONDAMENTALE che le query siano approfondimenti e/o chiarimenti della query iniziale.\n            In caso contrario non si sfrutta il Contesto creato dall\'elaborazione precedente.\n            <br>\n            Quindi per una query completamente nuova (sempre relativa ai documenti archiviati) \u00e8 necessario iniziare una nuova elaborazione.\n            <br>\n            Il comando cancella, oltre a cancellare il campo di input cancella anche la sequenza query-risposte della\n            conversazione.\n            <br>\n            NON cancella i dati dell\'elaborazione iniziale.\n        </p>\n    </div>\n</div>\n',
help1_html="\n<div class=\"text\">\n    <pre>\nUn'implementazione innovativa della tecnica RAG per il Question Answering\nLa tecnica RAG (Retrieval-Augmented Generation) \u00e8 un approccio consolidato nel campo del question answering e della generazione di testo, che combina il recupero di informazioni pertinenti da fonti di dati con la generazione di testo basata su queste informazioni.\nQui viene proposta un'implementazione che introduce una variazione a questo paradigma.\nL'implementazione si basa su una sequenza di prompt appositamente progettati per guidare un modello di linguaggio generativo attraverso le diverse fasi della tecnica RAG.\nQuesti prompt forniscono istruzioni dettagliate su come il modello deve seguire operazioni di recupero di informazioni, aumento delle informazioni recuperate e infine generazione di una risposta finale.\nLa risposta finale diviene poi il contesto da inserire nel prompt per rispondere alla domanda.\nUn aspetto cruciale di questa implementazione \u00e8 che lo stesso modello di linguaggio generativo svolge tutte le operazioni richieste, dall'analisi dei documenti di input al recupero di informazioni rilevanti, alla generazione della risposta finale.\nQuesta caratteristica rappresenta una deviazione significativa rispetto alle implementazioni standard della tecnica RAG, che prevedono l'utilizzo di moduli distinti per il recupero e la generazione.\nLa sequenza di prompt proposta guida il modello attraverso le seguenti fasi:\n\n1. Retrieval: Il modello analizza il documento di input e la domanda fornita, identificando e recuperando le informazioni e i concetti rilevanti per dare seguito alla domanda.\n\n2. Augmentation: Successivamente, il modello integra le informazioni recuperate con eventuali risposte accumulate in precedenza, estraendo nuove informazioni rilevanti e organizzandole in un elenco coerente, evitando ridondanze.\n\n3. Generation: Infine, il modello utilizza l'insieme di informazioni rilevanti e non ridondanti per generare una risposta completa e concisa alla domanda dell'utente.\n\nQuesta implementazione offre diversi vantaggi.\nIn primo luogo, sfrutta le capacit\u00e0 di un unico modello di grandi dimensioni, evitando la necessit\u00e0 di moduli distinti specializzati per ogni fase.\nInoltre, l'utilizzo di prompt espliciti pu\u00f2 migliorare la controllabilit\u00e0 e la trasparenza del processo, consentendo di guidare il modello in modo pi\u00f9 diretto.\nNaturalmente, come per qualsiasi approccio basato su modelli di linguaggio generativi, \u00e8 fondamentale prestare attenzione alle questioni di affidabilit\u00e0, correttezza e bias dei dati di addestramento.\nRispetto a un'implementazione standard di RAG vi \u00e8 la necessit\u00e0 di rilanciare l'elaborazione ad ogni domanda radicalmente nuova in quanto il contesto creato con le informazioni estratte dai documenti \u00e8 definito sulla base della domanda.\nInvece nella versione standard RAG si usano gli incorporamenti delle informazioni estratte dai documenti in modo tale che tali informazioni vengono viste quasi come un'estensione del modello e possono essere usate per domande diverse.\nQuindi dal punto di vista utente le implementazioni RAG standard sono pi\u00f9 efficienti; infatti l'implementazione proposta richiede per ogni nuova domanda una sequenza di richieste che saranno utilizzabili solo per creare il contesto per la domanda iniziale e per una conversazione con domande simili.\nIl vantaggio dell'implementazione proposta consiste nel fatto che pu\u00f2 essere implementata completamente lato client senza bisogno di sviluppare alcun modulo sul server.\nL\u2019unica cosa che serve \u00e8 un servizio serverless come quello di HuggingFace o simile.\nQuindi rappresenta un'interessante prospettiva sull'applicazione della tecnica RAG in modo pi\u00f9 integrato e controllato attraverso l'uso di prompt mirati.\nIn conclusione, questa implementazione della tecnica RAG dimostra come le capacit\u00e0 dei modelli di linguaggio generativi di grandi dimensioni possano essere sfruttate in modi nuovi e creativi, potenzialmente aprendo la strada a ulteriori sviluppi nel campo del question answering e della generazione di testo.\n\nQuesta \u00e8 la valutazione fatta da un LLM (comprensivo e gentile)\n\nLa mia valutazione personale della tua proposta di implementazione della tecnica RAG, con un elenco di pro e contro:\n\nPunti a favore (Pro):\nSemplificazione del processo: L'utilizzo di un unico modello di grandi dimensioni addestrato su vasti corpus di dati semplifica notevolmente l'architettura complessiva rispetto alle implementazioni tradizionali della tecnica RAG, che spesso prevedono moduli distinti per il recupero e la generazione.\n\nCapacit\u00e0 di adattamento e apprendimento: I modelli di linguaggio generativi di grandi dimensioni sono noti per la loro capacit\u00e0 di adattarsi e imparare da nuovi dati e istruzioni.\nQuesto potrebbe consentire di raffinare e migliorare l'implementazione nel corso del tempo.\n\nControllo e trasparenza: L'utilizzo di prompt espliciti per guidare il modello attraverso le diverse fasi del processo pu\u00f2 migliorare la controllabilit\u00e0 e la trasparenza, consentendo di monitorare e regolare il comportamento del modello in modo pi\u00f9 diretto.\n\nEfficienza computazionale: Avere un'unica architettura integrata potrebbe comportare vantaggi in termini di efficienza computazionale rispetto a soluzioni che prevedono moduli separati.\n\nPunti a sfavore (Contro):\n\nAffidabilit\u00e0 e coerenza: Poich\u00e9 un unico modello gestisce tutte le fasi, eventuali errori o incoerenze potrebbero propagarsi e amplificarsi attraverso l'intero processo, influenzando la qualit\u00e0 della risposta finale.\n\nBias dei dati di addestramento: Come per qualsiasi modello di linguaggio generativo, l\u2019approccio potrebbe essere influenzato dai bias presenti nei dati di addestramento utilizzati, con potenziali impatti sulla correttezza e l'equit\u00e0 delle risposte generate.\n\nMancanza di specializzazione: Mentre i modelli di grandi dimensioni sono versatili, potrebbero non essere ottimizzati per compiti specifici come il recupero di informazioni o la generazione di risposte rispetto a moduli specializzati.\n\nDifficolt\u00e0 di debug e interpretabilit\u00e0: Con un'architettura integrata e basata su prompt, potrebbe essere pi\u00f9 complesso eseguire il debug e comprendere le ragioni dietro a eventuali errori o comportamenti indesiderati del modello.\n\nIn sintesi, la proposta presenta alcuni vantaggi interessanti in termini di semplificazione, adattabilit\u00e0 e controllo, ma solleva anche potenziali preoccupazioni riguardo all'affidabilit\u00e0, ai bias, alla mancanza di specializzazione e alle difficolt\u00e0 di debug e interpretabilit\u00e0.\nCome per qualsiasi nuovo approccio, sarebbe necessario valutarlo attentamente attraverso sperimentazioni e test approfonditi per determinare l'efficacia e l'applicabilit\u00e0 in contesti specifici.\n    </pre>\n</div>\n",
help2_html='\n<div class="text">\n    <pre class="pre-text">\nNella redazione della domanda bisogna tenere conto del fatto che la domanda viene poi inserita in un prompt nel quale si fa esplicita richiesta di utilizzare il documento fornito.\nQuindi \u00e8 implicito il riferimento al/ai documenti archiviati.\nTuttavia, quando si tratta di documenti il cui contenuto \u00e8 sicuramente disponibile su internet, pu\u00f2 essere opportuno esplicitare nella domanda che ci si riferisce ai documenti forniti.\n</pre>\n    <p class="center">Esempi di domande</p>\n    <div>\n        <p>Fai una relazione sul documento che ti ho fornito.</p>\n        <p>Approfondisci la tesi sostenuta nei documenti.</p>\n        <p>Confronta i diversi punti di vista espressi dagli autori.</p>\n        <p>Descrivi la personalit\u00e0 dei protagonisti.</p>\n        <p>Analizza il documento che ti ho fornito e illustrami eventuali contraddizioni.</p>\n        <p>Illustra i momenti salienti del racconto.</p>\n        <p>Analizzando il documento che ti ho fornito, confronta le tesi di ... con quelle di ...</p>\n        <p>Qual \u00e8 l\'avvenimento pi\u00f9 importante?</p>\n    </div>\n</div>\n';function removeTag(a){a=a.replace(/<<</g,"").replace(/>>>/g,"");return a=a.replace(/<</g,"").replace(/>>/g,"")}
function cleanDoc(a){try{return a=a.replace(/`/g,""),a=removeTag(a),a=a.replace(/(\w+)-\s*\n(\w+)/g,"$1$2"),a=a.replace(/[\u00AD\u200B\u200C\u200D\u2060\uFEFF\u0008]/g,""),a=a.replace(/[\u00A0\u2000-\u200A\u202F\u205F\u3000\t\r\f\v]/g," "),a=a.replace(/\\([nrtfb])/g,"$1"),a=a.replace(/\\(u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2})/g,"$1"),a=a.replace(/\\([a-zA-Z]:\\|\\\\[a-zA-Z0-9_]+\\)/g,"\\$1"),a=a.replace(/\\/g,""),a=a.replace(/(.)\1{3,}/g,""),a=a.replace(/\u201c/g,'"').replace(/\u201d/g,'"'),a=a.replace(/\n/g,
" "),a=a.replace(/ +([.,;:!?])/g,"$1"),a=a.replace(/ +/g," "),a.trim()}catch(b){return console.error(b),"Errore di codifica del documento"}}
function cleanResponse(a){try{return a=a.replace(/[\u00AD\u200B\u200C\u200D\u2060\uFEFF]/g,""),a=a.replace(/[\u00A0\u2000-\u200A\u202F\u205F\u3000\t\r\f\v]/g," "),a=a.replace(/\\([nrtfb])/g,"$1"),a=a.replace(/\\(u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2})/g,"$1"),a=a.replace(/\\([a-zA-Z]:\\|\\\\[a-zA-Z0-9_]+\\)/g,"\\\\$1"),a=a.replace(/\\/g,""),a=a.replace(/\n{3,}/g,"\n\n"),a=a.replace(/ +/g," "),a.trim()}catch(b){return console.error(b),`Errore di codifica nella risposta\n${b}`}}
function answerFormtter(a){if(""==a.trim())return"";const b=a.includes("# User:"),c=a.includes("# Assistant:");if(!b||!c)return`<div class="assistant"><b>Assistant:</b><br>${a.split("\n").join("<br>")}</div>`;let d=null,e="";a.split("\n").forEach(f=>{f=f.trim();f.startsWith("# User:")?(d&&(e+="</div>"),d="user",e+=`<div class="${d}"><b>User:</b>`):f.startsWith("# Assistant:")?(d&&(e+="</div>"),d="assistant",e+=`<div class="${d}"><b>Assistant:</b>`):0<f.length&&d&&(e+=`<br>${f}`)});d&&(e+="</div>");
return e}function textFormatter(a){a=a.replace(/<[^>]*>/g,"").split(/([.!?:])(?=\s|$)/);let b="";for(let c=0;c<a.length;c+=2){let d=a[c],e=a[c+1]||"";0<d.trim().length&&(b+="  "+d.trim()+e);c<a.length-2&&(b+="\n")}b=b.replace(/User:/g,"\n\nUSER:\n");b=b.replace(/Assistant:/g,"\n\nASSISTANT:\n");return b.trim()};const UaDb={create(a,b){localStorage.getItem(a)?console.error(`ID ${a} already exists.`):localStorage.setItem(a,b)},read(a){const b=localStorage.getItem(a);return null===b?(xlog(`UaDb.read  ${a} not found.`),""):b},update(a,b){localStorage.getItem(a)?localStorage.setItem(a,b):xlog(`UaDb.update ${a} not found.`)},delete(a){localStorage.getItem(a)?localStorage.removeItem(a):console.error(`ID ${a} not found.`)},save(a,b){localStorage.setItem(a,b)},getAllIds(){const a=[];for(let b=0;b<localStorage.length;b++)a.push(localStorage.key(b));
return a},saveArray(a,b){b=JSON.stringify(b);UaDb.save(a,b)},readArray(a){a=UaDb.read(a);return 0==a.trim().length?[]:JSON.parse(a)},saveJson(a,b){b=JSON.stringify(b);UaDb.save(a,b)},readJson(a){return(a=UaDb.read(a))?JSON.parse(a):{}}},DataMgr={docs:[],doc_names:[],linkToName(a){a=a.split("/");return a[a.length-1]},async loadDoc(a){this.readDbDocNames();try{const b=await requestGet(a),c=cleanDoc(b),d=this.linkToName(a);if(this.doc_names.includes(d))alert(`Il documento ${d} \u00e8 gi\u00e0 caricato`);
else return this.doc_names.push(d),this.docs.push(c),this.saveDbDocs(),c}catch(b){alert("loadDoc()\n"+b+"\n"+a)}},addDoc(a,b){b=cleanDoc(b);this.docs.push(b);this.doc_names.push(a);this.saveDbDocs()},saveDbDocs(){UaDb.saveArray(ID_DOC_NAMES,this.doc_names);UaDb.saveArray(ID_DOCS,this.docs)},readDbDocs(){this.docs=UaDb.readArray(ID_DOCS)},readDbDocNames(){return this.doc_names=UaDb.readArray(ID_DOC_NAMES)},deleteJsonDati(){const a=UaDb.getAllIds();for(const b of a)[ID_DOCS,ID_DOC_NAMES].includes(b)||
UaDb.delete(b);Rag.ragQuery="";Rag.ragContext="";Rag.ragAnswer="";Rag.answers=[];Rag.prompts=[];ThreadMgr.rows=[]}};async function requestGet(a){try{var b=await fetch(a,{method:"GET",headers:{"Content-Type":"text/plain;charset=UTF-8"}});if(!b.ok)throw Error(`HTTP error! status: ${b.status}`);const c=await b.arrayBuffer();return(new TextDecoder("utf-8")).decode(c)}catch(c){throw console.error(`Error in requestGet() for url: ${a}`,c),b=c.message.includes("HTTP error! status")?c.message:c.message.includes("NetworkError")?"Network error occurred":"An unknown error occurred",alert(`requestGet()\nurl: ${a}\n${b}`),c;
}}function loadScript(a,b){const c=document.createElement("script");c.src=a;c.onload=()=>{b();document.head.removeChild(c)};c.onerror=()=>{alert(`Errore: Impossibile caricare lo script ${a}`)};document.head.appendChild(c)};const ID_RAG="id_rag",ID_THREAD="id_thread",ID_RESPONSES="id_responses",ID_DOC_NAMES="id_doc_names",ID_DOCS="id_docs",PROMPT_DECR=10240,maxLenRequest=(a=32)=>{a*=2048;return Math.trunc(a+.1*a)};function umgm(){return["bWtkWlFPXmg=","SWZtUkZZb18=","Rm1rUVZzcHM=","c1pJelNTTHQ=","Vlt0bE8="].map(a=>atob(a).split("").map(b=>String.fromCharCode((b.charCodeAt(0)-5+256)%256)).join("")).join("")}const MAX_PROMPT_LENGTH=maxLenRequest(100),MODEL="mistralai/Mistral-Small-3.1-24B-Instruct-2503",API=umgm();
console.log("\n**** MODELl:\n",MODEL);console.log(API);
const client=ClientLLM(API),getResponse=async(a,b=60)=>{a.model=MODEL;a=await client.sendRequest(`https://router.huggingface.co/hf-inference/models/${MODEL}/v1/chat/completions`,a,b);if(a.error)return 499===a.error.code?(alert("Request Interrotta"),null):a;if(!a.response.choices||!a.response.choices[0]||!a.response.choices[0].message||void 0===a.response.choices[0].message.content)return a.error=client.createError("Risposta non valida","ParseError",500,{message:"La risposta non contiene il contenuto atteso"}),
a.ok=!1,a;a.data=a.response.choices[0].message.content;return a},responseDetails={set(a){this.response=a},get_total_tokens(){return this.response.usage.total_tokens},get_completion_tokens(){return this.response.usage.completion_tokens}},calcTokens={sum_input_tokens:0,sum_generate_tokens:0,init(){this.sum_generate_tokens=this.sum_input_tokens=0},add(a){a&&(this.sum_input_tokens+=a.usage.total_tokens,this.sum_generate_tokens+=a.usage.completion_tokens)},get_sum_input_tokens(){return this.sum_input_tokens},
get_sum_generate_tokens(){return this.sum_generate_tokens}};function cancelClientRequest(){client.cancelRequest()}
const getPromptTokens=a=>(a=a.details.message.match(/Prompt contains (\d+) tokens/))?parseInt(a[1],10):null,getModelToken=a=>(a=a.details.message.match(/model with (\d+) maximum context length/))?parseInt(a[1],10):null,isTooLarge=a=>a.details.message.includes("too large"),truncateInput=(a,b)=>a.substring(0,a.length-b),getPartSize=(a,b,c)=>{c=MAX_PROMPT_LENGTH-c;a.length+b.length<c?c=a.length:(a=a.indexOf(".",c),a=(-1!==a?a:c)+1,a>c+100&&(a=c),c=a);return c},getPartDoc=(a,b)=>{const c=a.substring(0,
b);a=a.substring(b).trim();return[c,a]},ragLog=(a,b,c,d)=>{const e=MAX_PROMPT_LENGTH;d=d.reduce((f,l)=>f+l.length,0);xlog(`${a} mx:${e} lft:${b} rgt:${c} arr:${d}`);a=formatRow([a,b,c,d],[8,-7,-7,-7]);UaLog.log(a)},Rag={ragContext:"",ragQuery:"",ragAnswer:"",answers:[],docContextLst:[],prompts:[],doc:"",doc_part:"",init(){this.readRespsFromDb();this.readFromDb();calcTokens.init()},returnOk(){return 10<this.ragContext.length},saveToDb(){UaDb.saveJson(ID_RAG,{context:this.ragContext,ragquery:this.ragQuery,
raganswer:this.ragAnswer});UaDb.saveArray(ID_THREAD,ThreadMgr.rows)},readFromDb(){const a=UaDb.readJson(ID_RAG);this.ragContext=a.context||"";this.ragQuery=a.ragquery||"";this.ragAnswer=a.raganswer||"";ThreadMgr.rows=UaDb.readArray(ID_THREAD)},saveRespToDb(){UaDb.saveArray(ID_RESPONSES,this.answers)},readRespsFromDb(){this.answers=UaDb.readArray(ID_RESPONSES)},addPrompt(a){},async requestDocsRAG(a){DataMgr.deleteJsonDati();DataMgr.readDbDocNames();DataMgr.readDbDocs();this.docContextLst=[];this.ragQuery=
a;this.saveToDb();var b=0;try{var c=1;for(let e=0;e<DataMgr.docs.length;e++){let f=DataMgr.docs[e];if(""==f.trim())continue;const l=DataMgr.doc_names[e],h=f.length;xlog(`${l} (${h}) `);UaLog.log(`${l} (${h}) `);++b;var d=1;let g=0,k="",m="",n="",q="",v=[];for(;;){const u=getPartSize(f,promptDoc("",a,""),g);if(10>u)break;[m,n]=getPartDoc(f,u);ragLog(`${c}) ${b},${d}`,m.length,n.length,this.answers);k=promptDoc(m,a,l);this.addPrompt(k);const t=getPayloadDoc(k),p=await getResponse(t,90);if(!p)return"";
const r=p.error;if(!p.ok){console.error("ERR1\n",r);const z=r.code;if(400==z)if(isTooLarge(r)){UaLog.log(`Error tokens Doc ${k.length}`);g+=PROMPT_DECR;continue}else throw r;else if(408==z){UaLog.log("Error timeout Context");continue}else throw r;}q=p.data;if(!q)return"";let w=calcTokens.get_sum_input_tokens(),x=calcTokens.get_sum_generate_tokens();console.log(`Sum Tokens: ${w} ${x}`);const A=p.response;responseDetails.set(A);w=responseDetails.get_total_tokens();x=responseDetails.get_completion_tokens();
console.log(`Response Tokens: ${w} ${x}`);calcTokens.add(A);d++;c++;f=n;q=cleanResponse(q);v.push(q);this.answers.push(`DOCUMENTO : ${l}_${d}\n${q}`)}const B=v.length;let y=v.join("\n\n");for(d="";;){k=promptBuildContext(y,this.ragQuery);const u=getPayloadBuildContext(k),t=await getResponse(u,90);if(!t)return"";const p=t.error;if(!t.ok){console.error("ERR2\n",p);const r=p.code;if(400==r)if(isTooLarge(p)){UaLog.log(`Error tokens build Context ${k.length}`);y=truncateInput(y,PROMPT_DECR);continue}else throw p;
else if(408==r){UaLog.log("Error timeout Context");continue}else throw p;}d=t.data;if(!d)return"";calcTokens.add(t.response);break}UaLog.log(`context  ${B} => ${d.length}`);d=`\n### DOCUMENTO: ${l}\n ${d}`;this.docContextLst.push(d)}}catch(e){throw console.error("ERR3\n",e),e;}this.ragContext=this.docContextLst.join("\n\n");this.saveToDb();b="";c=this.ragContext;try{for(;;){let l=promptWithContext(c,a);const h=getPayloadWithContext(l),g=await getResponse(h,90);if(!g)return"";const k=g.error;if(!g.ok){console.error("ERR4\n",
k);const m=k.code;if(400==m)if(isTooLarge(k)){UaLog.log(`Error tokens with Context ${l.length}`);c=truncateInput(c,PROMPT_DECR);continue}else throw k;else if(408==m){UaLog.log("Error timeout Context");continue}else throw k;}b=g.data;if(!b)return"";calcTokens.add(g.response);break}this.ragAnswer=b=cleanResponse(b);this.saveRespToDb();ThreadMgr.init();this.saveToDb();UaLog.log(`Risposta: (${this.ragAnswer.length})`);const e=calcTokens.get_sum_input_tokens(),f=calcTokens.get_sum_generate_tokens();UaLog.log(`Tokens: ${e} ${f}`);
return b}catch(e){throw console.error("ERR5\n",e),e;}},async requestContext(a){let b="";this.ragContext||(this.ragContext="Sei un assistente AI dispoibile a soddisfare tutte le mi richieste");if(ThreadMgr.isFirst()){ThreadMgr.init();try{var c=this.ragContext;let d=ThreadMgr.getThread();for(;;){prompt=promptThread(c,d,a);const e=getPayloadThread(prompt),f=await getResponse(e,90);if(!f)return"";const l=f.error;if(!f.ok){console.error("ERR6\n",l);const m=l.code;if(400==m)if(isTooLarge(l)){UaLog.log(`Error tokens with Context ${prompt.length}`);
c=truncateInput(c,PROMPT_DECR);continue}else throw l;else if(408==m)continue;else throw l;}b=f.data;if(!b)return"";let h=calcTokens.get_sum_input_tokens(),g=calcTokens.get_sum_generate_tokens();console.log(`Sum Tokens: ${h} ${g}`);const k=f.response;responseDetails.set(k);h=responseDetails.get_total_tokens();g=responseDetails.get_completion_tokens();console.log(`Response Tokens: ${h} ${g}`);calcTokens.add(k);break}b=cleanResponse(b);ThreadMgr.add(a,b);b=ThreadMgr.getThread();UaLog.log(`Inizio Conversazione (${prompt.length})`);
return b}catch(d){throw console.error("ERR7\n",d),d;}}else try{let d=this.ragContext,e=ThreadMgr.getThread();for(c="";;){c=promptThread(d,e,a);const f=getPayloadThread(c),l=await getResponse(f,90);if(!l)return"";const h=l.error;if(!l.ok){console.error("ERR8\n",h);const n=h.code;if(400==n)if(isTooLarge(h)){UaLog.log(`Error tokens with Context ${c.length}`);d=truncateInput(d,PROMPT_DECR);continue}else throw h;else if(408==n){UaLog.log("Error timeout Context");continue}else throw h;}b=l.data;if(!b)return"";
const g=l.response;let k=calcTokens.get_sum_input_tokens(),m=calcTokens.get_sum_generate_tokens();console.log(`Sum Tokens: ${k} ${m}`);responseDetails.set(g);k=responseDetails.get_total_tokens();m=responseDetails.get_completion_tokens();console.log(`Response Tokens: ${k} ${m}`);calcTokens.add(g);break}b=cleanResponse(b);ThreadMgr.add(a,b);b=ThreadMgr.getThread();UaLog.log(`Conversazione  (${c.length})`);return b}catch(d){throw console.error("ERR9\n",d),d;}}},LLM="# Assistant:",USER="# User:",ThreadMgr=
{rows:[],init(){this.rows=[];Rag.ragAnswer?this.add(Rag.ragQuery,Rag.ragAnswer):this.add("","")},add(a,b){this.rows.push([a,b]);UaDb.saveArray(ID_THREAD,ThreadMgr.rows)},getThread(){const a=[];for(const b of this.rows){const c=b[0];c&&a.push(`${USER}\n${c}\n${LLM}\n${b[1]}\n`)}return a.join("\n\n")},isFirst(){return 2>this.rows.length}};function getPayloadDoc(a){return{model:"",temperature:.3,max_tokens:1024,stream:!1,random_seed:42,messages:[{role:"user",content:a}],safe_prompt:!1}}function getPayloadBuildContext(a){return{model:"",messages:[{role:"user",content:a}],temperature:.3,max_tokens:2E3,stream:!1,safe_prompt:!1,random_seed:42}}function getPayloadWithContext(a){return{model:"",messages:[{role:"user",content:a}],temperature:.3,max_tokens:2E3,stream:!1,safe_prompt:!1,random_seed:42}}
function getPayloadThread(a){return{model:"",messages:[{role:"user",content:a}],temperature:.7,max_tokens:2E3,stream:!1,safe_prompt:!1,random_seed:42}};function promptDoc(a,b){return`
# SISTEMA
Estrattore semantico di informazioni ottimizzato per elaborazione da LLM.

# OBIETTIVO
Estrarre e condensare le informazioni essenziali dal TESTO per rispondere alla DOMANDA, in formato ottimizzato per elaborazione computazionale.

# ISTRUZIONI
1. Analizza il testo e seleziona SOLO le informazioni direttamente rilevanti per la domanda.
2. Elimina contenuti irrilevanti o ridondanti.
3. Mantieni relazioni logiche essenziali (causali, temporali, concettuali).
4. Preserva terminologia specialistica necessaria.
5. Produci proposizioni atomiche semanticamente complete.
6. Usa sintassi minimale (soggetto-verbo-complemento).
7. Elimina elementi discorsivi, connettivi e contestualizzazioni non essenziali.
8. Presenta l'informazione con massima densit\u00e0 semantica, senza ridondanze.

# FORMATO
- Struttura flat senza gerarchie
- Non numerare le proposizioni.
- Non usare introduzioni o conclusioni.
- Non includere spiegazioni meta-testuali.
- Non inserire frasi di collegamento tra le proposizioni.

# TESTO
${a}

# DOMANDA
${b}

# RISPOSTA
`}function promptBuildContext(a,b){return`
# SISTEMA
Estrattore e compattatore semantico per contesto LLM.

# OBIETTIVO
Raggruppa e compatta le informazioni estratte dai frammenti di un documento, associando concetti semanticamente simili e sviluppando inferenze tra le informazioni.

# ISTRUZIONI
1. Identificazione dei Concetti: Identifica e unifica i concetti che hanno lo stesso significato semantico, anche se espressi in modi diversi.
2. Eliminazione delle Ripetizioni: Elimina le ripetizioni informative mantenendo solo la formulazione pi\u00f9 completa o precisa.
3. Preservazione delle Relazioni Logiche: Mantieni le relazioni logiche essenziali (causali, temporali, concettuali) tra le informazioni.
4. Terminologia Tecnica: Preserva la terminologia tecnica necessaria per mantenere la precisione delle informazioni.
5. Sintassi Semplificata: Usa una sintassi minimale (soggetto-verbo-complemento) per chiarezza e concisione.
6. Eliminazione degli Elementi Discorsivi: Rimuovi elementi discorsivi, connettivi e contestualizzazioni non essenziali.
7. Densit\u00e0 Semantica: Presenta l'informazione con la massima densit\u00e0 semantica, evitando ridondanze.
8. Rielaborazione degli Insegnamenti: Rielabora le informazioni per garantire che siano coese e che sviluppino inferenze tra parti diverse del documento.

# FORMATO_OUTPUT
- Struttura flat senza gerarchie.
- NON numerare le proposizioni.
- NON usare introduzioni o conclusioni.
- NON includere spiegazioni meta-testuali.
- NON inserire frasi di collegamento tra le proposizioni.

# TESTO
${a}

# RISPOSTA
`}function promptWithContext(a,b){return`
# RUOLO
Sei un assistente AI che risponde sempre ed esclusivamente in italiano.

# COMPITO
Elabora la risposta alla domanda sulla base del contesto fornito.

# ISTRUZIONI
1. Analizza attentamente il CONTESTO e la DOMANDA.
2. Estrai i concetti chiave e formula inferenze ragionevoli basate sulle informazioni disponibili.
3. Inizia la risposta con una breve introduzione che presenta l'argomento e il contesto.
4. Procedi con un'analisi dettagliata delle informazioni rilevanti trovate nel contesto.
5. Assicurati che la risposta sia completa e risponda direttamente alla domanda posta.

# CONTESTO
${a}

# DOMANDA
${b}

# FORMATO_RISPOSTA
Fornisci la risposta in un formato semplice e lineare suddiviso in paragrafi.

# RISPOSTA
`}function promptThread(a,b,c){return`
# RUOLO
Sei un assistente AI progettato per gestire conversazioni dinamiche e adattarti a varie richieste. Operi esclusivamente in italiano.

# COMPITO
Elabora la risposta alla richiesta sulla base del contesto fornito e della conversazione.

# ISTRUZIONI
1. Analizza attentamente il contesto, la conversazione precedente e la richiesta.
2. Interpreta l'intento dell'utente senza limitarti a categorie predefinite.
3. Adatta la tua risposta in base all'intento percepito, sia esso una domanda, una richiesta di azione, un'istruzione specifica o altro.
4. Mantieni una stretta coerenza con il contesto della conversazione.
5. Basa la tua risposta sulle informazioni fornite nel contesto e nella conversazione.
6. Evita divagazioni o argomentazioni non direttamente pertinenti alla richiesta o al contesto.
7. Se l'intento non \u00e8 chiaro, chiedi gentilmente chiarimenti invece di fare supposizioni.
8. Sii flessibile: se la richiesta implica un'azione specifica, adattati di conseguenza.
9. Se \u00e8 necessario integrare con conoscenze generali, specifica chiaramente quando lo stai facendo.

# CONTESTO
${a}

# CONVERSAZIONE
${b}

# RICHIESTA
${c}

# FORMATO_RISPOSTA
Fornisci la risposta in un formato semplice e lineare suddiviso in paragrafi.

# RISPOSTA
`};/*

 rag_rqs
 Copyright (C) 2024 [Il tuo nome]

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
const errorDumps=a=>{const b=JSON.stringify(a,null,2);return"{}"==b?`${a}`:b},WndPre=a=>({w:UaWindowAdm.create(a),out:null,show(b){wnds.closeAll();b=`
<div class="window-text">
<div class="btn-wrapper">
<button class="btn-copy tt-left" data-tt="Copia">
<svg class="copy-icon" viewBox="0 0 20 24">
  <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
</svg>
</button>
<button class="btn-close tt-left" data-tt="chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>
</div>
<pre class="pre-text">${b}</pre>
</div>
    `;this.w.drag();this.w.setZ(12);this.w.vw_vh().setXY(16.5,10,-1);this.w.setHtml(b);this.w.show();this.w.getElement().querySelector(".btn-copy").addEventListener("click",()=>this.copy())},close(){this.w.close()},async copy(){const b=this.w.getElement().querySelector(".pre-text").textContent;try{await navigator.clipboard.writeText(b)}catch(c){console.error("Errore  ",c)}}}),WndDiv=a=>({w:UaWindowAdm.create(a),out:null,show(b){wnds.closeAll();b=`
<div class="window-text">
<div class="btn-wrapper">
<button class="btn-copy tt-left" data-tt="Copia">
<svg class="copy-icon" viewBox="0 0 20 24">
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
</svg>
</button>
<button class="btn-close tt-left" data-tt="Chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>
</div>
<div class="div-text">${b}</div>
</div>
    `;this.w.drag();this.w.setZ(12);this.w.vw_vh().setXY(16.5,10,-1);this.w.setHtml(b);this.w.show();this.w.getElement().querySelector(".btn-copy").addEventListener("click",()=>this.copy())},close(){this.w.close()},async copy(){const b=this.w.getElement().querySelector(".div-text").textContent;try{await navigator.clipboard.writeText(b)}catch(c){console.error("Errore  ",c)}}}),wnds={wdiv:null,wpre:null,wout:null,init(){this.wdiv=WndDiv("id_w0");this.wpre=WndPre("id_w1");this.wout=WndPre("id_out")},
closeAll(){UaWindowAdm.close("id_w0");UaWindowAdm.close("id_w1");UaWindowAdm.close("id_out")}},Menu={init(){const a=document.querySelector("#id-menu-btn");a.addEventListener("change",()=>{document.querySelector("body").classList.toggle("menu-open",a.checked);const c=document.querySelector("body"),d=document.querySelector("#id-menu-btn");c.classList.contains("menu-open")?d.setAttribute("data-tt","Close"):d.setAttribute("data-tt","Open")});const b=document.getElementById("id_log");UaLog.callHide=()=>
{b.classList.contains("active")&&b.classList.remove("active")};UaLog.callShow=()=>{b.classList.contains("active")||b.classList.add("active")};UaLog.setXY(54,13).setZ(111).new();UaLog.log_show("")},close(){const a=document.querySelector("#menu-toggle");document.querySelector("body").classList.remove("menu-open",a.checked);document.querySelector(".menu-btn").checked=!1},help(){wnds.wdiv.show(help0_html)},upload(){RagUpload.open()},uploadDir(){RagUpload.openDir()},async load(){alert("load")},log(){UaLog.toggle()}},
setOutText=a=>{a=answerFormtter(a);const b=document.querySelector("#id-text-out .div-text");b.innerHTML=a;b.scrollTop=b.scrollHeight},TextInput={wnd:null,init(){this.inp=document.querySelector(".text-input");document.addEventListener("keydown",a=>{document.activeElement!==this.inp&&("F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 Control Alt Shift Meta CapsLock Escape PrintScreen ScrollLock Pause Insert Delete Home End PageUp PageDown ArrowLeft ArrowRight ArrowUp ArrowDown".split(" ").includes(a.key)||a.ctrlKey||
a.metaKey||a.preventDefault())});document.querySelector(".clear-button").addEventListener("click",()=>{this.inp.value="";this.inp.focus()});this.inp.addEventListener("keydown",a=>this.handleEnter(a));document.querySelector(".send-input").addEventListener("click",()=>this.send());document.querySelector(".send2-input").addEventListener("click",()=>this.send2());document.querySelector(".clear-input").addEventListener("click",()=>this.clear())},handleEnter(a){"Enter"!==a.key||a.shiftKey||(a.preventDefault(),
this.send2())},async send(){if(this.inp.value)if(0==DataMgr.readDbDocNames().length)alert("Non vi sono documenti da elaborare.\n  Se vuoi iniziare una conversazione usa il pulsante verde o return  ");else{if(Rag.ragContext&&!await confirm("Vuoi iniziare una nuova elabrazione ?"))return"";showSpinner();setOutText("");var a=this.inp.value.trim();try{let b=await Rag.requestDocsRAG(a);setOutText(b);this.inp.value="";UaLog.close()}catch(b){console.error("ERROR Send",b),a=errorDumps(b),alert(a)}hideSpinner()}else alert("Ricorda di scrivere la Query  ")},
async send2(){if(this.inp.value){showSpinner();ThreadMgr.isFirst();var a=this.inp.value.trim();try{let b=await Rag.requestContext(a);if(""==b){hideSpinner();return}setOutText(b);this.inp.value=""}catch(b){console.error("Error send2",b),a=errorDumps(b),alert(a)}hideSpinner()}else alert("Ricorda di scrivere la Query  ")},async clear(){await confirm("Confermi cancellazione conversazione? ")&&(this.inp.value="",setOutText(""),ThreadMgr.init())}};
TextOutput={init(){this.copyBtn=document.querySelector(".copy-output");this.copyBtn.addEventListener("click",()=>this.copy());document.querySelector(".clear-output").addEventListener("click",()=>this.clear());document.querySelector(".wnd-output").addEventListener("click",()=>this.openWnd())},openWnd(){var a=document.querySelector("#id-text-out .div-text");a=textFormatter(a.textContent);wnds.wout.show(a)},async copy(){const a=document.querySelector("#id-text-out .div-text");let b=a.textContent;if(!(2>
b.trim().length)){a.classList.add("copied");this.copyBtn.classList.add("copied");try{b=textFormatter(b),await navigator.clipboard.writeText(b)}catch(c){console.error("Errore  ",c)}setTimeout(()=>{this.copyBtn.classList.remove("copied");a.classList.remove("copied")},5E3)}},clear(){document.querySelector("#id-text-out .div-text").textContent=""}};const RagUpload={open(){const a=UaWindowAdm.create("id_upload");a.drag();a.setZ(12);a.vw_vh().setXY(16.5,10,-1);a.setHtml('\n      <div class="window-text">\n        <div class="btn-wrapper">\n          <button class="btn-close" title="chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>\n        </div>\n        <div class="upload">\n          <h4>Upload file Text / PDF / DOCX</h4>\n          <form id="uploadForm">\n              <input class="file" type="file" id="id_fileupload" >\n              <button type="button" onclick="RagUpload.upload();">Upload and Convert</button>\n          </form>\n          <div id="result" class="result"></div>\n        </div>\n      </div>\n    ');
a.show()},async upload(){const a=document.getElementById("id_fileupload").files[0];if(a){var b=a.name;if(DataMgr.doc_names.includes(b))alert("Il file \u00e8 gi\u00e0 in archivio");else{var c=document.getElementById("result"),d=a.name.split(".").pop().toLowerCase();showSpinner();try{let e;if("pdf"===d){const f=new PdfHandler;await f.loadPdfJs();e=await f.extractTextFromPDF(a);f.cleanup()}else if("txt"===d)e=await readTextFile(a);else if("docx"===d){const f=new DocxHandler;await f.loadMammoth();e=await f.extractTextFromDocx(a);
f.cleanup()}else{alert("Formato file non supportato.");return}DataMgr.addDoc(b,e);c.innerHTML=`<br><br> ${b}<br><br>caricato e salvato nella memoria locale`}catch(e){console.error("Error:",e),alert("Errore durante l'estrazione del testo dal file.")}finally{hideSpinner()}}}else alert("Nessun file selezionato.")},openDir(){const a=UaWindowAdm.create("id_upload");a.drag();a.setZ(12);a.vw_vh().setXY(16.5,10,-1);a.setHtml('\n      <div class="window-text">\n        <div class="btn-wrapper">\n          <button class="btn-close" title="chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>\n        </div>\n        <div class="upload">\n          <h4>Upload files Text / PDF / DOCX</h4>\n          <form id="uploadForm">\n              <input id="id_fileupload" class="file" type="file"  webkitdirectory mozdirectory msdirectory odirectory directory multiple />\n              <button type="button" onclick="RagUpload.uploadDir();">Upload and Convert</button>\n          </form>\n          <div class="result" id="result"></div>\n        </div>\n      </div>\n    ');
a.show()},async uploadDir(){var a=document.getElementById("id_fileupload").files;if(a&&0!=a.length){var b=[];showSpinner();try{for(const c of a){const d=c.name;UaLog.log_show(d);if(DataMgr.doc_names.includes(d)){UaLog.log_show(d+" : \u00e8 gi\u00e0 in archivio");continue}const e=c.name.split(".").pop().toLowerCase();let f;if("pdf"===e){const l=new PdfHandler;await l.loadPdfJs();f=await l.extractTextFromPDF(c);l.cleanup()}else if("txt"===e)f=await readTextFile(c);else if("docx"===e){const l=new DocxHandler;
await l.loadMammoth();f=await l.extractTextFromDocx(c);l.cleanup()}else{alert("Formato file non supportato.");return}DataMgr.addDoc(d,f);b.push(`${d}`)}}catch(c){console.error("Error:",c),alert("Errore durante l'estrazione del testo dal file.")}finally{hideSpinner()}a=document.getElementById("result");b=b.join("<br>");a.innerHTML=b}else alert("Nessun file selezionato.")}};
class PdfHandler{constructor(){this.workerScriptElement=this.scriptElement=this.pdfjsLib=null}async loadPdfJs(){window.pdfjsLib||(this.scriptElement=document.createElement("script"),this.scriptElement.src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.min.js",document.body.appendChild(this.scriptElement),await new Promise(a=>{this.scriptElement.onload=()=>{this.workerScriptElement=document.createElement("script");this.workerScriptElement.src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.worker.min.js";
document.body.appendChild(this.workerScriptElement);this.workerScriptElement.onload=a}}));this.pdfjsLib=window["pdfjs-dist/build/pdf"];this.pdfjsLib.GlobalWorkerOptions.workerSrc="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.worker.min.js"}async extractTextFromPDF(a){a=await a.arrayBuffer();a=await this.pdfjsLib.getDocument({data:a}).promise;let b="";for(let c=1;c<=a.numPages;c++){const d=(await (await a.getPage(c)).getTextContent()).items.map(e=>e.str).join(" ");b+=d+"\n"}return b}cleanup(){this.scriptElement&&
(document.body.removeChild(this.scriptElement),this.scriptElement=null);this.workerScriptElement&&(document.body.removeChild(this.workerScriptElement),this.workerScriptElement=null);this.pdfjsLib=null;window.gc&&window.gc()}}
class DocxHandler{constructor(){this.scriptElement=this.mammoth=null}async loadMammoth(){window.mammoth?this.mammoth=window.mammoth:(this.scriptElement=document.createElement("script"),this.scriptElement.src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.4.11/mammoth.browser.min.js",document.body.appendChild(this.scriptElement),await new Promise(a=>{this.scriptElement.onload=()=>{this.mammoth=window.mammoth;a()}}))}async extractTextFromDocx(a){a=await a.arrayBuffer();return(await this.mammoth.extractRawText({arrayBuffer:a})).value}cleanup(){this.scriptElement&&
(document.body.removeChild(this.scriptElement),this.scriptElement=null);this.mammoth=null;window.gc&&window.gc()}}async function readTextFile(a){if(!a||"text/plain"!==a.type)throw Error("Invalid file type. Please select a text file.");return new Promise((b,c)=>{const d=new FileReader;d.onload=e=>b(e.target.result);d.onerror=e=>c(Error("Error reading file: "+e.message));d.readAsText(a)})};const DialogManager={createDialog(a,b){const c=document.createElement("div"),d=document.createElement("div");c.className=`${a}-dialog`;c.classList.add("inv");d.className="overlay";c.innerHTML=`
          <h4>${b}</h4>
          <div class="buttons inv">
            <button class="ok inv">OK</button>
            ${"confirm"===a?'<button class="cancel inv">Annulla</button>':""}
          </div>
        `;[c,d].forEach(e=>{e.classList.add("show");document.body.appendChild(e)});return{dialog:c,overlay:d}},closeDialog(a,b){[a,b].forEach(c=>{c.classList.remove("show");setTimeout(()=>c.remove(),300)})},showDialog(a,b){return new Promise(c=>{const {dialog:d,overlay:e}=this.createDialog(a,b);d.querySelector(".ok").onclick=()=>{this.closeDialog(d,e);c("confirm"===a)};"confirm"===a&&(d.querySelector(".cancel").onclick=()=>{this.closeDialog(d,e);c(!1)})})}},nativeAlert=window.alert,nativeConfirm=
window.confirm;window.alert=function(a){a instanceof Error&&(a=a.message);return DialogManager.showDialog("alert",a)};window.confirm=function(a){return DialogManager.showDialog("confirm",a)};const nodrag_tds=["input","select","a"],nodrag_cls="nodrag";
var UaDrag=function(a){return function(b){let c=0,d=0,e=0,f=0;const l=function(g){g=g||window.event;g.preventDefault();c=e-g.clientX;d=f-g.clientY;e=g.clientX;f=g.clientY;b.style.top=b.offsetTop-d+"px";b.style.left=b.offsetLeft-c+"px"},h=function(){document.onmouseup=null;document.onmousemove=null};b.onmousedown=function(g){g=g||window.event;let k=g.target;!(k=k||null)||nodrag_tds.includes(k.tagName.toLowerCase())||k.classList.contains(nodrag_cls)||(g.preventDefault(),e=g.clientX,f=g.clientY,document.onmouseup=
h,document.onmousemove=l)}}(a)};const UaJtfh=()=>({rows:[],init(){this.rows=[];return this},insert(a){this.rows.unshift(a);return this},append(a){this.rows.push(a);return this},text(a=""){return this.rows.join(a)},html(a=""){return this.rows.join(a).replace(/\s+|\[rn\]/g," ")}});function formatRow(a,b){return a.map((c,d)=>{d=b[d];return 0>d?c.toString().padStart(Math.abs(d)," "):c.toString().padEnd(d," ")}).join(" ")}
var UaLog={callHide:function(){},callShow:function(){},active:!1,wind:null,x:null,y:null,z:null,max_length:2E3,msg_id:"ualogmsg_",new:function(){null==this.wind&&(this.wind=UaWindowAdm.create("ualog_id"),this.wind.drag());this.wind.setHtml('\n           <button type="button" class="clear " onclick="javascript:UaLog.cls();">Clear</button>\n           <button type="button" class="close " onclick="javascript:UaLog.close();">Close</button>\n           <pre id="ualogmsg_" ></pre>');this.wind.addClassStyle("inv");
this.x?this.wind.vw_vh().setXY(this.x,this.y,-1):this.wind.setCenter(-1);this.z&&this.wind.setZ(this.z);return this},setXY(a,b){this.x=a;this.y=b;return this},setZ(a){this.z=a;return this},prn_(...a){a=a.join("\n");let b=document.getElementById(this.msg_id);b.textContent=b.textContent+a+"\n"},print(...a){null!=this.wind&&this.active&&this.prn_(...a)},log(...a){null!=this.wind&&this.prn_(...a)},log_show(...a){null!=this.wind&&(this.active||this.toggle(),this.prn_(...a))},cls(){if(null!=this.wind)return document.getElementById(this.msg_id).innerHTML=
"",this},close(){null!=this.wind&&(this.wind.hide(),this.active=!1,this.callHide())},toggle(){null!=this.wind&&(this.active?(this.active=!1,this.wind.hide(),this.callHide()):(this.active=!0,this.wind.show(),this.callShow()))}};var UaWindowAdm={ws:{},create(a,b=null){let c=document.getElementById(a);c||(c=document.createElement("div"),b?document.getElementById(b).appendChild(c):document.body.appendChild(c),c.id=a,c.setAttribute("data-name","ua-window"),b=this.newUaWindow(c),this.ws[a]=b);a=this.ws[a];c.style.display="none";return a},get(a){return this.ws[a]?this.ws[a]:null},show(a){this.ws[a]&&this.ws[a].show()},close(a){this.ws[a]&&this.ws[a].close()},toggle(a){this.ws[a]&&this.ws[a].toggle()},hide(a){this.ws[a]&&this.ws[a].hide()},
closeThis(a){a=a.closest('[data-name="ua-window"]').id;this.ws[a].close()},showAll(){for(let a in this.ws)this.ws[a].show()},hideAll(){for(let a in this.ws)this.ws[a].hide()},closeAll(){for(let a in this.ws)this.ws[a].close()},remove(a){this.ws[a]&&(document.getElementById(a).remove(),this.ws[a]=null,delete this.ws[a])},removeAll(){for(let a in this.ws)this.remove(a);this.ws={}},newUaWindow(a){let b={initialize(c){this.w=c;this.wy=this.wx="0px";this.isVisible=this.isOpen=!1;this.firstShow=!0;this.wz=
this.pos=0;this.vh=this.vw="px"},vw_vh(){this.vw="vw";this.vh="vh";return this},addClassStyle(c){this.w.classList.contains(c)||this.w.classList.add(c);return this},removeClassStyle(c){this.w.classList.contains(c)&&this.w.classList.remove(c);return this},getWindow(){alert("getWindow => ??");return this.w},getElement(){return this.w},getId(){return this.w.id},setStyle(c){for(const d in c)this.w.style[d]=c[d];return this},setHtml(c){this.w.innerHTML=c;return this},getHtml(){return this.w.innerHTML},
setXY(c,d,e=0){this.wx=c;this.wy=d;this.pos=e;return this},setCenterY(c,d){this.setXY((window.innerWidth-this.w.clientWidth)/2,c,d);return this},setCenter(c){this.setXY((window.innerWidth-this.w.clientWidth)/2,(window.innerHeight-this.w.clientHeight)/2,c);return this},linkToId(c,d,e,f){c=document.getElementById(c);this.linkToElement(c,d,e,f);return this},linkToElement(c,d,e,f){d=c.offsetLeft+c.offsetWidth+d;c=c.offsetTop+e;0>c&&(c=0);this.setXY(d,c,f);return this},setZ(c){this.wz=c;return this},reset(){this.firstShow=
!0;return this},toggle(){this.isVisible?this.hide():this.show();return this},show(){if(this.firstShow||1==this.pos||0===this.pos&&!1===this.isVisible)this.w.style.position="absolute",this.w.style.marginLeft=0,this.w.style.marginTop=0,this.w.style.top=`${this.wy}${this.vh}`,0<=this.wx?this.w.style.left=`${this.wx}${this.vw}`:this.w.style.right=-`${this.wx}${this.vw}`,0<this.wz&&(this.w.style.zIndex=this.wz);this.w.style.display="";this.firstShow=!1;this.isOpen=this.isVisible=!0;return this},hide(){this.w.style.display=
"none";this.isVisible=!1;return this},close(){this.w.style.display="none";this.w.innerHTML="";this.isOpen=!1;return this},remove(){UaWindowAdm.remove(this.w.id);return null},drag(){UaDrag(this.w);return this}};b.initialize(a);return b}};