{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ur8xi4C7S06n"
      },
      "outputs": [],
      "source": [
        "# Copyright 2024 Google LLC\n",
        "#\n",
        "# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "#     https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JAPoU8Sm5E6e"
      },
      "source": [
        "# Resume Generation\n",
        "\n",
        "<table align=\"left\">\n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/generative-ai/blob/main/gemini/use-cases/education/resume_generator.ipynb\">\n",
        "      <img width=\"32px\" src=\"https://www.gstatic.com/pantheon/images/bigquery/welcome_page/colab-logo.svg\" alt=\"Google Colaboratory logo\"><br> Open in Colab\n",
        "    </a>\n",
        "  </td>\n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://console.cloud.google.com/vertex-ai/colab/import/https:%2F%2Fraw.githubusercontent.com%2FGoogleCloudPlatform%2Fgenerative-ai%2Fmain%2Fgemini%2Fuse-cases%2Feducation%2Fresume_generator.ipynb\">\n",
        "      <img width=\"32px\" src=\"https://lh3.googleusercontent.com/JmcxdQi-qOpctIvWKgPtrzZdJJK-J3sWE1RsfjZNwshCFgE_9fULcNpuXYTilIR2hjwN\" alt=\"Google Cloud Colab Enterprise logo\"><br> Open in Colab Enterprise\n",
        "    </a>\n",
        "  </td>\n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/generative-ai/main/gemini/use-cases/education/resume_generator.ipynb\">\n",
        "      <img src=\"https://www.gstatic.com/images/branding/gcpiconscolors/vertexai/v1/32px.svg\" alt=\"Vertex AI logo\"><br> Open in Vertex AI Workbench\n",
        "    </a>\n",
        "  </td>\n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/use-cases/education/resume_generator.ipynb\">\n",
        "      <img width=\"32px\" src=\"https://raw.githubusercontent.com/primer/octicons/refs/heads/main/icons/mark-github-24.svg\" alt=\"GitHub logo\"><br> View on GitHub\n",
        "    </a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "84f0f73a0f76"
      },
      "source": [
        "| | | | |\n",
        "|-|-|-|-|\n",
        "|Author(s) | [Aniket Agrawal](https://github.com/aniketagrawal2012) | [Rupjit Chakraborty](https://github.com/lazyprgmr) |"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "tvgnzT1CKxrO"
      },
      "source": [
        "## Overview\n",
        "\n",
        "This notebook demonstrates how to generate resumes using the Gemini 2.0 model and LLM prompting. It employs various prompts to guide the model in extracting information from existing resumes, generating professional summaries tailored to specific job descriptions, and arranging skills and coursework in order of relevance. The prompts emphasize maintaining truthfulness, using active voice, and adhering to a valid JSON format for the output. This approach allows for the creation of customized and targeted resumes that effectively highlight relevant qualifications and experiences."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "61RBz8LLbxCR"
      },
      "source": [
        "## Get started"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "No17Cw5hgx12"
      },
      "source": [
        "### Install Vertex AI SDK and other required packages\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "tFy3H3aPgx12"
      },
      "outputs": [],
      "source": [
        "%pip install --upgrade --user --quiet google-cloud-aiplatform python-docx==1.1.2 pypdf==5.0.0 docx2txt==0.8"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dmWOrTJ3gx13"
      },
      "source": [
        "### Authenticate your notebook environment (Colab only)\n",
        "\n",
        "If you're running this notebook on Google Colab, run the cell below to authenticate your environment."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "NyKGtVQjgx13"
      },
      "outputs": [],
      "source": [
        "import sys\n",
        "\n",
        "if \"google.colab\" in sys.modules:\n",
        "    from google.colab import auth\n",
        "\n",
        "    auth.authenticate_user()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "DF4l8DTdWgPY"
      },
      "source": [
        "### Set Google Cloud project information and initialize Vertex AI SDK\n",
        "\n",
        "To get started using Vertex AI, you must have an existing Google Cloud project and [enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com).\n",
        "\n",
        "Learn more about [setting up a project and a development environment](https://cloud.google.com/vertex-ai/docs/start/cloud-environment)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Nqwi-5ufWp_B"
      },
      "outputs": [],
      "source": [
        "# Use the environment variable if the user doesn't provide Project ID.\n",
        "\n",
        "# Native Imports\n",
        "import os\n",
        "\n",
        "# Third-party Imports\n",
        "import vertexai\n",
        "from vertexai.generative_models import GenerationConfig, GenerativeModel\n",
        "\n",
        "# fmt: off\n",
        "PROJECT_ID = \"\"  # @param {type: \"string\", placeholder: \"[your-project-id]\", isTemplate: true}\n",
        "# fmt: on\n",
        "if not PROJECT_ID or PROJECT_ID == \"\":\n",
        "    PROJECT_ID = str(os.environ.get(\"GOOGLE_CLOUD_PROJECT\"))\n",
        "\n",
        "LOCATION = os.environ.get(\"GOOGLE_CLOUD_REGION\", \"us-central1\")\n",
        "\n",
        "print(f\"PROJECT_ID: {PROJECT_ID}\")\n",
        "print(f\"LOCATION: {LOCATION}\")\n",
        "\n",
        "vertexai.init(project=PROJECT_ID, location=LOCATION)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5303c05f7aa6"
      },
      "source": [
        "### Import libraries"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "6fc324893334"
      },
      "outputs": [],
      "source": [
        "# Native Imports\n",
        "import json\n",
        "\n",
        "# Third-party Imports\n",
        "import docx\n",
        "import docx2txt\n",
        "import pypdf\n",
        "from docx.document import Document\n",
        "from docx.oxml.table import CT_Tbl\n",
        "from docx.oxml.text.paragraph import CT_P\n",
        "from docx.table import Table, _Cell\n",
        "from docx.text.paragraph import Paragraph"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5303c05f7aa6"
      },
      "source": [
        "### Download a sample resume file"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "5c4978c07d9a"
      },
      "outputs": [],
      "source": [
        "! gcloud storage cp gs://github-repo/generative-ai/gemini/use-cases/education/resume-generation/Sample_1.docx ."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "e43229f3ad4f"
      },
      "source": [
        "### Load model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "cf93d5f0ce00"
      },
      "outputs": [],
      "source": [
        "MODEL_NAME = \"gemini-2.0-flash\"  # Choice of model\n",
        "\n",
        "model = GenerativeModel(model_name=MODEL_NAME)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VPylX87eREVh"
      },
      "source": [
        "## Resume Generation"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "oP_UflnpUVRL"
      },
      "source": [
        "### Resume Structure and Prompt Initialization\n",
        "\n",
        "After installing necessary packages and loading the language model, we initialize predefined prompts designed for resume generation and the related structure. These prompts guide the model to extract relevant information from an existing resume and create a tailored output that aligns with the provided job description."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "55af72f4922b"
      },
      "outputs": [],
      "source": [
        "# Resume structure\n",
        "resume_structure = [\n",
        "    \"personal_information\",\n",
        "    \"professional_summary\",\n",
        "    \"education\",\n",
        "    \"coursework\",\n",
        "    \"skills\",\n",
        "    \"experience\",\n",
        "    \"certifications\",\n",
        "    \"languages\",\n",
        "    \"extracurricular_activities\",\n",
        "    \"references\",\n",
        "]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1d17bfb0-f4ee-46b9-87b5-7b04ca6a1129"
      },
      "outputs": [],
      "source": [
        "# Prompt for extracting information from a resume\n",
        "PROMPT_EXTRACTION = \"\"\"\n",
        "You are a seasoned career advising professional expert in crafting resumes and cover letters.\n",
        "\n",
        "Consider the below details that have been extracted from a resume\n",
        "{0}\n",
        "\n",
        "INSTRUCTIONS:\n",
        "- Maintain truthfulness and objectivity.\n",
        "- Prefer active voice over passive voice.\n",
        "- Output the Education, Experience, Languages, Extracurricular_Activities and References\n",
        "sections as a simple numbered list.\n",
        "\"\"\"\n",
        "\n",
        "# Response schema for PROMPT_EXTRACTION\n",
        "RESPONSE_SCHEMA_PROMPT_EXTRACTION = {\n",
        "    \"type\": \"ARRAY\",\n",
        "    \"items\": {\n",
        "        \"type\": \"OBJECT\",\n",
        "        \"properties\": {\n",
        "            resume_structure[0]: {\n",
        "                \"type\": \"ARRAY\",\n",
        "                \"items\": {\n",
        "                    \"type\": \"OBJECT\",\n",
        "                    \"properties\": {\n",
        "                        \"name\": {\"type\": \"STRING\"},\n",
        "                        \"address\": {\"type\": \"STRING\"},\n",
        "                        \"mobile_no\": {\"type\": \"STRING\"},\n",
        "                        \"email\": {\"type\": \"STRING\"},\n",
        "                    },\n",
        "                },\n",
        "            },\n",
        "            resume_structure[2]: {\"type\": \"STRING\"},\n",
        "            resume_structure[5]: {\"type\": \"STRING\"},\n",
        "            resume_structure[7]: {\"type\": \"STRING\"},\n",
        "            resume_structure[8]: {\"type\": \"STRING\"},\n",
        "            resume_structure[9]: {\"type\": \"STRING\"},\n",
        "        },\n",
        "    },\n",
        "}\n",
        "\n",
        "# Prompt for generating information based on information extracted from resume\n",
        "PROMPT_GENERATION = \"\"\"\n",
        "You are a seasoned career advising professional expert in crafting resumes and cover letters.\n",
        "\n",
        "Consider the below details that have been extracted from a resume\n",
        "{0}\n",
        "\n",
        "Use the above details and craft a resume to satisfy the job description provided below\n",
        "{1}\n",
        "\n",
        "INSTRUCTIONS:\n",
        "- Maintain truthfulness and objectivity.\n",
        "- Prefer active voice over passive voice.\n",
        "- Generate a concise professional summary in 200 words based on the job description and the\n",
        "extracted resume.\n",
        "- Output the professional summary as a paragraph without any headers\n",
        "\"\"\"\n",
        "\n",
        "# Response schema for PROMPT_GENERATION\n",
        "RESPONSE_SCHEMA_PROMPT_GENERATION = {\n",
        "    \"type\": \"ARRAY\",\n",
        "    \"items\": {\n",
        "        \"type\": \"OBJECT\",\n",
        "        \"properties\": {\n",
        "            resume_structure[1]: {\n",
        "                \"type\": \"STRING\",\n",
        "            },\n",
        "        },\n",
        "    },\n",
        "}\n",
        "\n",
        "# Arrange the contents of sections in resume based on relevance to job description\n",
        "PROMPT_ARRANGE = \"\"\"\n",
        "You are a seasoned career advising professional expert in crafting resumes and cover letters.\n",
        "\n",
        "Consider the below details that have been extracted from a resume\n",
        "{0}\n",
        "\n",
        "Use the above details and craft a resume to satisfy the job description provided below\n",
        "{1}\n",
        "\n",
        "INSTRUCTIONS:\n",
        "- Maintain truthfulness and objectivity.\n",
        "- Proofread and correct spelling and grammatical errors.\n",
        "- Prefer passive voice over active voice.\n",
        "- Output Coursework, Skills and Certifications as numbered lists.\n",
        "- Arrange the Coursework such that the coursework that are most relevant to the job description are\n",
        "at the top.\n",
        "- Keep only the Coursework that are relevant to the job description.\n",
        "- Arrange the Skills such that the skill that are most relevant to the job description are\n",
        "at the top.\n",
        "- Keep only the Skills that are relevant to the job description.\n",
        "- Arrange the Certifications such that the certification that are most relevant to the job\n",
        "description are at the top.\n",
        "- Keep only the Certifications that are relevant to the job description.\n",
        "\"\"\"\n",
        "\n",
        "# Response schema for PROMPT_ARRANGE\n",
        "RESPONSE_SCHEMA_PROMPT_ARRANGE = {\n",
        "    \"type\": \"ARRAY\",\n",
        "    \"items\": {\n",
        "        \"type\": \"OBJECT\",\n",
        "        \"properties\": {\n",
        "            resume_structure[3]: {\n",
        "                \"type\": \"STRING\",\n",
        "            },\n",
        "            resume_structure[4]: {\n",
        "                \"type\": \"STRING\",\n",
        "            },\n",
        "            resume_structure[6]: {\n",
        "                \"type\": \"STRING\",\n",
        "            },\n",
        "        },\n",
        "    },\n",
        "}\n",
        "\n",
        "# Prompt to extract basic details from resume to help with parsing the resume\n",
        "PROMPT_EXTRACT_BASIC_DETAILS = f\"\"\"\n",
        "You are a seasoned career advising professional expert in crafting resumes and cover letters.\n",
        "\n",
        "Consider the below resume\n",
        "{0}\n",
        "\n",
        "Extract the following information from the given resume\n",
        "1. Name\n",
        "2. Address\n",
        "3. Mobile Number\n",
        "4. Email address\n",
        "\n",
        "INSTRUCTIONS:\n",
        "- Do not make up any information. \n",
        "- If you cannot find some information then say 'Not Found'.\n",
        "\"\"\"\n",
        "\n",
        "# Response schema for PROMPT_EXTRACT_BASIC_DETAILS\n",
        "RESPONSE_SCHEMA_PROMPT_EXTRACT_BASIC_DETAILS = {\n",
        "    \"type\": \"ARRAY\",\n",
        "    \"items\": {\n",
        "        \"type\": \"OBJECT\",\n",
        "        \"properties\": {\n",
        "            \"name\": {\n",
        "                \"type\": \"STRING\",\n",
        "            },\n",
        "            \"address\": {\"type\": \"STRING\"},\n",
        "            \"mobile_no\": {\"type\": \"STRING\"},\n",
        "            \"email\": {\"type\": \"STRING\"},\n",
        "        },\n",
        "    },\n",
        "}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qV1pqxYgSFr0"
      },
      "source": [
        "### Defining the core functionalities\n",
        "\n",
        "This code defines a series of functions for processing resumes. It uses Gemini to extract key information like contact details and to generate tailored professional summaries. The code also includes functions for parsing resumes from different file formats (docx, pdf, txt), handling potential missing information, and structuring the final output for readability."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "c8dc8fe8-890c-4471-915a-396787e84a1d"
      },
      "outputs": [],
      "source": [
        "def basic_info_extraction(resume: str) -> dict[str, str]:\n",
        "    \"\"\"Get the name, address, mobile number and email address from the resume\n",
        "\n",
        "    Args:\n",
        "        resume: The parsed resume as str\n",
        "\n",
        "    Returns:\n",
        "        Details requested in the prompt as dict\n",
        "    \"\"\"\n",
        "    resp = model.generate_content(\n",
        "        PROMPT_EXTRACT_BASIC_DETAILS.format(resume),\n",
        "        generation_config=GenerationConfig(\n",
        "            response_mime_type=\"application/json\",\n",
        "            response_schema=RESPONSE_SCHEMA_PROMPT_EXTRACT_BASIC_DETAILS,\n",
        "        ),\n",
        "    )\n",
        "    personal_details = json.loads(resp.text)\n",
        "    return personal_details[0]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "e87930b0-a15b-4ad7-86fd-a941cebc1637"
      },
      "outputs": [],
      "source": [
        "def read_pdf(file_path: str) -> str:\n",
        "    \"\"\"Extracts text from a PDF.\n",
        "\n",
        "    Args:\n",
        "        file_path: path to the pdf file\n",
        "\n",
        "    Returns:\n",
        "        resume content as plain text\n",
        "    \"\"\"\n",
        "    with open(file_path, \"rb\") as file:\n",
        "        reader = pypdf.PdfReader(file)\n",
        "        text = \"\"\n",
        "        for page in reader.pages:\n",
        "            text += page.extract_text()\n",
        "    return text"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "9a022cbe-ef5b-4131-8762-0358f578e500"
      },
      "outputs": [],
      "source": [
        "def iter_block_items(parent: Table) -> str:\n",
        "    \"\"\"Iterator over a docx file object.\n",
        "\n",
        "    Args:\n",
        "        parent: an iterable of type Table\n",
        "\n",
        "    Returns:\n",
        "        body text of each block\n",
        "    \"\"\"\n",
        "    if isinstance(parent, Document):\n",
        "        parent_elm = parent.element.body\n",
        "    elif isinstance(parent, _Cell):\n",
        "        parent_elm = parent._tc\n",
        "    else:\n",
        "        raise ValueError(\"Error in reading docx file\")\n",
        "\n",
        "    for child in parent_elm.iterchildren():\n",
        "        if isinstance(child, CT_P):\n",
        "            yield Paragraph(child, parent)\n",
        "        elif isinstance(child, CT_Tbl):\n",
        "            yield Table(child, parent)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "18adc15a-bae8-401c-b277-1df4dfa906e9"
      },
      "outputs": [],
      "source": [
        "def convert_docx_to_text(file_path: str) -> str:\n",
        "    \"\"\"Parse the docx file and convert it to text.\n",
        "\n",
        "    Args:\n",
        "        file_path: the path of the docx file to be parsed\n",
        "\n",
        "    Returns:\n",
        "        Parsed resume as string\n",
        "    \"\"\"\n",
        "    parsed_doc = \"\"\n",
        "    doc = docx.Document(file_path)\n",
        "    for block in iter_block_items(doc):\n",
        "        if isinstance(block, Table):  # check block is table\n",
        "            for row in block.rows:  # each table row\n",
        "                tab_row = [cell.text for cell in row.cells]\n",
        "                tab_row = list(\n",
        "                    filter(lambda x: x != \"\", tab_row)\n",
        "                )  # remove empty strings\n",
        "                if len(tab_row) > 1 and len(set(tab_row)) == 1:\n",
        "                    tab_row = tab_row[0]\n",
        "                    parsed_doc += \"\".join(tab_row) + \"\\n\"\n",
        "                else:\n",
        "                    parsed_doc += \", \".join(tab_row) + \"\\n\"\n",
        "        else:\n",
        "            parsed_doc += block.text + \"\\n\"  # paragraph text\n",
        "    return parsed_doc"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "f2541c9f-8d4a-4de5-80af-1d2561ceb3c7"
      },
      "outputs": [],
      "source": [
        "def parse_resume(res_path: str) -> str:\n",
        "    \"\"\"Driver method to parse resume with fallbacks.\n",
        "\n",
        "    Args:\n",
        "        res_path: Path to the resume file\n",
        "\n",
        "    Returns:\n",
        "        The parsed resume as string\n",
        "    \"\"\"\n",
        "    file_type = res_path.rsplit(\".\", 1)[-1]\n",
        "    if file_type == \"docx\":\n",
        "        parsed_resume = convert_docx_to_text(file_path=res_path).strip()\n",
        "        # check if name, address, email address and mobile no. has been extracted\n",
        "        personal_details = basic_info_extraction(parsed_resume)\n",
        "        if \"Not Found\" in personal_details.values():\n",
        "            parsed_resume_2 = docx2txt.process(res_path)\n",
        "            per_details_2 = \"\"\n",
        "            personal_details_2 = basic_info_extraction(parsed_resume_2)\n",
        "            for k, v in personal_details_2.items():\n",
        "                per_details_2 += f\"{k}: {v}\\n\"\n",
        "            parsed_resume = per_details_2 + \"\\n\" + parsed_resume\n",
        "    elif file_type == \"pdf\":\n",
        "        parsed_resume = read_pdf(res_path).strip()\n",
        "    elif file_type == \"txt\":\n",
        "        with open(res_path) as resume_text:\n",
        "            parsed_resume = resume_text.read().strip()\n",
        "    else:\n",
        "        raise Exception(\"File is not of valid type\")\n",
        "    return parsed_resume"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "7924162c-7318-4c56-a673-a7411e6fdfd8"
      },
      "outputs": [],
      "source": [
        "def structure_response(resume_generated: str) -> str:\n",
        "    \"\"\"Structure the resume to align with a given structure.\n",
        "\n",
        "    Args:\n",
        "        resume_generated: The resume generated using LLM\n",
        "\n",
        "    Returns:\n",
        "        The structured resume as string\n",
        "    \"\"\"\n",
        "    response_str = \"\"\n",
        "\n",
        "    for k in resume_structure:\n",
        "        try:\n",
        "            block, block_info = k, resume_generated[k]\n",
        "        except KeyError as k:\n",
        "            print(f\"Could not find section {k}\")\n",
        "            continue\n",
        "        response_str = f\"{response_str}\\n{block}\\n\"\n",
        "        if isinstance(block_info, list):\n",
        "            try:\n",
        "                response_str += \"\\n\".join(block_info) + \"\\n\"\n",
        "            except:\n",
        "                response_str += (\n",
        "                    \"\\n\".join([f\"{k}:{v}\" for k, v in block_info[0].items()]) + \"\\n\"\n",
        "                )\n",
        "        else:\n",
        "            response_str = f\"{response_str} {block_info}\\n\"\n",
        "    return response_str"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "835a87d0250f"
      },
      "outputs": [],
      "source": [
        "def get_response(\n",
        "    resume: str,\n",
        "    job_description: str,\n",
        ") -> str:\n",
        "    \"\"\"Generate the resume using the chosen model.\n",
        "\n",
        "    Args:\n",
        "        res: parsed resume as string\n",
        "        jd: parsed job description as string\n",
        "\n",
        "    Returns:\n",
        "        Collated resume information as string\n",
        "    \"\"\"\n",
        "    model_response_extraction = model.generate_content(\n",
        "        PROMPT_EXTRACTION.format(resume),\n",
        "        generation_config=GenerationConfig(\n",
        "            response_mime_type=\"application/json\",\n",
        "            response_schema=RESPONSE_SCHEMA_PROMPT_EXTRACTION,\n",
        "        ),\n",
        "    ).text\n",
        "\n",
        "    model_response_gen = model.generate_content(\n",
        "        PROMPT_GENERATION.format(resume, job_description),\n",
        "        generation_config=GenerationConfig(\n",
        "            response_mime_type=\"application/json\",\n",
        "            response_schema=RESPONSE_SCHEMA_PROMPT_GENERATION,\n",
        "        ),\n",
        "    ).text\n",
        "\n",
        "    model_response_arr = model.generate_content(\n",
        "        PROMPT_ARRANGE.format(resume, job_description),\n",
        "        generation_config=GenerationConfig(\n",
        "            response_mime_type=\"application/json\",\n",
        "            response_schema=RESPONSE_SCHEMA_PROMPT_ARRANGE,\n",
        "        ),\n",
        "    ).text\n",
        "\n",
        "    resume_generated = json.loads(model_response_extraction)[0]\n",
        "    resume_generated.update(json.loads(model_response_gen)[0])\n",
        "    resume_generated_3 = json.loads(model_response_arr)[0]\n",
        "    resume_generated.update(resume_generated_3)\n",
        "\n",
        "    return resume_generated"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "afuU6971UlYO"
      },
      "source": [
        "### Testing the overall functionality\n",
        "\n",
        "This code tests a resume generator. It parses a sample resume and job description, feeds them to an LLM, and structures the generated output."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "c469abaf-cbaa-47ef-aec2-c097bf464335"
      },
      "outputs": [],
      "source": [
        "# Test resume generation\n",
        "\n",
        "\n",
        "resume_path = \"Sample_1.docx\"\n",
        "parsed_resume = parse_resume(res_path=resume_path)\n",
        "\n",
        "sample_job_description = \"\"\"\n",
        "PHP Developer\n",
        "Job Description\n",
        "    •Development of robust and user-friendly PHP-based web applications\n",
        "    •Creation of site layout/user interface from provided design concepts\n",
        "    •Ability to work independently on projects without detailed\n",
        "    instructions; taking the initiative with this job is important.\n",
        "    •Routine daily maintenance of existing sites and web applications.\n",
        "Requirements\n",
        "    •Knowledge of PHP/MySQL.\n",
        "    •Experience developing in PHP, which requires integration with\n",
        "    databases such as MySQL.\n",
        "    •Experience programming in HTML, CSS, XML, JavaScript, jQuery, etc.\n",
        "    •Experience in WordPress development is a plus.\n",
        "    •Business requirements analysis ability is a plus.\n",
        "    •Good oral and written communication skills.\n",
        "    •Strong desire to develop new technical knowledge and professional\n",
        "    skills on a continual basis.\n",
        "    •Ability to work with only general supervision.\n",
        "    •Ability to supporting sales on technical demonstration of system\n",
        "    (if needed).\n",
        "    •Ability to give system training to customer (if needed).\n",
        "    •Ability to work well independently and with others.\n",
        "\"\"\"\n",
        "\n",
        "generated_resume = get_response(parsed_resume, sample_job_description)\n",
        "structured_resume = structure_response(generated_resume)\n",
        "print(f\"Generated Resume \\n {structured_resume}\")"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "name": "resume_generator.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
