Add utility modules and configuration settings for chatbot application
This commit is contained in:
1
utils/__init__.py
Normal file
1
utils/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Package initialization for display utilities
|
||||
15
utils/conversion.py
Normal file
15
utils/conversion.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import base64
|
||||
from io import BytesIO
|
||||
from PIL import Image
|
||||
|
||||
def base64_to_image(base64_data):
|
||||
"""Convertit une image base64 en objet Image pour l'affichage direct"""
|
||||
try:
|
||||
if not base64_data:
|
||||
return None
|
||||
image_bytes = base64.b64decode(base64_data)
|
||||
image = Image.open(BytesIO(image_bytes))
|
||||
return image
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de la conversion d'image: {e}")
|
||||
return None
|
||||
40
utils/display.py
Normal file
40
utils/display.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
import base64
|
||||
|
||||
def base64_to_image(base64_data):
|
||||
"""Convert base64 image data to PIL Image"""
|
||||
try:
|
||||
if not base64_data:
|
||||
return None
|
||||
image_bytes = base64.b64decode(base64_data)
|
||||
return Image.open(BytesIO(image_bytes))
|
||||
except Exception as e:
|
||||
print(f"Image conversion error: {e}")
|
||||
return None
|
||||
|
||||
def display_images(current_images):
|
||||
"""Format images for Gradio gallery display"""
|
||||
if not current_images:
|
||||
return None
|
||||
return [
|
||||
(img["image"], f"{img['caption']} (Source: {img['source']}, Page: {img['page']})")
|
||||
for img in current_images
|
||||
if img.get("image")
|
||||
]
|
||||
|
||||
def display_tables(current_tables):
|
||||
"""Format tables for HTML display"""
|
||||
if not current_tables:
|
||||
return None
|
||||
|
||||
html = ""
|
||||
for table in current_tables:
|
||||
html += f"""
|
||||
<div style="margin-bottom: 20px; border: 1px solid #ddd; padding: 15px; border-radius: 8px;">
|
||||
<h3>{table['caption']}</h3>
|
||||
<p style="color:#666; font-size:0.9em;">Source: {table['source']}, Page: {table['page']}</p>
|
||||
<div class="table-container">{table.get('data', '')}</div>
|
||||
</div>
|
||||
"""
|
||||
return html if html else None
|
||||
29
utils/image_utils.py
Normal file
29
utils/image_utils.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from io import BytesIO
|
||||
from PIL import Image
|
||||
import base64
|
||||
|
||||
def base64_to_image(base64_data):
|
||||
"""Convertit une image base64 en objet Image pour l'affichage direct"""
|
||||
try:
|
||||
if not base64_data:
|
||||
return None
|
||||
image_bytes = base64.b64decode(base64_data)
|
||||
image = Image.open(BytesIO(image_bytes))
|
||||
return image
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de la conversion d'image: {e}")
|
||||
return None
|
||||
|
||||
def display_images(current_images):
|
||||
"""Prépare les images pour l'affichage dans la galerie Gradio"""
|
||||
if not current_images:
|
||||
return None
|
||||
|
||||
gallery = []
|
||||
for img_data in current_images:
|
||||
image = img_data["image"]
|
||||
if image:
|
||||
caption = f"{img_data['caption']} (Source: {img_data['source']}, Page: {img_data['page']})"
|
||||
gallery.append((image, caption))
|
||||
|
||||
return gallery if gallery else None
|
||||
190
utils/katex_script.py
Normal file
190
utils/katex_script.py
Normal file
@@ -0,0 +1,190 @@
|
||||
KATEX_CSS_JS = """
|
||||
<style>
|
||||
.gradio-container {max-width: 1200px !important}
|
||||
#chatbot {height: 600px; overflow-y: auto;}
|
||||
#sources_info {margin-top: 10px; color: #666;}
|
||||
|
||||
/* Improved styles for equations */
|
||||
.katex { font-size: 1.1em !important; }
|
||||
.math-inline { background: #f8f9fa; padding: 2px 5px; border-radius: 4px; }
|
||||
.math-display { background: #f8f9f9; margin: 10px 0; padding: 10px; border-radius: 5px; overflow-x: auto; text-align: center; }
|
||||
|
||||
/* Table styles */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 15px 0;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
table, th, td {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
th, td {
|
||||
padding: 8px 12px;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
.table-container {
|
||||
overflow-x: auto;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Loading KaTeX -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js"></script>
|
||||
|
||||
<script>
|
||||
// Function to process math equations with KaTeX
|
||||
function renderMathInElement(element) {
|
||||
if (!window.renderMathInElement) return;
|
||||
|
||||
try {
|
||||
window.renderMathInElement(element, {
|
||||
delimiters: [
|
||||
{left: '$$', right: '$$', display: true},
|
||||
{left: '$', right: '$', display: false},
|
||||
{left: '\\\\(', right: '\\\\)', display: false},
|
||||
{left: '\\\\[', right: '\\\\]', display: true}
|
||||
],
|
||||
throwOnError: false,
|
||||
trust: true,
|
||||
strict: false,
|
||||
macros: {
|
||||
"\\\\R": "\\\\mathbb{R}",
|
||||
"\\\\N": "\\\\mathbb{N}"
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("KaTeX rendering error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to fix and prepare text for LaTeX rendering
|
||||
function prepareTextForLatex(text) {
|
||||
if (!text) return text;
|
||||
|
||||
// Don't modify code blocks
|
||||
if (text.indexOf('<pre>') !== -1) {
|
||||
const parts = text.split(/<pre>|<\/pre>/);
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
// Only process odd-indexed parts (non-code)
|
||||
if (i % 2 === 0) {
|
||||
parts[i] = prepareLatexInText(parts[i]);
|
||||
}
|
||||
}
|
||||
return parts.join('');
|
||||
}
|
||||
|
||||
return prepareLatexInText(text);
|
||||
}
|
||||
|
||||
// Helper to process LaTeX in regular text
|
||||
function prepareLatexInText(text) {
|
||||
// Make sure dollar signs used for math have proper spacing
|
||||
// First, protect existing well-formed math expressions
|
||||
text = text.replace(/(\\$\\$[^\\$]+\\$\\$)/g, '<protect>$1</protect>'); // protect display math
|
||||
text = text.replace(/(\\$[^\\$\\n]+\\$)/g, '<protect>$1</protect>'); // protect inline math
|
||||
|
||||
// Fix common LaTeX formatting issues outside protected regions
|
||||
text = text.replace(/([^<]protect[^>]*)(\\$)([^\\s])/g, '$1$2 $3'); // Add space after $ if needed
|
||||
text = text.replace(/([^\\s])(\\$)([^<]protect[^>]*)/g, '$1 $2$3'); // Add space before $ if needed
|
||||
|
||||
// Handle subscripts: transform x_1 into x_{1} for better LaTeX compatibility
|
||||
text = text.replace(/([a-zA-Z])_([0-9a-zA-Z])/g, '$1_{$2}');
|
||||
|
||||
// Restore protected content
|
||||
text = text.replace(/<protect>(.*?)<\/protect>/g, '$1');
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
// Enhanced message processor for KaTeX rendering
|
||||
function processMessage(message) {
|
||||
if (!message) return;
|
||||
|
||||
try {
|
||||
// Get direct textual content when possible
|
||||
const elements = message.querySelectorAll('p, li, h1, h2, h3, h4, h5, span');
|
||||
elements.forEach(el => {
|
||||
const originalText = el.innerHTML;
|
||||
const preparedText = prepareTextForLatex(originalText);
|
||||
|
||||
// Only update if changes were made
|
||||
if (preparedText !== originalText) {
|
||||
el.innerHTML = preparedText;
|
||||
}
|
||||
|
||||
// Render equations in this element
|
||||
renderMathInElement(el);
|
||||
});
|
||||
|
||||
// Also try to render on the entire message as fallback
|
||||
renderMathInElement(message);
|
||||
} catch (e) {
|
||||
console.error("Error processing message for LaTeX:", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to monitor for new messages
|
||||
function setupMathObserver() {
|
||||
const chatElement = document.getElementById('chatbot');
|
||||
if (!chatElement) {
|
||||
setTimeout(setupMathObserver, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
// Process any existing messages
|
||||
chatElement.querySelectorAll('.message').forEach(processMessage);
|
||||
|
||||
// Set up observer for new content
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.addedNodes.length > 0 || mutation.type === 'characterData') {
|
||||
chatElement.querySelectorAll('.message').forEach(processMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(chatElement, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
characterData: true
|
||||
});
|
||||
|
||||
console.log("LaTeX rendering observer set up successfully");
|
||||
}
|
||||
|
||||
// Initialize once the document is fully loaded
|
||||
function initializeRendering() {
|
||||
if (window.renderMathInElement) {
|
||||
setupMathObserver();
|
||||
} else {
|
||||
// If KaTeX isn't loaded yet, wait for it
|
||||
const katexScript = document.querySelector('script[src*="auto-render.min.js"]');
|
||||
if (katexScript) {
|
||||
katexScript.onload = setupMathObserver;
|
||||
} else {
|
||||
// Last resort: try again later
|
||||
setTimeout(initializeRendering, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set up multiple trigger points to ensure it loads
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
setTimeout(initializeRendering, 800);
|
||||
});
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
setTimeout(initializeRendering, 1200);
|
||||
});
|
||||
</script>
|
||||
"""
|
||||
19
utils/table_utils.py
Normal file
19
utils/table_utils.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from translations.lang_mappings import UI_TRANSLATIONS
|
||||
|
||||
def display_tables(current_tables, language=None):
|
||||
"""Version simplifiée qui ignore le paramètre language"""
|
||||
if not current_tables:
|
||||
return None
|
||||
|
||||
html = ""
|
||||
for table in current_tables:
|
||||
table_data = table.get('data', '')
|
||||
html += f"""
|
||||
<div style="margin-bottom: 20px; border: 1px solid #ddd; padding: 15px; border-radius: 8px;">
|
||||
<h3>{table.get('caption', 'Tableau')}</h3>
|
||||
<p style="color:#666; font-size:0.9em;">Source: {table.get('source', 'N/A')}, Page: {table.get('page', 'N/A')}</p>
|
||||
<pre>{table_data}</pre>
|
||||
</div>
|
||||
"""
|
||||
|
||||
return html if html else None
|
||||
Reference in New Issue
Block a user