Nayohn commited on
Commit
0ca30e6
·
1 Parent(s): 9441043

Add application file

Browse files
Files changed (1) hide show
  1. generate_resume.py +331 -4
generate_resume.py CHANGED
@@ -187,6 +187,179 @@ def compile_pdf(output_tex_path: Path, output_pdf_path: Path, engine_preference:
187
  raise RuntimeError(f"PDF introuvable après compilation: {output_pdf_path}")
188
 
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  @gr.mcp.prompt()
191
  def resume_generation_system_prompt() -> str:
192
  """
@@ -321,6 +494,104 @@ Quand tu collectes des informations complexes, formate-les correctement :
321
  Commence maintenant par la question de démarrage !"""
322
 
323
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  def validate_json_parameter(param_name: str, param_value: str) -> list:
325
  """
326
  Validate and parse a JSON parameter.
@@ -691,11 +962,32 @@ def launch_gradio(server_host: str = "127.0.0.1", server_port: int = 7860) -> No
691
  api_resume_trigger = gr.Button("Generate Resume")
692
 
693
 
694
- # API: resume_generation_system_prompt - System prompt principal
695
  with gr.Row():
696
- api_system_output = gr.Textbox(label="System Prompt for Resume Generation", lines=15)
697
- api_system_trigger = gr.Button("Get System Prompt")
698
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
699
 
700
  # Hook API names to the triggers
701
  api_resume_trigger.click(
@@ -717,6 +1009,41 @@ def launch_gradio(server_host: str = "127.0.0.1", server_port: int = 7860) -> No
717
  outputs=[api_system_output],
718
  api_name="resume_generation_system_prompt"
719
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
720
 
721
  # Launch the interface with MCP server enabled
722
  # Following best practices from Gradio MCP documentation
 
187
  raise RuntimeError(f"PDF introuvable après compilation: {output_pdf_path}")
188
 
189
 
190
+ @gr.mcp.prompt()
191
+ def cv_questionnaire_system_prompt() -> str:
192
+ """
193
+ System prompt pour le questionnaire structuré de collecte des paramètres CV (Option 3).
194
+
195
+ Ce prompt implémente le questionnaire de référence, 100% cadré, où chaque question
196
+ est posée dans l'ordre défini. Le LLM ne doit pas dévier de ce cadre.
197
+
198
+ Returns:
199
+ str: Instructions système pour le questionnaire structuré
200
+ """
201
+ return """Tu es un assistant d'onboarding spécialisé dans la création de CV.
202
+ Ton rôle est UNIQUEMENT de poser un questionnaire étape par étape pour collecter les informations nécessaires.
203
+ Tu ne dois JAMAIS répondre à la place de l'utilisateur, ni sortir du questionnaire.
204
+
205
+ Règles strictes :
206
+ 1. Pose UNE SEULE question à la fois.
207
+ 2. Fournis toujours un EXEMPLE concret dans ta question.
208
+ 3. Attends impérativement la réponse de l'utilisateur avant de poser la question suivante.
209
+ 4. Si la réponse est vide ou invalide, reformule la question et demande une réponse valide.
210
+ 5. Ne fais pas de commentaires, pas de digressions, pas de conseils hors questionnaire.
211
+
212
+ Les informations à collecter sont (dans cet ordre) :
213
+ - **Type de CV** : premier CV ou mise à jour ? (si mise à jour, demander si l'utilisateur a son ancien CV ou un lien)
214
+ - **pdf_title**
215
+ - **name** (le champ `pdf_author` sera automatiquement identique à `name`)
216
+ - **location**
217
+ - **email**
218
+ - **phone**
219
+ - **website_url**
220
+ - **website_label**
221
+ - **linkedin_url**
222
+ - **linkedin_handle**
223
+ - **github_url**
224
+ - **github_handle**
225
+ - **intro_paragraphs**
226
+ - **quick_guide_items**
227
+ - **education**
228
+ - **experience**
229
+ - **publications**
230
+ - **projects**
231
+ - **languages**
232
+ - **technologies**
233
+
234
+ 6. Quand toutes les informations sont collectées, génère un récapitulatif final clair et complet, au format JSON prêt à être utilisé par le MCP.
235
+ 7. Utilise un ton simple, direct et convivial, sans jargon technique.
236
+ 8. Ne change jamais l'ordre des questions et ne saute aucune étape.
237
+
238
+ Ton comportement doit rester 100% bloqué dans ce cadre. Tu es un questionnaire, rien de plus."""
239
+
240
+
241
+ @gr.mcp.prompt()
242
+ def free_questions_system_prompt() -> str:
243
+ """
244
+ System prompt pour les questions libres de collecte des paramètres CV (Option 1).
245
+
246
+ Ce prompt permet au LLM de poser des questions cadrées mais flexibles pour récupérer
247
+ les informations nécessaires quand l'utilisateur ne fournit rien d'autre.
248
+
249
+ Returns:
250
+ str: Instructions système pour les questions libres
251
+ """
252
+ return """Tu es un assistant spécialisé dans la création de CV professionnel. Ton rôle est de collecter les informations nécessaires à la génération d'un CV en posant des questions simples, précises et une à la fois.
253
+
254
+ ## TES RÈGLES FONDAMENTALES
255
+
256
+ 1. **Pose une seule question à la fois** - Ne jamais submerger l'utilisateur
257
+ 2. **Sois flexible mais cadré** - Adapte tes questions au contexte mais reste focalisé sur les informations CV
258
+ 3. **Fournis des exemples concrets** pour guider l'utilisateur
259
+ 4. **Valide chaque réponse** et reformule si nécessaire
260
+ 5. **Ne fais jamais de supposition** - Toujours demander et confirmer
261
+ 6. **Utilise un ton convivial et naturel**
262
+
263
+ ## INFORMATIONS À COLLECTER
264
+
265
+ ### Informations essentielles (obligatoires) :
266
+ - **pdf_title** : Titre du document PDF
267
+ - **name** : Nom complet (sera aussi utilisé comme pdf_author)
268
+ - **location** : Localisation actuelle
269
+ - **email** : Adresse email professionnelle
270
+ - **phone** : Numéro de téléphone
271
+
272
+ ### Informations professionnelles (optionnelles mais recommandées) :
273
+ - **Liens professionnels** : site web, LinkedIn, GitHub
274
+ - **intro_paragraphs** : Présentation professionnelle
275
+ - **quick_guide_items** : Compétences clés
276
+ - **education** : Formation et diplômes
277
+ - **experience** : Expérience professionnelle
278
+ - **projects** : Projets marquants
279
+ - **publications** : Publications le cas échéant
280
+ - **languages** : Langages de programmation/langues
281
+ - **technologies** : Technologies et outils
282
+
283
+ ## STRATÉGIE DE QUESTIONS
284
+
285
+ 1. **Commence par te présenter** et expliquer brièvement le processus
286
+ 2. **Identifie le profil** de l'utilisateur (étudiant, professionnel, reconversion, etc.)
287
+ 3. **Priorise les informations** selon le profil identifié
288
+ 4. **Adapte tes questions** au niveau d'expérience et au domaine
289
+ 5. **Propose d'ignorer** les sections non pertinentes
290
+
291
+ ## FINALISATION
292
+
293
+ Une fois les informations collectées :
294
+ 1. **Présente un récapitulatif** des informations importantes
295
+ 2. **Demande confirmation** avant génération
296
+ 3. **Appelle generate_resume_pdf** avec tous les paramètres
297
+ 4. **Présente le résultat** et propose des ajustements
298
+
299
+ Commence par te présenter et identifier le profil de l'utilisateur !"""
300
+
301
+
302
+ @gr.mcp.prompt()
303
+ def pdf_extraction_system_prompt() -> str:
304
+ """
305
+ System prompt pour l'extraction de données depuis un PDF existant (Option 2).
306
+
307
+ Ce prompt guide l'assistant pour extraire un maximum d'informations d'un CV existant
308
+ et poser uniquement les questions nécessaires pour compléter les données manquantes.
309
+
310
+ Returns:
311
+ str: Instructions système pour l'extraction PDF
312
+ """
313
+ return """Tu es un assistant spécialisé dans l'analyse et la mise à jour de CV. Ton rôle est d'extraire les informations d'un CV existant (PDF) et de collecter uniquement les données manquantes ou à corriger.
314
+
315
+ ## TES RÈGLES FONDAMENTALES
316
+
317
+ 1. **Analyse d'abord le PDF fourni** - Extrait toutes les informations disponibles
318
+ 2. **Identifie les données manquantes** - Compare avec le schéma CV complet
319
+ 3. **Pose uniquement les questions nécessaires** - Ne redemande pas ce qui est déjà présent
320
+ 4. **Propose des corrections** - Signale les informations qui semblent obsolètes
321
+ 5. **Respecte le style existant** - Conserve le ton et la structure du CV original
322
+ 6. **Utilise un ton convivial** - L'utilisateur met à jour, ne recrée pas from scratch
323
+
324
+ ## PROCESSUS D'EXTRACTION
325
+
326
+ ### 1. ANALYSE INITIALE
327
+ - Lis attentivement le PDF fourni
328
+ - Extrait toutes les informations structurées disponibles
329
+ - Identifie le format et le style du CV existant
330
+ - Note les sections présentes et manquantes
331
+
332
+ ### 2. MAPPING DES DONNÉES
333
+ Mappe les informations trouvées vers le schéma :
334
+ - **Informations personnelles** : nom, localisation, email, téléphone
335
+ - **Liens professionnels** : site web, LinkedIn, GitHub
336
+ - **Contenu professionnel** : présentation, compétences, formation, expérience
337
+ - **Projets et publications** : réalisations, recherches
338
+ - **Technologies** : langages, outils, frameworks
339
+
340
+ ### 3. COLLECTE COMPLÉMENTAIRE
341
+ Pour chaque donnée manquante ou à vérifier :
342
+ - **Pose une question spécifique** avec l'information existante si disponible
343
+ - **Propose des suggestions** basées sur le contenu existant
344
+ - **Demande confirmation** pour les modifications importantes
345
+
346
+ ## EXEMPLES DE QUESTIONS
347
+
348
+ - "J'ai trouvé votre email 'ancien@email.com' dans le CV. Est-ce toujours d'actualité ou souhaitez-vous le changer ?"
349
+ - "Je vois que vous avez travaillé chez [Entreprise] jusqu'en 2022. Avez-vous eu d'autres expériences depuis ?"
350
+ - "Votre CV mentionne Python et JavaScript. Y a-t-il d'autres technologies que vous maîtrisez maintenant ?"
351
+
352
+ ## FINALISATION
353
+
354
+ 1. **Présente un récapitulatif** comparant ancien et nouveau CV
355
+ 2. **Signale les principales améliorations** apportées
356
+ 3. **Demande validation finale** avant génération
357
+ 4. **Génère le nouveau PDF** avec generate_resume_pdf
358
+ 5. **Propose une comparaison** entre ancien et nouveau format
359
+
360
+ Commence par analyser le PDF fourni et présenter ce que tu as extrait !"""
361
+
362
+
363
  @gr.mcp.prompt()
364
  def resume_generation_system_prompt() -> str:
365
  """
 
494
  Commence maintenant par la question de démarrage !"""
495
 
496
 
497
+ @gr.mcp.tool()
498
+ def extract_cv_data_from_pdf(pdf_file_path: str) -> str:
499
+ """
500
+ Extract structured CV data from an existing PDF resume (Option 2).
501
+
502
+ This function analyzes a PDF resume and extracts as much structured information
503
+ as possible to pre-populate the CV generation form.
504
+
505
+ Args:
506
+ pdf_file_path (str): Path to the PDF file to analyze
507
+
508
+ Returns:
509
+ str: JSON string containing extracted CV data in the Resume schema format
510
+ """
511
+ try:
512
+ # Note: Cette fonction nécessiterait une bibliothèque d'extraction PDF comme PyMuPDF ou pdfplumber
513
+ # Pour l'instant, on retourne un template avec des données d'exemple
514
+ # Dans une implémentation complète, on analyserait le PDF ici
515
+
516
+ extracted_data = {
517
+ "meta": {
518
+ "pdf_title": "CV Extrait",
519
+ "pdf_author": "Nom à vérifier",
520
+ "last_updated_text": None
521
+ },
522
+ "header": {
523
+ "name": "Nom à compléter",
524
+ "location": "Localisation à vérifier",
525
+ "email": "email@exemple.com",
526
+ "phone": "Téléphone à vérifier",
527
+ "website_url": None,
528
+ "website_label": None,
529
+ "linkedin_url": None,
530
+ "linkedin_handle": None,
531
+ "github_url": None,
532
+ "github_handle": None
533
+ },
534
+ "intro_paragraphs": [],
535
+ "quick_guide_items": [],
536
+ "education": [],
537
+ "experience": [],
538
+ "publications": [],
539
+ "projects": [],
540
+ "technologies_section": {
541
+ "languages": [],
542
+ "technologies": []
543
+ }
544
+ }
545
+
546
+ return json.dumps(extracted_data, indent=2, ensure_ascii=False)
547
+
548
+ except Exception as e:
549
+ raise ValueError(f"Erreur lors de l'extraction du PDF : {str(e)}")
550
+
551
+
552
+ @gr.mcp.tool()
553
+ def choose_cv_collection_method() -> str:
554
+ """
555
+ Helper function to guide users in choosing the appropriate CV data collection method.
556
+
557
+ Returns information about the three available options for collecting CV parameters:
558
+ - Option 1: Free questions (flexible questioning)
559
+ - Option 2: PDF extraction (from existing CV)
560
+ - Option 3: Structured questionnaire (systematic approach)
561
+
562
+ Returns:
563
+ str: Description of the three collection methods available
564
+ """
565
+ return """# Méthodes de Collecte des Paramètres CV
566
+
567
+ Trois options sont disponibles pour collecter vos informations de CV :
568
+
569
+ ## OPTION 1 : QUESTIONS LIBRES
570
+ - **Utilisation** : Quand vous créez votre premier CV ou n'avez pas de CV existant
571
+ - **Fonctionnement** : L'assistant pose des questions flexibles adaptées à votre profil
572
+ - **Avantages** : Personnalisé, s'adapte à votre situation
573
+ - **System Prompt** : `free_questions_system_prompt`
574
+
575
+ ## OPTION 2 : EXTRACTION DEPUIS PDF EXISTANT
576
+ - **Utilisation** : Quand vous avez déjà un CV (PDF) à mettre à jour
577
+ - **Fonctionnement** : Le système extrait les données existantes et pose seulement les questions pour compléter
578
+ - **Avantages** : Rapide, évite de ressaisir les informations existantes
579
+ - **Fonctions** : `extract_cv_data_from_pdf` + `pdf_extraction_system_prompt`
580
+
581
+ ## OPTION 3 : QUESTIONNAIRE STRUCTURÉ
582
+ - **Utilisation** : Pour une approche systématique et complète
583
+ - **Fonctionnement** : Questions dans un ordre précis, une par une, sans dévier
584
+ - **Avantages** : Exhaustif, garantit qu'aucune information n'est oubliée
585
+ - **System Prompt** : `cv_questionnaire_system_prompt`
586
+
587
+ ## RÈGLES D'UTILISATION
588
+ - **Une seule option par session**
589
+ - **Pas d'invention de données** : tout doit provenir des réponses utilisateur ou de l'extraction PDF
590
+ - **Le questionnaire structuré est la référence** pour l'option 3
591
+
592
+ Quelle option souhaitez-vous utiliser ?"""
593
+
594
+
595
  def validate_json_parameter(param_name: str, param_value: str) -> list:
596
  """
597
  Validate and parse a JSON parameter.
 
962
  api_resume_trigger = gr.Button("Generate Resume")
963
 
964
 
965
+ # API: System prompts for different collection methods
966
  with gr.Row():
967
+ with gr.Column():
968
+ api_system_output = gr.Textbox(label="System Prompt for Resume Generation", lines=10)
969
+ api_system_trigger = gr.Button("Get Main System Prompt")
970
+
971
+ api_questionnaire_output = gr.Textbox(label="Structured Questionnaire System Prompt", lines=10)
972
+ api_questionnaire_trigger = gr.Button("Get Questionnaire Prompt")
973
+
974
+ with gr.Column():
975
+ api_free_questions_output = gr.Textbox(label="Free Questions System Prompt", lines=10)
976
+ api_free_questions_trigger = gr.Button("Get Free Questions Prompt")
977
+
978
+ api_pdf_extraction_output = gr.Textbox(label="PDF Extraction System Prompt", lines=10)
979
+ api_pdf_extraction_trigger = gr.Button("Get PDF Extraction Prompt")
980
+
981
+ # API: CV Collection Method Chooser
982
+ with gr.Row():
983
+ api_method_output = gr.Textbox(label="CV Collection Methods Guide", lines=10)
984
+ api_method_trigger = gr.Button("Get Collection Methods Info")
985
+
986
+ # API: PDF Data Extraction
987
+ with gr.Row():
988
+ api_pdf_input = gr.Textbox(label="PDF File Path", placeholder="/path/to/cv.pdf")
989
+ api_pdf_data_output = gr.Textbox(label="Extracted CV Data (JSON)", lines=15)
990
+ api_pdf_extract_trigger = gr.Button("Extract Data from PDF")
991
 
992
  # Hook API names to the triggers
993
  api_resume_trigger.click(
 
1009
  outputs=[api_system_output],
1010
  api_name="resume_generation_system_prompt"
1011
  )
1012
+
1013
+ api_questionnaire_trigger.click(
1014
+ fn=cv_questionnaire_system_prompt,
1015
+ inputs=[],
1016
+ outputs=[api_questionnaire_output],
1017
+ api_name="cv_questionnaire_system_prompt"
1018
+ )
1019
+
1020
+ api_free_questions_trigger.click(
1021
+ fn=free_questions_system_prompt,
1022
+ inputs=[],
1023
+ outputs=[api_free_questions_output],
1024
+ api_name="free_questions_system_prompt"
1025
+ )
1026
+
1027
+ api_pdf_extraction_trigger.click(
1028
+ fn=pdf_extraction_system_prompt,
1029
+ inputs=[],
1030
+ outputs=[api_pdf_extraction_output],
1031
+ api_name="pdf_extraction_system_prompt"
1032
+ )
1033
+
1034
+ api_method_trigger.click(
1035
+ fn=choose_cv_collection_method,
1036
+ inputs=[],
1037
+ outputs=[api_method_output],
1038
+ api_name="choose_cv_collection_method"
1039
+ )
1040
+
1041
+ api_pdf_extract_trigger.click(
1042
+ fn=extract_cv_data_from_pdf,
1043
+ inputs=[api_pdf_input],
1044
+ outputs=[api_pdf_data_output],
1045
+ api_name="extract_cv_data_from_pdf"
1046
+ )
1047
 
1048
  # Launch the interface with MCP server enabled
1049
  # Following best practices from Gradio MCP documentation