Update app.py
Browse files
app.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
import os
|
| 2 |
import dash
|
| 3 |
import json
|
|
@@ -25,11 +26,13 @@ from langgraph.checkpoint.memory import MemorySaver
|
|
| 25 |
from langchain_openai import ChatOpenAI
|
| 26 |
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage
|
| 27 |
|
|
|
|
| 28 |
import dash
|
| 29 |
from dash.dependencies import Input, Output, State
|
| 30 |
from dash import Dash, html, dcc, callback, callback_context, ctx, Output, Input, dash_table, State, no_update, _dash_renderer, clientside_callback
|
| 31 |
from dash import html
|
| 32 |
|
|
|
|
| 33 |
import dash_bootstrap_components as dbc
|
| 34 |
from dash.exceptions import PreventUpdate
|
| 35 |
import dash_mantine_components as dmc
|
|
@@ -37,6 +40,7 @@ from dash_iconify import DashIconify
|
|
| 37 |
_dash_renderer._set_react_version("18.2.0")
|
| 38 |
import flask
|
| 39 |
from flask_login import LoginManager, UserMixin, login_user, current_user, login_required, logout_user
|
|
|
|
| 40 |
from datetime import timedelta
|
| 41 |
|
| 42 |
from IPython.display import display, HTML
|
|
@@ -621,48 +625,37 @@ def init_agent_state(current_url, num, pathname) -> AgentState:
|
|
| 621 |
if task == "load_and_preprocess":
|
| 622 |
if key == "current_file":
|
| 623 |
result += f"Traitement du fichier {taskInfo['current_file']} en cours...\n"
|
| 624 |
-
|
| 625 |
if task == "classify_teachings":
|
| 626 |
if key == "status":
|
| 627 |
for key, value in taskInfo['classified_teachings'].items():
|
| 628 |
result += f"\n\n-**Enseignement classé dans la catégorie '{key}'** : "
|
| 629 |
for enseignement in value:
|
| 630 |
result += f"{enseignement}, "
|
| 631 |
-
|
| 632 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
| 633 |
-
|
| 634 |
if task == "create_categories":
|
| 635 |
if key == "status":
|
| 636 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
| 637 |
-
|
| 638 |
if task == "create_learning_situations":
|
| 639 |
if key == "status":
|
| 640 |
if taskInfo['learning_situations'].items():
|
| 641 |
for key, value in taskInfo['learning_situations'].items():
|
| 642 |
result += f"\n\n-**Situation d'apprentissage créée pour la catégorie '{key}'** : {value}\n"
|
| 643 |
-
|
| 644 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
| 645 |
-
|
| 646 |
else:
|
| 647 |
result += f"\n\nTraitement de la tâche : pas de situations d'apprentissage créées\n"
|
| 648 |
-
|
| 649 |
if task == "create_academic_competencies":
|
| 650 |
if key == "dataframe":
|
| 651 |
df = taskInfo['dataframe']
|
| 652 |
if key == "status":
|
| 653 |
if taskInfo['academic_competencies'].items():
|
| 654 |
for key, value in taskInfo['academic_competencies'].items():
|
| 655 |
-
result += f"\n\n-**Compétence académique créée pour la catégorie '{key}'** : {value}\n"
|
| 656 |
-
|
| 657 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
| 658 |
-
|
| 659 |
else:
|
| 660 |
result += f"\n\nTraitement de la tâche : pas de BCC créés\n"
|
| 661 |
-
|
| 662 |
if task == "export_to_excel_2":
|
| 663 |
if key == "status":
|
| 664 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
| 665 |
-
|
| 666 |
|
| 667 |
except Exception as e:
|
| 668 |
print(f"Erreur lors de l'exécution du workflow: {e}")
|
|
@@ -690,6 +683,40 @@ def getGitFilesFromRepo(DIRECTORY):
|
|
| 690 |
})
|
| 691 |
return all_files
|
| 692 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 693 |
# Fonction pour extraire les catégories et enseignements
|
| 694 |
def extract_categories_enseignements(data: Dict) -> pd.DataFrame:
|
| 695 |
"""Extraire les catégories et enseignements associés dans un DataFrame."""
|
|
@@ -745,11 +772,12 @@ def extract_situations_apprentissage(data: Dict) -> pd.DataFrame:
|
|
| 745 |
# the exception.
|
| 746 |
server = flask.Flask(__name__)
|
| 747 |
|
| 748 |
-
app = dash.Dash(__name__, server=server, external_stylesheets=dmc.styles.ALL,
|
| 749 |
title='BCC Agent',
|
| 750 |
update_title='Chargement...',
|
| 751 |
suppress_callback_exceptions=True)
|
| 752 |
|
|
|
|
| 753 |
# Updating the Flask Server configuration with Secret Key to encrypt the user session cookie
|
| 754 |
server.config['REMEMBER_COOKIE_DURATION'] = timedelta(seconds=3600)
|
| 755 |
|
|
@@ -775,39 +803,26 @@ def load_user(username):
|
|
| 775 |
return User(username)
|
| 776 |
|
| 777 |
# User status management views
|
| 778 |
-
index_page =
|
| 779 |
-
|
| 780 |
-
|
| 781 |
-
|
| 782 |
-
|
| 783 |
-
|
| 784 |
-
|
| 785 |
-
|
| 786 |
-
|
| 787 |
-
|
| 788 |
-
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
|
| 796 |
-
|
| 797 |
-
|
| 798 |
-
# html.Div([dcc.Location(id='url_login', refresh=True),
|
| 799 |
-
# dmc.Text("BCC Agent", id='h1',style={"fontSize": 48}, fw=900),
|
| 800 |
-
# dmc.TextInput(placeholder="login",w=250, ml="calc(50% - 125px)", id='uname-box'),
|
| 801 |
-
# dmc.PasswordInput(id='pwd-box',placeholder="Mot de passe",w=250, ml="calc(50% - 125px)", mt=10),
|
| 802 |
-
# dmc.Button("Continuer", w=250,variant="gradient", n_clicks=0, id='login-button', mt=20, mb=20),
|
| 803 |
-
# html.Div(children='', id='output-state')
|
| 804 |
-
# ]), span=4, offset=4, style={'textAlign': 'center', 'marginTop': 'calc(50vh - 120px)','border':'1px solid #495057','border-radius':'10px'}, c='white'
|
| 805 |
-
# )
|
| 806 |
-
# ]
|
| 807 |
-
# )
|
| 808 |
-
# ]
|
| 809 |
-
#)]
|
| 810 |
-
# )
|
| 811 |
|
| 812 |
# Successful login
|
| 813 |
success = html.Div([html.Div([html.H2('Login successful.'),
|
|
@@ -868,19 +883,19 @@ app.layout = dmc.MantineProvider(
|
|
| 868 |
html.Div(id='user-status-div'),
|
| 869 |
html.Div(id='page-content')
|
| 870 |
])])
|
| 871 |
-
|
| 872 |
-
|
| 873 |
-
|
| 874 |
-
|
| 875 |
-
|
| 876 |
-
|
| 877 |
-
|
| 878 |
-
|
| 879 |
-
|
| 880 |
-
|
| 881 |
-
|
| 882 |
-
|
| 883 |
-
|
| 884 |
|
| 885 |
app_page = dmc.MantineProvider(
|
| 886 |
[
|
|
@@ -1095,7 +1110,7 @@ app_page = dmc.MantineProvider(
|
|
| 1095 |
className="g-0"
|
| 1096 |
),
|
| 1097 |
html.H4(id="text-enseignement-dropdown", className="mb-3 text-success", style={"font-size": "0.7rem"}),
|
| 1098 |
-
|
| 1099 |
], md=6),
|
| 1100 |
dbc.Col([
|
| 1101 |
dbc.Row(
|
|
@@ -1109,7 +1124,7 @@ app_page = dmc.MantineProvider(
|
|
| 1109 |
className="g-0"
|
| 1110 |
),
|
| 1111 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC", className="mb-3", style={"font-size": "0.7rem"}),
|
| 1112 |
-
|
| 1113 |
], md=6)
|
| 1114 |
]),
|
| 1115 |
dbc.Row([
|
|
@@ -1125,7 +1140,7 @@ app_page = dmc.MantineProvider(
|
|
| 1125 |
className="g-0"
|
| 1126 |
),
|
| 1127 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC", className="mb-3", style={"font-size": "0.7rem"}),
|
| 1128 |
-
|
| 1129 |
], md=6),
|
| 1130 |
dbc.Col([
|
| 1131 |
dbc.Row(
|
|
@@ -1183,7 +1198,7 @@ app_page = dmc.MantineProvider(
|
|
| 1183 |
className="g-0"
|
| 1184 |
),
|
| 1185 |
html.Div(id="generation-status", className="mb-3"),
|
| 1186 |
-
|
| 1187 |
html.Div(id="competence-output", className="p-3 border rounded", style={"color":"rgb(90, 242, 156)","border-color":"rgb(90, 242, 156)!important","background-color":"rgba(90, 242, 156, 0.2)"}),
|
| 1188 |
),
|
| 1189 |
], md=12),
|
|
@@ -1253,7 +1268,7 @@ app_page = dmc.MantineProvider(
|
|
| 1253 |
align="left",
|
| 1254 |
className="g-0"
|
| 1255 |
),
|
| 1256 |
-
|
| 1257 |
html.Div(id="notification_wrapper", style={"margin-top":"1rem"}),
|
| 1258 |
], width=12)
|
| 1259 |
])
|
|
@@ -1483,7 +1498,7 @@ app_avid_page = dmc.MantineProvider(
|
|
| 1483 |
className="g-0"
|
| 1484 |
),
|
| 1485 |
html.H4(id="text-enseignement-dropdown", className="mb-3 text-success", style={"font-size": "0.7rem"}),
|
| 1486 |
-
|
| 1487 |
], md=6),
|
| 1488 |
dbc.Col([
|
| 1489 |
dbc.Row(
|
|
@@ -1497,7 +1512,7 @@ app_avid_page = dmc.MantineProvider(
|
|
| 1497 |
className="g-0"
|
| 1498 |
),
|
| 1499 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC AVID", className="mb-3", style={"font-size": "0.7rem"}),
|
| 1500 |
-
|
| 1501 |
], md=6)
|
| 1502 |
]),
|
| 1503 |
dbc.Row([
|
|
@@ -1513,7 +1528,7 @@ app_avid_page = dmc.MantineProvider(
|
|
| 1513 |
className="g-0"
|
| 1514 |
),
|
| 1515 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC AVID", className="mb-3", style={"font-size": "0.7rem"}),
|
| 1516 |
-
|
| 1517 |
], md=6),
|
| 1518 |
dbc.Col([
|
| 1519 |
dbc.Row(
|
|
@@ -1565,7 +1580,7 @@ app_avid_page = dmc.MantineProvider(
|
|
| 1565 |
className="g-0"
|
| 1566 |
),
|
| 1567 |
html.Div(id="generation-status", className="mb-3"),
|
| 1568 |
-
|
| 1569 |
html.Div(id="competence-output", className="p-3 border rounded", style={"color":"rgb(90, 242, 156)","border-color":"rgb(90, 242, 156)!important","background-color":"rgba(90, 242, 156, 0.2)"}),
|
| 1570 |
),
|
| 1571 |
], md=12),
|
|
@@ -1635,7 +1650,7 @@ app_avid_page = dmc.MantineProvider(
|
|
| 1635 |
align="left",
|
| 1636 |
className="g-0"
|
| 1637 |
),
|
| 1638 |
-
|
| 1639 |
html.Div(id="notification_wrapper-avid", style={"margin-top":"1rem"}),
|
| 1640 |
], width=12)
|
| 1641 |
])
|
|
@@ -1764,31 +1779,28 @@ def update_skills_dropdown(categorie_selected, pathname):
|
|
| 1764 |
)
|
| 1765 |
def update_enseignements_dropdown(categorie_selected, pathname):
|
| 1766 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
| 1767 |
-
|
| 1768 |
-
|
| 1769 |
-
|
| 1770 |
-
|
| 1771 |
-
|
| 1772 |
-
|
| 1773 |
-
|
| 1774 |
-
|
| 1775 |
-
default_text = "formation sélectionnée : "
|
| 1776 |
|
| 1777 |
-
|
| 1778 |
-
|
| 1779 |
-
|
| 1780 |
-
|
| 1781 |
-
|
| 1782 |
-
|
| 1783 |
-
|
| 1784 |
-
|
| 1785 |
-
|
| 1786 |
sort_keys = True, ensure_ascii=False), "Choisir d'abord une maquette de formation avec propositions BCC : " + default_text + jsonData.get("niveau", ""), modal_text
|
| 1787 |
-
|
| 1788 |
-
|
| 1789 |
-
|
| 1790 |
-
except:
|
| 1791 |
-
print("Aucun fichier chargé")
|
| 1792 |
|
| 1793 |
@app.callback(
|
| 1794 |
Output("classification-dropdown", "placeholder"),
|
|
@@ -1799,44 +1811,41 @@ def update_enseignements_dropdown(categorie_selected, pathname):
|
|
| 1799 |
)
|
| 1800 |
def update_classification_dropdown(categorie_selected, pathname):
|
| 1801 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
| 1802 |
-
|
| 1803 |
-
|
| 1804 |
-
|
| 1805 |
-
|
| 1806 |
-
|
| 1807 |
-
|
| 1808 |
-
|
| 1809 |
-
|
| 1810 |
-
default_text = ""
|
| 1811 |
|
| 1812 |
-
|
| 1813 |
-
|
| 1814 |
-
|
| 1815 |
-
|
| 1816 |
-
|
| 1817 |
-
|
| 1818 |
-
|
| 1819 |
-
|
| 1820 |
-
|
| 1821 |
-
|
| 1822 |
-
|
| 1823 |
-
|
| 1824 |
-
|
| 1825 |
-
|
| 1826 |
-
|
| 1827 |
-
|
| 1828 |
-
|
| 1829 |
-
|
| 1830 |
-
|
| 1831 |
|
| 1832 |
-
|
| 1833 |
-
|
| 1834 |
sort_keys = True, ensure_ascii=False),modal_text
|
| 1835 |
-
|
| 1836 |
-
|
| 1837 |
sort_keys = True, ensure_ascii=False),modal_text
|
| 1838 |
-
except:
|
| 1839 |
-
print("Aucun fichier chargé")
|
| 1840 |
|
| 1841 |
@app.callback(
|
| 1842 |
Output("situation-dropdown", "placeholder"),
|
|
@@ -1847,46 +1856,43 @@ def update_classification_dropdown(categorie_selected, pathname):
|
|
| 1847 |
)
|
| 1848 |
def update_situations_dropdown(categorie_selected, pathname):
|
| 1849 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1850 |
try:
|
| 1851 |
-
if
|
| 1852 |
-
|
|
|
|
| 1853 |
if pathname == "/bcc":
|
| 1854 |
-
|
|
|
|
|
|
|
| 1855 |
elif pathname == "/bcc-avid":
|
| 1856 |
-
|
| 1857 |
-
|
| 1858 |
-
|
| 1859 |
-
|
| 1860 |
-
|
| 1861 |
-
|
| 1862 |
-
|
| 1863 |
-
|
| 1864 |
-
jsonData = json.loads(base64.b64decode(res.json()['content']))
|
| 1865 |
-
modal_text = "**Description des situations d'apprentissage :**"
|
| 1866 |
-
if pathname == "/bcc":
|
| 1867 |
-
textarea_value = jsonData.get("learning_situations", [])
|
| 1868 |
-
for key, value in textarea_value.items():
|
| 1869 |
-
modal_text += f"\n\n- **{key}**: {value}"
|
| 1870 |
-
elif pathname == "/bcc-avid":
|
| 1871 |
-
textarea_value = jsonData.get("situations_apprentissage", [])
|
| 1872 |
-
for item in textarea_value:
|
| 1873 |
-
modal_text += f"\n\n- **Situation d'apprentissage**: {item['situation']}"
|
| 1874 |
-
if item['objectifs']:
|
| 1875 |
-
modal_text += f"\n\nObjectifs : "
|
| 1876 |
-
for objectif in item['objectifs']:
|
| 1877 |
-
modal_text += f"\n-{objectif}"
|
| 1878 |
-
modal_text += f"\n\nLien avec les thématiques ODD11 : {item['lien_odd11']}"
|
| 1879 |
|
| 1880 |
-
|
| 1881 |
-
|
| 1882 |
sort_keys = True, ensure_ascii=False), modal_text
|
| 1883 |
-
|
| 1884 |
-
|
| 1885 |
sort_keys = True, ensure_ascii=False), modal_text
|
| 1886 |
-
except:
|
| 1887 |
-
return "Choisir d'abord une maquette de formation avec proposition BCC", "", "**Aucune situation d'apprentissage définie pour cette maquette de formation.**"
|
| 1888 |
except:
|
| 1889 |
-
|
| 1890 |
|
| 1891 |
@app.callback(
|
| 1892 |
Output("selection-display", "children"),
|
|
@@ -2248,47 +2254,5 @@ def display_status(num, current, n_clicks, pathname):
|
|
| 2248 |
except:
|
| 2249 |
return html.Div(dcc.Markdown(f"""{agent}""", style={"color":"white","font-size":"0.75rem"})), []
|
| 2250 |
|
| 2251 |
-
clientside_callback(
|
| 2252 |
-
"""connected => !connected""",
|
| 2253 |
-
Output("submit-button", "disabled"),
|
| 2254 |
-
)
|
| 2255 |
-
|
| 2256 |
-
clientside_callback(
|
| 2257 |
-
"""(notification) => {
|
| 2258 |
-
if (!notification) return dash_clientside.no_update
|
| 2259 |
-
return notification
|
| 2260 |
-
}""",
|
| 2261 |
-
Output("notification_wrapper", "children", allow_duplicate=True),
|
| 2262 |
-
prevent_initial_call=True,
|
| 2263 |
-
)
|
| 2264 |
-
|
| 2265 |
-
clientside_callback(
|
| 2266 |
-
"""(word, text) => text + word""",
|
| 2267 |
-
Output("output-response", "children", allow_duplicate=True),
|
| 2268 |
-
State("output-response", "children"),
|
| 2269 |
-
prevent_initial_call=True,
|
| 2270 |
-
)
|
| 2271 |
-
|
| 2272 |
-
clientside_callback(
|
| 2273 |
-
"""connected => !connected""",
|
| 2274 |
-
Output("submit-button-avid", "disabled"),
|
| 2275 |
-
)
|
| 2276 |
-
|
| 2277 |
-
clientside_callback(
|
| 2278 |
-
"""(notification) => {
|
| 2279 |
-
if (!notification) return dash_clientside.no_update
|
| 2280 |
-
return notification
|
| 2281 |
-
}""",
|
| 2282 |
-
Output("notification_wrapper-avid", "children", allow_duplicate=True),
|
| 2283 |
-
prevent_initial_call=True,
|
| 2284 |
-
)
|
| 2285 |
-
|
| 2286 |
-
clientside_callback(
|
| 2287 |
-
"""(word, text) => text + word""",
|
| 2288 |
-
Output("output-response-avid", "children", allow_duplicate=True),
|
| 2289 |
-
State("output-response-avid", "children"),
|
| 2290 |
-
prevent_initial_call=True,
|
| 2291 |
-
)
|
| 2292 |
-
|
| 2293 |
if __name__ == '__main__':
|
| 2294 |
app.run_server(debug=True)
|
|
|
|
| 1 |
+
|
| 2 |
import os
|
| 3 |
import dash
|
| 4 |
import json
|
|
|
|
| 26 |
from langchain_openai import ChatOpenAI
|
| 27 |
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage
|
| 28 |
|
| 29 |
+
from dash_socketio import DashSocketIO
|
| 30 |
import dash
|
| 31 |
from dash.dependencies import Input, Output, State
|
| 32 |
from dash import Dash, html, dcc, callback, callback_context, ctx, Output, Input, dash_table, State, no_update, _dash_renderer, clientside_callback
|
| 33 |
from dash import html
|
| 34 |
|
| 35 |
+
import dash_bootstrap_components as dbc
|
| 36 |
import dash_bootstrap_components as dbc
|
| 37 |
from dash.exceptions import PreventUpdate
|
| 38 |
import dash_mantine_components as dmc
|
|
|
|
| 40 |
_dash_renderer._set_react_version("18.2.0")
|
| 41 |
import flask
|
| 42 |
from flask_login import LoginManager, UserMixin, login_user, current_user, login_required, logout_user
|
| 43 |
+
from flask_socketio import SocketIO, emit
|
| 44 |
from datetime import timedelta
|
| 45 |
|
| 46 |
from IPython.display import display, HTML
|
|
|
|
| 625 |
if task == "load_and_preprocess":
|
| 626 |
if key == "current_file":
|
| 627 |
result += f"Traitement du fichier {taskInfo['current_file']} en cours...\n"
|
|
|
|
| 628 |
if task == "classify_teachings":
|
| 629 |
if key == "status":
|
| 630 |
for key, value in taskInfo['classified_teachings'].items():
|
| 631 |
result += f"\n\n-**Enseignement classé dans la catégorie '{key}'** : "
|
| 632 |
for enseignement in value:
|
| 633 |
result += f"{enseignement}, "
|
|
|
|
| 634 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
|
|
|
| 635 |
if task == "create_categories":
|
| 636 |
if key == "status":
|
| 637 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
|
|
|
| 638 |
if task == "create_learning_situations":
|
| 639 |
if key == "status":
|
| 640 |
if taskInfo['learning_situations'].items():
|
| 641 |
for key, value in taskInfo['learning_situations'].items():
|
| 642 |
result += f"\n\n-**Situation d'apprentissage créée pour la catégorie '{key}'** : {value}\n"
|
|
|
|
| 643 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
|
|
|
| 644 |
else:
|
| 645 |
result += f"\n\nTraitement de la tâche : pas de situations d'apprentissage créées\n"
|
|
|
|
| 646 |
if task == "create_academic_competencies":
|
| 647 |
if key == "dataframe":
|
| 648 |
df = taskInfo['dataframe']
|
| 649 |
if key == "status":
|
| 650 |
if taskInfo['academic_competencies'].items():
|
| 651 |
for key, value in taskInfo['academic_competencies'].items():
|
| 652 |
+
result += f"\n\n-**Compétence académique créée pour la catégorie '{key}'** : {value}\n"
|
|
|
|
| 653 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
|
|
|
| 654 |
else:
|
| 655 |
result += f"\n\nTraitement de la tâche : pas de BCC créés\n"
|
|
|
|
| 656 |
if task == "export_to_excel_2":
|
| 657 |
if key == "status":
|
| 658 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
|
|
|
| 659 |
|
| 660 |
except Exception as e:
|
| 661 |
print(f"Erreur lors de l'exécution du workflow: {e}")
|
|
|
|
| 683 |
})
|
| 684 |
return all_files
|
| 685 |
|
| 686 |
+
def load_json_files(directory_path: str = "./BCC-Application/JSON"):
|
| 687 |
+
if not os.path.exists(directory_path):
|
| 688 |
+
print(f"Erreur: Le répertoire {directory_path} n'existe pas.")
|
| 689 |
+
return
|
| 690 |
+
|
| 691 |
+
# Récupérer la liste des fichiers CSV dans le répertoire
|
| 692 |
+
json_files = glob.glob(os.path.join(directory_path, "*.json"))
|
| 693 |
+
|
| 694 |
+
if not json_files:
|
| 695 |
+
print(f"Aucun fichier JSON trouvé dans le répertoire {directory_path}.")
|
| 696 |
+
return
|
| 697 |
+
|
| 698 |
+
print(f"Fichiers JSON trouvés: {len(json_files)}")
|
| 699 |
+
#for file in json_files:
|
| 700 |
+
# print(f"- {file}")
|
| 701 |
+
return json_files
|
| 702 |
+
|
| 703 |
+
def load_json_AVID_files(directory_path: str = "./VD-Agent/JSON"):
|
| 704 |
+
if not os.path.exists(directory_path):
|
| 705 |
+
print(f"Erreur: Le répertoire {directory_path} n'existe pas.")
|
| 706 |
+
return
|
| 707 |
+
|
| 708 |
+
# Récupérer la liste des fichiers CSV dans le répertoire
|
| 709 |
+
json_files = glob.glob(os.path.join(directory_path, "*.json"))
|
| 710 |
+
|
| 711 |
+
if not json_files:
|
| 712 |
+
print(f"Aucun fichier JSON trouvé dans le répertoire {directory_path}.")
|
| 713 |
+
return
|
| 714 |
+
|
| 715 |
+
print(f"Fichiers JSON trouvés: {len(json_files)}")
|
| 716 |
+
#for file in json_files:
|
| 717 |
+
# print(f"- {file}")
|
| 718 |
+
return json_files
|
| 719 |
+
|
| 720 |
# Fonction pour extraire les catégories et enseignements
|
| 721 |
def extract_categories_enseignements(data: Dict) -> pd.DataFrame:
|
| 722 |
"""Extraire les catégories et enseignements associés dans un DataFrame."""
|
|
|
|
| 772 |
# the exception.
|
| 773 |
server = flask.Flask(__name__)
|
| 774 |
|
| 775 |
+
app = dash.Dash(__name__, server=server, external_stylesheets=[dmc.styles.ALL, dbc.themes.DARKLY],
|
| 776 |
title='BCC Agent',
|
| 777 |
update_title='Chargement...',
|
| 778 |
suppress_callback_exceptions=True)
|
| 779 |
|
| 780 |
+
#socketio = SocketIO(app.server)
|
| 781 |
# Updating the Flask Server configuration with Secret Key to encrypt the user session cookie
|
| 782 |
server.config['REMEMBER_COOKIE_DURATION'] = timedelta(seconds=3600)
|
| 783 |
|
|
|
|
| 803 |
return User(username)
|
| 804 |
|
| 805 |
# User status management views
|
| 806 |
+
index_page = dmc.MantineProvider(
|
| 807 |
+
[
|
| 808 |
+
dmc.Container(
|
| 809 |
+
children=[
|
| 810 |
+
dmc.Grid(
|
| 811 |
+
children=[
|
| 812 |
+
dmc.GridCol(
|
| 813 |
+
html.Div([dcc.Location(id='url_login', refresh=True),
|
| 814 |
+
dmc.Text("BCC Agent", id='h1',style={"fontSize": 48}, fw=900),
|
| 815 |
+
dmc.TextInput(placeholder="login",w=250, ml="calc(50% - 125px)", id='uname-box'),
|
| 816 |
+
dmc.PasswordInput(id='pwd-box',placeholder="Mot de passe",w=250, ml="calc(50% - 125px)", mt=10),
|
| 817 |
+
dmc.Button("Continuer", w=250,variant="gradient", n_clicks=0, id='login-button', mt=20, mb=20),
|
| 818 |
+
html.Div(children='', id='output-state')
|
| 819 |
+
]), span=4, offset=4, style={'textAlign': 'center', 'marginTop': 'calc(50vh - 120px)','border':'1px solid #495057','border-radius':'10px'}, c='white'
|
| 820 |
+
)
|
| 821 |
+
]
|
| 822 |
+
)
|
| 823 |
+
]
|
| 824 |
+
)],forceColorScheme="dark"
|
| 825 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 826 |
|
| 827 |
# Successful login
|
| 828 |
success = html.Div([html.Div([html.H2('Login successful.'),
|
|
|
|
| 883 |
html.Div(id='user-status-div'),
|
| 884 |
html.Div(id='page-content')
|
| 885 |
])])
|
| 886 |
+
def layout(**kwargs):
|
| 887 |
+
return dmc.MantineProvider(
|
| 888 |
+
[
|
| 889 |
+
html.Div([
|
| 890 |
+
dcc.Location(id='url', refresh=False),
|
| 891 |
+
dcc.Location(id='redirect', refresh=True),
|
| 892 |
+
dcc.Store(id='login-status', storage_type='session'),
|
| 893 |
+
dcc.Store(id="history-store", storage_type="session", data=[]),
|
| 894 |
+
dcc.Store(id="model-params-store", storage_type="session", data={"model": "mistralai/Mistral-Small-3.1-24B-Instruct-2503","temperature": 0.7,"max_tokens": 1024,"top_p": 0.9}),
|
| 895 |
+
html.Div(id='user-status-div'),
|
| 896 |
+
html.Div(id='page-content')
|
| 897 |
+
]),
|
| 898 |
+
],forceColorScheme="dark", span=12, offset=0, c='white')
|
| 899 |
|
| 900 |
app_page = dmc.MantineProvider(
|
| 901 |
[
|
|
|
|
| 1110 |
className="g-0"
|
| 1111 |
),
|
| 1112 |
html.H4(id="text-enseignement-dropdown", className="mb-3 text-success", style={"font-size": "0.7rem"}),
|
| 1113 |
+
dbc.Textarea(id="enseignement-dropdown", className="mb-3", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
| 1114 |
], md=6),
|
| 1115 |
dbc.Col([
|
| 1116 |
dbc.Row(
|
|
|
|
| 1124 |
className="g-0"
|
| 1125 |
),
|
| 1126 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC", className="mb-3", style={"font-size": "0.7rem"}),
|
| 1127 |
+
dbc.Textarea(id="classification-dropdown", className="mb-3", placeholder="Choisir d'abord une maquette avec propositions BCC", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
| 1128 |
], md=6)
|
| 1129 |
]),
|
| 1130 |
dbc.Row([
|
|
|
|
| 1140 |
className="g-0"
|
| 1141 |
),
|
| 1142 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC", className="mb-3", style={"font-size": "0.7rem"}),
|
| 1143 |
+
dbc.Textarea(id="situation-dropdown", className="mb-3", placeholder="Choisir d'abord une maquette avec propositions BCC", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
| 1144 |
], md=6),
|
| 1145 |
dbc.Col([
|
| 1146 |
dbc.Row(
|
|
|
|
| 1198 |
className="g-0"
|
| 1199 |
),
|
| 1200 |
html.Div(id="generation-status", className="mb-3"),
|
| 1201 |
+
dbc.Spinner(
|
| 1202 |
html.Div(id="competence-output", className="p-3 border rounded", style={"color":"rgb(90, 242, 156)","border-color":"rgb(90, 242, 156)!important","background-color":"rgba(90, 242, 156, 0.2)"}),
|
| 1203 |
),
|
| 1204 |
], md=12),
|
|
|
|
| 1268 |
align="left",
|
| 1269 |
className="g-0"
|
| 1270 |
),
|
| 1271 |
+
html.Div(id='output-response', style={"color":"rgb(90, 242, 156)","border-radius":"3px","border":"1px solid rgb(255,255,255)!important","background-color":"rgba(90, 242, 156, 0.2)","padding":"5px"}),
|
| 1272 |
html.Div(id="notification_wrapper", style={"margin-top":"1rem"}),
|
| 1273 |
], width=12)
|
| 1274 |
])
|
|
|
|
| 1498 |
className="g-0"
|
| 1499 |
),
|
| 1500 |
html.H4(id="text-enseignement-dropdown", className="mb-3 text-success", style={"font-size": "0.7rem"}),
|
| 1501 |
+
dbc.Textarea(id="enseignement-dropdown", className="mb-3", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
| 1502 |
], md=6),
|
| 1503 |
dbc.Col([
|
| 1504 |
dbc.Row(
|
|
|
|
| 1512 |
className="g-0"
|
| 1513 |
),
|
| 1514 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC AVID", className="mb-3", style={"font-size": "0.7rem"}),
|
| 1515 |
+
dbc.Textarea(id="classification-dropdown", className="mb-3", placeholder="Choisir d'abord une maquette avec propositions BCC AVID", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
| 1516 |
], md=6)
|
| 1517 |
]),
|
| 1518 |
dbc.Row([
|
|
|
|
| 1528 |
className="g-0"
|
| 1529 |
),
|
| 1530 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC AVID", className="mb-3", style={"font-size": "0.7rem"}),
|
| 1531 |
+
dbc.Textarea(id="situation-dropdown", className="mb-3", placeholder="Choisir d'abord une maquette avec propositions BCC AVID", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
| 1532 |
], md=6),
|
| 1533 |
dbc.Col([
|
| 1534 |
dbc.Row(
|
|
|
|
| 1580 |
className="g-0"
|
| 1581 |
),
|
| 1582 |
html.Div(id="generation-status", className="mb-3"),
|
| 1583 |
+
dbc.Spinner(
|
| 1584 |
html.Div(id="competence-output", className="p-3 border rounded", style={"color":"rgb(90, 242, 156)","border-color":"rgb(90, 242, 156)!important","background-color":"rgba(90, 242, 156, 0.2)"}),
|
| 1585 |
),
|
| 1586 |
], md=12),
|
|
|
|
| 1650 |
align="left",
|
| 1651 |
className="g-0"
|
| 1652 |
),
|
| 1653 |
+
html.Div(id='output-response-avid', style={"color":"rgb(156, 242, 242)","border-radius":"3px","border":"1px solid rgb(255,255,255)!important","background-color":"rgba(156, 242, 242, 0.2)","padding":"5px"}),
|
| 1654 |
html.Div(id="notification_wrapper-avid", style={"margin-top":"1rem"}),
|
| 1655 |
], width=12)
|
| 1656 |
])
|
|
|
|
| 1779 |
)
|
| 1780 |
def update_enseignements_dropdown(categorie_selected, pathname):
|
| 1781 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
| 1782 |
+
if not categorie_selected:
|
| 1783 |
+
default_text = "par défaut : "
|
| 1784 |
+
if pathname == "/bcc":
|
| 1785 |
+
categorie_selected = 'JSON/L1-Anglais.json'
|
| 1786 |
+
elif pathname == "/bcc-avid":
|
| 1787 |
+
categorie_selected = 'VD/JSON/L1-Lettres-Modernes.json'
|
| 1788 |
+
else:
|
| 1789 |
+
default_text = "formation sélectionnée : "
|
|
|
|
| 1790 |
|
| 1791 |
+
url = f"https://api.github.com/repos/{OWNER}/{REPO}/contents/{categorie_selected}"
|
| 1792 |
+
res = requests.get(url, headers=headers, params=params)
|
| 1793 |
+
if res.status_code == 200:
|
| 1794 |
+
jsonData = json.loads(base64.b64decode(res.json()['content']))
|
| 1795 |
+
modal_text = "**Description des catégories d'enseignements : **\n\n"
|
| 1796 |
+
for item in jsonData.get("categories", []):
|
| 1797 |
+
modal_text += f"- **{item['nom']}**:\n\n{item['description']}\n\n"
|
| 1798 |
+
if pathname == "/bcc":
|
| 1799 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(jsonData.get("categories", []), indent = 6, separators =(",", ":"),
|
| 1800 |
sort_keys = True, ensure_ascii=False), "Choisir d'abord une maquette de formation avec propositions BCC : " + default_text + jsonData.get("niveau", ""), modal_text
|
| 1801 |
+
elif pathname == "/bcc-avid":
|
| 1802 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(jsonData.get("categories", []), indent = 6, separators =(",", ":"),
|
| 1803 |
+
sort_keys = True, ensure_ascii=False), "Choisir d'abord une maquette de formation avec propositions BCC : " + default_text + jsonData.get("niveau_etude", ""), modal_text
|
|
|
|
|
|
|
| 1804 |
|
| 1805 |
@app.callback(
|
| 1806 |
Output("classification-dropdown", "placeholder"),
|
|
|
|
| 1811 |
)
|
| 1812 |
def update_classification_dropdown(categorie_selected, pathname):
|
| 1813 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
| 1814 |
+
if not categorie_selected:
|
| 1815 |
+
default_text = "par défaut : "
|
| 1816 |
+
if pathname == "/bcc":
|
| 1817 |
+
categorie_selected = 'JSON/L1-Anglais.json'
|
| 1818 |
+
elif pathname == "/bcc-avid":
|
| 1819 |
+
categorie_selected = 'VD/JSON/L1-Lettres-Modernes.json'
|
| 1820 |
+
else:
|
| 1821 |
+
default_text = ""
|
|
|
|
| 1822 |
|
| 1823 |
+
url = f"https://api.github.com/repos/{OWNER}/{REPO}/contents/{categorie_selected}"
|
| 1824 |
+
res = requests.get(url, headers=headers, params=params)
|
| 1825 |
+
if res.status_code == 200:
|
| 1826 |
+
jsonData = json.loads(base64.b64decode(res.json()['content']))
|
| 1827 |
+
modal_text = "**Classification des enseignements :**"
|
| 1828 |
+
if pathname == "/bcc":
|
| 1829 |
+
textarea_value = jsonData.get("classified_teachings", [])
|
| 1830 |
+
for key, value in textarea_value.items():
|
| 1831 |
+
modal_text += f"\n\n- **{key}**: "
|
| 1832 |
+
for i in range(0,len(value)):
|
| 1833 |
+
modal_text += f"{value[i]}\t"
|
| 1834 |
+
elif pathname == "/bcc-avid":
|
| 1835 |
+
textarea_value = jsonData.get("dataframe", [])
|
| 1836 |
+
test = " "
|
| 1837 |
+
for item in sorted(textarea_value, key=lambda x: x['categorie'] if x['categorie'] else ""):
|
| 1838 |
+
if test != item['categorie']:
|
| 1839 |
+
modal_text += f"\n\n- **{item['categorie']}**: "
|
| 1840 |
+
modal_text += f"{item['enseignements']}\t"
|
| 1841 |
+
test = item['categorie']
|
| 1842 |
|
| 1843 |
+
if pathname == "/bcc":
|
| 1844 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(textarea_value, indent = 6, separators =(",", ":"),
|
| 1845 |
sort_keys = True, ensure_ascii=False),modal_text
|
| 1846 |
+
elif pathname == "/bcc-avid":
|
| 1847 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(textarea_value, indent = 6, separators =(",", ":"),
|
| 1848 |
sort_keys = True, ensure_ascii=False),modal_text
|
|
|
|
|
|
|
| 1849 |
|
| 1850 |
@app.callback(
|
| 1851 |
Output("situation-dropdown", "placeholder"),
|
|
|
|
| 1856 |
)
|
| 1857 |
def update_situations_dropdown(categorie_selected, pathname):
|
| 1858 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
| 1859 |
+
if not categorie_selected:
|
| 1860 |
+
default_text = "par défaut : "
|
| 1861 |
+
if pathname == "/bcc":
|
| 1862 |
+
categorie_selected = 'JSON/L1-Anglais.json'
|
| 1863 |
+
elif pathname == "/bcc-avid":
|
| 1864 |
+
categorie_selected = 'VD/JSON/L1-Lettres-Modernes.json'
|
| 1865 |
+
else:
|
| 1866 |
+
default_text = ""
|
| 1867 |
+
|
| 1868 |
+
url = f"https://api.github.com/repos/{OWNER}/{REPO}/contents/{categorie_selected}"
|
| 1869 |
+
res = requests.get(url, headers=headers, params=params)
|
| 1870 |
try:
|
| 1871 |
+
if res.status_code == 200:
|
| 1872 |
+
jsonData = json.loads(base64.b64decode(res.json()['content']))
|
| 1873 |
+
modal_text = "**Description des situations d'apprentissage :**"
|
| 1874 |
if pathname == "/bcc":
|
| 1875 |
+
textarea_value = jsonData.get("learning_situations", [])
|
| 1876 |
+
for key, value in textarea_value.items():
|
| 1877 |
+
modal_text += f"\n\n- **{key}**: {value}"
|
| 1878 |
elif pathname == "/bcc-avid":
|
| 1879 |
+
textarea_value = jsonData.get("situations_apprentissage", [])
|
| 1880 |
+
for item in textarea_value:
|
| 1881 |
+
modal_text += f"\n\n- **Situation d'apprentissage**: {item['situation']}"
|
| 1882 |
+
if item['objectifs']:
|
| 1883 |
+
modal_text += f"\n\nObjectifs : "
|
| 1884 |
+
for objectif in item['objectifs']:
|
| 1885 |
+
modal_text += f"\n-{objectif}"
|
| 1886 |
+
modal_text += f"\n\nLien avec les thématiques ODD11 : {item['lien_odd11']}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1887 |
|
| 1888 |
+
if pathname == "/bcc":
|
| 1889 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(textarea_value, indent = 6, separators =(",", ":"),
|
| 1890 |
sort_keys = True, ensure_ascii=False), modal_text
|
| 1891 |
+
elif pathname == "/bcc-avid":
|
| 1892 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(textarea_value, indent = 6, separators =(",", ":"),
|
| 1893 |
sort_keys = True, ensure_ascii=False), modal_text
|
|
|
|
|
|
|
| 1894 |
except:
|
| 1895 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", "", "**Aucune situation d'apprentissage définie pour cette maquette de formation.**"
|
| 1896 |
|
| 1897 |
@app.callback(
|
| 1898 |
Output("selection-display", "children"),
|
|
|
|
| 2254 |
except:
|
| 2255 |
return html.Div(dcc.Markdown(f"""{agent}""", style={"color":"white","font-size":"0.75rem"})), []
|
| 2256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2257 |
if __name__ == '__main__':
|
| 2258 |
app.run_server(debug=True)
|