-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprompt.py
219 lines (191 loc) · 10.7 KB
/
prompt.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
import logging
import re
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.prompts.chat import (ChatPromptTemplate,
HumanMessagePromptTemplate,
SystemMessagePromptTemplate)
from langchain.vectorstores import Chroma
from langchain.schema import HumanMessage, SystemMessage, AIMessage
import constants
log_format = "%(asctime)s - %(levelname)s - %(message)s"
logging.basicConfig(format=log_format, level=logging.INFO)
# Import conditionnel selon si on est sur les API officielles d'OpenAI ou sur Azure.
if constants.OPENAI_API_TYPE == "azure":
from langchain.chat_models import AzureChatOpenAI as Chat
else:
from langchain.chat_models import ChatOpenAI as Chat
# Configure le logger
logging.basicConfig(format='%(levelname)s: %(message)s',
encoding='utf-8', level=logging.INFO)
# template du prompt Système
SYSTEM_PROMPT = """
Tu es un chatbot ARM. Assistant médical de régulation. Ton rôle est de pré-qualifier les appels entrants pour le SAMU pour faciliter le travail des ARM.
Tu dois IMPERATIVEMENT transférer l'appel vers un ARM s'il s'agit d'une urgence (niveau 1 : Urgence vitale / niveau 2 : Urgence absolue) en expliquant la qualification de l'urgence
Une fois le l'absence d'urgence avérée, tu peux consolider les informations suivantes dans cet ordre de priorité : Adresse complète, avec des détails spécifiques si nécessaire (étage, appartement, points de repère); Numéro de téléphone de rappel ; Nature de l'urgence ; État de la personne en détresse ; Antécédents médicaux ; Identité et âge de la personne concernée ; Circonstances spécifiques.
Ne pose pas des questions sur plusieurs thématiques en même temps pour rendre la discussion plus naturelle.
Parle dans la langue de l'appelant
Tu ne doit JAMAIS dire « mais il est important de noter que » ou « en tant que modèle de langage d'IA ».
Pour information voici les missions de l'ARM :
RM1 . recueil des données administratives de l'appelant: numéro de téléphone, adresse complète, identité (appelant,
patient) ...
ARM2. écoute de la demande, dialogue empathique et qualification de l'appel.
ARM3. recherche de signes d'une détresse vitale (et engagement réflexe éventuel des moyens).
ARM4. priorisation de la régulation médicale.
ARMS. transmission d'une synthèse ()motif de recours) au médecin régulateur.
MR1. phase de reconnaissance sur la base de la synthèse effectuée par l'ARM.
MR2, interrogatoire médical: analyse du contexte, des demandes et attentes du patient; recherche des antécédents
médicaux, des traitements, des facteurs de risque; qualification du besoin de soins; si nécessaire, hypothèses
diagnostiques ou pronostiques.
MR3. estimation des risques de la situation en regard des bénéfices attendus des différentes prises en charge possibles;
respect du libre choix du patient; décision : choix des moyens adaptés et éventuellement leur composition.
MR4. information de l'appelant et contrat de soins; mise en œuvre d'une éventuelle prescription.
demander à l'appelant de laisser libre la ligne téléphonique.
ARM6. déclenchement des moyens, mise en œuvre des décisions du médecin régulateur.
MRS. conseils en attendant l'arrivée des secours; anticipation de chacune des étapes de la prise en charge du patient.
ARM7. suivi de l'intervention ; réception des messages secouristes ; conseils éventuels; rappel systématique une heure
après dispensation d'un conseil médical se référer à la procédure « rappel »).
MR6. transmission de l'information médicale utile aux intervenants.
ARM8. recherche de lits d'aval si besoin.
MR7. suivi de l'intervention, réception des messages médicaux et parfois secouristes, conseils et assistance aux éventuels
intervenants, codification de la partie régulation médicale.
ARM9. recherche de compléments d'information administrative, finalisation du dossier (codification de la partie
qualification, éditions éventuelles ...).
MR8. si besoin: préparation de l'accueil dans un établissement de soins; recueil de l'accord du service receveur; respect
du libre choix du patient.
ARM10. clôture du dossier administratif.
MR9. clôture du dossier médical.
MR10. clôture du dossier de régulation médicale (DRM).».
===========
Niveau d'urgence :
{urgency}
===========
Contexte:
{context}
===========
Historique réponses:
{reponses}
===========
"""
CHAT = Chat(model_name=constants.MODEL_NAME, temperature=constants.TEMPERATURE)
DB = Chroma(persist_directory=constants.DATABASE_DIR,
embedding_function=OpenAIEmbeddings(
deployment=constants.OPENAI_DEPLOYMENT_NAME,
model=constants.EMBEDDINGS_MODEL,
openai_organization=constants.OPENAI_ORGANIZATION,
openai_api_base=constants.OPENAI_API_BASE,
openai_api_version=constants.OPENAI_API_VERSION))
def format_context(results):
"""Formate les résultats de la recherche pour les inclure dans le contexte."""
context = ""
for result in results:
context += f"{result.page_content}\n"
return context
def ask_question(question, urgency, reponse_history):
"""Poser une question au modèle."""
# Cherche des chunks de textes similaires à la question
results = DB.as_retriever(search_type="similarity", search_kwargs={'k': 3}).get_relevant_documents(query=question)
# Nettoie le résultats des caractères problématiques {}
for result in results:
result.page_content = re.sub(r'\{', '', result.page_content)
result.page_content = re.sub(r'\}', '', result.page_content)
logging.info("Sources: %s", results)
# Formate le contexte à partir des résultats
context = format_context(results)
# Constitue la séquence de chat avec le conditionnement du bot et la question de l'utilisateur
system_message_prompt = SystemMessagePromptTemplate.from_template(SYSTEM_PROMPT.format(urgency=urgency, context=context, reponses=reponse_history))
human_message_prompt = HumanMessagePromptTemplate.from_template("QUESTION: {question}")
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
# Ajouter l'historique des messages
messages = chat_prompt.format_prompt(context=context, question=question).to_messages()
# Log messages pour débogage
logging.info("Messages: %s", messages)
# Pose la question au LLM
response = CHAT(messages).content
logging.info("Réponse: %s", response)
return response, results
def sentiment_analysis(question):
"""Analyser le sentiment d'une question avec le modèle."""
# Constitue la séquence de chat avec le conditionnement du bot et la question
# de l'utilisateur
system_message_prompt = SystemMessagePromptTemplate.from_template(
"""Vous êtes un modèle de langage formé par OpenAI.
Concentre ton analyse sur l'utilisateur qui appelle le SAMU
Votre tâche est d'analyser le sentiment du texte suivant :""")
human_message_prompt = HumanMessagePromptTemplate.from_template(
"{question}")
chat_prompt = ChatPromptTemplate.from_messages(
[system_message_prompt, human_message_prompt]
)
messages = chat_prompt.format_prompt(
question=question
).to_messages()
# Pose la question au LLM
response = CHAT(messages).content
logging.info("Sentiment: %s", response)
return response
def categorize_urgency(question):
"""Catégorise l'urgence d'un texte en fonction de sa similarité avec les descriptions des niveaux d'urgence."""
# Constitue la séquence de chat avec le conditionnement du bot et la question
# de l'utilisateur
system_message_prompt = SystemMessagePromptTemplate.from_template(
"""Vous êtes un modèle de langage formé par OpenAI.
Votre tâche est d'analyser le sentiment pour déterminer le niveau d'urgence sur une échelle de 1 à 5 :
Niveau 1 : Urgence vitale, Niveau 2 : Urgence absolue, Niveau 3 : Urgence relative, Niveau 4 : Consultation médicale urgente, Niveau 5 : Consultation non urgente, Niveau 6 : Fausse alerte.
Concentre ton analyse sur l'utilisateur qui appelle le SAMU
Commence ta réponse par le niveau identifié""")
human_message_prompt = HumanMessagePromptTemplate.from_template(
"{question}")
chat_prompt = ChatPromptTemplate.from_messages(
[system_message_prompt, human_message_prompt]
)
messages = chat_prompt.format_prompt(
question=question
).to_messages()
# Pose la question au LLM
response = CHAT(messages).content
logging.info("Urgency question: %s", question)
logging.info("Urgency message: %s", messages)
logging.info("Urgency response: %s", response)
return response
def summarize_call_informations(question):
"""Résumer les informations d'un appel."""
system_message_prompt = SystemMessagePromptTemplate.from_template(
"""Vous êtes un modèle de langage formé par OpenAI. Votre tâche est de résumer les informations d'un appel.
En mettant en avant les informations suivantes : Adresse complète, Numéro de téléphone de rappel, Nature de l'urgence, État de la personne en détresse, Antécédents médicaux, Identité et âge de la personne concernée, Circonstances spécifiques.
En l'absence d'information, dit juste : Aucune information collectée.
Fait une réponse sous format liste à puce""")
human_message_prompt = HumanMessagePromptTemplate.from_template(
"{question}")
chat_prompt = ChatPromptTemplate.from_messages(
[system_message_prompt, human_message_prompt]
)
messages = chat_prompt.format_prompt(
question=question
).to_messages()
# Pose la question au LLM
response = CHAT(messages).content
return response
if __name__ == "__main__":
print("""
👨💼👩💼 ARM 💬
Posez simplement votre question:
""")
print("----------------------------------------------------")
print("💬 Votre question: ")
while True:
question = input()
if question.lower() in ["exit", "quit"]:
break
answer, sources = ask_question(question)
print("----------------------------------------------------")
print("🤖 Réponse de l'expert: ")
print(answer)
print("----------------------------------------------------")
print("📚 Documents utilisés: ")
unique_sources = set()
for source in sources:
unique_sources.add((source.metadata['source'], source.metadata['page']))
for source in unique_sources:
print(f"- Document: {source[0]}, Page: {source[1]}")
print("----------------------------------------------------")
print("Posez une autre question ou tapez 'exit' pour quitter.")