{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Preparación del notebook con OpenAI API key" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "API key: sk-proj-****************************************************************************************************************************************************-amA_5sA\n" ] } ], "source": [ "import sys\n", "import os\n", "import json\n", "import gradio as gr\n", "sys.path.append('../src')\n", "from procesador_de_cvs_con_llm import ProcesadorCV\n", "from dotenv import load_dotenv\n", "load_dotenv(\"../../../../../../../apis/.env\")\n", "api_key = os.getenv(\"OPENAI_API_KEY\")\n", "unmasked_chars = 8\n", "masked_key = api_key[:unmasked_chars] + '*' * (len(api_key) - unmasked_chars*2) + api_key[-unmasked_chars:]\n", "print(f\"API key: {masked_key}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prueba del módulo de procesamiento" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cliente inicializado como \n", "Respuesta:\n", " {\n", " \"puntuacion\": 100,\n", " \"experiencia\": [\n", " {\n", " \"empresa\": \"Talking to Chatbots, by Reddgr\",\n", " \"puesto\": \"Web Publisher and Generative AI Researcher\",\n", " \"duracion\": 218\n", " },\n", " {\n", " \"empresa\": \"IBM\",\n", " \"puesto\": \"Relationship Manager | Cognitive Solutions SaaS\",\n", " \"duracion\": 43\n", " },\n", " {\n", " \"empresa\": \"Acoustic\",\n", " \"puesto\": \"Principal Consultant | Martech SaaS\",\n", " \"duracion\": 35\n", " },\n", " {\n", " \"empresa\": \"IBM\",\n", " \"puesto\": \"Engagement Manager, in support of Acoustic | B2B SaaS Retail Analytics\",\n", " \"duracion\": 10\n", " },\n", " {\n", " \"empresa\": \"IBM\",\n", " \"puesto\": \"Engagement Manager | B2B SaaS Retail Analytics\",\n", " \"duracion\": 9\n", " },\n", " {\n", " \"empresa\": \"MBD Analytics\",\n", " \"puesto\": \"Business Intelligence Consultant\",\n", " \"duracion\": 10\n", " }\n", " ],\n", " \"descripcion de la experiencia\": \"El candidato ha demostrado una experiencia excepcional en el campo de la inteligencia artificial generativa, acumulando más de 18 años en roles relevantes. Su posición más destacada como Web Publisher y Generative AI Researcher en 'Talking to Chatbots, by Reddgr' le ha proporcionado una base sólida en investigación y desarrollo de tecnologías de IA. Además, su tiempo en IBM, donde ocupó múltiples roles relacionados con soluciones cognitivas y análisis de datos, ha reforzado su capacidad para manejar proyectos complejos en entornos SaaS. La combinación de estas experiencias, junto con su larga duración en cada puesto, justifica la puntuación máxima de 100, evidenciando su idoneidad para el rol de Generative AI Engineer.\"\n", "}\n", "Descripción de la experiencia:\n", "El candidato ha demostrado una experiencia excepcional en el campo de la inteligencia artificial generativa, acumulando\n", "más de 18 años en roles relevantes. Su posición más destacada como Web Publisher y Generative AI Researcher en 'Talking\n", "to Chatbots, by Reddgr' le ha proporcionado una base sólida en investigación y desarrollo de tecnologías de IA. Además,\n", "su tiempo en IBM, donde ocupó múltiples roles relacionados con soluciones cognitivas y análisis de datos, ha reforzado\n", "su capacidad para manejar proyectos complejos en entornos SaaS. La combinación de estas experiencias, junto con su larga\n", "duración en cada puesto, justifica la puntuación máxima de 100, evidenciando su idoneidad para el rol de Generative AI\n", "Engineer.\n" ] } ], "source": [ "# Parámetros de ejecución:\n", "job_text = \"Generative AI engineer\"\n", "cv_sample_path = '../../ejemplos_cvs/DavidGR_cv.txt' # Ruta al fichero de texto con un currículo de ejemplo\n", "with open(cv_sample_path, 'r') as file:\n", " cv_text = file.read()\n", "# Prompts:\n", "with open('../prompts/ner_pre_prompt.txt', 'r', encoding='utf-8') as f:\n", " ner_pre_prompt = f.read()\n", "with open('../prompts/system_prompt.txt', 'r', encoding='utf-8') as f:\n", " system_prompt = f.read()\n", "with open('../prompts/user_prompt.txt', 'r', encoding='utf-8') as f:\n", " user_prompt = f.read()\n", "# Esquemas JSON:\n", "with open('../json/ner_schema.json', 'r', encoding='utf-8') as f:\n", " ner_schema = json.load(f)\n", "with open('../json/response_schema.json', 'r', encoding='utf-8') as f:\n", " response_schema = json.load(f)\n", "\n", "\n", "procesador_cvs_prueba_final = ProcesadorCV(api_key, cv_text, job_text, ner_pre_prompt, \n", " system_prompt, user_prompt, ner_schema, response_schema)\n", "req_experience = 48 # Experiencia requerida en meses\n", "positions_cap=10 # Número máximo de puestos a considerar\n", "dist_threshold_low=0.5 # Distancia límite para considerar un puesto equivalente\n", "dist_threshold_high=0.7 # Distancia límite para considerar un puesto no relevante\n", "dict_respuesta = procesador_cvs_prueba_final.procesar_cv_completo(req_experience=req_experience,\n", " positions_cap=positions_cap,\n", " dist_threshold_low=dist_threshold_low,\n", " dist_threshold_high=dist_threshold_high\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prueba de la aplicación Gradio" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Función de carga de la aplicación de \"backend\" para la interfaz Gradio:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def process_cv(job_text, cv_text, req_experience, positions_cap, dist_threshold_low, dist_threshold_high):\n", " if dist_threshold_low >= dist_threshold_high:\n", " return {\"error\": \"dist_threshold_low debe ser más bajo que dist_threshold_high.\"}\n", " \n", " if not isinstance(cv_text, str) or not cv_text.strip():\n", " return {\"error\": \"Por favor, introduce el CV o sube un fichero.\"}\n", "\n", " try:\n", " procesador = ProcesadorCV(api_key, cv_text, job_text, ner_pre_prompt, \n", " system_prompt, user_prompt, ner_schema, response_schema)\n", " dict_respuesta = procesador.procesar_cv_completo(\n", " req_experience=req_experience,\n", " positions_cap=positions_cap,\n", " dist_threshold_low=dist_threshold_low,\n", " dist_threshold_high=dist_threshold_high\n", " )\n", " return dict_respuesta\n", " except Exception as e:\n", " return {\"error\": f\"Error en el procesamiento: {str(e)}\"}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Interfaz de Gradio:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running on local URL: http://127.0.0.1:7860\n", "\n", "To create a public link, set `share=True` in `launch()`.\n" ] }, { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "c:\\Users\\david\\anaconda3\\Lib\\site-packages\\gradio\\analytics.py:106: UserWarning: IMPORTANT: You are using gradio version 4.44.0, however version 4.44.1 is available, please upgrade. \n", "--------\n", " warnings.warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Cliente inicializado como \n", "Respuesta:\n", " {\n", " \"puntuacion\": 54.75,\n", " \"experiencia\": [\n", " {\n", " \"empresa\": \"bar de tapas\",\n", " \"puesto\": \"charcutero\",\n", " \"duracion\": 47\n", " },\n", " {\n", " \"empresa\": \"\",\n", " \"puesto\": \"camarero\",\n", " \"duracion\": 2\n", " }\n", " ],\n", " \"descripcion de la experiencia\": \"El candidato cuenta con una experiencia total de 47 meses como charcutero en un bar de tapas, lo que le proporciona habilidades relevantes en atención al cliente y manejo de productos alimenticios. Sin embargo, su experiencia como camarero es limitada, con solo 2 meses, lo que no contribuye significativamente a su perfil para el puesto de cajero de supermercado. La puntuación de 54.75 refleja que, aunque tiene una experiencia considerable en un rol relacionado, no cumple completamente con el requisito de 48 meses de experiencia específica en el área de caja o supermercado.\"\n", "}\n", "Descripción de la experiencia:\n", "El candidato cuenta con una experiencia total de 47 meses como charcutero en un bar de tapas, lo que le proporciona\n", "habilidades relevantes en atención al cliente y manejo de productos alimenticios. Sin embargo, su experiencia como\n", "camarero es limitada, con solo 2 meses, lo que no contribuye significativamente a su perfil para el puesto de cajero de\n", "supermercado. La puntuación de 54.75 refleja que, aunque tiene una experiencia considerable en un rol relacionado, no\n", "cumple completamente con el requisito de 48 meses de experiencia específica en el área de caja o supermercado.\n" ] } ], "source": [ "# Fichero de ejemplo para autocompletar (opción que aparece en la parte de abajo de la interfaz de usuario):\n", "with open('../cv_examples/reddgr_cv.txt', 'r') as file:\n", " cv_example = file.read()\n", "\n", "default_parameters = [48, 10, 0.5, 0.7] # Parámetros por defecto para el reinicio de la interfaz y los ejemplos predefinidos \n", "\n", "# Código CSS para truncar el texto de ejemplo en la interfaz (bloque \"Examples\" en la parte de abajo):\n", "css = \"\"\"\n", " table tbody tr {\n", " height: 2.5em; /* Set a fixed height for the rows */\n", " overflow: hidden; /* Hide overflow content */\n", " }\n", "\n", " table tbody tr td {\n", " overflow: hidden; /* Ensure content within cells doesn't overflow */\n", " text-overflow: ellipsis; /* Add ellipsis for overflowing text */\n", " white-space: nowrap; /* Prevent text from wrapping */\n", " vertical-align: middle; /* Align text vertically within the fixed height */\n", " }\n", " \"\"\"\n", "\n", "# Interfaz Gradio:\n", "with gr.Blocks(css=css) as interface:\n", " # Inputs\n", " job_text_input = gr.Textbox(label=\"Título oferta de trabajo\", lines=1, placeholder=\"Introduce el título de la oferta de trabajo\")\n", " cv_text_input = gr.Textbox(label=\"CV en formato texto\", lines=5, max_lines=5, placeholder=\"Introduce el texto del CV\")\n", " \n", " # Opciones avanzadas ocultas en un objeto \"Accordion\"\n", " with gr.Accordion(\"Opciones avanzadas\", open=False):\n", " req_experience_input = gr.Number(label=\"Experiencia requerida (en meses)\", value=default_parameters[0], precision=0)\n", " positions_cap_input = gr.Number(label=\"Número máximo de puestos a extraer\", value=default_parameters[1], precision=0)\n", " dist_threshold_low_slider = gr.Slider(\n", " label=\"Umbral mínimo de distancia de embeddings (puesto equivalente)\", \n", " minimum=0, maximum=1, value=default_parameters[2], step=0.05\n", " )\n", " dist_threshold_high_slider = gr.Slider(\n", " label=\"Umbral máximo de distancia de embeddings (puesto irrelevante)\", \n", " minimum=0, maximum=1, value=default_parameters[3], step=0.05\n", " )\n", " \n", " submit_button = gr.Button(\"Procesar\")\n", " clear_button = gr.Button(\"Limpiar\")\n", " \n", " output_json = gr.JSON(label=\"Resultado\")\n", "\n", " # Ejemplos:\n", " examples = gr.Examples(\n", " examples=[\n", " [\"Cajero de supermercado\", \"Trabajo de charcutero desde 2021. Antes trabajé 2 meses de camarero en un bar de tapas.\"] + default_parameters,\n", " [\"Generative AI Engineer\", cv_example] + default_parameters\n", " ],\n", " inputs=[job_text_input, cv_text_input, req_experience_input, positions_cap_input, dist_threshold_low_slider, dist_threshold_high_slider]\n", " )\n", "\n", " # Botón \"Procesar\"\n", " submit_button.click(\n", " fn=process_cv,\n", " inputs=[\n", " job_text_input, \n", " cv_text_input, \n", " req_experience_input, \n", " positions_cap_input, \n", " dist_threshold_low_slider, \n", " dist_threshold_high_slider\n", " ],\n", " outputs=output_json\n", " )\n", "\n", " # Botón \"Limpiar\"\n", " clear_button.click(\n", " fn=lambda: (\"\",\"\",*default_parameters),\n", " inputs=[],\n", " outputs=[\n", " job_text_input, \n", " cv_text_input, \n", " req_experience_input, \n", " positions_cap_input, \n", " dist_threshold_low_slider, \n", " dist_threshold_high_slider\n", " ]\n", " )\n", "\n", " # Footer\n", " gr.Markdown(\"\"\"\n", " \n", " \"\"\")\n", "\n", "# Lanzar la aplicación:\n", "if __name__ == \"__main__\":\n", " interface.launch()" ] } ], "metadata": { "kernelspec": { "display_name": "base", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.5" } }, "nbformat": 4, "nbformat_minor": 2 }