diff --git a/services/embeddings_basic.py b/services/embeddings_basic.py index 5815df5..7fb2f71 100644 --- a/services/embeddings_basic.py +++ b/services/embeddings_basic.py @@ -162,6 +162,14 @@ def buscar_en_weaviate(pregunta, k=5): historial_conversacion = [] + +### +### - For a single page: (Source: "{{filename}}", Page: "{{page_number}}") +### - For a range of consecutive pages: (multi-source: "{{filename}}", Page: "{{start_page}}-{{end_page}}") +### - For non-consecutive pages, separate each source reference as follows: + +### + def generar_respuesta_llm(pregunta, contextos): try: current_app.logger.info("Iniciando la generación de respuesta para la pregunta.") @@ -192,17 +200,22 @@ def generar_respuesta_llm(pregunta, contextos): Always follow this format. PLEASE DO NOT DISOBEY THIS FORMAT. If the answer involves information from specific documents, include the document name and page number(s) in the following format: - - For a single page: (Source: "{{filename}}", Page: "{{page_number}}") - - For a range of consecutive pages: (Source: "{{filename}}", Page: "{{start_page}}-{{end_page}}") - - For non-consecutive pages, separate each source reference as follows: - (Source: "{{filename}}", Page: "{{page_number_1}}") - (Source: "{{filename}}", Page: "{{page_number_2}}") + + [ + {{ source: filename_1, + page: page_number_1 + }}, + {{ source: filename_2, + page: page_number_2 + }} + ] + PLEASE DO NOT DISOBEY THIS FORMAT. If there are multiple pieces of context from different sources, include each source as a separate reference in the answer. - If the context or the chat history does not provide an answer, state "No tinc suficient informació per respondre aquesta pregunta." + If the context or the chat history does not provide an answer, state "Lamentablement, no he pogut trobar una resposta a la teva pregunta a partir de la informació disponible als documents. Si pots proporcionar més detalls o reformular la pregunta, estaré encantat d’ajudar-te!" Chat History: {historial_texto} @@ -223,7 +236,8 @@ def generar_respuesta_llm(pregunta, contextos): messages=[ {"role": "system", "content": "Eres un asistente inteligente."}, {"role": "user", "content": prompt}, - ] + ], + temperature= 0.2, ) current_app.logger.info("Respuesta generada exitosamente.") diff --git a/static/scripts.js b/static/scripts.js index fcf5ae9..d33fa2b 100644 --- a/static/scripts.js +++ b/static/scripts.js @@ -161,57 +161,115 @@ function askQuestion() { }, body: JSON.stringify({ question: question }) }) - .then(response => response.json()) - .then(data => { - clearInterval(loadingInterval); - if (chatBox.contains(loadingDiv)) { - chatBox.removeChild(loadingDiv); - } - if (data.error) { - console.error('Error:', data.error); - } else { - console.log('Respuesta del servidor:', data.answer); + .then(response => response.json()) + .then(data => { + clearInterval(loadingInterval); - if (!data.answer || data.answer.trim() === '') { - console.error('La respuesta está vacía.'); - return; - } + if (chatBox.contains(loadingDiv)) { + chatBox.removeChild(loadingDiv); + } - const answerDiv = document.createElement('div'); - answerDiv.className = 'message answer'; + if (data.error) { + console.error('Error:', data.error); + } else { + console.log('Respuesta del servidor:', data.answer); - // Formatear y mostrar la respuesta con hipervínculos - const formattedAnswer = formatAnswerWithLink(data.answer); - console.log(formattedAnswer); - answerDiv.innerHTML = formattedAnswer; - chatBox.appendChild(answerDiv); - scrollToBottom(); - } - }) - .catch(error => { - clearInterval(loadingInterval); - if (chatBox.contains(loadingDiv)) { - chatBox.removeChild(loadingDiv); + if (!data.answer || data.answer.trim() === '') { + console.error('La respuesta está vacía.'); + return; } - console.error('Error:', error); - }); + + const answerDiv = document.createElement('div'); + answerDiv.className = 'message answer'; + + const formattedAnswer = formatAnswerWithLink(answerDiv, data.answer); + //answerDiv.innerHTML = formattedAnswer; + chatBox.appendChild(answerDiv); + scrollToBottom(); + } + }) + .catch(error => { + clearInterval(loadingInterval); + if (chatBox.contains(loadingDiv)) { + chatBox.removeChild(loadingDiv); + } + console.error('Error:', error); + }); document.getElementById('questionInput').value = ''; scrollToBottom(); } -function formatAnswerWithLink(inputText) { - const regex = /\(Source:\s*"([^"]+\.pdf)",\s*Page:\s*(\d+(-\d+)?)(\))/g; +function formatAnswerWithLink(answerDiv, inputText) { + const regex = /^(.*?)(.*?)<\/JAVASCRIPT>(.*?)$/s; - const formattedText = inputText.replace(regex, (match, pdfName, pageRange) => { - const pageLink = pageRange.includes("-") - ? pageRange.split("-")[0] - : pageRange; + const match = inputText.match(regex); + let before = ''; + let inside = ''; + let after = ''; - return `(${pdfName}, página: ${pageRange})`; - }); + if (match) { + before = match[1].trim(); // Contenido antes de + inside = match[2].trim(); // Contenido entre y + after = match[3].trim(); // Contenido después de + + console.log("Antes:", before); + console.log("Dentro:", inside); + console.log("Después:", after); + } else { + console.warn("No se encontró la estructura esperada. Mostrando respuesta completa."); + const fallbackPElement = document.createElement("p"); + + // Eliminar comillas del inicio y el final si están presentes + const sanitizedText = inputText.replace(/^"(.*)"$/, '$1'); + fallbackPElement.textContent = sanitizedText; + + answerDiv.appendChild(fallbackPElement); + return answerDiv; + } + + // Agregar texto antes + if (before) { + const beforePElement = document.createElement("p"); + beforePElement.textContent = before; + answerDiv.appendChild(beforePElement); + } + + // Parsear la sección + let sources; + try { + sources = JSON.parse(inside); // Manejar el JSON de manera segura + console.log("Fuentes parseadas:", sources); + } catch (error) { + console.error("Error al parsear la sección :", error); + return answerDiv; + } + + // Agregar los enlaces de las fuentes + if (sources && sources.length > 0) { + sources.forEach((source) => { + const linkElement = document.createElement("a"); + linkElement.textContent = `${source.source} - Página: ${source.page}`; + linkElement.href = `/download/${encodeURIComponent(source.source)}#page=${source.page}`; + linkElement.target = "_blank"; + linkElement.style.color = "blue"; + answerDiv.appendChild(linkElement); + + const lineBreak = document.createElement("br"); + answerDiv.appendChild(lineBreak); + }); + } else { + console.warn("No se encontraron fuentes en la sección ."); + } + + // Agregar texto después + if (after) { + const afterPElement = document.createElement("p"); + afterPElement.textContent = after; + answerDiv.appendChild(afterPElement); + } - return formattedText; + return answerDiv; } function scrollToBottom() { diff --git a/static/scripts_user.js b/static/scripts_user.js index 58ada47..6196aa4 100644 --- a/static/scripts_user.js +++ b/static/scripts_user.js @@ -59,8 +59,8 @@ function askQuestion() { const answerDiv = document.createElement('div'); answerDiv.className = 'message answer'; - const formattedAnswer = formatAnswerWithLink(data.answer); - answerDiv.innerHTML = formattedAnswer; + const formattedAnswer = formatAnswerWithLink(answerDiv, data.answer); + //answerDiv.innerHTML = formattedAnswer; chatBox.appendChild(answerDiv); scrollToBottom(); } @@ -77,19 +77,79 @@ function askQuestion() { scrollToBottom(); } -function formatAnswerWithLink(inputText) { - const regex = /\(Source:\s*"([^"]+\.pdf)",\s*Page:\s*(\d+(-\d+)?)(\))/g; - - const formattedText = inputText.replace(regex, (match, pdfName, pageRange) => { - const pageLink = pageRange.includes("-") - ? pageRange.split("-")[0] - : pageRange; +function formatAnswerWithLink(answerDiv, inputText) { + const regex = /^(.*?)(.*?)<\/JAVASCRIPT>(.*?)$/s; + + const match = inputText.match(regex); + let before = ''; + let inside = ''; + let after = ''; + + if (match) { + before = match[1].trim(); // Contenido antes de + inside = match[2].trim(); // Contenido entre y + after = match[3].trim(); // Contenido después de + + console.log("Antes:", before); + console.log("Dentro:", inside); + console.log("Después:", after); + } else { + console.warn("No se encontró la estructura esperada. Mostrando respuesta completa."); + const fallbackPElement = document.createElement("p"); + + // Eliminar comillas del inicio y el final si están presentes + const sanitizedText = inputText.replace(/^"(.*)"$/, '$1'); + fallbackPElement.textContent = sanitizedText; + + answerDiv.appendChild(fallbackPElement); + return answerDiv; + } + + // Agregar texto antes + if (before) { + const beforePElement = document.createElement("p"); + beforePElement.textContent = before; + answerDiv.appendChild(beforePElement); + } + + // Parsear la sección + let sources; + try { + sources = JSON.parse(inside); // Manejar el JSON de manera segura + console.log("Fuentes parseadas:", sources); + } catch (error) { + console.error("Error al parsear la sección :", error); + return answerDiv; + } + + // Agregar los enlaces de las fuentes + if (sources && sources.length > 0) { + sources.forEach((source) => { + const linkElement = document.createElement("a"); + linkElement.textContent = `${source.source} - Página: ${source.page}`; + linkElement.href = `/download/${encodeURIComponent(source.source)}#page=${source.page}`; + linkElement.target = "_blank"; + linkElement.style.color = "blue"; + answerDiv.appendChild(linkElement); + + const lineBreak = document.createElement("br"); + answerDiv.appendChild(lineBreak); + }); + } else { + console.warn("No se encontraron fuentes en la sección ."); + } + + // Agregar texto después + if (after) { + const afterPElement = document.createElement("p"); + afterPElement.textContent = after; + answerDiv.appendChild(afterPElement); + } + + return answerDiv; +} - return `(${pdfName}, página: ${pageRange})`; - }); - return formattedText; -} function scrollToBottom() { const chatBox = document.getElementById('chatBox');