Spaces:
Sleeping
Sleeping
File size: 16,606 Bytes
22dc1a7 133efee 22dc1a7 1727bbe 660490c 133efee 22dc1a7 9f5c642 e507f01 22dc1a7 e507f01 660490c 02affac 3c0cc99 9bd12aa 3c0cc99 22dc1a7 2098c14 22dc1a7 2098c14 22dc1a7 7c32141 22dc1a7 9f5c642 22dc1a7 7c32141 22dc1a7 9f5c642 22dc1a7 9f5c642 f34e7a9 55db01c 22dc1a7 e507f01 2098c14 22dc1a7 e507f01 2098c14 22dc1a7 9f5c642 22dc1a7 9f5c642 22dc1a7 e507f01 2098c14 22dc1a7 fb1e952 ec1843b 22dc1a7 002e137 ec1843b 1d1f54f 02affac 22dc1a7 133efee b0102ad |
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 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
import requests
import json
import gradio as gr
import logging
from urllib.parse import urlparse, parse_qs
from gradio import Request
logging.basicConfig(level=logging.ERROR)
logger = logging.getLogger(__name__)
# Clés API et informations
OPENROUTER_API_KEY = "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"
AIRTABLE_API_KEY = "patUUQ6NE9zUOqooM.ec8d096169d754852305c88c7966ad1f8a151f3bf015d39f80bb895bdad0e2f5"
AIRTABLE_BASE_ID = "appht9RdYAQVd32Py"
AIRTABLE_TABLE_NAME = "DescriptionsEtudiants"
YOUR_SITE_URL = "votre-site.com"
YOUR_APP_NAME = "MonChatbot"
# ID de l'étudiant
#student_id = 34
def getParams(x, request: gr.Request):
params = request.query_params
if 'name' in params:
return params['name']
else:
return None
def get_id_by_name(student_name):
url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/Inscription_Etudiants"
headers = {
"Authorization": f"Bearer {AIRTABLE_API_KEY}",
"Content-Type": "application/json"
}
# Filtrer les enregistrements par ID_Etu
params = {
"filterByFormula": f"FIND('{student_name}', {{Nom}})"
}
try:
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
if len(data['records']) > 0:
record = data['records'][0] # On prend le premier enregistrement correspondant
student_id = record['fields'].get('ID_Etu', 'Aucun id trouvé')
user_email = record['fields'].get('Email', 'Aucun email trouvé')
return student_id, user_email
else:
return None, None
else:
logger.error(f"Erreur lors de la récupération des informations : {response.status_code} - {response.text}")
return None, None
except Exception as e:
logger.error(f"Erreur lors de la récupération des informations : {str(e)}")
return None, None
def get_student_description(student_id):
url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE_NAME}"
headers = {
"Authorization": f"Bearer {AIRTABLE_API_KEY}",
"Content-Type": "application/json"
}
try:
response = requests.get(url, headers=headers)
if response.status_code == 200:
data = response.json()
if 'records' in data:
for record in data['records']:
if record['fields'].get('ID_Etudiant') == student_id:
return record['fields'].get('Description Compétences Etudiants', 'Pas de description trouvée.')
return "Aucun enregistrement trouvé pour cet étudiant."
else:
logger.error(f"Erreur lors de la récupération de la description : {response.status_code} - {response.text}")
return f"Erreur lors de la récupération : {response.status_code} - {response.text}"
except Exception as e:
logger.error(f"Erreur lors de la récupération : {str(e)}")
return "Erreur lors de la récupération."
def update_student_description(student_id, new_description):
# Étape 1 : Récupérer tous les enregistrements
url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE_NAME}"
headers = {
"Authorization": f"Bearer {AIRTABLE_API_KEY}",
"Content-Type": "application/json"
}
try:
response = requests.get(url, headers=headers)
if response.status_code == 200:
data = response.json()
# Étape 2 : Trouver l'enregistrement correspondant à student_id
record_to_update = None
for record in data.get('records', []):
if 'fields' in record and record['fields'].get('ID_Etudiant') == student_id:
record_to_update = record
break
if record_to_update:
# Étape 3 : Mettre à jour la description
record_id = record_to_update['id']
update_url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE_NAME}/{record_id}"
update_data = {
"fields": {
"Description Compétences Etudiants": new_description
}
}
update_response = requests.patch(update_url, headers=headers, json=update_data)
if update_response.status_code == 200:
return "Description mise à jour avec succès."
else:
logger.error(f"Erreur lors de la mise à jour : {update_response.status_code} - {update_response.text}")
return "Erreur lors de la mise à jour."
else:
return "Aucun étudiant trouvé avec cet ID."
else:
logger.error(f"Erreur lors de la récupération des enregistrements : {response.status_code} - {response.text}")
return "Erreur lors de la récupération des enregistrements."
except Exception as e:
logger.error(f"Erreur lors de la mise à jour : {str(e)}")
return "Erreur lors de la mise à jour."
def call_api_for_response_analysis(current_skills, user_response):
messages = [
{
"role": "system",
"content": "Tu es un expert en analyse de compétences. En fonction de la réponse de l'utilisateur, "
"tu dois reformuler et mettre à jour les compétences actuelles. "
"Retourne uniquement la nouvelle description des compétences mise à jour."
},
{
"role": "user",
"content": f"Compétences actuelles :\n{current_skills}\n\n"
f"Réponse de l'utilisateur :\n{user_response}\n\n"
"Reformule les compétences en prenant en compte la réponse de l'utilisateur."
}
]
try:
api_response = requests.post(
url="https://openrouter.ai/api/v1/chat/completions",
headers={
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
"Content-Type": "application/json"
},
data=json.dumps({
"model": "google/gemma-2-9b-it:free",
"messages": messages
})
)
if api_response.status_code == 200:
data = api_response.json()
return data['choices'][0]['message']['content']
else:
logger.error(f"Erreur lors de l'analyse de la réponse : {api_response.status_code} - {api_response.text}")
return "Erreur lors de l'analyse de la réponse."
except Exception as e:
logger.error(f"Erreur lors de l'appel API: {str(e)}")
return "Erreur lors de l'appel API."
def get_enterprise_descriptions():
url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/Formulaire firm"
headers = {
"Authorization": f"Bearer {AIRTABLE_API_KEY}",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
data = response.json()
firm_data = [
(
record['fields'].get('Recruteur / Entreprise'),
record['fields'].get('Compétences requises'),
record['fields'].get('ID_Offre'),
record['fields'].get('email')
)
for record in data['records']
]
return firm_data
else:
logger.error(f"Erreur lors de la récupération des descriptions d'entreprises : {response.status_code} - {response.text}")
return []
def compare_skills_ai(student_skills, enterprise_skills):
messages = [
{"role": "system", "content": "Vous êtes un expert en recrutement chargé d'évaluer la correspondance entre les compétences d'un étudiant et celles requises par une entreprise. Votre tâche est d'analyser ces compétences et de fournir une valeur de correspondance entre l'étudiant et les différentes entreprise, je veux simplement la note global pour chaque entreprise. Tenez compte des compétences similaires ou complémentaires, pas seulement des correspondances exactes."},
{"role": "user", "content": f"Compétences de l'étudiant :\n{student_skills}\n\nCompétences requises par l'entreprise :\n{enterprise_skills}\n\nVeuillez analyser ces compétences et fournir un chiffre entre 0 et 100 pour la correspondance entre l'etudiant et l'entreprise afin de voir le taux de compatibilité entre l'etudiants et les différentes entreprises. ne détaille rien, juste la note global sans le détail. Ecrit que et uniquement le score, par exemple : 100 et pas : Score : 100, juste 100. Sans tiret nin rien juste le nombre"}
]
try:
response = requests.post(
url="https://openrouter.ai/api/v1/chat/completions",
headers={
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
"HTTP-Referer": f"{YOUR_SITE_URL}",
"X-Title": f"{YOUR_APP_NAME}",
"Content-Type": "application/json"
},
data=json.dumps({
"model": "google/gemma-2-9b-it:free",
"messages": messages
})
)
if response.status_code == 200:
data = response.json()
ai_analysis = data['choices'][0]['message']['content']
try:
score = int(ai_analysis.strip())
return score
except ValueError:
logger.error(f"Erreur lors de la conversion du score : la réponse était '{ai_analysis}'")
return "Erreur lors de l'analyse des compétences : score non valide."
else:
logger.error(f"Erreur lors de l'appel à l'API : {response.status_code} - {response.text}")
return "Erreur lors de l'analyse des compétences."
except Exception as e:
logger.error(f"Erreur lors de l'appel API: {str(e)}")
return f"Erreur lors de l'analyse des compétences : {str(e)}"
def update_compatibility_table(student_id, skill_assessment, enterprise_skills, offer_id, compatibility_rate, student_name, student_mail, emailEntreprise, enterprise_name):
url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/TauxCompatibilité"
headers = {
"Authorization": f"Bearer {AIRTABLE_API_KEY}",
"Content-Type": "application/json"
}
data = {
"fields": {
"ID_Etu": student_id,
"DescriptionEtu": skill_assessment,
"ID_Offre": offer_id,
"DescriptionOffre": enterprise_skills,
"Taux de compatibilité" : compatibility_rate,
"Nom": student_name,
"EmailEtudiant": student_mail,
"EmailEntreprise": emailEntreprise,
"Nom_Recruteur_Entreprise": enterprise_name,
"Postuler": "Non"
}
}
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
return "Données ajoutées avec succès !"
else:
logger.error(f"Erreur lors de l'ajout à la table de compatibilité : {response.status_code} - {response.text}")
return f"Erreur lors de l'ajout à la table de compatibilité : {response.status_code}"
except Exception as e:
logger.error(f"Erreur lors de l'ajout à Airtable : {str(e)}")
return f"Erreur lors de l'ajout à Airtable : {str(e)}"
def delete_compatibility_records(student_id):
"""
Supprime tous les enregistrements de la table TauxCompatibilité associés à un étudiant donné (ID_Etu).
"""
url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/TauxCompatibilité"
headers = {
"Authorization": f"Bearer {AIRTABLE_API_KEY}",
"Content-Type": "application/json"
}
try:
# Récupérer les enregistrements existants pour l'ID_Etu donné
response = requests.get(url, headers=headers)
response.raise_for_status()
records = response.json().get('records', [])
# Supprimer les enregistrements existants avec l'ID_Etu correspondant
for record in records:
if record['fields'].get('ID_Etu') == student_id:
delete_url = f"{url}/{record['id']}"
delete_response = requests.delete(delete_url, headers=headers)
delete_response.raise_for_status() # Vérifier si la suppression a réussi
return "Suppression des enregistrements existants réussie."
except Exception as e:
logger.error(f"Erreur lors de la suppression des enregistrements : {str(e)}")
return f"Erreur lors de la suppression des enregistrements : {str(e)}"
def start_conversation(request: gr.Request):
student_name = getParams(None, request)
student_id, student_mail = get_id_by_name(student_name)
description = get_student_description(student_id)
initial_message = f"Bienvenue ! Voici vos compétences :\n{description}\n\nQue souhaitez-vous modifier ou améliorer dans vos compétences ?"
return [[None, initial_message]], description
def chatbot_conversation(message, history, request: gr.Request):
student_name = getParams(None, request)
student_id, student_mail = get_id_by_name(student_name)
current_skills = get_student_description(student_id)
# Analyse la réponse et obtient les compétences mises à jour
updated_skills = call_api_for_response_analysis(current_skills, message)
enterprise_descriptions = get_enterprise_descriptions()
results = []
delete_compatibility_records(student_id)
for enterprise_name, enterprise_desc, offer_id, emailEntreprise in enterprise_descriptions:
analysis = compare_skills_ai(updated_skills, enterprise_desc)
add_response = update_compatibility_table(student_id, updated_skills, enterprise_desc, offer_id, analysis, student_name, student_mail, emailEntreprise, enterprise_name)
results.append(f"Entreprise : {enterprise_name}\n{add_response}")
# Prépare la réponse pour le chatbot
response = "Voici la version mise à jour de vos compétences :\n\n" + updated_skills
history.append((message, response))
return history, updated_skills
def validate_update(updated_skills, request: gr.Request):
student_name = getParams(None, request)
student_id, student_mail = get_id_by_name(student_name)
response = update_student_description(student_id, updated_skills)
return response
def open_url():
return f'<a href="https://albatrossstudent.softr.app" target="_blank">Cliquez ici pour retourner au site.</a>'
with gr.Blocks() as demo:
gr.HTML("""
<style>
#scroll-container {
max-height: 80vh; /* Limite la hauteur du conteneur */
overflow-y: auto; /* Permet le défilement vertical */
padding: 20px; /* Optionnel : ajoute un peu d'espace autour */
}
</style>
""")
with gr.Row(elem_id="scroll-container"):
with gr.Column(scale=1):
chatbot = gr.Chatbot(label="Chatbot", elem_id="chatbot") # Chatbot pour la conversation
msg = gr.Textbox(label="Message", placeholder="Tapez votre message ici...") # Champ de texte pour envoyer des messages
skill_assessment_output = gr.Textbox(label="Compétences actuelles", interactive=False) # Sortie des compétences
validate_button = gr.Button("Valider la mise à jour") # Bouton pour valider la mise à jour
validation_output = gr.Textbox(label="Résultat de la mise à jour", interactive=False)
button = gr.Button("Retour au site")
output = gr.HTML()
button.click(open_url, outputs=output)
msg.submit(fn=chatbot_conversation,
inputs=[msg, chatbot],
outputs=[chatbot, skill_assessment_output])
# Action du bouton pour mettre à jour la description
validate_button.click(fn=validate_update, inputs=skill_assessment_output, outputs=validation_output) # Utilisation du bloc validation_output
# Chargement initial du message de bienvenue
demo.load(start_conversation,
inputs=None,
outputs=[chatbot, skill_assessment_output])
if __name__ == "__main__":
demo.launch(share=True) |