Rodolfo Torres commited on
Commit
97c4064
1 Parent(s): 83f4a9b

Enable news, other fixes

Browse files
Files changed (6) hide show
  1. README.md +2 -2
  2. main.py +54 -53
  3. requirements.txt +3 -2
  4. static/index.html +43 -2
  5. static/js/app.js +158 -25
  6. static/json/prompts-en.json +2 -2
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Text Talk
3
  emoji: 🐨
4
  colorFrom: blue
5
  colorTo: purple
@@ -12,7 +12,7 @@ license: mit
12
 
13
  **Intel® oneAPI Hackathon 2023: The LLM Challenge**
14
 
15
- Live Demo - https://huggingface.co/spaces/roaltopo/scan-u-doc
16
 
17
  Blog - https://medium.com/@roaltopo/unleashing-textual-understanding-with-scanudoc-f2e12499ae11
18
 
 
1
  ---
2
+ title: ScanUDoc
3
  emoji: 🐨
4
  colorFrom: blue
5
  colorTo: purple
 
12
 
13
  **Intel® oneAPI Hackathon 2023: The LLM Challenge**
14
 
15
+ Live Demo - https://roaltopo-scan-u-doc.hf.space
16
 
17
  Blog - https://medium.com/@roaltopo/unleashing-textual-understanding-with-scanudoc-f2e12499ae11
18
 
main.py CHANGED
@@ -1,25 +1,19 @@
1
- from time import time
2
- t_ini = time()
3
- from fastapi import FastAPI, UploadFile, File
4
  from fastapi.staticfiles import StaticFiles
5
  from fastapi.responses import FileResponse
6
- #from fastapi.middleware.cors import CORSMiddleware
7
  from typing import Optional
8
  from transformers import pipeline
9
  from pydantic import BaseModel
10
  from fastapi.responses import JSONResponse
11
  from io import BytesIO
12
  import PyPDF2
 
13
 
14
- print('End loading libraries: ', round(time()-t_ini))
15
- t_ini = time()
16
  model_name = "roaltopo/scan-u-doc_question-answer"
17
  qa_pipeline = pipeline(
18
  "question-answering",
19
  model=model_name,
20
  )
21
- print('End loading model: ', round(time()-t_ini))
22
- t_ini = time()
23
 
24
  app = FastAPI()
25
 
@@ -36,73 +30,80 @@ class QuestionInfo(BaseModel):
36
 
37
  @app.post("/store_text/{uuid}")
38
  async def store_text(uuid: str, text_info: TextInfo):
39
- # Almacena la información en el diccionario en memoria
40
- text_storage[uuid] = {
41
- 'text': text_info.text,
42
- #'pdf': text_info.pdf,
43
- #'html_url': text_info.html_url
44
- }
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
- return {'success': True}
 
 
 
 
47
 
48
  # Ruta para cargar un archivo
49
  @app.post("/upload_file/{uuid}")
50
  async def upload_file(uuid: str, file: UploadFile = File(...)):
51
  try:
52
- pdf_content = await file.read()
53
- pdf_stream = BytesIO(pdf_content)
54
- pdf_reader = PyPDF2.PdfReader(pdf_stream)
55
-
56
- # Aquí puedes trabajar con el objeto pdf_reader
57
- # por ejemplo, puedes imprimir el número de páginas del PDF
58
- #print(f"Número de páginas: {len(pdf_reader.pages)}")
59
-
60
- # Variable para almacenar el texto extraído del PDF
61
- extracted_text = ''
62
-
63
- # Itera sobre todas las páginas del PDF
64
- for page_num in range(len(pdf_reader.pages)):
65
- # Obtiene el objeto de la página
66
- page = pdf_reader.pages[page_num]
67
- # Extrae el texto de la página y agrégalo a la variable extracted_text
68
- #extracted_text += page.extract_text().replace('\n', ' ')
69
- tmp = page.extract_text()
70
- tmp = tmp.replace('\n', ' ')
71
- tmp = tmp.replace(' ', ' ')
72
- tmp = tmp.replace('. ', '.\n')
73
- extracted_text += tmp
74
- if len(extracted_text) > 4000:
75
- extracted_text = extracted_text[:4000]
76
- break
77
-
78
- # Almacena la información en el diccionario en memoria
79
  text_storage[uuid] = {
80
  'text': extracted_text,
81
  }
82
 
83
  return JSONResponse(content={'success': True})
 
84
  except Exception as e:
85
- return JSONResponse(content={"message": f"Error al cargar el archivo: {e}"}, status_code=500)
86
 
87
  @app.post("/answer_question/{uuid}")
88
  async def answer_question(uuid: str, question_info: QuestionInfo):
89
- #text_id = question_info.text_id
90
  question = question_info.question
91
 
92
  # Verifica si el texto con el ID existe en el diccionario
93
  if uuid not in text_storage:
94
  return {'error': 'Text not found'}
95
 
96
- # Implementa la lógica de procesamiento de la pregunta aquí
97
- # En este ejemplo, simplemente devuelve una respuesta fija
98
- #print(type(text_storage[text_id]), text_storage[text_id]['text'])
99
- #response = "El texto original es: " + text_storage[text_id]['text']
100
-
101
- #return {'response': response}
102
- #return qa_pipeline(question=question, context=text_storage[text_id]['text'])
103
  r = qa_pipeline(question=question, context=text_storage[uuid]['text'], top_k=10)
104
- #print(r)
105
- #print('-----------------------------')
106
  return r[0]
107
 
108
 
 
1
+ from fastapi import FastAPI, UploadFile, File, HTTPException
 
 
2
  from fastapi.staticfiles import StaticFiles
3
  from fastapi.responses import FileResponse
 
4
  from typing import Optional
5
  from transformers import pipeline
6
  from pydantic import BaseModel
7
  from fastapi.responses import JSONResponse
8
  from io import BytesIO
9
  import PyPDF2
10
+ from newspaper import Article
11
 
 
 
12
  model_name = "roaltopo/scan-u-doc_question-answer"
13
  qa_pipeline = pipeline(
14
  "question-answering",
15
  model=model_name,
16
  )
 
 
17
 
18
  app = FastAPI()
19
 
 
30
 
31
  @app.post("/store_text/{uuid}")
32
  async def store_text(uuid: str, text_info: TextInfo):
33
+ try:
34
+ url = text_info.html_url.strip() if text_info.html_url else None
35
+ if url:
36
+ print('url:', url)
37
+ article = Article(url)
38
+ article.download()
39
+ article.parse()
40
+ text = f'{article.title}\n{article.text}'
41
+ elif text_info.text:
42
+ text = text_info.text
43
+ else:
44
+ raise HTTPException(status_code=400, detail="Invalid Option: 'url' or 'text' required in text_info.")
45
+
46
+ # Store information in the in-memory dictionary
47
+ text_storage[uuid] = {
48
+ 'text': text,
49
+ 'url': text_info.html_url
50
+ }
51
 
52
+ return {'success': True}
53
+ except Exception as e:
54
+ error_message = f"Error: {str(e)}"
55
+ print(error_message)
56
+ raise HTTPException(status_code=500, detail="Internal Server Error: An unexpected error occurred.")
57
 
58
  # Ruta para cargar un archivo
59
  @app.post("/upload_file/{uuid}")
60
  async def upload_file(uuid: str, file: UploadFile = File(...)):
61
  try:
62
+ file_extension = file.filename.split('.')[-1].lower()
63
+
64
+ if file_extension == 'pdf':
65
+ content = await file.read()
66
+ stream = BytesIO(content)
67
+ reader = PyPDF2.PdfReader(stream)
68
+
69
+ extracted_text = ''
70
+
71
+ for page_num in range(len(reader.pages)):
72
+ page = reader.pages[page_num]
73
+ tmp = page.extract_text()
74
+ tmp = tmp.replace('\n', ' ')
75
+ tmp = tmp.replace(' ', ' ')
76
+ tmp = tmp.replace('. ', '.\n')
77
+ extracted_text += tmp
78
+ if len(extracted_text) > 4000:
79
+ extracted_text = extracted_text[:4000]
80
+ break
81
+
82
+ elif file_extension == 'txt':
83
+ content = await file.read()
84
+ extracted_text = content.decode('utf-8')
85
+
86
+ else:
87
+ raise ValueError("Unsupported file format.")
88
+
89
  text_storage[uuid] = {
90
  'text': extracted_text,
91
  }
92
 
93
  return JSONResponse(content={'success': True})
94
+
95
  except Exception as e:
96
+ return JSONResponse(content={"message": f"Error while uploading the file: {e}"}, status_code=500)
97
 
98
  @app.post("/answer_question/{uuid}")
99
  async def answer_question(uuid: str, question_info: QuestionInfo):
 
100
  question = question_info.question
101
 
102
  # Verifica si el texto con el ID existe en el diccionario
103
  if uuid not in text_storage:
104
  return {'error': 'Text not found'}
105
 
 
 
 
 
 
 
 
106
  r = qa_pipeline(question=question, context=text_storage[uuid]['text'], top_k=10)
 
 
107
  return r[0]
108
 
109
 
requirements.txt CHANGED
@@ -6,5 +6,6 @@ intel_extension_for_pytorch==2.0.100
6
  torch==2.0.1
7
  transformers==4.29.2
8
  pydantic==2.4.2
9
- pypdf2==3.0.1
10
- python-multipart==0.*
 
 
6
  torch==2.0.1
7
  transformers==4.29.2
8
  pydantic==2.4.2
9
+ pypdf2==3.0.*
10
+ python-multipart==0.*
11
+ newspaper3k==0.*
static/index.html CHANGED
@@ -26,6 +26,8 @@
26
  <link rel="icon" type="image/png" sizes="16x16" href="fav/favicon-16x16.png">
27
  <link rel="manifest" href="fav/site.webmanifest">
28
  <link rel="mask-icon" href="fav/safari-pinned-tab.svg" color="#5bbad5">
 
 
29
  </head>
30
  <body>
31
 
@@ -99,7 +101,13 @@
99
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{button_close_modal}"></button>
100
  </div>
101
  <div class="modal-body">
102
- <textarea id="textArea" rows="4" cols="50"></textarea>
 
 
 
 
 
 
103
  </div>
104
  <div class="modal-footer">
105
  <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{button_close_modal}}</button>
@@ -117,8 +125,17 @@
117
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{button_close_modal}"></button>
118
  </div>
119
  <div class="modal-body">
 
 
 
 
120
  <form id="file-form" enctype="multipart/form-data">
121
- <input id="fileInput" type="file" name="file" accept=".pdf">
 
 
 
 
 
122
  </form>
123
  </div>
124
  <div class="modal-footer">
@@ -129,6 +146,30 @@
129
  </div>
130
  </div>
131
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  <header class="hide-section">
133
  <div class="container">
134
  <div class="row">
 
26
  <link rel="icon" type="image/png" sizes="16x16" href="fav/favicon-16x16.png">
27
  <link rel="manifest" href="fav/site.webmanifest">
28
  <link rel="mask-icon" href="fav/safari-pinned-tab.svg" color="#5bbad5">
29
+ <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css">
30
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
31
  </head>
32
  <body>
33
 
 
101
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{button_close_modal}"></button>
102
  </div>
103
  <div class="modal-body">
104
+ <div class="alert alert-info" role="alert">
105
+ Please enter a text of maximum 4000 characters.
106
+ </div>
107
+ <textarea id="textArea" class="form-control" rows="4" maxlength="4000"></textarea>
108
+ <div class="mt-2">
109
+ <span id="charCount">4000</span> characters remaining
110
+ </div>
111
  </div>
112
  <div class="modal-footer">
113
  <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{button_close_modal}}</button>
 
125
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{button_close_modal}"></button>
126
  </div>
127
  <div class="modal-body">
128
+ <div class="alert alert-info" role="alert">
129
+ You can upload a PDF or TXT file, maximum 1MB in size.<br>
130
+ Only the first 4000 characters of the text will be processed.
131
+ </div>
132
  <form id="file-form" enctype="multipart/form-data">
133
+ <div class="input-group mb-3">
134
+ <div class="custom-file">
135
+ <input type="file" class="custom-file-input" id="fileInput" name="file" accept=".pdf,.txt">
136
+ <label class="custom-file-label" for="fileInput">Choose file</label>
137
+ </div>
138
+ </div>
139
  </form>
140
  </div>
141
  <div class="modal-footer">
 
146
  </div>
147
  </div>
148
 
149
+ <div class="modal fade" tabindex="-1" id="modalUrl">
150
+ <div class="modal-dialog">
151
+ <div class="modal-content">
152
+ <div class="modal-header">
153
+ <h5 class="modal-title">Enter the Webpage URL</h5>
154
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{button_close_modal}"></button>
155
+ </div>
156
+ <div class="modal-body">
157
+ <div class="alert alert-info" role="alert">
158
+ You can input a URL from a news website.<br>Note that with other types of websites, the functionality may not work as effectively.
159
+ </div>
160
+ <div class="form-group">
161
+ <label for="url">URL:</label>
162
+ <input type="text" class="form-control" id="url" value="">
163
+ </div>
164
+ </div>
165
+ <div class="modal-footer">
166
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{button_close_modal}}</button>
167
+ <button type="button" class="btn btn-primary" id="sendButton3">Send</button>
168
+ </div>
169
+ </div>
170
+ </div>
171
+ </div>
172
+
173
  <header class="hide-section">
174
  <div class="container">
175
  <div class="row">
static/js/app.js CHANGED
@@ -595,13 +595,27 @@ function hideChat() {
595
  }
596
 
597
  // Agrega el evento para el botón "Enviar"
598
- document.getElementById('sendButton').addEventListener('click', function () {
 
 
599
  var textData = {
600
  text: $('#textArea').val(),
601
- pdf: null,
602
- html_url: null
603
  };
604
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
605
  // Realiza una llamada POST al endpoint /store_text
606
  $.ajax({
607
  type: "POST",
@@ -609,41 +623,147 @@ document.getElementById('sendButton').addEventListener('click', function () {
609
  data: JSON.stringify(textData),
610
  contentType: "application/json",
611
  success: function (data) {
 
 
 
 
612
  $('#textArea').val('');
613
  // Cierra el modal después de enviar el texto
614
  textModal.hide();
615
  displayChat(chatId);
616
- }
 
 
 
 
 
 
 
 
 
 
 
 
617
  });
618
  });
619
 
620
  $('#sendButton2').click(function (evt) {
621
- evt.preventDefault();
622
- var formData = new FormData($('#file-form')[0]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
623
 
624
- $.ajax({
625
- url: `/upload_file/${uuid}`,
626
- type: 'POST',
627
- data: formData,
628
- async: false,
629
- cache: false,
630
- contentType: false,
631
- processData: false,
632
- success: function (data) {
633
- $('#fileInput').val('');
634
- // Cierra el modal después de enviar el texto
635
- textModal.hide();
636
- displayChat(chatId);
637
- },
638
- error: function (error) {
639
- console.log(error);
640
- alert('Error al cargar el archivo');
641
- }
642
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
643
  });
644
 
645
 
646
 
 
647
  $(document).delegate(".start-chat", "click", function () {
648
  chatId = $(this).attr("data-index");
649
  if (chatId == 0) {
@@ -656,6 +776,11 @@ $(document).delegate(".start-chat", "click", function () {
656
  keyboard: false
657
  });
658
  textModal.show();
 
 
 
 
 
659
  }
660
  //console.log(chatId);
661
  //displayChat($(this).attr("data-index"));
@@ -1474,4 +1599,12 @@ $(document).ready(function () {
1474
  localStorage.setItem('text-talk-settings', JSON.stringify(settings));
1475
  $('#modalConfig').modal('hide');
1476
  });
 
 
 
 
 
 
 
 
1477
  });
 
595
  }
596
 
597
  // Agrega el evento para el botón "Enviar"
598
+ $('#sendButton').click(function (evt) {
599
+ evt.preventDefault();
600
+
601
  var textData = {
602
  text: $('#textArea').val(),
 
 
603
  };
604
 
605
+ // Configurar la posición de Toastr en la parte superior
606
+ toastr.options.positionClass = 'toast-top-center';
607
+
608
+ // Verificar si la variable de texto está vacía
609
+ if (textData.text.trim() === '') {
610
+ toastr.error("Error: Text cannot be empty.");
611
+ return;
612
+ }
613
+
614
+ // Deshabilitar el botón y agregar un spinner
615
+ var sendButton = $('#sendButton');
616
+ sendButton.prop('disabled', true);
617
+ sendButton.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Sending...');
618
+
619
  // Realiza una llamada POST al endpoint /store_text
620
  $.ajax({
621
  type: "POST",
 
623
  data: JSON.stringify(textData),
624
  contentType: "application/json",
625
  success: function (data) {
626
+ // Habilitar el botón nuevamente
627
+ sendButton.prop('disabled', false);
628
+ sendButton.html('Send');
629
+
630
  $('#textArea').val('');
631
  // Cierra el modal después de enviar el texto
632
  textModal.hide();
633
  displayChat(chatId);
634
+ },
635
+ error: function (xhr, status, error) {
636
+ // Verificar si hay un código de error del backend
637
+ if (xhr.status === 400 || xhr.status === 500) {
638
+ toastr.error(`Error: ${xhr.status} - ${error}`);
639
+ } else {
640
+ toastr.error("Error: Connection refused. Please try again later.");
641
+ }
642
+
643
+ // Habilitar el botón nuevamente
644
+ sendButton.prop('disabled', false);
645
+ sendButton.html('Send');
646
+ }
647
  });
648
  });
649
 
650
  $('#sendButton2').click(function (evt) {
651
+ evt.preventDefault();
652
+ var formData = new FormData($('#file-form')[0]);
653
+ var sendButton = $('#sendButton2');
654
+
655
+ // Configurar la posición de Toastr en la parte superior
656
+ toastr.options.positionClass = 'toast-top-center';
657
+
658
+ var fileInput = $('#fileInput')[0];
659
+ var fileSize = fileInput.files[0].size; // Tamaño en bytes
660
+ var maxSize = 1*1024*1024; // 1MB en bytes
661
+
662
+ // Validar el tamaño del archivo
663
+ if (fileSize > maxSize) {
664
+ toastr.error('Error: File size exceeds 1MB limit.');
665
+ return;
666
+ }
667
+
668
+ // Deshabilitar el botón y agregar un spinner
669
+ sendButton.prop('disabled', true);
670
+ sendButton.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Uploading...');
671
+
672
+ $.ajax({
673
+ url: `/upload_file/${uuid}`,
674
+ type: 'POST',
675
+ data: formData,
676
+ async: false,
677
+ cache: false,
678
+ contentType: false,
679
+ processData: false,
680
+ success: function (data) {
681
+ $('#fileInput').val('');
682
+ // Habilitar el botón nuevamente
683
+ sendButton.prop('disabled', false);
684
+ sendButton.html('Send');
685
+
686
+ // Cierra el modal después de enviar el texto
687
+ textModal.hide();
688
+ displayChat(chatId);
689
+ },
690
+ error: function (xhr, status, error) {
691
+ // Mostrar mensaje de error con Toastr
692
+ toastr.error('Error uploading the file');
693
+
694
+ // Habilitar el botón nuevamente
695
+ sendButton.prop('disabled', false);
696
+ sendButton.html('Send');
697
+ }
698
+ });
699
+ });
700
 
701
+
702
+ $('#sendButton3').click(function () {
703
+ var textData = {
704
+ html_url: $('#url').val(),
705
+ };
706
+
707
+ // Configurar la posición de Toastr en la parte superior
708
+ toastr.options.positionClass = 'toast-top-center';
709
+
710
+ var sendButton = $('#sendButton3');
711
+
712
+ // Verificar si la variable de texto está vacía
713
+ if (textData.html_url.trim() === '') {
714
+ toastr.error("Error: URL cannot be empty.");
715
+ return;
716
+ }
717
+
718
+ // Validar la URL
719
+ var urlRegex = new RegExp('^(https?:\\/\\/)?'+
720
+ '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+
721
+ '((\\d{1,3}\\.){3}\\d{1,3}))'+
722
+ '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+
723
+ '(\\?[;&a-z\\d%_.~+=-]*)?'+
724
+ '(\\#[-a-z\\d_]*)?$','i');
725
+ if (!urlRegex.test(textData.html_url)) {
726
+ toastr.error("Error: Invalid URL.");
727
+ return;
728
+ }
729
+
730
+ // Deshabilitar el botón y agregar un spinner
731
+ sendButton.prop('disabled', true);
732
+ sendButton.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Sending...');
733
+
734
+ // Realiza una llamada POST al endpoint /store_text
735
+ $.ajax({
736
+ type: "POST",
737
+ url: `/store_text/${uuid}`,
738
+ data: JSON.stringify(textData),
739
+ contentType: "application/json",
740
+ success: function (data) {
741
+ $('#url').val('');
742
+ // Habilitar el botón nuevamente
743
+ sendButton.prop('disabled', false);
744
+ sendButton.html('Send');
745
+
746
+ // Cierra el modal después de enviar el texto
747
+ textModal.hide();
748
+ displayChat(chatId);
749
+ },
750
+ error: function (xhr, status, error) {
751
+ if (xhr.status === 0) {
752
+ toastr.error('Error: Connection refused. Please try again later.');
753
+ } else if (xhr.status === 400 || xhr.status === 500) {
754
+ toastr.error(`Error: ${xhr.status} - ${error}`);
755
+ }
756
+
757
+ // Habilitar el botón nuevamente
758
+ sendButton.prop('disabled', false);
759
+ sendButton.html('Send');
760
+ }
761
+ });
762
  });
763
 
764
 
765
 
766
+
767
  $(document).delegate(".start-chat", "click", function () {
768
  chatId = $(this).attr("data-index");
769
  if (chatId == 0) {
 
776
  keyboard: false
777
  });
778
  textModal.show();
779
+ } else if (chatId == 2) {
780
+ textModal = new bootstrap.Modal(document.getElementById('modalUrl'), {
781
+ keyboard: false
782
+ });
783
+ textModal.show();
784
  }
785
  //console.log(chatId);
786
  //displayChat($(this).attr("data-index"));
 
1599
  localStorage.setItem('text-talk-settings', JSON.stringify(settings));
1600
  $('#modalConfig').modal('hide');
1601
  });
1602
+
1603
+ // Maneja el conteo de caracteres
1604
+ $('#textArea').on('input', function () {
1605
+ var maxLength = 4000;
1606
+ var currentLength = $(this).val().length;
1607
+ var remaining = maxLength - currentLength;
1608
+ $('#charCount').text(remaining);
1609
+ });
1610
  });
static/json/prompts-en.json CHANGED
@@ -17,7 +17,7 @@
17
  "widget_name": "{{widget_name_2}}",
18
  "image": "img/icon-file.svg",
19
  "welcome_message": "Welcome! Feel free to ask any questions about the selected text. I'm here to provide you with insightful answers.",
20
- "description": "<h6>Tips:</h6> Haz las preguntas que quieras acerca del texto",
21
  "display_welcome_message": true,
22
  "chat_minlength": 2,
23
  "chat_maxlength": 1000,
@@ -29,7 +29,7 @@
29
  "widget_name": "{{widget_name_3}}",
30
  "image": "img/icon-webpage.svg",
31
  "welcome_message": "Welcome! Feel free to ask any questions about the selected text. I'm here to provide you with insightful answers.",
32
- "description": "<h6>Tips:</h6> Haz las preguntas que quieras acerca del texto",
33
  "display_welcome_message": true,
34
  "chat_minlength": 3,
35
  "chat_maxlength": 1000,
 
17
  "widget_name": "{{widget_name_2}}",
18
  "image": "img/icon-file.svg",
19
  "welcome_message": "Welcome! Feel free to ask any questions about the selected text. I'm here to provide you with insightful answers.",
20
+ "description": "Our mission is to simplify text processing and enhance information retrieval using cutting-edge LLM models. Explore our project on <a href=\"https://github.com/roaltopo/scan-u-doc\">GitHub</a>.",
21
  "display_welcome_message": true,
22
  "chat_minlength": 2,
23
  "chat_maxlength": 1000,
 
29
  "widget_name": "{{widget_name_3}}",
30
  "image": "img/icon-webpage.svg",
31
  "welcome_message": "Welcome! Feel free to ask any questions about the selected text. I'm here to provide you with insightful answers.",
32
+ "description": "Our mission is to simplify text processing and enhance information retrieval using cutting-edge LLM models. Explore our project on <a href=\"https://github.com/roaltopo/scan-u-doc\">GitHub</a>.",
33
  "display_welcome_message": true,
34
  "chat_minlength": 3,
35
  "chat_maxlength": 1000,