286 lines
12 KiB
Python
286 lines
12 KiB
Python
import gradio as gr
|
|
from config.settings import DEFAULT_MODEL, QDRANT_COLLECTION_NAME, AVAILABLE_MODELS
|
|
from translations.lang_mappings import UI_TRANSLATIONS, UI_SUPPORTED_LANGUAGES, LANGUAGE_MAPPING
|
|
from utils.katex_script import KATEX_CSS_JS
|
|
|
|
def update_ui_language_elements(language):
|
|
"""Met à jour tous les éléments de l'interface avec la langue sélectionnée"""
|
|
|
|
# Vérifier si la langue est supportée par l'interface
|
|
if language not in UI_SUPPORTED_LANGUAGES:
|
|
language = "Français" # Langue par défaut
|
|
|
|
# Récupérer les traductions pour la langue sélectionnée
|
|
translations = UI_TRANSLATIONS[language]
|
|
|
|
# Créer un dictionnaire pour stocker tous les éléments modifiés
|
|
ui_elements = {}
|
|
|
|
# Mettre à jour le titre
|
|
ui_elements["title"] = translations["title"]
|
|
|
|
# Mettre à jour le placeholder et les boutons
|
|
ui_elements["placeholder"] = translations["placeholder"]
|
|
ui_elements["send_btn"] = translations["send_btn"]
|
|
ui_elements["clear_btn"] = translations["clear_btn"]
|
|
|
|
# Ajouter les traductions pour la langue de l'interface
|
|
ui_elements["ui_language_label"] = translations["ui_language_label"]
|
|
ui_elements["ui_language_info"] = translations["ui_language_info"]
|
|
|
|
# Mettre à jour les libellés des options
|
|
ui_elements["options_label"] = "Options" # Ce texte pourrait aussi être traduit
|
|
ui_elements["model_label"] = translations["model_selector"]
|
|
ui_elements["model_info"] = translations["model_info"]
|
|
ui_elements["model_current_prefix"] = translations["model_current"]
|
|
|
|
ui_elements["language_label"] = translations["language_selector"]
|
|
ui_elements["language_info"] = translations["language_info"]
|
|
|
|
ui_elements["collection_label"] = translations["collection_input"]
|
|
ui_elements["collection_info"] = translations["collection_info"]
|
|
ui_elements["collection_current_prefix"] = translations["collection_current"]
|
|
ui_elements["apply_btn"] = translations["apply_btn"]
|
|
|
|
ui_elements["streaming_label"] = translations["streaming_label"]
|
|
ui_elements["streaming_info"] = translations["streaming_info"]
|
|
ui_elements["sources_label"] = translations["sources_label"]
|
|
ui_elements["max_images_label"] = translations["max_images_label"]
|
|
|
|
ui_elements["images_title"] = translations["images_title"]
|
|
ui_elements["tables_title"] = translations["tables_title"]
|
|
|
|
return ui_elements
|
|
|
|
|
|
|
|
def build_interface(
|
|
process_query_fn,
|
|
reset_conversation_fn,
|
|
change_model_fn,
|
|
change_collection_fn,
|
|
update_ui_language_fn
|
|
):
|
|
"""Construit l'interface utilisateur avec Gradio"""
|
|
print("Initialisation de l'interface")
|
|
print("AVAILABLE_MODELS chargé dans ui.py:", AVAILABLE_MODELS)
|
|
# Initialiser avec la langue par défaut (Français)
|
|
ui_elements = update_ui_language_elements("Français")
|
|
|
|
with gr.Blocks(css=KATEX_CSS_JS, theme=gr.themes.Soft(primary_hue="blue")) as interface:
|
|
title_md = gr.Markdown(f"# {ui_elements['title']}")
|
|
|
|
with gr.Row():
|
|
with gr.Column(scale=2):
|
|
chat_interface = gr.Chatbot(
|
|
height=800,
|
|
bubble_full_width=False,
|
|
show_copy_button=True,
|
|
type="messages"
|
|
# likeable=False,
|
|
)
|
|
|
|
with gr.Row():
|
|
msg = gr.Textbox(
|
|
show_label=False,
|
|
placeholder=ui_elements['placeholder'],
|
|
container=False,
|
|
scale=4
|
|
)
|
|
submit_btn = gr.Button(ui_elements['send_btn'], variant="primary", scale=1)
|
|
|
|
clear_btn = gr.Button(ui_elements['clear_btn'])
|
|
source_info = gr.Markdown("", elem_id="sources_info")
|
|
|
|
with gr.Column(scale=1):
|
|
with gr.Accordion("Options", open=True):
|
|
# Sélecteur de langue pour l'interface
|
|
language_ui_selector = gr.Dropdown(
|
|
choices=UI_SUPPORTED_LANGUAGES,
|
|
value="Français",
|
|
label=ui_elements['ui_language_label'], # Utiliser une clé différente
|
|
info=ui_elements['ui_language_info']
|
|
)
|
|
# Sélecteur de modèle - assurez-vous que cette section est présente
|
|
model_selector = gr.Dropdown(
|
|
choices=AVAILABLE_MODELS,
|
|
value=DEFAULT_MODEL,
|
|
label=ui_elements['model_label'],
|
|
info=ui_elements['model_info']
|
|
)
|
|
model_status = gr.Markdown(f"{ui_elements['model_current_prefix']}: **{DEFAULT_MODEL}**")
|
|
|
|
# Sélecteur de langue pour les réponses
|
|
language_selector = gr.Dropdown(
|
|
choices=list(LANGUAGE_MAPPING.keys()),
|
|
value="Français",
|
|
label=ui_elements['language_label'],
|
|
info=ui_elements['language_info']
|
|
)
|
|
|
|
# Sélecteur de collection Qdrant
|
|
collection_name_input = gr.Textbox(
|
|
value=QDRANT_COLLECTION_NAME,
|
|
label=ui_elements['collection_label'],
|
|
info=ui_elements['collection_info']
|
|
)
|
|
collection_status = gr.Markdown(f"{ui_elements['collection_current_prefix']}: **{QDRANT_COLLECTION_NAME}**")
|
|
|
|
# Bouton pour appliquer la collection
|
|
apply_collection_btn = gr.Button(ui_elements['apply_btn'])
|
|
|
|
# Options de streaming et sources
|
|
streaming = gr.Checkbox(
|
|
label=ui_elements['streaming_label'],
|
|
value=True,
|
|
info=ui_elements['streaming_info']
|
|
)
|
|
show_sources = gr.Checkbox(label=ui_elements['sources_label'], value=True)
|
|
max_images = gr.Slider(
|
|
minimum=1,
|
|
maximum=10,
|
|
value=3,
|
|
step=1,
|
|
label=ui_elements['max_images_label']
|
|
)
|
|
|
|
# Ne pas supprimer ces lignes dans ui.py
|
|
images_title = gr.Markdown(f"### {ui_elements['images_title']}")
|
|
image_gallery = gr.Gallery(label="Images")
|
|
tables_title = gr.Markdown(f"### {ui_elements['tables_title']}")
|
|
tables_display = gr.HTML()
|
|
|
|
# Ajouter cette fonction juste avant de connecter le changement de langue
|
|
def preserve_models_wrapper(language):
|
|
"""Préserve la liste des modèles lors du changement de langue"""
|
|
# Obtenir les mises à jour depuis la fonction d'origine
|
|
updates = update_ui_language_fn(language)
|
|
|
|
# Force la liste complète des modèles disponibles (position 5 dans les sorties)
|
|
# Cela garantit que quelles que soient les mises à jour, la liste des modèles reste intacte
|
|
if isinstance(updates[5], dict) and "choices" in updates[5]:
|
|
print("Préservation de la liste des modèles:", AVAILABLE_MODELS)
|
|
updates[5]["choices"] = AVAILABLE_MODELS
|
|
|
|
return updates
|
|
|
|
# Puis modifier la connexion du language_ui_selector.change comme suit :
|
|
language_ui_selector.change(
|
|
fn=preserve_models_wrapper, # Utiliser notre wrapper au lieu de la fonction directe
|
|
inputs=language_ui_selector,
|
|
outputs=[
|
|
title_md,
|
|
msg,
|
|
submit_btn,
|
|
clear_btn,
|
|
language_ui_selector,
|
|
model_selector,
|
|
model_status,
|
|
language_selector,
|
|
collection_name_input,
|
|
collection_status,
|
|
apply_collection_btn,
|
|
streaming,
|
|
show_sources,
|
|
max_images
|
|
]
|
|
)
|
|
|
|
# Fonction pour effacer l'entrée
|
|
def clear_input():
|
|
return ""
|
|
|
|
# Configuration des actions principales
|
|
msg.submit(
|
|
process_query_fn,
|
|
inputs=[msg, chat_interface, streaming, show_sources, max_images, language_selector],
|
|
outputs=[chat_interface, source_info, image_gallery, tables_display]
|
|
).then(clear_input, None, msg)
|
|
|
|
submit_btn.click(
|
|
process_query_fn,
|
|
inputs=[msg, chat_interface, streaming, show_sources, max_images, language_selector],
|
|
outputs=[chat_interface, source_info, image_gallery, tables_display]
|
|
).then(clear_input, None, msg)
|
|
|
|
clear_btn.click(
|
|
reset_conversation_fn,
|
|
outputs=[chat_interface, source_info] # Retirer image_gallery et tables_display
|
|
)
|
|
|
|
# Connecter le changement de modèle
|
|
model_selector.change(
|
|
fn=change_model_fn,
|
|
inputs=model_selector,
|
|
outputs=model_status
|
|
)
|
|
|
|
# Connecter le changement de collection
|
|
apply_collection_btn.click(
|
|
fn=change_collection_fn,
|
|
inputs=collection_name_input,
|
|
outputs=collection_status
|
|
)
|
|
|
|
# Style KaTeX et amélioration du design
|
|
gr.Markdown("""
|
|
<style>
|
|
.gradio-container {max-width: 1200px !important}
|
|
#chatbot {height: 800px; 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>
|
|
// Script pour rendre les équations mathématiques avec KaTeX
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
setTimeout(function() {
|
|
if (window.renderMathInElement) {
|
|
renderMathInElement(document.body, {
|
|
delimiters: [
|
|
{left: '$$', right: '$$', display: true},
|
|
{left: '$', right: '$', display: false}
|
|
],
|
|
throwOnError: false
|
|
});
|
|
}
|
|
}, 1000);
|
|
});
|
|
</script>
|
|
""")
|
|
|
|
return interface |