Nayohn commited on
Commit
09498d4
·
1 Parent(s): 5f590f2

Ajout API job search avec Gradio

Browse files
Files changed (1) hide show
  1. app.py +150 -30
app.py CHANGED
@@ -40,7 +40,20 @@ def search_jobs(job_title="", location="", user_desc=None, salary=None, studies=
40
 
41
  # Si des champs obligatoires manquent, retourner les champs manquants
42
  if missing_fields:
43
- return {"error": f"Paramètres obligatoires manquants : {', '.join(missing_fields)}"}
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
 
46
  # Fonction pour extraire un mot clé principal d'un terme
@@ -97,7 +110,21 @@ def search_jobs(job_title="", location="", user_desc=None, salary=None, studies=
97
  try:
98
  response = requests.get(url, params=payload)
99
  if response.status_code != 200:
100
- return {"error": f"Erreur SerpAPI {response.status_code}", "debug_payload": payload}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
  data = response.json()
103
  jobs_results = data.get("jobs_results", [])
@@ -130,52 +157,145 @@ def search_jobs(job_title="", location="", user_desc=None, salary=None, studies=
130
 
131
  if not jobs_results:
132
  return {
133
- "STATUS": "NO_RESULTS",
134
- "MESSAGE_FOR_LLM": "❌ AUCUNE OFFRE TROUVÉE - Informe l'utilisateur qu'aucun emploi n'a été trouvé",
135
- "JOBS_COUNT": 0,
136
- "SEARCH_QUERY": query,
137
- "LOCATION": location,
138
- "JOBS_RESULTS": [],
139
- "SUGGESTION": "Essayez avec un terme de métier plus général ou une ville différente",
140
- "INSTRUCTION_FOR_LLM": "Aucun résultat trouvé. Suggère à l'utilisateur d'essayer avec des termes différents.",
141
- "debug_info": search_info
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  }
143
 
144
- # Retourner la liste de jobs avec informations détaillées
145
  jobs_list = []
146
  for job in jobs_results:
147
  job_info = {
 
148
  "title": job.get("title", ""),
149
  "company_name": job.get("company_name", ""),
 
150
  "location": job.get("location", ""),
151
- "description": job.get("description", "")[:200] + "..." if job.get("description") else "",
 
 
 
 
 
 
 
 
 
 
152
  "link": job.get("link", ""),
153
- "salary": job.get("salary", "Non spécifié")
154
  }
155
  jobs_list.append(job_info)
156
 
157
- final_jobs = jobs_list[:10] # Limiter à 10 résultats
 
158
 
159
- # Format optimisé pour que le LLM comprenne bien qu'il y a des résultats
160
  return {
161
- "STATUS": "SUCCESS - JOBS FOUND",
162
- "MESSAGE_FOR_LLM": f"✅ TROUVÉ {len(final_jobs)} OFFRES D'EMPLOI - Présente ces résultats à l'utilisateur",
163
- "JOBS_COUNT": len(final_jobs),
164
- "SEARCH_QUERY": query,
165
- "LOCATION": location,
166
- "JOBS_RESULTS": final_jobs,
167
- "INSTRUCTION_FOR_LLM": "Ces offres d'emploi ont été trouvées avec succès. Présente-les à l'utilisateur sous forme de liste claire.",
168
- "debug_info": search_info
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  }
170
 
171
  except Exception as e:
172
  return {
173
- "STATUS": "ERROR",
174
- "MESSAGE_FOR_LLM": f"❌ ERREUR TECHNIQUE - Informe l'utilisateur qu'il y a eu une erreur: {str(e)}",
175
- "JOBS_COUNT": 0,
176
- "JOBS_RESULTS": [],
177
- "ERROR_DETAILS": str(e),
178
- "INSTRUCTION_FOR_LLM": "Une erreur s'est produite lors de la recherche. Explique à l'utilisateur et suggère de réessayer."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  }
180
 
181
 
 
40
 
41
  # Si des champs obligatoires manquent, retourner les champs manquants
42
  if missing_fields:
43
+ return {
44
+ "jsonrpc": "2.0",
45
+ "error": {
46
+ "code": -32602,
47
+ "message": "Invalid params",
48
+ "data": {
49
+ "missing_parameters": missing_fields,
50
+ "required_parameters": ["job_title", "location"],
51
+ "optional_parameters": ["user_desc", "salary", "studies", "domain"],
52
+ "description": f"Paramètres obligatoires manquants : {', '.join(missing_fields)}"
53
+ }
54
+ },
55
+ "id": None
56
+ }
57
 
58
 
59
  # Fonction pour extraire un mot clé principal d'un terme
 
110
  try:
111
  response = requests.get(url, params=payload)
112
  if response.status_code != 200:
113
+ return {
114
+ "jsonrpc": "2.0",
115
+ "error": {
116
+ "code": -32603,
117
+ "message": "Internal error",
118
+ "data": {
119
+ "serpapi_status_code": response.status_code,
120
+ "serpapi_response": response.text[:500] if response.text else "No response body",
121
+ "request_payload": payload,
122
+ "error_type": "SerpAPI HTTP Error",
123
+ "description": f"SerpAPI returned status code {response.status_code}"
124
+ }
125
+ },
126
+ "id": None
127
+ }
128
 
129
  data = response.json()
130
  jobs_results = data.get("jobs_results", [])
 
157
 
158
  if not jobs_results:
159
  return {
160
+ "jsonrpc": "2.0",
161
+ "result": {
162
+ "success": False,
163
+ "status": "NO_RESULTS_FOUND",
164
+ "message": "Aucune offre d'emploi trouvée pour les critères spécifiés",
165
+ "search_metadata": {
166
+ "original_query": query,
167
+ "location": location,
168
+ "search_parameters": {
169
+ "job_title": job_title,
170
+ "location": location,
171
+ "user_desc": user_desc,
172
+ "salary": salary,
173
+ "studies": studies,
174
+ "domain": domain
175
+ },
176
+ "serpapi_parameters": payload,
177
+ "search_radius_km": 50,
178
+ "fallback_attempted": search_info.get("fallback_query") is not None,
179
+ "fallback_query": search_info.get("fallback_query"),
180
+ "fallback_results_count": search_info.get("fallback_results", 0)
181
+ },
182
+ "jobs": {
183
+ "total_count": 0,
184
+ "displayed_count": 0,
185
+ "results": []
186
+ },
187
+ "suggestions": [
188
+ "Essayez avec un terme de métier plus général",
189
+ "Vérifiez l'orthographe de la localisation",
190
+ "Élargissez la zone géographique",
191
+ "Utilisez des synonymes pour le métier recherché"
192
+ ],
193
+ "debug_information": search_info
194
+ },
195
+ "id": None
196
  }
197
 
198
+ # Retourner la liste de jobs avec informations très détaillées
199
  jobs_list = []
200
  for job in jobs_results:
201
  job_info = {
202
+ "job_id": job.get("job_id", ""),
203
  "title": job.get("title", ""),
204
  "company_name": job.get("company_name", ""),
205
+ "company_url": job.get("company_url", ""),
206
  "location": job.get("location", ""),
207
+ "via": job.get("via", ""),
208
+ "description": job.get("description", ""),
209
+ "posted_at": job.get("posted_at", ""),
210
+ "schedule_type": job.get("schedule_type", ""),
211
+ "salary": job.get("salary", ""),
212
+ "job_highlights": job.get("job_highlights", {}),
213
+ "related_links": job.get("related_links", []),
214
+ "thumbnail": job.get("thumbnail", ""),
215
+ "extensions": job.get("extensions", []),
216
+ "detected_extensions": job.get("detected_extensions", {}),
217
+ "apply_options": job.get("apply_options", []),
218
  "link": job.get("link", ""),
219
+ "serpapi_link": job.get("serpapi_link", "")
220
  }
221
  jobs_list.append(job_info)
222
 
223
+ total_jobs_found = len(jobs_list)
224
+ displayed_jobs = jobs_list # Afficher TOUS les résultats, pas de limite
225
 
226
+ # Format JSON-RPC 2.0 complet avec toutes les informations
227
  return {
228
+ "jsonrpc": "2.0",
229
+ "result": {
230
+ "success": True,
231
+ "status": "JOBS_FOUND_SUCCESSFULLY",
232
+ "message": f"Recherche réussie : {total_jobs_found} offres d'emploi trouvées",
233
+ "search_metadata": {
234
+ "original_query": query,
235
+ "processed_keywords": query.split(),
236
+ "location": location,
237
+ "search_timestamp": None, # Peut être ajouté si nécessaire
238
+ "search_parameters": {
239
+ "job_title": job_title,
240
+ "location": location,
241
+ "user_desc": user_desc,
242
+ "salary": salary,
243
+ "studies": studies,
244
+ "domain": domain
245
+ },
246
+ "serpapi_parameters": payload,
247
+ "search_radius_km": 50,
248
+ "fallback_attempted": search_info.get("fallback_query") is not None,
249
+ "fallback_query": search_info.get("fallback_query"),
250
+ "fallback_results_count": search_info.get("fallback_results", 0),
251
+ "serpapi_response_keys": search_info.get("serpapi_response_keys", [])
252
+ },
253
+ "jobs": {
254
+ "total_count": total_jobs_found,
255
+ "displayed_count": len(displayed_jobs),
256
+ "results": displayed_jobs
257
+ },
258
+ "statistics": {
259
+ "jobs_with_salary": len([j for j in displayed_jobs if j.get("salary")]),
260
+ "jobs_with_description": len([j for j in displayed_jobs if j.get("description")]),
261
+ "jobs_with_company_url": len([j for j in displayed_jobs if j.get("company_url")]),
262
+ "unique_companies": len(set([j.get("company_name", "") for j in displayed_jobs if j.get("company_name")])),
263
+ "job_sources": list(set([j.get("via", "") for j in displayed_jobs if j.get("via")]))
264
+ },
265
+ "debug_information": search_info
266
+ },
267
+ "id": None
268
  }
269
 
270
  except Exception as e:
271
  return {
272
+ "jsonrpc": "2.0",
273
+ "error": {
274
+ "code": -32603,
275
+ "message": "Internal error",
276
+ "data": {
277
+ "error_type": "Python Exception",
278
+ "error_message": str(e),
279
+ "error_details": {
280
+ "exception_type": type(e).__name__,
281
+ "search_parameters": {
282
+ "job_title": job_title,
283
+ "location": location,
284
+ "user_desc": user_desc,
285
+ "salary": salary,
286
+ "studies": studies,
287
+ "domain": domain
288
+ }
289
+ },
290
+ "description": "Une erreur interne s'est produite lors de la recherche d'emploi",
291
+ "suggestions": [
292
+ "Vérifiez les paramètres de recherche",
293
+ "Réessayez dans quelques instants",
294
+ "Contactez le support si l'erreur persiste"
295
+ ]
296
+ }
297
+ },
298
+ "id": None
299
  }
300
 
301