maxenceLIOGIER commited on
Commit
c642aa9
·
verified ·
1 Parent(s): 86e2833

Upload folder using huggingface_hub

Browse files
README.md CHANGED
@@ -1,3 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
  # SmartRescue
2
 
3
  SmartRescue est une application conçue pour assister les opérateurs d'urgence grâce à l'intégration d'un **LLM (Large Language Model)** et d'un **RAG (Retrieval-Augmented Generation)**. Cette technologie permet d'améliorer la prise de décision en temps réel et de fournir une assistance rapide et efficace lors des appels d'urgence.
 
1
+ ---
2
+ title: "SmartRescue"
3
+ emoji: "🚑"
4
+ colorFrom: "red"
5
+ colorTo: "blue"
6
+ sdk: "streamlit"
7
+ sdk_version: "1.41.1"
8
+ app_file: app/app.py
9
+ pinned: false
10
+ ---
11
+
12
+
13
  # SmartRescue
14
 
15
  SmartRescue est une application conçue pour assister les opérateurs d'urgence grâce à l'intégration d'un **LLM (Large Language Model)** et d'un **RAG (Retrieval-Augmented Generation)**. Cette technologie permet d'améliorer la prise de décision en temps réel et de fournir une assistance rapide et efficace lors des appels d'urgence.
app/views/__pycache__/admin.cpython-311.pyc CHANGED
Binary files a/app/views/__pycache__/admin.cpython-311.pyc and b/app/views/__pycache__/admin.cpython-311.pyc differ
 
app/views/__pycache__/aide_telephonique.cpython-311.pyc CHANGED
Binary files a/app/views/__pycache__/aide_telephonique.cpython-311.pyc and b/app/views/__pycache__/aide_telephonique.cpython-311.pyc differ
 
app/views/__pycache__/dashboard.cpython-311.pyc CHANGED
Binary files a/app/views/__pycache__/dashboard.cpython-311.pyc and b/app/views/__pycache__/dashboard.cpython-311.pyc differ
 
app/views/__pycache__/home.cpython-311.pyc CHANGED
Binary files a/app/views/__pycache__/home.cpython-311.pyc and b/app/views/__pycache__/home.cpython-311.pyc differ
 
app/views/aide_telephonique.py CHANGED
@@ -98,10 +98,9 @@ def summarize_conversation(messages, llm):
98
  llm_chain = prompt | llm
99
  start_time = time.time()
100
  summary = llm_chain.invoke({"conversation": conversation})
101
- latency = (time.time() - start_time) * 1000 # Convertir en ms
102
- token_count = len(summary.split())
103
- track_metrics(latency, token_count)
104
- return summary
105
 
106
 
107
  def aide_telephonique_page():
@@ -117,10 +116,8 @@ def aide_telephonique_page():
117
  Cela peut être gênant en faussant les résultats du LLM.
118
  """
119
 
120
- st.title("Aide téléphonique pour les opérateurs du SAMU")
121
- st.subheader(
122
- "Interrogez l'IA durant votre appel pour obtenir des aides et conseils"
123
- )
124
 
125
  # Initialisation de l'état de session
126
  if "recording" not in st.session_state:
@@ -139,6 +136,14 @@ def aide_telephonique_page():
139
  st.session_state.message_count = 0
140
  if "session_id" not in st.session_state:
141
  st.session_state.session_id = str(uuid.uuid4())
 
 
 
 
 
 
 
 
142
 
143
  # Contrôles d'enregistrement
144
  col1, col2 = st.columns(2)
@@ -166,7 +171,10 @@ def aide_telephonique_page():
166
  st.info("Enregistrement en cours...")
167
 
168
  template = """
169
- Tu es une IA conçue pour assister les agents des urgences en analysant leurs appels.
 
 
 
170
 
171
  **Règles à respecter :**
172
  - Tu dois être **empathique, calme, direct et professionnel**.
@@ -177,22 +185,21 @@ def aide_telephonique_page():
177
  - **Tes réponses doivent toujours être en français, sauf si l'opérateur parle en anglais.**
178
  - **Formule tes réponses sous forme d’instructions précises pour l’opérateur.**
179
  - **Tes réponses doivent toujours être en français, correctes grammaticalement et sans faute de syntaxe.**
180
- - **Tes réponses ne doivent jamais commencer par "réponse correcte". Réponds directement comme cela t'a été demandé.**
181
 
182
  **Important :** Tu n’as accès **qu'à la voix de l'opérateur**. Tu ne dois pas générer de contenu supplémentaire ni interpréter des éléments que tu ne peux pas entendre.
183
 
184
  ### **Exemple de réponse attendue :**
185
  **Opérateur :** "Il y a eu un accident, des blessés peut-être."
186
- **Réponse correcte :** "Demandez à l'appelant combien de blessés il y a."
187
 
188
  **Opérateur :** "Où est l’accident ?"
189
- **Réponse correcte :** "Demandez une adresse exacte ou un point de repère."
190
 
191
  **Voici la dernière déclaration ou question de l'opérateur :**
192
  {text_query}
193
 
194
- **Voici le contexte dont tu auras besoin pour répondre au mieux aux questions:**
195
- {context}
196
  """
197
 
198
  prompt = PromptTemplate(
@@ -233,8 +240,11 @@ def aide_telephonique_page():
233
  recent_messages = all_messages[-5:] # on garde les 5 derniers
234
 
235
  # Résumé de la conversation via le LLM
236
- summary = summarize_conversation(old_messages, llm)
237
-
 
 
 
238
  # Mettre à jour l'historique avec le résumé et les messages récents
239
  st.session_state.history = ChatMessageHistory()
240
  for msg in recent_messages:
@@ -362,6 +372,7 @@ def aide_telephonique_page():
362
 
363
  # Appel du LLM si le test de sécurité est accepté
364
  if filtre["status"] == "Accepté" and test_sim_cos:
 
365
  response = llm_chain.invoke(
366
  {
367
  "text_query": st.session_state.history.messages,
@@ -370,6 +381,12 @@ def aide_telephonique_page():
370
  ),
371
  }
372
  )
 
 
 
 
 
 
373
  st.session_state.history.add_ai_message(response)
374
  with st.chat_message("assistant"):
375
  st.markdown(response)
@@ -406,5 +423,19 @@ def aide_telephonique_page():
406
  # Résumé de la conversation via le LLM
407
  st.write("Résumé de la conversation :")
408
  messages = st.session_state.history.messages
409
- summary = summarize_conversation(messages, llm)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
  st.write(summary)
 
98
  llm_chain = prompt | llm
99
  start_time = time.time()
100
  summary = llm_chain.invoke({"conversation": conversation})
101
+ latency_summary = (time.time() - start_time) * 1000 # Convertir en ms
102
+ tokens_summary = len(summary.split())
103
+ return summary, latency_summary, tokens_summary
 
104
 
105
 
106
  def aide_telephonique_page():
 
116
  Cela peut être gênant en faussant les résultats du LLM.
117
  """
118
 
119
+ st.title("Requête du modèle")
120
+ st.subheader("Interrogez le LLM via votre voix ou texte")
 
 
121
 
122
  # Initialisation de l'état de session
123
  if "recording" not in st.session_state:
 
136
  st.session_state.message_count = 0
137
  if "session_id" not in st.session_state:
138
  st.session_state.session_id = str(uuid.uuid4())
139
+ if "latency_summary_list" not in st.session_state:
140
+ st.session_state.latency_summary_list = []
141
+ if "tokens_summary_list" not in st.session_state:
142
+ st.session_state.tokens_summary_list = []
143
+ if "latency_response_list" not in st.session_state:
144
+ st.session_state.latency_response_list = []
145
+ if "tokens_response_list" not in st.session_state:
146
+ st.session_state.tokens_response_list = []
147
 
148
  # Contrôles d'enregistrement
149
  col1, col2 = st.columns(2)
 
171
  st.info("Enregistrement en cours...")
172
 
173
  template = """
174
+ Tu es une IA conçue pour assister les agents des urgences en analysant leurs appels.
175
+
176
+ **Voici le contexte dont tu auras besoin pour répondre au mieux aux questions:**
177
+ {context}
178
 
179
  **Règles à respecter :**
180
  - Tu dois être **empathique, calme, direct et professionnel**.
 
185
  - **Tes réponses doivent toujours être en français, sauf si l'opérateur parle en anglais.**
186
  - **Formule tes réponses sous forme d’instructions précises pour l’opérateur.**
187
  - **Tes réponses doivent toujours être en français, correctes grammaticalement et sans faute de syntaxe.**
188
+ - **Tes réponses ne doivent jamais commencer en introduisant la réponse (ex: "réponse :"). Réponds directement comme cela t'a été demandé.**
189
 
190
  **Important :** Tu n’as accès **qu'à la voix de l'opérateur**. Tu ne dois pas générer de contenu supplémentaire ni interpréter des éléments que tu ne peux pas entendre.
191
 
192
  ### **Exemple de réponse attendue :**
193
  **Opérateur :** "Il y a eu un accident, des blessés peut-être."
194
+ "Demandez à l'appelant combien de blessés il y a."
195
 
196
  **Opérateur :** "Où est l’accident ?"
197
+ "Demandez une adresse exacte ou un point de repère."
198
 
199
  **Voici la dernière déclaration ou question de l'opérateur :**
200
  {text_query}
201
 
202
+ **Pour rappel** tu dois absolument répondre uniquement en français avec des réponses les plus courtes possibles.
 
203
  """
204
 
205
  prompt = PromptTemplate(
 
240
  recent_messages = all_messages[-5:] # on garde les 5 derniers
241
 
242
  # Résumé de la conversation via le LLM
243
+ summary, latency_summary, tokens_summary = summarize_conversation(
244
+ old_messages, llm
245
+ )
246
+ st.session_state.latency_summary_list.append(latency_summary)
247
+ st.session_state.tokens_summary_list.append(tokens_summary)
248
  # Mettre à jour l'historique avec le résumé et les messages récents
249
  st.session_state.history = ChatMessageHistory()
250
  for msg in recent_messages:
 
372
 
373
  # Appel du LLM si le test de sécurité est accepté
374
  if filtre["status"] == "Accepté" and test_sim_cos:
375
+ start_time = time.time()
376
  response = llm_chain.invoke(
377
  {
378
  "text_query": st.session_state.history.messages,
 
381
  ),
382
  }
383
  )
384
+ latency_response = (time.time() - start_time) * 1000 # ms
385
+ tokens_response = len(response.split())
386
+
387
+ st.session_state.latency_response_list.append(latency_response)
388
+ st.session_state.tokens_response_list.append(tokens_response)
389
+
390
  st.session_state.history.add_ai_message(response)
391
  with st.chat_message("assistant"):
392
  st.markdown(response)
 
423
  # Résumé de la conversation via le LLM
424
  st.write("Résumé de la conversation :")
425
  messages = st.session_state.history.messages
426
+ summary, latency_summary, tokens_summary = summarize_conversation(
427
+ messages, llm
428
+ )
429
+ st.session_state.latency_summary_list.append(latency_summary)
430
+ st.session_state.tokens_summary_list.append(tokens_summary)
431
+ total_latency_response = sum(st.session_state.latency_response_list)
432
+ total_tokens_response = sum(st.session_state.tokens_response_list)
433
+ total_latency_summary = sum(st.session_state.latency_summary_list)
434
+ total_tokens_summary = sum(st.session_state.tokens_summary_list)
435
+
436
+ track_metrics(
437
+ total_latency_response + total_latency_summary,
438
+ total_tokens_response + total_tokens_summary,
439
+ )
440
+
441
  st.write(summary)
app/views/dashboard.py CHANGED
@@ -1,5 +1,3 @@
1
- """ Tableau de bord des performances et de l'impact écologique et financier """
2
-
3
  import streamlit as st
4
  import plotly.express as px
5
 
@@ -13,6 +11,7 @@ CARBON_PER_QUERY = 0.8
13
  def track_metrics(latency, token_count):
14
  """Met à jour les métriques avec une nouvelle requête"""
15
 
 
16
  if "metrics" not in st.session_state:
17
  st.session_state.metrics = {
18
  "total_queries": 0,
@@ -40,23 +39,13 @@ def get_metrics():
40
 
41
 
42
  def dashboard_page():
43
- """Page permettant de visualiser les métriques de performance et d'impact"""
44
-
45
  st.title("Tableau de Bord des Performances")
46
  st.subheader("Suivi des performances et de l'impact")
47
 
48
  # si enregistrement en cours, on l'arrête
49
  arret_enregistrement()
50
 
51
- # Stocker les métriques globales
52
- if "metrics" not in st.session_state:
53
- st.session_state.metrics = {
54
- "total_queries": 0,
55
- "latency_history": [],
56
- "cost_history": [],
57
- "carbon_history": [],
58
- }
59
-
60
  metrics = get_metrics()
61
 
62
  col1, col2, col3 = st.columns(3)
@@ -66,32 +55,38 @@ def dashboard_page():
66
 
67
  if st.session_state.metrics["total_queries"] == 0:
68
  st.warning(
69
- "Aucune donnée disponible pour le moment. \
70
- Posez des questions pour générer des métriques."
71
  )
72
  return
73
 
74
- # if len(st.session_state.metrics["latency_history"]) > 0:
75
  st.subheader("📊 Visualisation des métriques")
76
 
77
  col1, col2 = st.columns(2)
78
 
79
  with col1:
80
- fig1 = px.line(
81
- x=list(range(1, len(st.session_state.metrics["latency_history"]) + 1)),
82
- y=st.session_state.metrics["latency_history"],
83
- labels={"x": "Numéro de la requête", "y": "Latence (ms)"},
84
- title="Latence par requête",
85
- color_discrete_sequence=["#1f8b4c"],
86
- )
87
- st.plotly_chart(fig1, use_container_width=True)
 
 
 
 
 
88
 
89
  with col2:
90
- fig2 = px.line(
91
- x=list(range(1, len(st.session_state.metrics["cost_history"]) + 1)),
92
- y=st.session_state.metrics["cost_history"],
93
- labels={"x": "Numéro de la requête", "y": "Coût (€)"},
94
- title="Coût cumulé des requêtes",
95
- color_discrete_sequence=["#1f8b4c"],
96
- )
97
- st.plotly_chart(fig2, use_container_width=True)
 
 
 
 
 
 
1
  import streamlit as st
2
  import plotly.express as px
3
 
 
11
  def track_metrics(latency, token_count):
12
  """Met à jour les métriques avec une nouvelle requête"""
13
 
14
+ # Initialiser les métriques globales si elles n'existent pas déja
15
  if "metrics" not in st.session_state:
16
  st.session_state.metrics = {
17
  "total_queries": 0,
 
39
 
40
 
41
  def dashboard_page():
42
+ """Affichage des métriques et graphiques"""
 
43
  st.title("Tableau de Bord des Performances")
44
  st.subheader("Suivi des performances et de l'impact")
45
 
46
  # si enregistrement en cours, on l'arrête
47
  arret_enregistrement()
48
 
 
 
 
 
 
 
 
 
 
49
  metrics = get_metrics()
50
 
51
  col1, col2, col3 = st.columns(3)
 
55
 
56
  if st.session_state.metrics["total_queries"] == 0:
57
  st.warning(
58
+ "Aucune donnée disponible pour le moment. Posez des questions pour générer des métriques."
 
59
  )
60
  return
61
 
 
62
  st.subheader("📊 Visualisation des métriques")
63
 
64
  col1, col2 = st.columns(2)
65
 
66
  with col1:
67
+ if st.session_state.metrics["latency_history"]:
68
+ fig1 = px.line(
69
+ x=list(range(1, len(st.session_state.metrics["latency_history"]) + 1)),
70
+ y=st.session_state.metrics["latency_history"],
71
+ labels={"x": "Numéro de la requête", "y": "Latence (ms)"},
72
+ title="Latence par requête",
73
+ color_discrete_sequence=["#1f8b4c"],
74
+ )
75
+ st.plotly_chart(fig1, use_container_width=True)
76
+ else:
77
+ st.warning(
78
+ "🚨 Aucune donnée de latence disponible pour générer le graphique."
79
+ )
80
 
81
  with col2:
82
+ if st.session_state.metrics["cost_history"]:
83
+ fig2 = px.line(
84
+ x=list(range(1, len(st.session_state.metrics["cost_history"]) + 1)),
85
+ y=st.session_state.metrics["cost_history"],
86
+ labels={"x": "Numéro de la requête", "y": "Coût (€)"},
87
+ title="Coût cumulé des requêtes",
88
+ color_discrete_sequence=["#1f8b4c"],
89
+ )
90
+ st.plotly_chart(fig2, use_container_width=True)
91
+ else:
92
+ st.warning("🚨 Aucune donnée de coût disponible pour générer le graphique.")
database/db_logsv2.db CHANGED
Binary files a/database/db_logsv2.db and b/database/db_logsv2.db differ
 
database/embed_s1000_o100/dcf34afb-fc87-46fb-9704-f9f238154972/length.bin CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:9f74697ebc9a797c33ddeedbee4a8b66e9b22d882f24bf4355c1fa77801824e8
3
  size 4000
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fc19b1997119425765295aeab72d76faa6927d4f83985d328c26f20468d6cc76
3
  size 4000
packages.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ portaudio19-dev
requirements.txt CHANGED
@@ -1,119 +1,23 @@
1
- accelerate==1.2.1
2
- aiohappyeyeballs==2.4.4
3
- aiohttp==3.11.11
4
- aiosignal==1.3.2
5
- asttokens
6
- async-timeout==5.0.1
7
- attrs==24.3.0
8
- audioread==3.0.1
9
- backcall
10
- certifi==2024.12.14
11
- cffi==1.17.1
12
- charset-normalizer==3.4.1
13
- click==8.1.8
14
- colorama
15
- comm
16
- contourpy==1.3.0
17
- cycler==0.12.1
18
- datasets==3.2.0
19
- debugpy
20
- decorator
21
- dill==0.3.8
22
- evaluate==0.4.3
23
- exceptiongroup
24
- executing
25
- fastapi
26
- filelock==3.16.1
27
- fonttools==4.55.3
28
- frozenlist==1.5.0
29
- fsspec==2024.9.0
30
- huggingface-hub==0.27.1
31
- idna==3.10
32
- importlib_metadata
33
- importlib_resources==6.5.2
34
- ipykernel
35
- ipython
36
- jedi
37
- Jinja2==3.1.5
38
- jiwer==3.0.5
39
- joblib==1.4.2
40
- jupyter_client
41
- jupyter_core
42
- kiwisolver==1.4.7
43
- langchain
44
- langchain_chroma
45
  langchain-community
46
- langchain_core
47
- langchain_huggingface
48
- langchain_mistralai
49
- # langchain_openai # passe par une api payante
50
- langgraph
51
- lazy_loader==0.4
52
- librosa==0.10.2.post1
53
- llvmlite==0.43.0
54
- MarkupSafe==3.0.2
55
- matplotlib==3.9.4
56
- matplotlib-inline
57
- mpmath==1.3.0
58
- msgpack==1.1.0
59
- multidict==6.1.0
60
- multiprocess==0.70.16
61
- nest-asyncio
62
- networkx==3.2.1
63
- numba==0.60.0
64
- # numpy==2.0.2
65
- packaging
66
  pandas==2.2.3
67
- parso
68
- pickleshare
69
- pillow==11.1.0
70
- platformdirs
71
- plotly
72
- pooch==1.8.2
73
- prompt-toolkit
74
- propcache==0.2.1
75
- psutil
76
- pure-eval
77
- pyarrow==18.1.0
78
- PyAudio==0.2.14
79
- pycparser==2.22
80
- pydantic
81
- Pygments
82
- pyparsing==3.2.1
83
- python-dateutil
84
- python-dotenv
85
- pytz==2024.2
86
- pywin32==308
87
- PyYAML==6.0.2
88
- pyzmq
89
- RapidFuzz==3.11.0
90
- regex==2024.11.6
91
- requests==2.32.3
92
- safetensors==0.5.2
93
- scikit-learn==1.6.1
94
- scipy==1.13.1
95
- seaborn==0.13.2
96
- sendgrid
97
- six
98
- sqlalchemy
99
- soundfile==0.13.0
100
- soxr==0.5.0.post1
101
- stack-data
102
- streamlit
103
- streamlit_option_menu
104
- sympy==1.13.1
105
- threadpoolctl==3.5.0
106
- tokenizers==0.21.0
107
  torch==2.5.1
108
- tornado
109
- tqdm==4.67.1
110
- traitlets
111
  transformers==4.48.0
112
- typing_extensions
113
- tzdata==2024.2
114
- urllib3==2.3.0
115
- uvicorn
116
- wcwidth
117
- xxhash==3.5.0
118
- yarl==1.18.3
119
- zipp
 
1
+ fastapi==0.115.8
2
+ langchain==0.3.17
3
+ langchain_chroma==0.2.1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  langchain-community
5
+ langchain_core==0.3.33
6
+ langchain_huggingface==0.1.2
7
+ langchain_mistralai==0.2.6
8
+ matplotlib==3.10.0
9
+ numpy
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  pandas==2.2.3
11
+ plotly==6.0.0
12
+ pyaudio
13
+ python-dotenv==1.0.1
14
+ rapidfuzz==3.12.1
15
+ Requests==2.32.3
16
+ scikit_learn==1.6.1
17
+ sendgrid==6.11.0
18
+ SQLAlchemy==2.0.37
19
+ streamlit==1.41.1
20
+ streamlit_option_menu==0.4.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  torch==2.5.1
 
 
 
22
  transformers==4.48.0
23
+ uvicorn==0.34.0
 
 
 
 
 
 
 
src/__pycache__/speech_to_text.cpython-311.pyc CHANGED
Binary files a/src/__pycache__/speech_to_text.cpython-311.pyc and b/src/__pycache__/speech_to_text.cpython-311.pyc differ
 
src/security/__pycache__/security_check.cpython-311.pyc CHANGED
Binary files a/src/security/__pycache__/security_check.cpython-311.pyc and b/src/security/__pycache__/security_check.cpython-311.pyc differ
 
src/security/__pycache__/security_report.cpython-311.pyc CHANGED
Binary files a/src/security/__pycache__/security_report.cpython-311.pyc and b/src/security/__pycache__/security_report.cpython-311.pyc differ
 
src/security/security_report.py CHANGED
@@ -20,7 +20,7 @@ FROM_EMAIL = os.getenv("FROM_EMAIL")
20
  RECIPIENT_EMAIL = os.getenv("RECIPIENT_EMAIL")
21
 
22
  # Chemin vers la DB
23
- db_path = "sqlite:///../../database/db_logs.db"
24
 
25
 
26
  class SecurityReport:
@@ -65,7 +65,7 @@ class SecurityReport:
65
  prompt.prompt AS prompt,
66
  prompt.response AS response,
67
  status.status AS status,
68
- origin.response AS origin
69
  FROM log
70
  LEFT JOIN prompt ON log.id_prompt = prompt.id_prompt
71
  LEFT JOIN status ON log.id_status = status.id_status
@@ -84,6 +84,8 @@ class SecurityReport:
84
  # Logs récupérés au format DataFrame
85
  df = pd.read_sql_query(query, conn, params=params)
86
  conn.close()
 
 
87
 
88
  return df
89
 
 
20
  RECIPIENT_EMAIL = os.getenv("RECIPIENT_EMAIL")
21
 
22
  # Chemin vers la DB
23
+ db_path = "sqlite:///../../database/db_logsv2.db"
24
 
25
 
26
  class SecurityReport:
 
65
  prompt.prompt AS prompt,
66
  prompt.response AS response,
67
  status.status AS status,
68
+ origin.origin AS origin
69
  FROM log
70
  LEFT JOIN prompt ON log.id_prompt = prompt.id_prompt
71
  LEFT JOIN status ON log.id_status = status.id_status
 
84
  # Logs récupérés au format DataFrame
85
  df = pd.read_sql_query(query, conn, params=params)
86
  conn.close()
87
+ df["timestamp"] = df["timestamp"].astype(str)
88
+ df= df.fillna("unknow")
89
 
90
  return df
91