Le Contexte Stratégique : L'Augmentation Cognitive du Candidat
Le marché de l'emploi moderne est un problème de "signal/bruit". Des centaines d'offres (le bruit) masquent quelques opportunités réellement pertinentes (le signal). Une approche purement manuelle est épuisante et inefficace, tandis qu'une automatisation totale manque de discernement.
La thèse de ce projet : La solution la plus efficace n'est pas de remplacer l'humain, mais de l'augmenter. Cet agent est conçu comme un **système d'aide à la décision**, où l'humain reste le stratège et l'IA un puissant outil d'analyse tactique, activé à la demande.
I. Prérequis et Mise en Place de l'Environnement
Un projet de cette nature exige une base de travail propre et reproductible. L'utilisation d'un environnement virtuel est une pratique non négociable en Python pour isoler les dépendances du projet et éviter les conflits.
Stack Technique Requise
- Python : Version 3.9 ou supérieure.
- Gestion de l'environnement :
venv, un standard de la bibliothèque Python. - Dépendances : Gérées via un fichier
requirements.txtpour une installation en une seule commande.
# 1. Création de l'environnement virtuel dans le dossier du projet
python3 -m venv venv
# 2. Activation de l'environnement
# Sur Linux/macOS:
source venv/bin/activate
# Sur Windows (cmd.exe):
# venv\Scripts\activate.bat
# 3. Installation des dépendances du projet
pip install -r requirements.txt
Le fichier requirements.txt contiendrait les bibliothèques essentielles : selenium pour le scraping, pandas pour la manipulation de données, google-generativeai pour l'API de l'IA, et python-dotenv pour la gestion sécurisée des configurations.
II. Architecture et Configuration Centrale (`config.py`)
L'Objectif Stratégique
La robustesse d'une application se mesure à sa capacité à s'adapter. En externalisant la configuration (clés API, mots-clés, chemins de fichiers), on découple la logique métier des paramètres variables. Cela permet de modifier le comportement de l'agent sans toucher une seule ligne de son code source, une pratique fondamentale de l'ingénierie logicielle durable.
L'Implémentation Technique
Le fichier config.py sert de point de centralisation. Pour les secrets, comme les clés API, il est impératif de ne jamais les stocker en clair dans le code. Nous utilisons la bibliothèque python-dotenv pour charger ces secrets depuis un fichier .env local, qui est exclu du contrôle de version (via .gitignore).
# config.py
import os
from dotenv import load_dotenv
# Charger les variables d'environnement depuis le fichier .env
load_dotenv()
# --- Clés API et Secrets ---
# La clé est chargée depuis l'environnement, avec une valeur par défaut pour le développement
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "VOTRE_CLE_API_PAR_DEFAUT_ICI")
# --- Paramètres du Scraper ---
SEARCH_KEYWORDS = ["administrateur infrastructure sécurité", "devops", "cloud engineer"]
SEARCH_LOCATION = "France"
JOB_BOARD_URL = "https://www.example-job-board.com/jobs?q={keyword}&l={location}"
# --- Chemins des Fichiers de Données ---
CV_TEXT_PATH = "data/cv_bruno_henry.txt"
RAW_OFFERS_CSV_PATH = "data/offres_brutes.csv"
FILTERED_OFFERS_CSV_PATH = "data/offres_filtrees.csv"
COVER_LETTERS_PATH = "data/lettres_motivation/"
III. Phase d'Acquisition : Scraping (`app.py`)
L'Objectif Stratégique
L'enjeu est de construire un dataset initial de haute qualité. Il faut pour cela interagir avec des sites web dynamiques conçus pour décourager les robots, tout en structurant l'information extraite pour qu'elle soit immédiatement utilisable.
L'Implémentation Technique
L'utilisation de Selenium WebDriver en mode headless permet de piloter un navigateur complet, capable d'interpréter le JavaScript et de simuler une interaction humaine. La clé de la fiabilité réside dans les attentes explicites (WebDriverWait) qui forcent le script à attendre que les éléments d'intérêt soient non seulement présents dans le DOM, mais aussi interactifs, prévenant ainsi les erreurs liées au chargement asynchrone.
# Extrait significatif de app.py
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pandas as pd
import config
def scrape_job_offers():
# ... (Configuration des options de Chrome et initialisation du driver) ...
all_offers = []
for keyword in config.SEARCH_KEYWORDS:
try:
url = config.JOB_BOARD_URL.format(keyword=keyword, location=config.SEARCH_LOCATION)
driver.get(url)
# Attente robuste que le conteneur des offres soit visible
offer_container = WebDriverWait(driver, 15).until(
EC.visibility_of_element_located((By.ID, "job-listings-container"))
)
offer_cards = offer_container.find_elements(By.CLASS_NAME, "job-card")
for card in offer_cards:
# Utilisation de try-except pour chaque champ pour une robustesse maximale
try:
title = card.find_element(By.CLASS_NAME, "job-title").text
company = card.find_element(By.CLASS_NAME, "company-name").text
# ... extraire les autres champs ...
all_offers.append({"titre": title, "entreprise": company, ...})
except Exception:
continue # On ignore une carte si elle est mal formée
except Exception as e:
print(f"Erreur majeure lors du scraping pour '{keyword}': {e}")
driver.quit()
if all_offers:
df = pd.DataFrame(all_offers)
df.to_csv(config.RAW_OFFERS_CSV_PATH, index=False)
print(f"Succès : {len(df)} offres brutes sauvegardées.")
IV. Phase de Traitement : Le Filtrage "Human-in-the-Loop"
L'Objectif Stratégique et le Choix d'Architecture
Ici, nous abordons le cœur de la valeur du projet. Une automatisation totale du filtrage serait non seulement coûteuse en appels API, mais elle ignorerait l'intuition du candidat. L'architecture choisie est donc celle de l'**intelligence hybride**. L'utilisateur, via l'interface web, effectue un premier tri rapide sur la liste des offres brutes. Il sélectionne ensuite un lot d'offres prometteuses et déclenche l'analyse de l'IA via un bouton dédié.
L'IA n'agit pas comme un filtre autonome, mais comme un **consultant expert à la demande**, fournissant une analyse sémantique profonde uniquement là où l'effort est justifié.
L'Implémentation Technique (`filter_offers.py`)
Le script reçoit une liste d'offres présélectionnées. Pour chacune, il exécute la fonction la plus critique du projet : la classification par l'IA. Le prompt est une instruction précise qui force le LLM à se comporter de manière déterministe et à retourner un JSON structuré, essentiel pour une intégration logicielle fiable.
# La fonction clé de filter_offers.py
import google.generativeai as genai
import json
def get_ai_relevance_analysis(offer_description, cv_content):
genai.configure(api_key=config.GEMINI_API_KEY)
model = genai.GenerativeModel('gemini-pro')
prompt = f"""
En tant que recruteur technique expert en infrastructure et sécurité, évalue l'adéquation entre le CV suivant et cette description de poste.
CONTEXTE DU CV:
---
{cv_content}
---
DESCRIPTION DU POSTE À ANALYSER:
---
{offer_description}
---
Fournis ton analyse dans un objet JSON valide et unique, avec les clés suivantes :
1. "is_relevant": un booléen (true si l'offre est une excellente opportunité pour ce profil, sinon false).
2. "relevance_score": un entier de 1 à 100.
3. "justification": une phrase concise expliquant ton score.
4. "matching_keywords": un tableau de 3 à 5 compétences ou technologies clés qui correspondent.
"""
try:
response = model.generate_content(prompt)
# ... (logique de nettoyage et de parsing du JSON) ...
return json.loads(cleaned_response_text)
except Exception:
# Gérer les erreurs d'API ou de parsing
return None
Conclusion : L'IA comme Outil d'Augmentation
Ce projet démontre une approche mature et pragmatique de l'intégration de l'IA. L'objectif n'est pas une automatisation aveugle, mais la création d'un **système d'augmentation cognitive** qui décuple les capacités de l'utilisateur.
La véritable expertise mise en avant ici n'est pas seulement technique (maîtrise de Python, Selenium, IA), mais surtout **architecturale**. C'est la capacité à concevoir un système où l'humain et la machine collaborent, chacun se concentrant sur ses points forts : la vision stratégique et l'intuition pour l'humain, l'analyse de données à grande échelle et la génération de contenu pour l'IA. C'est la démonstration d'un développeur qui ne code pas seulement, mais qui conçoit des solutions.