QuentinL52 commited on
Commit
89ecbe8
·
verified ·
1 Parent(s): 5e2f20c

Create agents/scoring_agent.py

Browse files
Files changed (1) hide show
  1. src/agents/scoring_agent.py +150 -0
src/agents/scoring_agent.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import logging
3
+ from datetime import datetime
4
+ from typing import Dict, List, Any
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ class ScoringAgent:
9
+ ALPHA = 0.5
10
+ BETA = 0.3
11
+ GAMMA = 0.2
12
+
13
+ CONTEXT_VALUES = {
14
+ "formations": 0.3,
15
+ "projets": 0.6,
16
+ "experiences_professionnelles": 0.8,
17
+ }
18
+
19
+ def calculate_scores(self, candidat_data: Dict[str, Any]) -> Dict[str, List[Dict[str, Any]]]:
20
+ skills_data = candidat_data.get("compétences", {})
21
+ skills_list = []
22
+
23
+ if isinstance(skills_data, dict):
24
+ skills_list.extend(skills_data.get("hard_skills", []))
25
+ skills_list.extend(skills_data.get("soft_skills", []))
26
+ elif isinstance(skills_data, list):
27
+ skills_list = [item.get("nom") for item in skills_data if item.get("nom")]
28
+
29
+ if not skills_list:
30
+ return {"analyse_competences": []}
31
+
32
+ skill_metrics = {
33
+ skill.lower(): {
34
+ "original_name": skill,
35
+ "contexts": set(),
36
+ "frequency": 0,
37
+ "max_duration": 0.0
38
+ }
39
+ for skill in skills_list if skill
40
+ }
41
+
42
+ self._analyze_experiences(candidat_data, skill_metrics)
43
+ self._analyze_projects(candidat_data, skill_metrics)
44
+ self._analyze_formations(candidat_data, skill_metrics)
45
+
46
+ final_scores = self._calculate_final_scores(skill_metrics)
47
+
48
+ return {"analyse_competences": final_scores}
49
+
50
+ def _analyze_experiences(self, candidat_data: Dict[str, Any], skill_metrics: Dict[str, Any]):
51
+ experiences_key = "expériences" if "expériences" in candidat_data else "experiences_professionnelles"
52
+
53
+ for exp in candidat_data.get(experiences_key, []):
54
+ exp_text = json.dumps(exp, ensure_ascii=False).lower()
55
+ duration = self._calculate_duration_in_years(
56
+ exp.get("date_debut", exp.get("start_date", "")),
57
+ exp.get("date_fin", exp.get("end_date", ""))
58
+ )
59
+
60
+ for skill in skill_metrics:
61
+ if skill in exp_text:
62
+ skill_metrics[skill]["contexts"].add("experiences_professionnelles")
63
+ skill_metrics[skill]["frequency"] += exp_text.count(skill)
64
+ if duration > skill_metrics[skill]["max_duration"]:
65
+ skill_metrics[skill]["max_duration"] = duration
66
+
67
+ def _analyze_projects(self, candidat_data: Dict[str, Any], skill_metrics: Dict[str, Any]):
68
+ projects_data = candidat_data.get("projets", {})
69
+
70
+ if isinstance(projects_data, dict):
71
+ for project_type in ["professional", "personal"]:
72
+ for project in projects_data.get(project_type, []):
73
+ project_text = json.dumps(project, ensure_ascii=False).lower()
74
+ for skill in skill_metrics:
75
+ if skill in project_text:
76
+ skill_metrics[skill]["contexts"].add("projets")
77
+ skill_metrics[skill]["frequency"] += project_text.count(skill)
78
+
79
+ def _analyze_formations(self, candidat_data: Dict[str, Any], skill_metrics: Dict[str, Any]):
80
+ for formation in candidat_data.get("formations", []):
81
+ formation_text = json.dumps(formation, ensure_ascii=False).lower()
82
+ for skill in skill_metrics:
83
+ if skill in formation_text:
84
+ skill_metrics[skill]["contexts"].add("formations")
85
+ skill_metrics[skill]["frequency"] += formation_text.count(skill)
86
+
87
+ def _calculate_final_scores(self, skill_metrics: Dict[str, Any]) -> List[Dict[str, Any]]:
88
+ final_scores = []
89
+
90
+ for skill, metrics in skill_metrics.items():
91
+ if metrics["frequency"] == 0:
92
+ continue
93
+
94
+ context_score = max(
95
+ (self.CONTEXT_VALUES.get(c, 0) for c in metrics["contexts"]),
96
+ default=0.1
97
+ )
98
+
99
+ if len(metrics["contexts"]) > 1:
100
+ context_score = 1.0
101
+
102
+ normalized_frequency = self._normalize_score(metrics["frequency"])
103
+ normalized_depth = self._normalize_score(metrics["max_duration"])
104
+
105
+ final_score = (self.ALPHA * context_score) + \
106
+ (self.BETA * normalized_frequency) + \
107
+ (self.GAMMA * normalized_depth)
108
+
109
+ final_scores.append({
110
+ "skill": metrics["original_name"],
111
+ "score": round(final_score, 2),
112
+ "details": {
113
+ "context_score": round(context_score, 2),
114
+ "contexts_found": list(metrics["contexts"]),
115
+ "frequency": metrics["frequency"],
116
+ "max_duration_years": round(metrics["max_duration"], 1)
117
+ }
118
+ })
119
+
120
+ final_scores.sort(key=lambda x: x["score"], reverse=True)
121
+ return final_scores
122
+
123
+ def _normalize_score(self, value: float) -> float:
124
+ return 1 - (1 / (1 + float(value)))
125
+
126
+ def _parse_date(self, date_str: str) -> datetime:
127
+ if not date_str or not isinstance(date_str, str):
128
+ return None
129
+
130
+ date_str_lower = date_str.lower()
131
+ if date_str_lower in ["aujourd'hui", "maintenant", "en cours", "current"]:
132
+ return datetime.now()
133
+
134
+ for fmt in ("%m/%Y", "%Y"):
135
+ parsed_date = datetime.strptime(date_str, fmt)
136
+ if parsed_date:
137
+ return parsed_date
138
+
139
+ return None
140
+
141
+ def _calculate_duration_in_years(self, start_date_str: str, end_date_str: str) -> float:
142
+ start_date = self._parse_date(start_date_str)
143
+ end_date = self._parse_date(end_date_str)
144
+
145
+ if start_date and end_date:
146
+ if end_date < start_date:
147
+ return 0.0
148
+ return (end_date - start_date).days / 365.25
149
+
150
+ return 0.0