Proyectos de Subversion LeadersLinked - Services

Rev

Rev 516 | Rev 519 | Ir a la última revisión | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 516 Rev 518
Línea 103... Línea 103...
103
        }
103
        }
Línea 104... Línea 104...
104
 
104
 
Línea 105... Línea 105...
105
        if ($request->isGet()) {
105
        if ($request->isGet()) {
106
 
106
 
Línea 107... Línea 107...
107
            // Llamar a la función que obtiene los archivos de la vacante
107
            // Llamar a la función que obtiene los archivos de la vacante
108
            $competencies = $this->getJobDescriptionCompetencies($jobDescriptionId);
108
            $competencies = $this->analyzeJobDescriptionCompetencies($jobDescriptionId);
109
 
109
 
110
            return new JsonModel([
110
            return new JsonModel([
Línea 208... Línea 208...
208
        } catch (\Exception $e) {
208
        } catch (\Exception $e) {
209
            // Aquí podrías loggear el error si es necesario
209
            // Aquí podrías loggear el error si es necesario
210
            return null;
210
            return null;
211
        }
211
        }
212
    }
212
    }
-
 
213
 
-
 
214
    function cleanContent($text)
-
 
215
    {
-
 
216
        // Eliminar la palabra "json"
-
 
217
        $text = str_replace("json", "", $text);
-
 
218
 
-
 
219
        // Eliminar los saltos de línea \n
-
 
220
        $text = str_replace("\n", "", $text);
-
 
221
 
-
 
222
        // Eliminar los acentos invertidos (```)
-
 
223
        $text = str_replace("```", "", $text);
-
 
224
 
-
 
225
        // Retornar el contenido arreglado
-
 
226
        return $text;
-
 
227
    }
-
 
228
 
-
 
229
    public function analyzeJobDescriptionCompetencies($jobDescriptionId)
-
 
230
    {
-
 
231
        // 🔹 Obtener texto de la descripción de cargo y competencias
-
 
232
        $descriptionText = $this->getJobDescriptionCompetencies($jobDescriptionId);
-
 
233
 
-
 
234
        if (!$descriptionText) {
-
 
235
            return [
-
 
236
                'success' => false,
-
 
237
                'message' => 'No se encontró la descripción del cargo.',
-
 
238
                'data' => null
-
 
239
            ];
-
 
240
        }
-
 
241
 
-
 
242
        // 🔹 Crear el mensaje para OpenAI
-
 
243
        $messages = [
-
 
244
            [
-
 
245
                'role' => 'system',
-
 
246
                'content' => "Eres un experto en talento humano, análisis de perfiles laborales y gestión de competencias para 
-
 
247
                el mercado laboral actual."
-
 
248
            ],
-
 
249
            [
-
 
250
                'role' => 'user',
-
 
251
                'content' => "A continuación te proporciono una descripción de un cargo con sus funciones, objetivos y competencias requeridas. 
-
 
252
                Analiza si las competencias listadas están actualizadas para los requerimientos actuales de la industria y el trabajo moderno. 
-
 
253
 
-
 
254
                Retorna una respuesta estructurada en formato JSON como este:
-
 
255
 
-
 
256
                {
-
 
257
                \"actualizado\": true o false,
-
 
258
                \"competencias\": [
-
 
259
                    {
-
 
260
                    \"nombre competencia 1\": \"nombre de la competencia\",
-
 
261
                    \"descripcion\": \"recomendación o análisis de si está o no actualizada, o si falta complementar\"
-
 
262
                    }
-
 
263
                ]
-
 
264
                }
-
 
265
 
-
 
266
                Texto a analizar:
-
 
267
                \"\"\"$descriptionText\"\"\"
-
 
268
                "
-
 
269
            ]
-
 
270
        ];
-
 
271
 
-
 
272
        // 🔹 Consultar OpenAI
-
 
273
        $response = $this->analyzeCvWithAi($messages);
-
 
274
 
-
 
275
        // 🔹 Validar y retornar
-
 
276
        if (!isset($response['success']) || !$response['success']) {
-
 
277
            return [
-
 
278
                'success' => false,
-
 
279
                'message' => 'Error al consultar la API de OpenAI',
-
 
280
                'data' => $response['message'] ?? null
-
 
281
            ];
-
 
282
        }
-
 
283
 
-
 
284
        // 🔹 Intentar extraer JSON del mensaje generado
-
 
285
        $reply = $this->cleanContent($response['data']['choices'][0]['message']['content'] ?? null);
-
 
286
 
-
 
287
        if (!$reply) {
-
 
288
            return [
-
 
289
                'success' => false,
-
 
290
                'message' => 'No se obtuvo una respuesta válida de la IA.',
-
 
291
                'data' => null
-
 
292
            ];
-
 
293
        }
-
 
294
 
-
 
295
        // 🔹 Intentar decodificar respuesta JSON (por si OpenAI responde directamente con JSON)
-
 
296
        $decoded = json_decode($reply, true);
-
 
297
 
-
 
298
        if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
-
 
299
            return [
-
 
300
                'success' => true,
-
 
301
                'message' => 'Análisis completado',
-
 
302
                'data' => $decoded
-
 
303
            ];
-
 
304
        }
-
 
305
 
-
 
306
        // 🔹 Si no fue posible decodificar, devolver contenido bruto para revisión
-
 
307
        return [
-
 
308
            'success' => false,
-
 
309
            'message' => 'No se pudo decodificar el JSON de la respuesta',
-
 
310
            'data' => $reply
-
 
311
        ];
-
 
312
    }
-
 
313
 
-
 
314
    function callExternalApi($url, $payload, $headers)
-
 
315
    {
-
 
316
        $ch = curl_init($url);
-
 
317
        curl_setopt($ch, CURLOPT_CAINFO, '/etc/apache2/ssl/cacert.pem');
-
 
318
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-
 
319
        curl_setopt($ch, CURLOPT_POST, true);
-
 
320
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
-
 
321
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
-
 
322
 
-
 
323
        $response = curl_exec($ch);
-
 
324
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
-
 
325
        $curlError = curl_error($ch);
-
 
326
 
-
 
327
        curl_close($ch);
-
 
328
 
-
 
329
        // Verificar si hubo un error en la petición
-
 
330
        if ($curlError) {
-
 
331
            error_log("cURL Error: " . $curlError);
-
 
332
            return [false, "cURL Error: " . $curlError];
-
 
333
        }
-
 
334
 
-
 
335
        // Si la API devuelve un código de error (4xx o 5xx), registrarlo
-
 
336
        if ($httpCode >= 400) {
-
 
337
            error_log("Error HTTP {$httpCode}: " . $response);
-
 
338
            return [false, "Error HTTP {$httpCode}: " . $response];
-
 
339
        }
-
 
340
 
-
 
341
        // Intentar decodificar la respuesta JSON
-
 
342
        $decodedResponse = json_decode($response, true);
-
 
343
 
-
 
344
        // Verificar si la respuesta es válida
-
 
345
        if (json_last_error() !== JSON_ERROR_NONE) {
-
 
346
            error_log("Error al decodificar JSON: " . json_last_error_msg());
-
 
347
            return [false, "Error al decodificar JSON: " . json_last_error_msg()];
-
 
348
        }
-
 
349
 
-
 
350
        return $decodedResponse;
-
 
351
    }
-
 
352
 
-
 
353
    function analyzeCvWithAi(array $messages)
-
 
354
    {
-
 
355
        $apiKey = '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';
-
 
356
        $url = "https://api.openai.com/v1/chat/completions";
-
 
357
 
-
 
358
        $payload = json_encode([
-
 
359
            'model' => 'gpt-4o-mini',
-
 
360
            'messages' => $messages,
-
 
361
            'temperature' => 0.7
-
 
362
        ]);
-
 
363
 
-
 
364
        $headers = [
-
 
365
            'Content-Type: application/json',
-
 
366
            "Authorization: Bearer $apiKey"
-
 
367
        ];
-
 
368
 
-
 
369
        return $this->callExternalApi($url, $payload, $headers);
-
 
370
    }
213
}
371
}